mirror of
https://github.com/ROCm/composable_kernel.git
synced 2026-05-18 03:49:41 +00:00
Add column to image kernel (#930)
* Add column to image kernel * Minor fixes for dtypes and client examples * Disable tests for disabled dtypes * Disable add instances functions for disabled data types * Minor stylistic fixes * Revert "Disable add instances functions for disabled data types" This reverts commit728b869563. * Instances reduction * Add comments in device_column_to_image_impl * Update changelog and Copyrights * Improve changelog [ROCm/composable_kernel commit:e2243a4d1e]
This commit is contained in:
@@ -155,7 +155,7 @@ add_subdirectory(contraction)
|
||||
add_subdirectory(pool)
|
||||
add_subdirectory(batched_gemm_multi_d)
|
||||
add_subdirectory(grouped_convnd_bwd_data)
|
||||
add_subdirectory(image_to_column)
|
||||
add_subdirectory(conv_tensor_rearrange)
|
||||
if(GPU_TARGETS MATCHES "gfx11")
|
||||
add_subdirectory(wmma_op)
|
||||
endif()
|
||||
|
||||
4
test/conv_tensor_rearrange/CMakeLists.txt
Normal file
4
test/conv_tensor_rearrange/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
add_gtest_executable(test_conv_tensor_rearrange test_conv_tensor_rearrange.cpp)
|
||||
target_link_libraries(test_conv_tensor_rearrange PRIVATE utility device_image_to_column_instance device_column_to_image_instance)
|
||||
add_gtest_executable(test_conv_tensor_rearrange_interface test_conv_tensor_rearrange_interface.cpp)
|
||||
target_link_libraries(test_conv_tensor_rearrange_interface PRIVATE utility)
|
||||
153
test/conv_tensor_rearrange/test_conv_tensor_rearrange.cpp
Normal file
153
test/conv_tensor_rearrange/test_conv_tensor_rearrange.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "profiler/profile_conv_tensor_rearrange_impl.hpp"
|
||||
|
||||
template <typename Tuple>
|
||||
class TestConvTensorRearrange : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
using ImLayout = std::tuple_element_t<0, Tuple>;
|
||||
using ConvTensorRearrangeOp = std::tuple_element_t<1, Tuple>;
|
||||
|
||||
std::vector<ck::utils::conv::ConvParam> conv_params;
|
||||
|
||||
template <ck::index_t NDimSpatial, typename InDataType, typename OutDataType>
|
||||
void Run()
|
||||
{
|
||||
EXPECT_FALSE(conv_params.empty());
|
||||
bool pass = true;
|
||||
for(auto& param : conv_params)
|
||||
{
|
||||
pass = pass && ck::profiler::profile_conv_tensor_rearrange_impl<NDimSpatial,
|
||||
ImLayout,
|
||||
InDataType,
|
||||
OutDataType,
|
||||
ConvTensorRearrangeOp>(
|
||||
true, // do_verification
|
||||
1, // init_method: integer value
|
||||
false, // do_log
|
||||
false, // time_kernel
|
||||
param);
|
||||
}
|
||||
EXPECT_TRUE(pass);
|
||||
}
|
||||
};
|
||||
|
||||
using namespace ck::tensor_layout::convolution;
|
||||
using namespace ck::conv_tensor_rearrange_op;
|
||||
|
||||
using KernelTypes1d =
|
||||
::testing::Types<std::tuple<GNWC, ImageToColumn>, std::tuple<GNWC, ColumnToImage>>;
|
||||
|
||||
using KernelTypes2d =
|
||||
::testing::Types<std::tuple<GNHWC, ImageToColumn>, std::tuple<GNHWC, ColumnToImage>>;
|
||||
|
||||
using KernelTypes3d =
|
||||
::testing::Types<std::tuple<GNDHWC, ImageToColumn>, std::tuple<GNDHWC, ColumnToImage>>;
|
||||
|
||||
template <typename Tuple>
|
||||
class TestConvTensorRearrange1d : public TestConvTensorRearrange<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
class TestConvTensorRearrange2d : public TestConvTensorRearrange<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
class TestConvTensorRearrange3d : public TestConvTensorRearrange<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE(TestConvTensorRearrange1d, KernelTypes1d);
|
||||
TYPED_TEST_SUITE(TestConvTensorRearrange2d, KernelTypes2d);
|
||||
TYPED_TEST_SUITE(TestConvTensorRearrange3d, KernelTypes3d);
|
||||
|
||||
TYPED_TEST(TestConvTensorRearrange1d, Test1D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
|
||||
this->conv_params.push_back({1, 1, 4, 1, 192, {3}, {28}, {1}, {1}, {1}, {1}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {3}, {14}, {1}, {1}, {1}, {1}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {1}, {7}, {3}, {1}, {0}, {0}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {1}, {3}, {1}, {1}, {0}, {0}});
|
||||
// ScalarPerVector should be 1
|
||||
this->conv_params.push_back({1, 1, 4, 1, 1, {3}, {28}, {1}, {1}, {1}, {1}});
|
||||
// stride != 1
|
||||
this->conv_params.push_back({1, 1, 1, 1, 4, {3}, {28}, {2}, {1}, {1}, {1}});
|
||||
// dilation != 1
|
||||
this->conv_params.push_back({1, 1, 1, 1, 4, {3}, {28}, {1}, {2}, {1}, {1}});
|
||||
#ifdef CK_ENABLE_FP32
|
||||
this->template Run<1, float, float>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_BF16
|
||||
this->template Run<1, ck::bhalf_t, ck::bhalf_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_FP16
|
||||
this->template Run<1, ck::half_t, ck::half_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_INT8
|
||||
this->template Run<1, int8_t, int8_t>();
|
||||
#endif
|
||||
}
|
||||
|
||||
TYPED_TEST(TestConvTensorRearrange2d, Test2D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
|
||||
this->conv_params.push_back(
|
||||
{2, 1, 4, 1, 192, {3, 3}, {28, 28}, {1, 1}, {1, 1}, {1, 1}, {1, 1}});
|
||||
this->conv_params.push_back(
|
||||
{2, 1, 64, 1, 64, {3, 3}, {14, 14}, {1, 1}, {1, 1}, {1, 1}, {1, 1}});
|
||||
this->conv_params.push_back({2, 1, 64, 1, 64, {1, 1}, {7, 7}, {3, 3}, {1, 1}, {0, 0}, {0, 0}});
|
||||
this->conv_params.push_back({2, 1, 64, 1, 64, {1, 1}, {3, 3}, {1, 1}, {1, 1}, {0, 0}, {0, 0}});
|
||||
this->conv_params.push_back(
|
||||
{2, 1, 64, 1, 64, {3, 3}, {28, 28}, {2, 2}, {2, 2}, {1, 1}, {1, 1}});
|
||||
#ifdef CK_ENABLE_FP32
|
||||
this->template Run<2, float, float>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_BF16
|
||||
this->template Run<2, ck::bhalf_t, ck::bhalf_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_FP16
|
||||
this->template Run<2, ck::half_t, ck::half_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_INT8
|
||||
this->template Run<2, int8_t, int8_t>();
|
||||
#endif
|
||||
}
|
||||
|
||||
TYPED_TEST(TestConvTensorRearrange3d, Test3D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 16, 1, 64, {1, 1, 1}, {7, 7, 7}, {2, 2, 2}, {3, 3, 3}, {0, 0, 0}, {0, 0, 0}});
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 2, 1, 64, {3, 3, 3}, {14, 14, 3}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}});
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 32, 1, 64, {1, 1, 1}, {3, 3, 3}, {1, 1, 1}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}});
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 64, 1, 64, {3, 3, 3}, {14, 14, 14}, {2, 2, 2}, {2, 2, 2}, {1, 1, 1}, {1, 1, 1}});
|
||||
#ifdef CK_ENABLE_FP32
|
||||
this->template Run<3, float, float>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_BF16
|
||||
this->template Run<3, ck::bhalf_t, ck::bhalf_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_FP16
|
||||
this->template Run<3, ck::half_t, ck::half_t>();
|
||||
#endif
|
||||
#ifdef CK_ENABLE_INT8
|
||||
this->template Run<3, int8_t, int8_t>();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "ck/ck.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/tensor_layout.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/impl/device_image_to_column_impl.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/impl/device_column_to_image_impl.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/conv_tensor_rearrange_op.hpp"
|
||||
|
||||
#include "ck/library/utility/convolution_parameter.hpp"
|
||||
#include "ck/library/utility/algorithm.hpp"
|
||||
#include "ck/library/utility/convolution_host_tensor_descriptor_helper.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using DataType = float;
|
||||
using ImLayout = ck::tensor_layout::convolution::GNWC;
|
||||
|
||||
template <ck::index_t... Is>
|
||||
using S = ck::Sequence<Is...>;
|
||||
|
||||
using namespace ck::conv_tensor_rearrange_op;
|
||||
|
||||
template <ck::index_t ScalarPerVector, bool IsCPacked>
|
||||
class TestConvTensorRearrangeInterface : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static constexpr ck::index_t NDimSpatial = 1;
|
||||
|
||||
// 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, DataType, DataType, 256, 128, 128, S<16, 16>,ScalarPerVector>;
|
||||
using DeviceColToimgInstance = ck::tensor_operation::device::DeviceColumnToImageImpl
|
||||
// Num| ImLayout| InDataType| OutDataType| Block| MPer| KPer| Thread| Scalar|
|
||||
// Dim| | | | Size| Block| Block| Cluster| Per|
|
||||
// Spatial| | | | | | | Lengths| Vector|
|
||||
// | | | | | | | | |
|
||||
< NDimSpatial, ImLayout, DataType, DataType, 256, 128, 128, S<16, 16>,ScalarPerVector>;
|
||||
// clang-format on
|
||||
|
||||
ck::utils::conv::ConvParam conv_param;
|
||||
|
||||
template <typename ConvTensorRearrangeOp>
|
||||
bool Run()
|
||||
{
|
||||
|
||||
const auto N = conv_param.N_;
|
||||
const auto C = conv_param.C_;
|
||||
const auto FakeC =
|
||||
conv_param.C_ / 2; // Fake C to simulate the behavior that C is not packed
|
||||
|
||||
const ck::index_t NDoHoWo =
|
||||
N *
|
||||
ck::accumulate_n<ck::index_t>(
|
||||
conv_param.output_spatial_lengths_.begin(), NDimSpatial, 1, std::multiplies<>());
|
||||
const ck::index_t CZYX =
|
||||
C *
|
||||
ck::accumulate_n<ck::index_t>(
|
||||
conv_param.filter_spatial_lengths_.begin(), NDimSpatial, 1, std::multiplies<>());
|
||||
|
||||
const auto image_desc =
|
||||
ck::utils::conv::make_input_host_tensor_descriptor_g_n_c_wis_packed<ImLayout>(
|
||||
conv_param);
|
||||
const auto gemm_desc = HostTensorDescriptor({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> input_g_n_c_wis_strides{};
|
||||
std::array<ck::index_t, 2> output_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_param.input_spatial_lengths_, input_spatial_lengths);
|
||||
copy(conv_param.filter_spatial_lengths_, filter_spatial_lengths);
|
||||
copy(conv_param.output_spatial_lengths_, output_spatial_lengths);
|
||||
copy(image_desc.GetStrides(), input_g_n_c_wis_strides);
|
||||
copy(gemm_desc.GetStrides(), output_m_k_strides);
|
||||
copy(conv_param.conv_filter_strides_, conv_filter_strides);
|
||||
copy(conv_param.conv_filter_dilations_, conv_filter_dilations);
|
||||
copy(conv_param.input_left_pads_, input_left_pads);
|
||||
copy(conv_param.input_right_pads_, input_right_pads);
|
||||
|
||||
if constexpr(std::is_same_v<ConvTensorRearrangeOp, ImageToColumn>)
|
||||
{
|
||||
auto img2col = DeviceImgToColInstance{};
|
||||
auto argument = img2col.MakeArgument(nullptr,
|
||||
nullptr,
|
||||
N,
|
||||
IsCPacked ? C : FakeC,
|
||||
input_spatial_lengths,
|
||||
filter_spatial_lengths,
|
||||
output_spatial_lengths,
|
||||
input_g_n_c_wis_strides,
|
||||
output_m_k_strides,
|
||||
conv_filter_strides,
|
||||
conv_filter_dilations,
|
||||
input_left_pads,
|
||||
input_right_pads);
|
||||
|
||||
return img2col.IsSupportedArgument(argument);
|
||||
}
|
||||
else if constexpr(std::is_same_v<ConvTensorRearrangeOp, ColumnToImage>)
|
||||
{
|
||||
auto col2img = DeviceColToimgInstance{};
|
||||
auto argument = col2img.MakeArgument(nullptr,
|
||||
nullptr,
|
||||
N,
|
||||
IsCPacked ? C : FakeC,
|
||||
input_spatial_lengths,
|
||||
filter_spatial_lengths,
|
||||
output_spatial_lengths,
|
||||
input_g_n_c_wis_strides,
|
||||
output_m_k_strides,
|
||||
conv_filter_strides,
|
||||
conv_filter_dilations,
|
||||
input_left_pads,
|
||||
input_right_pads);
|
||||
|
||||
return col2img.IsSupportedArgument(argument);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TestConvTensorRearrangeInterface1ScalarPerVector
|
||||
: public TestConvTensorRearrangeInterface<1, true>
|
||||
{
|
||||
};
|
||||
|
||||
class TestConvTensorRearrangeInterface4ScalarPerVector
|
||||
: public TestConvTensorRearrangeInterface<4, true>
|
||||
{
|
||||
};
|
||||
|
||||
class TestConvTensorRearrangeInterface4ScalarPerVectorFakeC
|
||||
: public TestConvTensorRearrangeInterface<4, false>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(TestConvTensorRearrangeInterface1ScalarPerVector, X1ScalarPerVector)
|
||||
{
|
||||
// vector load C * X % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {3}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C * left_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {3}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C * right_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {0}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C % ScalarPerVector, right_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {0}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C % ScalarPerVector, left_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {3}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C % ScalarPerVector, dilation
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {2}, {0}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 4, {3}, {3}, {1}, {1}, {3}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
|
||||
TEST_F(TestConvTensorRearrangeInterface4ScalarPerVector, X4ScalarPerVector)
|
||||
{
|
||||
// vector load C * X % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {3}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C * left_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {3}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C * right_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {0}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C % ScalarPerVector, right_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {0}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C % ScalarPerVector, left_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {3}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C % ScalarPerVector, dilation
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {2}, {0}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 4, {3}, {3}, {1}, {1}, {3}, {3}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
|
||||
TEST_F(TestConvTensorRearrangeInterface4ScalarPerVectorFakeC, X4ScalarPerVectorFakeC)
|
||||
{
|
||||
// C = 3
|
||||
this->conv_param = {1, 1, 1, 1, 3, {4}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 8, {4}, {3}, {1}, {1}, {0}, {0}};
|
||||
is_supported = this->template Run<ImageToColumn>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
is_supported = this->template Run<ColumnToImage>();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
add_gtest_executable(test_image_to_column test_image_to_column.cpp)
|
||||
target_link_libraries(test_image_to_column PRIVATE utility device_image_to_column_instance)
|
||||
add_gtest_executable(test_image_to_column_interface test_image_to_column_interface.cpp)
|
||||
target_link_libraries(test_image_to_column_interface PRIVATE utility)
|
||||
@@ -1,121 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2018-2023, Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "profiler/profile_image_to_column_impl.hpp"
|
||||
|
||||
template <typename Tuple>
|
||||
class TestImageToColumn : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
using InDataType = std::tuple_element_t<0, Tuple>;
|
||||
using OutDataType = std::tuple_element_t<1, Tuple>;
|
||||
using InLayout = std::tuple_element_t<2, Tuple>;
|
||||
|
||||
std::vector<ck::utils::conv::ConvParam> conv_params;
|
||||
|
||||
template <ck::index_t NDimSpatial>
|
||||
void Run()
|
||||
{
|
||||
EXPECT_FALSE(conv_params.empty());
|
||||
bool pass = true;
|
||||
for(auto& param : conv_params)
|
||||
{
|
||||
pass = pass && ck::profiler::profile_image_to_column_impl<NDimSpatial,
|
||||
InLayout,
|
||||
InDataType,
|
||||
OutDataType>(
|
||||
true, // do_verification
|
||||
1, // init_method: integer value
|
||||
false, // do_log
|
||||
false, // time_kernel
|
||||
param);
|
||||
}
|
||||
EXPECT_TRUE(pass);
|
||||
}
|
||||
};
|
||||
|
||||
using namespace ck::tensor_layout::convolution;
|
||||
|
||||
using KernelTypes1d = ::testing::Types<std::tuple<float, float, GNWC>,
|
||||
std::tuple<ck::bhalf_t, ck::bhalf_t, GNWC>,
|
||||
std::tuple<ck::half_t, ck::half_t, GNWC>,
|
||||
std::tuple<int8_t, int8_t, GNWC>>;
|
||||
|
||||
using KernelTypes2d = ::testing::Types<std::tuple<float, float, GNHWC>,
|
||||
std::tuple<ck::bhalf_t, ck::bhalf_t, GNHWC>,
|
||||
std::tuple<ck::half_t, ck::half_t, GNHWC>,
|
||||
std::tuple<int8_t, int8_t, GNHWC>>;
|
||||
|
||||
using KernelTypes3d = ::testing::Types<std::tuple<float, float, GNDHWC>,
|
||||
std::tuple<ck::bhalf_t, ck::bhalf_t, GNDHWC>,
|
||||
std::tuple<ck::half_t, ck::half_t, GNDHWC>,
|
||||
std::tuple<int8_t, int8_t, GNDHWC>>;
|
||||
|
||||
template <typename Tuple>
|
||||
class TestImageToColumn1d : public TestImageToColumn<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
class TestImageToColumn2d : public TestImageToColumn<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
class TestImageToColumn3d : public TestImageToColumn<Tuple>
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE(TestImageToColumn1d, KernelTypes1d);
|
||||
TYPED_TEST_SUITE(TestImageToColumn2d, KernelTypes2d);
|
||||
TYPED_TEST_SUITE(TestImageToColumn3d, KernelTypes3d);
|
||||
|
||||
TYPED_TEST(TestImageToColumn1d, Test1D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
|
||||
this->conv_params.push_back({1, 1, 4, 1, 192, {3}, {28}, {1}, {1}, {1}, {1}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {3}, {14}, {1}, {1}, {1}, {1}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {1}, {7}, {2}, {1}, {0}, {0}});
|
||||
this->conv_params.push_back({1, 1, 64, 1, 64, {1}, {3}, {1}, {1}, {0}, {0}});
|
||||
// ScalarPerVector should be 1
|
||||
this->conv_params.push_back({1, 1, 4, 1, 1, {3}, {28}, {1}, {1}, {1}, {1}});
|
||||
// stride != 1
|
||||
this->conv_params.push_back({1, 1, 1, 1, 4, {3}, {28}, {2}, {1}, {1}, {1}});
|
||||
// dilation != 1
|
||||
this->conv_params.push_back({1, 1, 1, 1, 4, {3}, {28}, {1}, {2}, {1}, {1}});
|
||||
this->template Run<1>();
|
||||
}
|
||||
|
||||
TYPED_TEST(TestImageToColumn2d, Test2D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
|
||||
this->conv_params.push_back(
|
||||
{2, 1, 4, 1, 192, {3, 3}, {28, 28}, {1, 1}, {1, 1}, {1, 1}, {1, 1}});
|
||||
this->conv_params.push_back(
|
||||
{2, 1, 64, 1, 64, {3, 3}, {14, 14}, {1, 1}, {1, 1}, {1, 1}, {1, 1}});
|
||||
this->conv_params.push_back({2, 1, 64, 1, 64, {1, 1}, {7, 7}, {2, 2}, {1, 1}, {0, 0}, {0, 0}});
|
||||
this->conv_params.push_back({2, 1, 64, 1, 64, {1, 1}, {3, 3}, {1, 1}, {1, 1}, {0, 0}, {0, 0}});
|
||||
this->template Run<2>();
|
||||
}
|
||||
|
||||
TYPED_TEST(TestImageToColumn3d, Test3D)
|
||||
{
|
||||
this->conv_params.clear();
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 16, 1, 64, {1, 1, 1}, {7, 7, 7}, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}});
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 2, 1, 64, {3, 3, 3}, {14, 14, 3}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}});
|
||||
this->conv_params.push_back(
|
||||
{3, 1, 32, 1, 64, {1, 1, 1}, {3, 3, 3}, {1, 1, 1}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}});
|
||||
this->template Run<3>();
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2018-2023, Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "ck/ck.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/tensor_layout.hpp"
|
||||
#include "ck/tensor_operation/gpu/device/impl/device_image_to_column_impl.hpp"
|
||||
|
||||
#include "ck/library/utility/convolution_parameter.hpp"
|
||||
#include "ck/library/utility/algorithm.hpp"
|
||||
#include "ck/library/utility/convolution_host_tensor_descriptor_helper.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using DataType = float;
|
||||
using InLayout = ck::tensor_layout::convolution::GNWC;
|
||||
|
||||
template <ck::index_t... Is>
|
||||
using S = ck::Sequence<Is...>;
|
||||
|
||||
template <ck::index_t ScalarPerVector, bool IsCPacked>
|
||||
class TestImageToColumnInterface : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static constexpr ck::index_t NDimSpatial = 1;
|
||||
|
||||
// clang-format off
|
||||
using DeviceImgToColInstance = ck::tensor_operation::device::DeviceImageToColumnImpl
|
||||
//#####################| Num| InLayout| InDataType| OutDataType| Block| MPer| KPer| Thread| Scalar|
|
||||
//#####################| Dim| | | | Size| Block| Block| Cluster| Per|
|
||||
//#####################| Spatial| | | | | | | Lengths| Vector|
|
||||
//#####################| | | | | | | | | |
|
||||
< NDimSpatial, InLayout, DataType, DataType, 256, 128, 128, S<16, 16>,ScalarPerVector>;
|
||||
// clang-format on
|
||||
|
||||
ck::utils::conv::ConvParam conv_param;
|
||||
|
||||
bool Run()
|
||||
{
|
||||
|
||||
const auto N = conv_param.N_;
|
||||
const auto C = conv_param.C_;
|
||||
const auto FakeC =
|
||||
conv_param.C_ / 2; // Fake C to simulate the behavior that C is not packed
|
||||
|
||||
const ck::index_t NDoHoWo =
|
||||
N *
|
||||
ck::accumulate_n<ck::index_t>(
|
||||
conv_param.output_spatial_lengths_.begin(), NDimSpatial, 1, std::multiplies<>());
|
||||
const ck::index_t CZYX =
|
||||
C *
|
||||
ck::accumulate_n<ck::index_t>(
|
||||
conv_param.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<InLayout>(
|
||||
conv_param);
|
||||
const auto out_desc = HostTensorDescriptor({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> input_g_n_c_wis_strides{};
|
||||
std::array<ck::index_t, 2> output_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_param.input_spatial_lengths_, input_spatial_lengths);
|
||||
copy(conv_param.filter_spatial_lengths_, filter_spatial_lengths);
|
||||
copy(conv_param.output_spatial_lengths_, output_spatial_lengths);
|
||||
copy(in_desc.GetStrides(), input_g_n_c_wis_strides);
|
||||
copy(out_desc.GetStrides(), output_m_k_strides);
|
||||
copy(conv_param.conv_filter_strides_, conv_filter_strides);
|
||||
copy(conv_param.conv_filter_dilations_, conv_filter_dilations);
|
||||
copy(conv_param.input_left_pads_, input_left_pads);
|
||||
copy(conv_param.input_right_pads_, input_right_pads);
|
||||
|
||||
auto img2col = DeviceImgToColInstance{};
|
||||
auto argument = img2col.MakeArgument(nullptr,
|
||||
nullptr,
|
||||
N,
|
||||
IsCPacked ? C : FakeC,
|
||||
input_spatial_lengths,
|
||||
filter_spatial_lengths,
|
||||
output_spatial_lengths,
|
||||
input_g_n_c_wis_strides,
|
||||
output_m_k_strides,
|
||||
conv_filter_strides,
|
||||
conv_filter_dilations,
|
||||
input_left_pads,
|
||||
input_right_pads);
|
||||
|
||||
return img2col.IsSupportedArgument(argument);
|
||||
}
|
||||
};
|
||||
|
||||
class TestImageToColumnInterface1ScalarPerVector : public TestImageToColumnInterface<1, true>
|
||||
{
|
||||
};
|
||||
|
||||
class TestImageToColumnInterface4ScalarPerVector : public TestImageToColumnInterface<4, true>
|
||||
{
|
||||
};
|
||||
|
||||
class TestImageToColumnInterface4ScalarPerVectorFakeC : public TestImageToColumnInterface<4, false>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(TestImageToColumnInterface1ScalarPerVector, X1ScalarPerVector)
|
||||
{
|
||||
// vector load C * X % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {3}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C * left_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {3}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C * right_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {0}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
|
||||
// vector load C % ScalarPerVector, right_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {0}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C % ScalarPerVector, left_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {3}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
// vector load C % ScalarPerVector, dilation
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {2}, {0}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 4, {3}, {3}, {1}, {1}, {3}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
|
||||
TEST_F(TestImageToColumnInterface4ScalarPerVector, X4ScalarPerVector)
|
||||
{
|
||||
// vector load C * X % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {3}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C * left_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {3}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C * right_pad_x % ScalarPerVector
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {1}, {0}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
|
||||
// vector load C % ScalarPerVector, right_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {0}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C % ScalarPerVector, left_pad and stride
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {2}, {1}, {3}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// vector load C % ScalarPerVector, dilation
|
||||
this->conv_param = {1, 1, 1, 1, 1, {4}, {3}, {1}, {2}, {0}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 4, {3}, {3}, {1}, {1}, {3}, {3}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
|
||||
TEST_F(TestImageToColumnInterface4ScalarPerVectorFakeC, X4ScalarPerVectorFakeC)
|
||||
{
|
||||
// C = 3
|
||||
this->conv_param = {1, 1, 1, 1, 3, {4}, {3}, {1}, {1}, {0}, {0}};
|
||||
bool is_supported = this->Run();
|
||||
EXPECT_FALSE(is_supported);
|
||||
// C = 4
|
||||
this->conv_param = {1, 1, 1, 1, 8, {4}, {3}, {1}, {1}, {0}, {0}};
|
||||
is_supported = this->Run();
|
||||
EXPECT_TRUE(is_supported);
|
||||
}
|
||||
Reference in New Issue
Block a user