// 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) { const auto inputType = getDataTypeEnumFromType(); std::cout << "Running convolution backward weights graph " << inputType << " [" << layout << "]" << (config.cpuValidation ? " (with CPU validation)" : "") << "...\n"; // Input (x) 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 (dw) 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; // Output gradient (dy dimensions) const int64_t outH = (h + 2 * padH - dilH * (r - 1) - 1) / u + 1; const int64_t outW = (w + 2 * padW - dilW * (s - 1) - 1) / v + 1; auto graph = std::make_shared(); graph->set_io_data_type(inputType).set_compute_data_type(hipdnn_frontend::DataType::FLOAT); setPreferredEngine(graph, config); auto dyAttr = createTensor({n, k, outH, outW}, inputType, layout); auto xAttr = createTensor({n, c, h, w}, inputType, layout); graph::ConvWgradAttributes convAttributes; convAttributes.set_name("conv_backward_weights_node"); convAttributes.set_pre_padding({padH, padW}); convAttributes.set_post_padding({padH, padW}); convAttributes.set_stride({u, v}); convAttributes.set_dilation({dilH, dilW}); auto dwAttr = graph->conv_wgrad(dyAttr, xAttr, convAttributes); dwAttr->set_dim({k, c, r, s}); dwAttr->set_output(true); HIPDNN_FE_CHECK_SKIPPABLE(graph->build(handle)); std::cout << "Graph build successful.\n"; utilities::Tensor dyTensor(dyAttr->get_dim(), layout); utilities::Tensor xTensor(xAttr->get_dim(), layout); utilities::Tensor dwTensor(dwAttr->get_dim(), layout); dyTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); xTensor.fillWithRandomValues(static_cast(0.0f), static_cast(1.0f)); dwTensor.fillWithValue(static_cast(0.0f)); std::unordered_map variantPack; variantPack[dyAttr->get_uid()] = dyTensor.memory().deviceData(); variantPack[xAttr->get_uid()] = xTensor.memory().deviceData(); variantPack[dwAttr->get_uid()] = dwTensor.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())); dwTensor.memory().markDeviceModified(); auto dwHostPtr = dwTensor.memory().hostData(); std::cout << "First 10 dw values: "; for(int i = 0; i < 10; ++i) { std::cout << static_cast(dwHostPtr[i]) << " "; } std::cout << '\n'; bool validationPassed = true; if(config.cpuValidation) { std::cout << "Running CPU reference validation...\n"; utilities::Tensor dwRefTensor(dwAttr->get_dim(), layout); hipdnn_test_sdk::utilities::CpuFpReferenceConvolution::wgrad( xTensor, dwRefTensor, dyTensor, {u, v}, {dilH, dilW}, {padH, padW}); auto absoluteTolerance = hipdnn_test_sdk::utilities::conv:: calculateConvWrwTolerance( 0.0, 1.0, 0.0, 1.0, dyAttr->get_dim()); constexpr float RELATIVE_TOLERANCE = 0.01f; auto dwValidator = hipdnn_test_sdk::utilities::CpuFpReferenceValidation( absoluteTolerance, RELATIVE_TOLERANCE); std::cout << "CPU reference validation:\n"; const bool dwValid = hipdnn_test_sdk::utilities::validateAndReport(std::cout, "dw", dwValidator, dwRefTensor, dwTensor, absoluteTolerance, RELATIVE_TOLERANCE); validationPassed = dwValid; } std::cout << "Convolution backward weights 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 convolution backward weights runs completed successfully.\n"; return 0; } std::cout << "One or more convolution backward weights runs failed validation.\n"; return 1; } catch(const std::exception& e) { std::fprintf(stderr, "Unhandled exception: %s\n", e.what()); return 1; } }