// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #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) { const auto inputType = getDataTypeEnumFromType(); std::cout << "Running fused convolution fprop + activ graph " << inputType << " [" << layout << "]" << (config.cpuValidation ? " (with CPU validation)" : "") << "...\n"; // Input 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 const int64_t h = config.dims.size() > 2 ? config.dims[2] : 16; // Height const int64_t w = config.dims.size() > 3 ? config.dims[3] : 16; // Width // Filter const int64_t k = config.filter.size() > 0 ? config.filter[0] : 16; // Output channels const int64_t r = config.filter.size() > 1 ? config.filter[1] : 3; // Filter height const int64_t s = config.filter.size() > 2 ? config.filter[2] : 3; // Filter width // Stride const int64_t u = config.stride.size() > 0 ? config.stride[0] : 1; const int64_t v = config.stride.size() > 1 ? config.stride[1] : 1; // Padding const int64_t padH = config.padding.size() > 0 ? config.padding[0] : 1; const int64_t padW = config.padding.size() > 1 ? config.padding[1] : 1; // Dilation const int64_t dilH = config.dilation.size() > 0 ? config.dilation[0] : 1; const int64_t dilW = config.dilation.size() > 1 ? config.dilation[1] : 1; auto graph = std::make_shared(); graph->set_io_data_type(inputType) .set_compute_data_type(hipdnn_frontend::DataType::FLOAT) .set_intermediate_data_type(hipdnn_frontend::DataType::FLOAT); setPreferredEngine(graph, config); auto xAttr = createTensor({n, c, h, w}, inputType, layout); auto wAttr = createTensor({k, c, r, s}, inputType, layout); graph::ConvFpropAttributes convAttributes; convAttributes.set_name("conv_fprop_node"); convAttributes.set_padding({padH, padW}); convAttributes.set_stride({u, v}); convAttributes.set_dilation({dilH, dilW}); auto yAttr = graph->conv_fprop(xAttr, wAttr, convAttributes); yAttr->set_output(false); graph::PointwiseAttributes pointwiseAttributes; pointwiseAttributes.set_mode(PointwiseMode::RELU_FWD); // Set values to clamp between 0.2 - 0.7 pointwiseAttributes.set_relu_lower_clip(0.2f); pointwiseAttributes.set_relu_upper_clip(0.7f); auto pointwiseOutAttr = graph->pointwise(yAttr, pointwiseAttributes); pointwiseOutAttr->set_output(true); HIPDNN_FE_CHECK_SKIPPABLE(graph->build(handle)); std::cout << "Graph build successful.\n"; utilities::Tensor xTensor(xAttr->get_dim(), layout); utilities::Tensor wTensor(wAttr->get_dim(), layout); utilities::Tensor pointwiseOutTensor(pointwiseOutAttr->get_dim(), layout); xTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); wTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); pointwiseOutTensor.fillWithValue(static_cast(0.0f)); std::unordered_map variantPack; variantPack[xAttr->get_uid()] = xTensor.memory().deviceData(); variantPack[wAttr->get_uid()] = wTensor.memory().deviceData(); variantPack[pointwiseOutAttr->get_uid()] = pointwiseOutTensor.memory().deviceData(); int64_t workspaceSize = 0; HIPDNN_FE_CHECK(graph->get_workspace_size(workspaceSize)); const utilities::Workspace workspace(static_cast(workspaceSize)); HIPDNN_FE_CHECK(graph->execute(handle, variantPack, workspace.get())); pointwiseOutTensor.memory().markDeviceModified(); auto pointwiseOutHostPtr = pointwiseOutTensor.memory().hostData(); std::cout << "First 10 pointwise out values: "; for(int i = 0; i < 10; ++i) { std::cout << static_cast(pointwiseOutHostPtr[i]) << " "; } std::cout << '\n'; bool validationPassed = true; if(config.cpuValidation) { std::cout << "Running CPU reference validation...\n"; utilities::Tensor yRefTensor(yAttr->get_dim(), layout); utilities::Tensor pointwiseOutRefTensor(pointwiseOutAttr->get_dim(), layout); hipdnn_test_sdk::utilities::CpuFpReferenceConvolution::fprop( xTensor, wTensor, yRefTensor, {u, v}, {dilH, dilW}, {padH, padW}); hipdnn_test_sdk::utilities::CpuReferencePointwiseImpl::pointwiseCompute( hipdnn_flatbuffers_sdk::data_objects::PointwiseMode::RELU_FWD, pointwiseOutRefTensor, yRefTensor, pointwiseAttributes.get_relu_lower_clip().value(), pointwiseAttributes.get_relu_upper_clip().value(), 0.0f); auto tolerance = hipdnn_test_sdk::utilities::conv::getToleranceFwd(); auto outValidator = hipdnn_test_sdk::utilities::CpuFpReferenceValidation(tolerance, tolerance); std::cout << "CPU reference validation:\n"; const bool outValid = hipdnn_test_sdk::utilities::validateAndReport(std::cout, "pointwise out", outValidator, pointwiseOutRefTensor, pointwiseOutTensor, tolerance, tolerance); validationPassed = outValid; } std::cout << "Fused Convolution fprop + Activ 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 fused Conv fwd + Activation runs completed successfully.\n"; return 0; } std::cout << "One or more fused Conv fwd + Activation runs failed validation.\n"; return 1; } catch(const std::exception& e) { std::fprintf(stderr, "Unhandled exception: %s\n", e.what()); return 1; } }