convnd_fwd_common.hpp 9.97 KB
Newer Older
Chao Liu's avatar
Chao Liu committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2022, Advanced Micro Devices, Inc. All rights reserved.

#include <cstdlib>
#include <iostream>
#include <numeric>
#include <type_traits>

#include "ck/ck.hpp"
#include "ck/tensor_operation/gpu/device/tensor_layout.hpp"
#include "ck/tensor_operation/gpu/element/element_wise_operation.hpp"

#include "ck/library/utility/check_err.hpp"
#include "ck/library/utility/device_memory.hpp"
#include "ck/library/utility/host_tensor.hpp"
#include "ck/library/utility/host_tensor_generator.hpp"
Chao Liu's avatar
Chao Liu committed
17
#include "ck/library/utility/convolution_parameter.hpp"
Chao Liu's avatar
Chao Liu committed
18
#include "ck/library/reference_tensor_operation/cpu/reference_conv_fwd.hpp"
Chao Liu's avatar
Chao Liu committed
19

Chao Liu's avatar
Chao Liu committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void print_helper_msg()
{
    std::cout << "arg1: verification (0=no, 1=yes)\n"
              << "arg2: initialization (0=no init, 1=integer value, 2=decimal value)\n"
              << "arg3: time kernel (0=no, 1=yes)\n"
              << "arg4: N spatial dimensions (default 2)\n"
              << "Following arguments (depending on number of spatial dims):\n"
              << " N, K, C, \n"
              << " <filter spatial dimensions>, (ie Y, X for 2D)\n"
              << " <in_n_hi_wi_c image spatial dimensions>, (ie Hi, Wi for 2D)\n"
              << " <strides>, (ie Sy, Sx for 2D)\n"
              << " <dilations>, (ie Dy, Dx for 2D)\n"
              << " <left padding>, (ie LeftPy, LeftPx for 2D)\n"
              << " <right padding>, (ie RightPy, RightPx for 2D)\n"
              << std::endl;
}
Chao Liu's avatar
Chao Liu committed
36
ck::tensor_operation::device::ConvParams
Chao Liu's avatar
Chao Liu committed
37

Chao Liu's avatar
Chao Liu committed
38
39
parse_conv_params(int num_dim_spatial, int arg_idx, char* const argv[])
{
Chao Liu's avatar
Chao Liu committed
40
41
42
    const ck::index_t N = std::stoi(argv[arg_idx++]);
    const ck::index_t K = std::stoi(argv[arg_idx++]);
    const ck::index_t C = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
43

Chao Liu's avatar
Chao Liu committed
44
45
46
47
48
49
    std::vector<ck::index_t> filter_spatial_lengths(num_dim_spatial);
    std::vector<ck::index_t> input_spatial_lengths(num_dim_spatial);
    std::vector<ck::index_t> conv_filter_strides(num_dim_spatial);
    std::vector<ck::index_t> conv_filter_dilations(num_dim_spatial);
    std::vector<ck::index_t> input_left_pads(num_dim_spatial);
    std::vector<ck::index_t> input_right_pads(num_dim_spatial);
Chao Liu's avatar
Chao Liu committed
50
51
52

    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
53
        filter_spatial_lengths[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
54
    }
Chao Liu's avatar
Chao Liu committed
55

Chao Liu's avatar
Chao Liu committed
56
57
    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
58
        input_spatial_lengths[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
59
    }
Chao Liu's avatar
Chao Liu committed
60

Chao Liu's avatar
Chao Liu committed
61
62
    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
63
        conv_filter_strides[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
64
    }
Chao Liu's avatar
Chao Liu committed
65

Chao Liu's avatar
Chao Liu committed
66
67
    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
68
        conv_filter_dilations[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
69
    }
Chao Liu's avatar
Chao Liu committed
70

Chao Liu's avatar
Chao Liu committed
71
72
    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
73
        input_left_pads[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
74
    }
Chao Liu's avatar
Chao Liu committed
75

Chao Liu's avatar
Chao Liu committed
76
77
    for(int i = 0; i < num_dim_spatial; ++i)
    {
Chao Liu's avatar
Chao Liu committed
78
        input_right_pads[i] = std::stoi(argv[arg_idx++]);
Chao Liu's avatar
Chao Liu committed
79
80
    }

Chao Liu's avatar
Chao Liu committed
81
82
83
84
85
86
87
88
89
90
    return ck::tensor_operation::device::ConvParams{num_dim_spatial,
                                                    N,
                                                    K,
                                                    C,
                                                    filter_spatial_lengths,
                                                    input_spatial_lengths,
                                                    conv_filter_strides,
                                                    conv_filter_dilations,
                                                    input_left_pads,
                                                    input_right_pads};
Chao Liu's avatar
Chao Liu committed
91
92
}

