"vscode:/vscode.git/clone" did not exist on "8265429e1ed98aa79639a8a52fbedca8f1c94d88"
dynamic_buffer.hpp 11.3 KB
Newer Older
Chao Liu's avatar
rename  
Chao Liu committed
1
2
#ifndef CK_BUFFER_HPP
#define CK_BUFFER_HPP
3

Chao Liu's avatar
tidy  
Chao Liu committed
4
#include "amd_buffer_addressing.hpp"
Chao Liu's avatar
Chao Liu committed
5
#include "c_style_pointer_cast.hpp"
Chao Liu's avatar
Chao Liu committed
6
#include "enable_if.hpp"
Chao Liu's avatar
Chao Liu committed
7
8

namespace ck {
9

10
11
12
13
template <AddressSpaceEnum_t BufferAddressSpace,
          typename T,
          typename ElementSpaceSize,
          bool InvalidElementUseNumericalZeroValue>
14
15
16
17
18
19
struct DynamicBuffer
{
    using type = T;

    T* p_data_;
    ElementSpaceSize element_space_size_;
20
    T invalid_element_value_ = T{0};
21
22
23
24
25
26

    __host__ __device__ constexpr DynamicBuffer(T* p_data, ElementSpaceSize element_space_size)
        : p_data_{p_data}, element_space_size_{element_space_size}
    {
    }

27
28
29
30
31
32
33
34
35
    __host__ __device__ constexpr DynamicBuffer(T* p_data,
                                                ElementSpaceSize element_space_size,
                                                T invalid_element_value)
        : p_data_{p_data},
          element_space_size_{element_space_size},
          invalid_element_value_{invalid_element_value}
    {
    }

36
    __host__ __device__ static constexpr AddressSpaceEnum_t GetAddressSpace()
37
38
39
40
41
    {
        return BufferAddressSpace;
    }

    template <typename X,
Chao Liu's avatar
Chao Liu committed
42
43
44
              typename enable_if<is_same<typename scalar_type<remove_cvref_t<X>>::type,
                                         typename scalar_type<remove_cvref_t<T>>::type>::value,
                                 bool>::type = false>
45
    __host__ __device__ constexpr auto Get(index_t i, bool is_valid_element) const
46
47
    {
        // X contains multiple T
Chao Liu's avatar
Chao Liu committed
48
        constexpr index_t scalar_per_t_vector = scalar_type<remove_cvref_t<T>>::vector_size;
49

Chao Liu's avatar
Chao Liu committed
50
        constexpr index_t scalar_per_x_vector = scalar_type<remove_cvref_t<X>>::vector_size;
51
52
53
54
55

        static_assert(scalar_per_x_vector % scalar_per_t_vector == 0,
                      "wrong! X need to be multiple T");

#if CK_USE_AMD_BUFFER_ADDRESSING
56
        bool constexpr use_amd_buffer_addressing = true;
57
#else
58
        bool constexpr use_amd_buffer_addressing = false;
59
#endif
60
61
62
63
64
65
66

        if constexpr(GetAddressSpace() == AddressSpaceEnum_t::Global && use_amd_buffer_addressing)
        {
            constexpr index_t t_per_x = scalar_per_x_vector / scalar_per_t_vector;

            if constexpr(InvalidElementUseNumericalZeroValue)
            {
Chao Liu's avatar
Chao Liu committed
67
68
69
                return amd_buffer_load_invalid_element_return_return_zero<remove_cvref_t<T>,
                                                                          t_per_x>(
                    p_data_, i, is_valid_element, element_space_size_);
70
71
72
            }
            else
            {
Chao Liu's avatar
Chao Liu committed
73
74
                return amd_buffer_load_invalid_element_return_customized_value<remove_cvref_t<T>,
                                                                               t_per_x>(
75
76
                    p_data_, i, is_valid_element, element_space_size_, invalid_element_value_);
            }
77
78
79
        }
        else
        {
80
81
82
83
84
85
86
87
88
            if constexpr(InvalidElementUseNumericalZeroValue)
            {
                return is_valid_element ? *c_style_pointer_cast<const X*>(&p_data_[i]) : X{0};
            }
            else
            {
                return is_valid_element ? *c_style_pointer_cast<const X*>(&p_data_[i])
                                        : X{invalid_element_value_};
            }
89
90
91
92
        }
    }

