mirror of
https://github.com/ROCm/composable_kernel.git
synced 2026-03-27 18:47:39 +00:00
* chore(copyright): update copyright header for codegen directory * chore(copyright): update copyright header for example directory
173 lines
7.2 KiB
C++
173 lines
7.2 KiB
C++
// Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include "common.hpp"
|
|
|
|
using ::ck::DeviceMem;
|
|
using ::ck::HostTensorDescriptor;
|
|
using ::ck::Tensor;
|
|
|
|
using InDataType = FP32;
|
|
using OutDataType = FP32;
|
|
|
|
using ImLayout = ck::tensor_layout::convolution::GNHWC;
|
|
using ImageToColumnOp = ck::conv_tensor_rearrange_op::ImageToColumn;
|
|
|
|
// clang-format off
|
|
using DeviceImgToColInstance = ck::tensor_operation::device::DeviceImageToColumnImpl
|
|
//#####################| Num| ImLayout| InDataType| OutDataType| Block| MPer| KPer| Thread| Scalar|
|
|
//#####################| Dim| | | | Size| Block| Block| Cluster| Per|
|
|
//#####################| Spatial| | | | | | | Lengths| Vector|
|
|
//#####################| | | | | | | | | |
|
|
< NDimSpatial, ImLayout, InDataType, OutDataType, 256, 128, 128, S<16, 16>, 1>;
|
|
// clang-format on
|
|
|
|
bool RunImageToColumn(const ExecutionConfig& config, const ck::utils::conv::ConvParam& conv_params)
|
|
{
|
|
const auto G = conv_params.G_;
|
|
const auto N = conv_params.N_;
|
|
const auto C = conv_params.C_;
|
|
|
|
const ck::index_t NDoHoWo =
|
|
N * ck::accumulate_n<ck::index_t>(
|
|
conv_params.output_spatial_lengths_.begin(), NDimSpatial, 1, std::multiplies<>());
|
|
const ck::index_t CZYX =
|
|
C * ck::accumulate_n<ck::index_t>(
|
|
conv_params.filter_spatial_lengths_.begin(), NDimSpatial, 1, std::multiplies<>());
|
|
|
|
const auto in_desc =
|
|
ck::utils::conv::make_input_host_tensor_descriptor_g_n_c_wis_packed<ImLayout>(conv_params);
|
|
const auto out_desc = HostTensorDescriptor({G, NDoHoWo, CZYX});
|
|
|
|
std::array<ck::index_t, NDimSpatial> input_spatial_lengths{};
|
|
std::array<ck::index_t, NDimSpatial> filter_spatial_lengths{};
|
|
std::array<ck::index_t, NDimSpatial> output_spatial_lengths{};
|
|
std::array<ck::index_t, NDimSpatial + 3> image_g_n_c_wis_strides{};
|
|
std::array<ck::index_t, 3> gemm_g_m_k_strides{};
|
|
std::array<ck::index_t, NDimSpatial> conv_filter_strides{};
|
|
std::array<ck::index_t, NDimSpatial> conv_filter_dilations{};
|
|
std::array<ck::index_t, NDimSpatial> input_left_pads{};
|
|
std::array<ck::index_t, NDimSpatial> input_right_pads{};
|
|
|
|
auto copy = [](const auto& x, auto& y) { std::copy(x.begin(), x.end(), y.begin()); };
|
|
|
|
copy(conv_params.input_spatial_lengths_, input_spatial_lengths);
|
|
copy(conv_params.filter_spatial_lengths_, filter_spatial_lengths);
|
|
copy(conv_params.output_spatial_lengths_, output_spatial_lengths);
|
|
copy(in_desc.GetStrides(), image_g_n_c_wis_strides);
|
|
copy(out_desc.GetStrides(), gemm_g_m_k_strides);
|
|
copy(conv_params.conv_filter_strides_, conv_filter_strides);
|
|
copy(conv_params.conv_filter_dilations_, conv_filter_dilations);
|
|
copy(conv_params.input_left_pads_, input_left_pads);
|
|
copy(conv_params.input_right_pads_, input_right_pads);
|
|
|
|
Tensor<InDataType> in(in_desc);
|
|
Tensor<OutDataType> out_device(out_desc);
|
|
Tensor<OutDataType> out_host(out_desc);
|
|
|
|
std::cout << "in: " << in.mDesc << std::endl;
|
|
std::cout << "out: " << out_device.mDesc << std::endl;
|
|
|
|
switch(config.init_method)
|
|
{
|
|
case 0: break;
|
|
case 1: in.GenerateTensorValue(GeneratorTensor_2<InDataType>{-5, 5}); break;
|
|
default: in.GenerateTensorValue(GeneratorTensor_3<InDataType>{-0.5, 0.5});
|
|
}
|
|
|
|
DeviceMem in_device_buf(sizeof(InDataType) * in.mDesc.GetElementSpaceSize());
|
|
DeviceMem out_device_buf(sizeof(OutDataType) * out_device.mDesc.GetElementSpaceSize());
|
|
|
|
in_device_buf.ToDevice(in.mData.data());
|
|
|
|
// reset input to zero
|
|
out_device_buf.SetZero();
|
|
|
|
static_assert(std::is_default_constructible_v<DeviceImgToColInstance>);
|
|
|
|
// do conv
|
|
auto img2col = DeviceImgToColInstance{};
|
|
auto invoker = img2col.MakeInvoker();
|
|
auto argument = img2col.MakeArgument(in_device_buf.GetDeviceBuffer(),
|
|
out_device_buf.GetDeviceBuffer(),
|
|
G,
|
|
N,
|
|
C,
|
|
input_spatial_lengths,
|
|
filter_spatial_lengths,
|
|
output_spatial_lengths,
|
|
image_g_n_c_wis_strides,
|
|
gemm_g_m_k_strides,
|
|
conv_filter_strides,
|
|
conv_filter_dilations,
|
|
input_left_pads,
|
|
input_right_pads);
|
|
|
|
if(!img2col.IsSupportedArgument(argument))
|
|
{
|
|
std::cerr << "wrong! device_img2col with the specified compilation parameters does "
|
|
"not support this img2col problem"
|
|
<< std::endl;
|
|
|
|
return false;
|
|
}
|
|
|
|
float ave_time = invoker.Run(argument, StreamConfig{nullptr, config.time_kernel});
|
|
std::size_t num_btype = G * NDoHoWo * CZYX * (sizeof(OutDataType) + sizeof(InDataType));
|
|
float gb_per_sec = num_btype / 1.E6 / ave_time;
|
|
std::cout << "Perf: " << ave_time << " ms, " << gb_per_sec << " GB/s" << std::endl;
|
|
|
|
if(config.do_verification)
|
|
{
|
|
auto ref_image_to_column = ck::tensor_operation::host::
|
|
ReferenceImageToColumn<NDimSpatial, ImLayout, InDataType, OutDataType>();
|
|
|
|
auto ref_invoker = ref_image_to_column.MakeInvoker();
|
|
|
|
auto ref_argument = ref_image_to_column.MakeArgument(in,
|
|
out_host,
|
|
conv_params.filter_spatial_lengths_,
|
|
conv_params.conv_filter_strides_,
|
|
conv_params.conv_filter_dilations_,
|
|
conv_params.input_left_pads_,
|
|
conv_params.input_right_pads_);
|
|
|
|
if(!ref_image_to_column.IsSupportedArgument(&ref_argument))
|
|
{
|
|
std::cerr << "wrong! ref_img2col with the specified compilation parameters does "
|
|
"not support this img2col problem"
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
ref_invoker.Run(ref_argument);
|
|
|
|
out_device_buf.FromDevice(out_device.mData.data());
|
|
|
|
return ck::utils::check_err(out_device.mData, out_host.mData);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int RunImageToColumnExample(int argc, char* argv[])
|
|
{
|
|
ExecutionConfig config;
|
|
ck::utils::conv::ConvParam conv_params = DefaultConvParams;
|
|
|
|
if(!parse_cmd_args(argc, argv, config, conv_params))
|
|
{
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if(conv_params.num_dim_spatial_ != NDimSpatial)
|
|
{
|
|
std::cerr << "unsupported # of spatial dimensions" << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
return !RunImageToColumn(config, conv_params);
|
|
}
|
|
|
|
int main(int argc, char* argv[]) { return RunImageToColumnExample(argc, argv); }
|