|
14 | 14 |
|
15 | 15 | #include "helper.h" |
16 | 16 |
|
17 | | -inline cudaError_t GetGridSize(int64_t n, int block_size, int num_waves, int* num_blocks) { |
| 17 | +inline cudaError_t GetGridSize(int64_t n, |
| 18 | + int block_size, |
| 19 | + int num_waves, |
| 20 | + int* num_blocks) { |
18 | 21 | int dev; |
19 | 22 | { |
20 | 23 | cudaError_t err = cudaGetDevice(&dev); |
@@ -45,195 +48,195 @@ inline cudaError_t GetGridSize(int64_t n, int block_size, int num_waves, int* nu |
45 | 48 | return cudaSuccess; |
46 | 49 | } |
47 | 50 |
|
48 | | -template<typename T, int VecSize> |
49 | | -__global__ void text_image_scatter_kernel( |
50 | | - T* input_ptr, |
51 | | - T* text_gather_ptr, |
52 | | - T* image_gather_ptr, |
53 | | - int32_t* token_type_ids, |
54 | | - int32_t* text_index, |
55 | | - int32_t* image_index, |
56 | | - const int64_t hidden_size, |
57 | | - const int64_t total_element_num |
58 | | -){ |
59 | | - constexpr int HalfVecSize = VecSize / 2; |
60 | | - using T_Vec = AlignedVector<T, VecSize>; |
61 | | - T_Vec input_ptr_vec; |
62 | | - T_Vec text_images_vec; |
63 | | - |
64 | | - int64_t global_thread_id = blockIdx.x * blockDim.x + threadIdx.x; |
65 | | - const int64_t step = blockDim.x * gridDim.x * VecSize; |
66 | | - |
67 | | - for(int64_t element_idx = global_thread_id * VecSize; |
68 | | - element_idx < total_element_num; |
69 | | - element_idx += step){ |
70 | | - int64_t token_idx = element_idx / hidden_size; |
71 | | - int64_t hidden_offset = element_idx % hidden_size; |
72 | | - int32_t token_type_ids_num = token_type_ids[token_idx]; |
73 | | - |
74 | | - int64_t input_load_offset = token_idx * hidden_size + hidden_offset; |
75 | | - |
76 | | - Load<T, VecSize>(input_ptr + input_load_offset, &input_ptr_vec); |
77 | | - #pragma unroll |
78 | | - for(int vi = 0; vi < VecSize; ++vi) { |
79 | | - text_images_vec[vi] = input_ptr_vec[vi]; |
80 | | - } |
81 | | - |
82 | | - if (token_type_ids_num == 0) { |
83 | | - int64_t text_load_offset = text_index[token_idx] * hidden_size + hidden_offset; |
84 | | - Store<T,VecSize>(text_images_vec, text_gather_ptr + text_load_offset); |
85 | | - |
86 | | - } else if(token_type_ids_num == 1){ |
87 | | - int64_t image_load_offset = image_index[token_idx] * hidden_size + hidden_offset; |
88 | | - Store<T,VecSize>(text_images_vec, image_gather_ptr + image_load_offset); |
89 | | - |
90 | | - } else { |
91 | | - // skip cuda graph padding value |
92 | | - continue; |
93 | | - } |
| 51 | +template <typename T, int VecSize> |
| 52 | +__global__ void text_image_scatter_kernel(T* input_ptr, |
| 53 | + T* text_gather_ptr, |
| 54 | + T* image_gather_ptr, |
| 55 | + int32_t* token_type_ids, |
| 56 | + int32_t* text_index, |
| 57 | + int32_t* image_index, |
| 58 | + const int64_t hidden_size, |
| 59 | + const int64_t total_element_num) { |
| 60 | + constexpr int HalfVecSize = VecSize / 2; |
| 61 | + using T_Vec = AlignedVector<T, VecSize>; |
| 62 | + T_Vec input_ptr_vec; |
| 63 | + T_Vec text_images_vec; |
| 64 | + |
| 65 | + int64_t global_thread_id = blockIdx.x * blockDim.x + threadIdx.x; |
| 66 | + const int64_t step = blockDim.x * gridDim.x * VecSize; |
| 67 | + |
| 68 | + for (int64_t element_idx = global_thread_id * VecSize; |
| 69 | + element_idx < total_element_num; |
| 70 | + element_idx += step) { |
| 71 | + int64_t token_idx = element_idx / hidden_size; |
| 72 | + int64_t hidden_offset = element_idx % hidden_size; |
| 73 | + int32_t token_type_ids_num = token_type_ids[token_idx]; |
| 74 | + |
| 75 | + int64_t input_load_offset = token_idx * hidden_size + hidden_offset; |
| 76 | + |
| 77 | + Load<T, VecSize>(input_ptr + input_load_offset, &input_ptr_vec); |
| 78 | +#pragma unroll |
| 79 | + for (int vi = 0; vi < VecSize; ++vi) { |
| 80 | + text_images_vec[vi] = input_ptr_vec[vi]; |
94 | 81 | } |
| 82 | + |
| 83 | + if (token_type_ids_num == 0) { |
| 84 | + int64_t text_load_offset = |
| 85 | + text_index[token_idx] * hidden_size + hidden_offset; |
| 86 | + Store<T, VecSize>(text_images_vec, text_gather_ptr + text_load_offset); |
| 87 | + |
| 88 | + } else if (token_type_ids_num == 1) { |
| 89 | + int64_t image_load_offset = |
| 90 | + image_index[token_idx] * hidden_size + hidden_offset; |
| 91 | + Store<T, VecSize>(text_images_vec, image_gather_ptr + image_load_offset); |
| 92 | + |
| 93 | + } else { |
| 94 | + // skip cuda graph padding value |
| 95 | + continue; |
| 96 | + } |
| 97 | + } |
95 | 98 | } |
96 | 99 |
|
97 | | -template<typename T, int VecSize> |
98 | | -__global__ void text_image_gather_kernel( |
99 | | - T* output_ptr, |
100 | | - T* text_gather_ptr, |
101 | | - T* image_gather_ptr, |
102 | | - int32_t* token_type_ids, |
103 | | - int32_t* text_index, |
104 | | - int32_t* image_index, |
105 | | - const int64_t hidden_size, |
106 | | - const int64_t total_element_num |
107 | | -){ |
108 | | - constexpr int HalfVecSize = VecSize / 2; |
109 | | - using T_Vec = AlignedVector<T, VecSize>; |
110 | | - T_Vec output_ptr_vec; |
111 | | - T_Vec text_imgaes_vec; |
112 | | - |
113 | | - int64_t global_thread_id = blockIdx.x * blockDim.x + threadIdx.x; |
114 | | - const int64_t step = blockDim.x * gridDim.x * VecSize; |
115 | | - |
116 | | - for(int64_t element_idx = global_thread_id * VecSize; |
117 | | - element_idx < total_element_num; |
118 | | - element_idx += step){ |
119 | | - int64_t token_idx = element_idx / hidden_size; |
120 | | - int64_t hidden_offset = element_idx % hidden_size; |
121 | | - int32_t token_type_ids_num = token_type_ids[token_idx]; |
122 | | - |
123 | | - if (token_type_ids_num == 0) { |
124 | | - int64_t text_load_offset = text_index[token_idx] * hidden_size + hidden_offset; |
125 | | - Load<T,VecSize>(text_gather_ptr + text_load_offset, &text_imgaes_vec); |
126 | | - |
127 | | - } else if (token_type_ids_num == 1){ |
128 | | - int64_t image_load_offset = image_index[token_idx] * hidden_size + hidden_offset; |
129 | | - Load<T,VecSize>(image_gather_ptr + image_load_offset, &text_imgaes_vec); |
130 | | - } else { |
131 | | - // skip cuda graph padding value |
132 | | - continue; |
133 | | - } |
134 | | - |
135 | | - #pragma unroll |
136 | | - for(int vi = 0; vi < VecSize; ++vi) { |
137 | | - output_ptr_vec[vi] = text_imgaes_vec[vi]; |
138 | | - } |
139 | | - |
140 | | - int64_t input_load_offset = token_idx * hidden_size + hidden_offset; |
141 | | - |
142 | | - Store<T, VecSize>(output_ptr_vec, output_ptr + input_load_offset); |
| 100 | +template <typename T, int VecSize> |
| 101 | +__global__ void text_image_gather_kernel(T* output_ptr, |
| 102 | + T* text_gather_ptr, |
| 103 | + T* image_gather_ptr, |
| 104 | + int32_t* token_type_ids, |
| 105 | + int32_t* text_index, |
| 106 | + int32_t* image_index, |
| 107 | + const int64_t hidden_size, |
| 108 | + const int64_t total_element_num) { |
| 109 | + constexpr int HalfVecSize = VecSize / 2; |
| 110 | + using T_Vec = AlignedVector<T, VecSize>; |
| 111 | + T_Vec output_ptr_vec; |
| 112 | + T_Vec text_imgaes_vec; |
| 113 | + |
| 114 | + int64_t global_thread_id = blockIdx.x * blockDim.x + threadIdx.x; |
| 115 | + const int64_t step = blockDim.x * gridDim.x * VecSize; |
| 116 | + |
| 117 | + for (int64_t element_idx = global_thread_id * VecSize; |
| 118 | + element_idx < total_element_num; |
| 119 | + element_idx += step) { |
| 120 | + int64_t token_idx = element_idx / hidden_size; |
| 121 | + int64_t hidden_offset = element_idx % hidden_size; |
| 122 | + int32_t token_type_ids_num = token_type_ids[token_idx]; |
| 123 | + |
| 124 | + if (token_type_ids_num == 0) { |
| 125 | + int64_t text_load_offset = |
| 126 | + text_index[token_idx] * hidden_size + hidden_offset; |
| 127 | + Load<T, VecSize>(text_gather_ptr + text_load_offset, &text_imgaes_vec); |
| 128 | + |
| 129 | + } else if (token_type_ids_num == 1) { |
| 130 | + int64_t image_load_offset = |
| 131 | + image_index[token_idx] * hidden_size + hidden_offset; |
| 132 | + Load<T, VecSize>(image_gather_ptr + image_load_offset, &text_imgaes_vec); |
| 133 | + } else { |
| 134 | + // skip cuda graph padding value |
| 135 | + continue; |
| 136 | + } |
| 137 | + |
| 138 | +#pragma unroll |
| 139 | + for (int vi = 0; vi < VecSize; ++vi) { |
| 140 | + output_ptr_vec[vi] = text_imgaes_vec[vi]; |
143 | 141 | } |
| 142 | + |
| 143 | + int64_t input_load_offset = token_idx * hidden_size + hidden_offset; |
| 144 | + |
| 145 | + Store<T, VecSize>(output_ptr_vec, output_ptr + input_load_offset); |
| 146 | + } |
144 | 147 | } |
145 | 148 |
|
146 | 149 | template <paddle::DataType D> |
147 | | -void LaunchTextImageGatherScatter( |
148 | | - paddle::Tensor& input, |
149 | | - paddle::Tensor& text_input, |
150 | | - paddle::Tensor& image_input, |
151 | | - paddle::Tensor& token_type_ids, |
152 | | - paddle::Tensor& text_index, |
153 | | - paddle::Tensor& image_index, |
154 | | - const bool is_scatter) { |
155 | | - |
156 | | - typedef PDTraits<D> traits_; |
157 | | - typedef typename traits_::DataType DataType_; |
158 | | - typedef typename traits_::data_t data_t; |
159 | | - auto stream = input.stream(); |
160 | | - const auto& in_dims = input.dims(); |
161 | | - const int64_t token_num = in_dims[0]; |
162 | | - const int64_t hidden_size = in_dims[1]; |
163 | | - |
164 | | - const int VecSize = 16 / sizeof(data_t); |
165 | | - const int64_t tot_element_num = token_num * hidden_size; |
166 | | - |
167 | | - int64_t tot_pack_num = (tot_element_num + VecSize - 1) / VecSize; |
168 | | - |
169 | | - const int block_size = 128; |
170 | | - int grid_index = (token_num + block_size - 1) / block_size; |
171 | | - constexpr int32_t kNumWaves = 16; |
172 | | - int grid_size_x = -1; |
173 | | - |
174 | | - PADDLE_ENFORCE_GPU_SUCCESS(GetGridSize(tot_pack_num, block_size, kNumWaves, &grid_size_x)); |
175 | | - dim3 grid_dim = dim3(grid_size_x, 1, 1); |
176 | | - if (is_scatter) { |
177 | | - text_image_scatter_kernel<DataType_, VecSize><<<grid_dim, block_size, 0, stream>>>( |
| 150 | +void LaunchTextImageGatherScatter(paddle::Tensor& input, |
| 151 | + paddle::Tensor& text_input, |
| 152 | + paddle::Tensor& image_input, |
| 153 | + paddle::Tensor& token_type_ids, |
| 154 | + paddle::Tensor& text_index, |
| 155 | + paddle::Tensor& image_index, |
| 156 | + const bool is_scatter) { |
| 157 | + typedef PDTraits<D> traits_; |
| 158 | + typedef typename traits_::DataType DataType_; |
| 159 | + typedef typename traits_::data_t data_t; |
| 160 | + auto stream = input.stream(); |
| 161 | + const auto& in_dims = input.dims(); |
| 162 | + const int64_t token_num = in_dims[0]; |
| 163 | + const int64_t hidden_size = in_dims[1]; |
| 164 | + |
| 165 | + const int VecSize = 16 / sizeof(data_t); |
| 166 | + const int64_t tot_element_num = token_num * hidden_size; |
| 167 | + |
| 168 | + int64_t tot_pack_num = (tot_element_num + VecSize - 1) / VecSize; |
| 169 | + |
| 170 | + const int block_size = 128; |
| 171 | + int grid_index = (token_num + block_size - 1) / block_size; |
| 172 | + constexpr int32_t kNumWaves = 16; |
| 173 | + int grid_size_x = -1; |
| 174 | + |
| 175 | + PADDLE_ENFORCE_GPU_SUCCESS( |
| 176 | + GetGridSize(tot_pack_num, block_size, kNumWaves, &grid_size_x)); |
| 177 | + dim3 grid_dim = dim3(grid_size_x, 1, 1); |
| 178 | + if (is_scatter) { |
| 179 | + text_image_scatter_kernel<DataType_, VecSize> |
| 180 | + <<<grid_dim, block_size, 0, stream>>>( |
178 | 181 | reinterpret_cast<DataType_*>(input.data<data_t>()), |
179 | 182 | reinterpret_cast<DataType_*>(text_input.data<data_t>()), |
180 | 183 | reinterpret_cast<DataType_*>(image_input.data<data_t>()), |
181 | 184 | reinterpret_cast<int32_t*>(token_type_ids.data<int32_t>()), |
182 | 185 | reinterpret_cast<int32_t*>(text_index.data<int32_t>()), |
183 | 186 | reinterpret_cast<int32_t*>(image_index.data<int32_t>()), |
184 | 187 | hidden_size, |
185 | | - tot_element_num |
186 | | - ); |
187 | | - } else { |
188 | | - text_image_gather_kernel<DataType_, VecSize><<<grid_dim, block_size, 0, stream>>>( |
| 188 | + tot_element_num); |
| 189 | + } else { |
| 190 | + text_image_gather_kernel<DataType_, VecSize> |
| 191 | + <<<grid_dim, block_size, 0, stream>>>( |
189 | 192 | reinterpret_cast<DataType_*>(input.data<data_t>()), |
190 | 193 | reinterpret_cast<DataType_*>(text_input.data<data_t>()), |
191 | 194 | reinterpret_cast<DataType_*>(image_input.data<data_t>()), |
192 | 195 | reinterpret_cast<int32_t*>(token_type_ids.data<int32_t>()), |
193 | 196 | reinterpret_cast<int32_t*>(text_index.data<int32_t>()), |
194 | 197 | reinterpret_cast<int32_t*>(image_index.data<int32_t>()), |
195 | 198 | hidden_size, |
196 | | - tot_element_num |
197 | | - ); |
198 | | - } |
| 199 | + tot_element_num); |
| 200 | + } |
199 | 201 | } |
200 | 202 |
|
201 | | -void TextImageGatherScatter( |
202 | | - paddle::Tensor& input, |
203 | | - paddle::Tensor& text_input, |
204 | | - paddle::Tensor& image_input, |
205 | | - paddle::Tensor& token_type_ids, |
206 | | - paddle::Tensor& text_index, |
207 | | - paddle::Tensor& image_index, |
208 | | - const bool is_scatter) { |
209 | | - |
210 | | - switch (input.type()) { |
211 | | - case paddle::DataType::BFLOAT16: { |
212 | | - return LaunchTextImageGatherScatter<paddle::DataType::BFLOAT16>(input, text_input, image_input, token_type_ids, text_index, image_index, is_scatter); |
213 | | - } |
214 | | - default: { |
215 | | - PD_THROW( |
216 | | - "NOT supported data type. Only support BFLOAT16. "); |
217 | | - break; |
218 | | - } |
| 203 | +std::vector<paddle::Tensor> TextImageGatherScatter( |
| 204 | + paddle::Tensor& input, |
| 205 | + paddle::Tensor& text_input, |
| 206 | + paddle::Tensor& image_input, |
| 207 | + paddle::Tensor& token_type_ids, |
| 208 | + paddle::Tensor& text_index, |
| 209 | + paddle::Tensor& image_index, |
| 210 | + const bool is_scatter) { |
| 211 | + switch (input.dtype()) { |
| 212 | + case paddle::DataType::BFLOAT16: { |
| 213 | + LaunchTextImageGatherScatter<paddle::DataType::BFLOAT16>(input, |
| 214 | + text_input, |
| 215 | + image_input, |
| 216 | + token_type_ids, |
| 217 | + text_index, |
| 218 | + image_index, |
| 219 | + is_scatter); |
| 220 | + break; |
| 221 | + } |
| 222 | + default: { |
| 223 | + PD_THROW("NOT supported data type. Only support BFLOAT16, but got", |
| 224 | + input.dtype()); |
219 | 225 | } |
| 226 | + } |
| 227 | + return {input, text_input, image_input}; |
220 | 228 | } |
221 | 229 |
|
222 | | - |
223 | 230 | PD_BUILD_STATIC_OP(text_image_gather_scatter) |
224 | 231 | .Inputs({"input", |
225 | 232 | "text_input", |
226 | 233 | "image_input", |
227 | 234 | "token_type_ids", |
228 | 235 | "text_index", |
229 | 236 | "image_index"}) |
230 | | - .Outputs({"text_input_out", |
231 | | - "image_input_out", |
232 | | - "text_index_out", |
233 | | - "image_index_out"}) |
| 237 | + .Outputs({"output", "text_input_out", "image_input_out"}) |
234 | 238 | .Attrs({"is_scatter:bool"}) |
235 | | - .SetInplaceMap({{"text_input", "text_input_out"}, |
236 | | - {"image_input", "image_input_out"}, |
237 | | - {"text_index", "text_index_out"}, |
238 | | - {"image_index", "image_index_out"}}) |
| 239 | + .SetInplaceMap({{"input", "output"}, |
| 240 | + {"text_input", "text_input_out"}, |
| 241 | + {"image_input", "image_input_out"}}) |
239 | 242 | .SetKernelFn(PD_KERNEL(TextImageGatherScatter)); |
0 commit comments