    template <typename X,
Chao Liu's avatar
Chao Liu committed
93
94
95
              typename enable_if<is_same<typename scalar_type<remove_cvref_t<X>>::type,
                                         typename scalar_type<remove_cvref_t<T>>::type>::value,
                                 bool>::type = false>
96
    __host__ __device__ void Set(index_t i, bool is_valid_element, const X& x)
97
98
    {
        // X contains multiple T
Chao Liu's avatar
Chao Liu committed
99
        constexpr index_t scalar_per_t_vector = scalar_type<remove_cvref_t<T>>::vector_size;
100

Chao Liu's avatar
Chao Liu committed
101
        constexpr index_t scalar_per_x_vector = scalar_type<remove_cvref_t<X>>::vector_size;
102
103
104
105

        static_assert(scalar_per_x_vector % scalar_per_t_vector == 0,
                      "wrong! X need to be multiple T");

106
        if constexpr(GetAddressSpace() == AddressSpaceEnum_t::Global)
107
108
        {
#if CK_USE_AMD_BUFFER_ADDRESSING
Chao Liu's avatar
Chao Liu committed
109
110
            constexpr index_t t_per_x = scalar_per_x_vector / scalar_per_t_vector;

Chao Liu's avatar
Chao Liu committed
111
            amd_buffer_store<remove_cvref_t<T>, t_per_x>(
112
                x, p_data_, i, is_valid_element, element_space_size_);
113
#else
114
            if(is_valid_element)
115
            {
Chao Liu's avatar
Chao Liu committed
116
                *c_style_pointer_cast<X*>(&p_data_[i]) = x;
117
118
119
            }
#endif
        }
120
        else if constexpr(GetAddressSpace() == AddressSpaceEnum_t::Lds)
121
        {
122
            if(is_valid_element)
123
124
            {
#if !CK_WORKAROUND_SWDEV_XXXXXX_INT8_DS_WRITE_ISSUE
Chao Liu's avatar
Chao Liu committed
125
                *c_style_pointer_cast<X*>(&p_data_[i]) = x;
126
#else
127
128
                // HACK: compiler would lower IR "store<i8, 16> address_space(3)" into
                // inefficient
Chao Liu's avatar
Chao Liu committed
129
                // ISA, so I try to let compiler emit IR "store<i32, 4>" which would be lower to
130
131
                // ds_write_b128
                // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
132
                if constexpr(is_same<typename scalar_type<remove_cvref_t<T>>::type, int8_t>::value)
133
                {
Chao Liu's avatar
Chao Liu committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
                    static_assert((is_same<remove_cvref_t<T>, int8_t>::value &&
                                   is_same<remove_cvref_t<X>, int8_t>::value) ||
                                      (is_same<remove_cvref_t<T>, int8_t>::value &&
                                       is_same<remove_cvref_t<X>, int8x2_t>::value) ||
                                      (is_same<remove_cvref_t<T>, int8_t>::value &&
                                       is_same<remove_cvref_t<X>, int8x4_t>::value) ||
                                      (is_same<remove_cvref_t<T>, int8x4_t>::value &&
                                       is_same<remove_cvref_t<X>, int8x4_t>::value) ||
                                      (is_same<remove_cvref_t<T>, int8x8_t>::value &&
                                       is_same<remove_cvref_t<X>, int8x8_t>::value) ||
                                      (is_same<remove_cvref_t<T>, int8x16_t>::value &&
                                       is_same<remove_cvref_t<X>, int8x16_t>::value),
                                  "wrong! not implemented for this combination, please add "
                                  "implementation");
148

Chao Liu's avatar
Chao Liu committed
149
150
                    if constexpr(is_same<remove_cvref_t<T>, int8_t>::value &&
                                 is_same<remove_cvref_t<X>, int8_t>::value)
Chao Liu's avatar
Chao Liu committed
151
152
153
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
154
155
                        *c_style_pointer_cast<int8_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int8_t*>(&x);
Chao Liu's avatar
Chao Liu committed
156
                    }
Chao Liu's avatar
Chao Liu committed
157
158
                    else if constexpr(is_same<remove_cvref_t<T>, int8_t>::value &&
                                      is_same<remove_cvref_t<X>, int8x2_t>::value)
Chao Liu's avatar
Chao Liu committed
159
160
161
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
162
163
                        *c_style_pointer_cast<int16_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int16_t*>(&x);
Chao Liu's avatar
Chao Liu committed
164
                    }
Chao Liu's avatar
Chao Liu committed
165
166
                    else if constexpr(is_same<remove_cvref_t<T>, int8_t>::value &&
                                      is_same<remove_cvref_t<X>, int8x4_t>::value)
Chao Liu's avatar
Chao Liu committed
167
168
169
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
170
171
                        *c_style_pointer_cast<int32_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int32_t*>(&x);
Chao Liu's avatar
Chao Liu committed
172
                    }
Chao Liu's avatar
Chao Liu committed
173
174
                    else if constexpr(is_same<remove_cvref_t<T>, int8x4_t>::value &&
                                      is_same<remove_cvref_t<X>, int8x4_t>::value)
175
176
177
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
178
179
                        *c_style_pointer_cast<int32_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int32_t*>(&x);
180
                    }
Chao Liu's avatar
Chao Liu committed
181
182
                    else if constexpr(is_same<remove_cvref_t<T>, int8x8_t>::value &&
                                      is_same<remove_cvref_t<X>, int8x8_t>::value)
183
184
185
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
186
187
                        *c_style_pointer_cast<int32x2_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int32x2_t*>(&x);
188
                    }
Chao Liu's avatar
Chao Liu committed
189
190
                    else if constexpr(is_same<remove_cvref_t<T>, int8x16_t>::value &&
                                      is_same<remove_cvref_t<X>, int8x16_t>::value)
191
192
193
                    {
                        // HACK: cast pointer of x is bad
                        // TODO: remove this after compiler fix
Chao Liu's avatar
Chao Liu committed
194
195
                        *c_style_pointer_cast<int32x4_t*>(&p_data_[i]) =
                            *c_style_pointer_cast<const int32x4_t*>(&x);
196
197
198
199
                    }
                }
                else
                {
Chao Liu's avatar
Chao Liu committed
200
                    *c_style_pointer_cast<X*>(&p_data_[i]) = x;
201
202
203
204
205
206
                }