Chao Liu's avatar
Chao Liu committed
93
94
95
96
97
98
99
100
template <ck::index_t NDimSpatial,
          typename InDataType,
          typename WeiDataType,
          typename OutDataType,
          typename AccDataType,
          typename InElementOp,
          typename WeiElementOp,
          typename OutElementOp,
Chao Liu's avatar
Chao Liu committed
101
102
          typename DeviceConvNDFwdInstance>
int run_conv_fwd_nhwc(bool do_verification,
Chao Liu's avatar
Chao Liu committed
103
                      int init_method,
Chao Liu's avatar
Chao Liu committed
104
105
106
107
108
                      bool time_kernel,
                      const ck::tensor_operation::device::ConvParams& params,
                      const InElementOp& in_element_op,
                      const WeiElementOp& wei_element_op,
                      const OutElementOp& out_element_op)
Chao Liu's avatar
Chao Liu committed
109
{
Chao Liu's avatar
Chao Liu committed
110
    auto f_nhwc_host_tensor_descriptor =
Chao Liu's avatar
Chao Liu committed
111
112
113
114
115
116
        [](ck::index_t n, ck::index_t c, std::vector<ck::index_t> spatial_lengths) {
            std::vector<std::size_t> nhwc_lengths{static_cast<std::size_t>(n),
                                                  static_cast<std::size_t>(c)};
            nhwc_lengths.insert(
                nhwc_lengths.begin() + 1, spatial_lengths.begin(), spatial_lengths.end());

Chao Liu's avatar
Chao Liu committed
117
            return HostTensorDescriptor(nhwc_lengths);
Chao Liu's avatar
Chao Liu committed
118
119
        };

Chao Liu's avatar
Chao Liu committed
120
    Tensor<InDataType> in_n_hi_wi_c(
Chao Liu's avatar
Chao Liu committed
121
        f_nhwc_host_tensor_descriptor(params.N_, params.C_, params.input_spatial_lengths_));
Chao Liu's avatar
Chao Liu committed
122
    Tensor<WeiDataType> wei_k_y_x_c(
Chao Liu's avatar
Chao Liu committed
123
        f_nhwc_host_tensor_descriptor(params.K_, params.C_, params.filter_spatial_lengths_));
Chao Liu's avatar
Chao Liu committed
124
    Tensor<OutDataType> out_n_ho_wo_k_host(
Chao Liu's avatar
Chao Liu committed
125
        f_nhwc_host_tensor_descriptor(params.N_, params.K_, params.GetOutputSpatialLengths()));
Chao Liu's avatar
Chao Liu committed
126
    Tensor<OutDataType> out_n_ho_wo_k_device(
Chao Liu's avatar
Chao Liu committed
127
        f_nhwc_host_tensor_descriptor(params.N_, params.K_, params.GetOutputSpatialLengths()));
Chao Liu's avatar
Chao Liu committed
128

Chao Liu's avatar
Chao Liu committed
129
130
131
    std::cout << "in_n_hi_wi_c: " << in_n_hi_wi_c.mDesc << std::endl;
    std::cout << "wei_k_y_x_c: " << wei_k_y_x_c.mDesc << std::endl;
    std::cout << "output: " << out_n_ho_wo_k_host.mDesc << std::endl;
Chao Liu's avatar
Chao Liu committed
132
133
134
135
136

    switch(init_method)
    {
    case 0: break;
    case 1:
Chao Liu's avatar
Chao Liu committed
137
138
        in_n_hi_wi_c.GenerateTensorValue(GeneratorTensor_2<InDataType>{-5, 5});
        wei_k_y_x_c.GenerateTensorValue(GeneratorTensor_2<WeiDataType>{-5, 5});
Chao Liu's avatar
Chao Liu committed
139
140
        break;
    default:
Chao Liu's avatar
Chao Liu committed
141
142
        in_n_hi_wi_c.GenerateTensorValue(GeneratorTensor_3<InDataType>{0.0, 1.0});
        wei_k_y_x_c.GenerateTensorValue(GeneratorTensor_3<WeiDataType>{-0.5, 0.5});
Chao Liu's avatar
Chao Liu committed
143
144
    }

Chao Liu's avatar
Chao Liu committed
145
146
147
    DeviceMem in_device_buf(sizeof(InDataType) * in_n_hi_wi_c.mDesc.GetElementSpace());
    DeviceMem wei_device_buf(sizeof(WeiDataType) * wei_k_y_x_c.mDesc.GetElementSpace());
    DeviceMem out_device_buf(sizeof(OutDataType) * out_n_ho_wo_k_device.mDesc.GetElementSpace());
Chao Liu's avatar
Chao Liu committed
148

Chao Liu's avatar
Chao Liu committed
149
150
    in_device_buf.ToDevice(in_n_hi_wi_c.mData.data());
    wei_device_buf.ToDevice(wei_k_y_x_c.mData.data());
Chao Liu's avatar
Chao Liu committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

    // do GEMM
    auto conv     = DeviceConvNDFwdInstance{};
    auto invoker  = conv.MakeInvoker();
    auto argument = conv.MakeArgument(static_cast<InDataType*>(in_device_buf.GetDeviceBuffer()),
                                      static_cast<WeiDataType*>(wei_device_buf.GetDeviceBuffer()),
                                      static_cast<OutDataType*>(out_device_buf.GetDeviceBuffer()),
                                      params.N_,
                                      params.K_,
                                      params.C_,
                                      params.input_spatial_lengths_,
                                      params.filter_spatial_lengths_,
                                      params.GetOutputSpatialLengths(),
                                      params.conv_filter_strides_,
                                      params.conv_filter_dilations_,
                                      params.input_left_pads_,
                                      params.input_right_pads_,
Chao Liu's avatar
Chao Liu committed
168
169
170
                                      in_element_op,
                                      wei_element_op,
                                      out_element_op);
Chao Liu's avatar
Chao Liu committed
171
172
173
174
175
176
177
178

    if(!conv.IsSupportedArgument(argument))
    {
        throw std::runtime_error(
            "wrong! device_conv with the specified compilation parameters does "
            "not support this Conv problem");
    }

Chao Liu's avatar
Chao Liu committed
179
    float avg_time = invoker.Run(argument, StreamConfig{nullptr, time_kernel});
Chao Liu's avatar
Chao Liu committed
180
181
182
183

    std::size_t flop      = params.GetFlops();
    std::size_t num_btype = params.GetByte<InDataType, WeiDataType, OutDataType>();

Chao Liu's avatar
Chao Liu committed
184
185
186
    float tflops     = static_cast<float>(flop) / 1.E9 / avg_time;
    float gb_per_sec = num_btype / 1.E6 / avg_time;
    std::cout << "Perf: " << avg_time << " ms, " << tflops << " TFlops, " << gb_per_sec << " GB/s, "
Chao Liu's avatar
Chao Liu committed
187
188
189
190
              << conv.GetTypeString() << std::endl;

    if(do_verification)
    {
Chao Liu's avatar
Chao Liu committed
191
192
193
194
195
196
197
198
199
200
201
        auto ref_conv =
            ck::tensor_operation::host::ReferenceConvFwd<NDimSpatial,
                                                         ck::tensor_layout::convolution::NHWC,
                                                         ck::tensor_layout::convolution::KYXC,
                                                         ck::tensor_layout::convolution::NHWK,
                                                         InDataType,
                                                         WeiDataType,
                                                         OutDataType,
                                                         InElementOp,
                                                         WeiElementOp,
                                                         OutElementOp>();
Chao Liu's avatar
Chao Liu committed
202
203

        auto ref_invoker  = ref_conv.MakeInvoker();
Chao Liu's avatar
Chao Liu committed
204
205
206
        auto ref_argument = ref_conv.MakeArgument(in_n_hi_wi_c,
                                                  wei_k_y_x_c,
                                                  out_n_ho_wo_k_host,
Chao Liu's avatar
Chao Liu committed
207
208
209
210
                                                  params.conv_filter_strides_,
                                                  params.conv_filter_dilations_,
                                                  params.input_left_pads_,
                                                  params.input_right_pads_,
Chao Liu's avatar
Chao Liu committed
211
212
213
                                                  in_element_op,
                                                  wei_element_op,
                                                  out_element_op);
Chao Liu's avatar
Chao Liu committed
214
215
216

        ref_invoker.Run(ref_argument);

Chao Liu's avatar
Chao Liu committed
217
        out_device_buf.FromDevice(out_n_ho_wo_k_device.mData.data());
Chao Liu's avatar
Chao Liu committed
218

Chao Liu's avatar
Chao Liu committed
219
220
        return ck::utils::check_err(out_n_ho_wo_k_host.mData,
                                    out_n_ho_wo_k_device.mData,
Chao Liu's avatar
Chao Liu committed
221
222
223
224
225
226
227
228
229
                                    "Error: incorrect results!",
                                    1e-5f,
                                    1e-4f)
                   ? 0
                   : 1;
    }

    return 0;
}