// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include #include #include #include #include #include #include #include #include #include "../utils/Helpers.hpp" using namespace hipdnn_frontend; using namespace hipdnn_data_sdk; template bool SampleRunner::operator()(const TensorLayout& layout) { auto inputType = getDataTypeEnumFromType(); auto intermediateType = getDataTypeEnumFromType(); std::cout << "Running batch normalization inference with variance graph " << inputType << " [" << layout << "]" << (config.cpuValidation ? " (with CPU validation)" : "") << "...\n"; // Input dimensions const int64_t n = config.dims.size() > 0 ? config.dims[0] : 16; // BATCH SIZE const int64_t c = config.dims.size() > 1 ? config.dims[1] : 16; // CHANNELS (FEATURES) const int64_t h = config.dims.size() > 2 ? config.dims[2] : 16; // HEIGHT (SPATIAL DIMENSION) const int64_t w = config.dims.size() > 3 ? config.dims[3] : 16; // WIDTH (SPATIAL DIMENSION) auto graph = std::make_shared(); graph->set_io_data_type(inputType) .set_intermediate_data_type(intermediateType) .set_compute_data_type(hipdnn_frontend::DataType::FLOAT); setPreferredEngine(graph, config); auto x = createTensor({n, c, h, w}, inputType, layout); auto scale = createTensor({1, c, 1, 1}, intermediateType); auto bias = createTensor({1, c, 1, 1}, intermediateType); auto mean = createTensor({1, c, 1, 1}, intermediateType); auto variance = createTensor({1, c, 1, 1}, intermediateType); // Epsilon is a pass-by-value scalar, not a buffer auto epsilonTensor = std::make_shared(); epsilonTensor->set_value(utilities::BATCHNORM_DEFAULT_EPSILON); auto bnAttributes = graph::BatchnormInferenceAttributesVarianceExt(); bnAttributes.set_name("bn_inference_variance_ext_node"); auto y = graph->batchnorm_inference_variance_ext( x, mean, variance, scale, bias, epsilonTensor, bnAttributes); y->set_output(true); HIPDNN_FE_CHECK_SKIPPABLE(graph->build(handle)); std::cout << "Graph build successful.\n"; utilities::Tensor xTensor(x->get_dim(), layout); utilities::Tensor scaleTensor(scale->get_dim()); utilities::Tensor biasTensor(bias->get_dim()); utilities::Tensor meanTensor(mean->get_dim()); utilities::Tensor varianceTensor(variance->get_dim()); utilities::Tensor yTensor(y->get_dim(), layout); xTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); scaleTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); biasTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); meanTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); varianceTensor.fillWithRandomValues(static_cast(0.1f), static_cast(1.0f)); std::unordered_map variantPack; variantPack[x->get_uid()] = xTensor.memory().deviceData(); variantPack[scale->get_uid()] = scaleTensor.memory().deviceData(); variantPack[bias->get_uid()] = biasTensor.memory().deviceData(); variantPack[mean->get_uid()] = meanTensor.memory().deviceData(); variantPack[variance->get_uid()] = varianceTensor.memory().deviceData(); variantPack[y->get_uid()] = yTensor.memory().deviceData(); HIPDNN_FE_CHECK(graph->execute(handle, variantPack, nullptr)); yTensor.memory().markDeviceModified(); auto yHostPtr = yTensor.memory().hostData(); bool validationPassed = true; if(config.cpuValidation) { std::cout << "Running CPU reference validation...\n"; utilities::Tensor yRefTensor(y->get_dim(), layout); auto tolerance = hipdnn_test_sdk::utilities::batchnorm::getToleranceInferenceWithVariance(); const double epsilon = utilities::BATCHNORM_DEFAULT_EPSILON; hipdnn_test_sdk::utilities::CpuFpReferenceBatchnorm::fwdInferenceWithVariance( xTensor, scaleTensor, biasTensor, meanTensor, varianceTensor, yRefTensor, epsilon); auto validator = hipdnn_test_sdk::utilities::CpuFpReferenceValidation(tolerance, tolerance); std::cout << "CPU reference validation:\n"; const bool yValid = hipdnn_test_sdk::utilities::validateAndReport( std::cout, "y", validator, yRefTensor, yTensor, tolerance, tolerance); validationPassed = yValid; } std::cout << "First 10 y values: "; for(int i = 0; i < 10; ++i) { std::cout << static_cast(yHostPtr[i]) << " "; } std::cout << "\nBatch normalization inference with variance graph execution complete for " << inputType << ".\n\n"; return validationPassed; } int main(int argc, char* argv[]) { try { RETURN_SUCCESS_IF_NO_DEVICE(); auto config = parseCommandLineArgs(argc, argv); auto [handle, handleError] = createHipdnnHandle(); HIPDNN_FE_CHECK(handleError); const bool allPassed = run(SampleRunner{*handle, config}); if(allPassed) { std::cout << "All batch normalization inference with variance runs completed successfully.\n"; return 0; } std::cout << "One or more batch normalization inference with variance runs failed validation.\n"; return 1; } catch(const std::exception& e) { std::fprintf(stderr, "Unhandled exception: %s\n", e.what()); return 1; } }