#endif
            }
        }
        else
        {
207
            if(is_valid_element)
208
            {
Chao Liu's avatar
Chao Liu committed
209
                *c_style_pointer_cast<X*>(&p_data_[i]) = x;
210
211
212
213
            }
        }
    }

zjing14's avatar
zjing14 committed
214
    template <typename X,
Chao Liu's avatar
Chao Liu committed
215
216
217
              typename enable_if<is_same<typename scalar_type<remove_cvref_t<X>>::type,
                                         typename scalar_type<remove_cvref_t<T>>::type>::value,
                                 bool>::type = false>
zjing14's avatar
zjing14 committed
218
219
220
    __host__ __device__ void AtomicAdd(index_t i, bool is_valid_element, const X& x)
    {
        // X contains multiple T
Chao Liu's avatar
Chao Liu committed
221
        constexpr index_t scalar_per_t_vector = scalar_type<remove_cvref_t<T>>::vector_size;
zjing14's avatar
zjing14 committed
222

Chao Liu's avatar
Chao Liu committed
223
        constexpr index_t scalar_per_x_vector = scalar_type<remove_cvref_t<X>>::vector_size;
zjing14's avatar
zjing14 committed
224
225
226
227
228
229
230
231
232

        static_assert(scalar_per_x_vector % scalar_per_t_vector == 0,
                      "wrong! X need to be multiple T");

        static_assert(GetAddressSpace() == AddressSpaceEnum_t::Global, "only support global mem");

#if CK_USE_AMD_BUFFER_ADDRESSING
        constexpr index_t t_per_x = scalar_per_x_vector / scalar_per_t_vector;

Chao Liu's avatar
Chao Liu committed
233
        amd_buffer_atomic_add<remove_cvref_t<T>, t_per_x>(
zjing14's avatar
zjing14 committed
234
235
236
237
238
239
240
241
242
            x, p_data_, i, is_valid_element, element_space_size_);
#else
        if(is_valid_element)
        {
            atomicAdd(&p_data_[i], x);
        }
#endif
    }

243
244
245
246
247
    __host__ __device__ static constexpr bool IsStaticBuffer() { return false; }

    __host__ __device__ static constexpr bool IsDynamicBuffer() { return true; }
};

248
template <AddressSpaceEnum_t BufferAddressSpace, typename T, typename ElementSpaceSize>
249
250
__host__ __device__ constexpr auto make_dynamic_buffer(T* p, ElementSpaceSize element_space_size)
{
251
252
253
    return DynamicBuffer<BufferAddressSpace, T, ElementSpaceSize, true>{p, element_space_size};
}

Chao Liu's avatar
Chao Liu committed
254
255
256
257
258
259
template <
    AddressSpaceEnum_t BufferAddressSpace,
    typename T,
    typename ElementSpaceSize,
    typename X,
    typename enable_if<is_same<remove_cvref_t<T>, remove_cvref_t<X>>::value, bool>::type = false>
260
__host__ __device__ constexpr auto
Chao Liu's avatar
Chao Liu committed
261
make_dynamic_buffer(T* p, ElementSpaceSize element_space_size, X invalid_element_value)
262
263
264
{
    return DynamicBuffer<BufferAddressSpace, T, ElementSpaceSize, false>{
        p, element_space_size, invalid_element_value};
265
266
267
268
}

} // namespace ck
#endif