Prompt48 commited on
Commit
37bd41b
·
verified ·
1 Parent(s): 87232ca

Upload edit\Qwen3-TTS-test\.venv\Lib\site-packages\torch\include\ATen\native\cuda\MultiTensorApply.cuh with huggingface_hub

Browse files
edit//Qwen3-TTS-test//.venv//Lib//site-packages//torch//include//ATen//native//cuda//MultiTensorApply.cuh ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <ATen/core/Tensor.h>
3
+ #include <ATen/cuda/CUDAContext.h>
4
+ #include <c10/cuda/CUDAGuard.h>
5
+ #include <ATen/native/cuda/Loops.cuh>
6
+ #include <ATen/native/cuda/MemoryAccess.cuh>
7
+ #include <vector>
8
+
9
+ namespace at::native {
10
+
11
+ namespace {
12
+
13
+ static constexpr int64_t kILP = 4;
14
+ static constexpr int64_t kChunkSize = 65536;
15
+ static constexpr int64_t kBlockSize = 512;
16
+
17
+ // TODO(crcrpar): Add `n>5` for `low prec params & their higher prec copy`
18
+ // TensorListMetadata has to be < 4KB - the limit for kernel launch argument
19
+ static constexpr int depth_to_max_tensors[5] = {110, 64, 48, 36, 30};
20
+ static constexpr int depth_to_max_blocks[5] = {320, 320, 320, 320, 320};
21
+ static constexpr int depth_to_max_tensors_scalarlist[5] = {96, 64, 48, 36, 30};
22
+ static constexpr int depth_to_max_tensors_scalarlist_of_complex_double[2] = {
23
+ 72,
24
+ 60};
25
+
26
+ template <typename T>
27
+ __device__ __forceinline__ bool is_aligned(T* p) {
28
+ return ((uint64_t)p) % (kILP * sizeof(T)) == 0;
29
+ }
30
+
31
+ template <typename T>
32
+ __device__ __forceinline__ void load_store(
33
+ T* dst,
34
+ T* src,
35
+ int64_t dst_offset,
36
+ int64_t src_offset) {
37
+ using LT = at::native::memory::aligned_vector<T, kILP>;
38
+ ((LT*)dst)[dst_offset] = ((LT*)src)[src_offset];
39
+ }
40
+
41
+ template <int n>
42
+ struct TensorListMetadata {
43
+ const void* addresses[n][depth_to_max_tensors[n - 1]];
44
+ int64_t numel_for_tensor[depth_to_max_tensors[n - 1]];
45
+ unsigned char block_to_tensor[depth_to_max_blocks[n - 1]];
46
+ int block_to_chunk[depth_to_max_blocks[n - 1]];
47
+ int start_tensor_this_launch;
48
+ };
49
+
50
+ template <typename scalar_vals_t, int n>
51
+ struct TensorListScalarListMetadata {
52
+ const void* addresses[n][depth_to_max_tensors_scalarlist[n - 1]];
53
+ int64_t numel_for_tensor[depth_to_max_tensors_scalarlist[n - 1]];
54
+ scalar_vals_t scalar_vals[depth_to_max_tensors_scalarlist[n - 1]];
55
+ unsigned char block_to_tensor[depth_to_max_blocks[n - 1]];
56
+ int block_to_chunk[depth_to_max_blocks[n - 1]];
57
+ };
58
+
59
+ // note(mkozuki): `n` of 1&2 violate the limit of cuda kernel argument size of
60
+ // 4kb with `c10::complex<double>`
61
+ template <>
62
+ struct TensorListScalarListMetadata<c10::complex<double>, 1> {
63
+ const void* addresses[1]
64
+ [depth_to_max_tensors_scalarlist_of_complex_double[0]];
65
+ int64_t
66
+ numel_for_tensor[depth_to_max_tensors_scalarlist_of_complex_double[0]];
67
+ c10::complex<double>
68
+ scalar_vals[depth_to_max_tensors_scalarlist_of_complex_double[0]];
69
+ unsigned char block_to_tensor[depth_to_max_blocks[1 - 1]];
70
+ int block_to_chunk[depth_to_max_blocks[1 - 1]];
71
+ };
72
+
73
+ template <>
74
+ struct TensorListScalarListMetadata<c10::complex<double>, 2> {
75
+ const void* addresses[2]
76
+ [depth_to_max_tensors_scalarlist_of_complex_double[1]];
77
+ int64_t
78
+ numel_for_tensor[depth_to_max_tensors_scalarlist_of_complex_double[1]];
79
+ c10::complex<double>
80
+ scalar_vals[depth_to_max_tensors_scalarlist_of_complex_double[1]];
81
+ unsigned char block_to_tensor[depth_to_max_blocks[2 - 1]];
82
+ int block_to_chunk[depth_to_max_blocks[2 - 1]];
83
+ };
84
+
85
+ // NOTE(crcrpar): This is a conservative resolution to handle `state_steps`
86
+ // whose each element is `at::Tensor` of 1 element representing the number of
87
+ // `step`s called so far.
88
+ template <int n>
89
+ struct FusedOptimizerTensorListMetadata {
90
+ const void* addresses[n][depth_to_max_tensors[n - 1]];
91
+ int64_t numel_for_tensor[depth_to_max_tensors[n - 1]];
92
+ const void* state_steps_addresses[depth_to_max_tensors_scalarlist[n - 1]];
93
+ unsigned char block_to_tensor[depth_to_max_blocks[n - 1]];
94
+ int block_to_chunk[depth_to_max_blocks[n - 1]];
95
+ int start_tensor_this_launch;
96
+ };
97
+
98
+ template <typename T, typename U, typename... ArgTypes>
99
+ C10_LAUNCH_BOUNDS_1(kBlockSize)
100
+ __global__ void multi_tensor_apply_kernel(
101
+ T tensorListMeta,
102
+ U callable,
103
+ ArgTypes... args) {
104
+ // Hand the chunk information to the user-supplied functor to process however
105
+ // it likes.
106
+ callable(kChunkSize, tensorListMeta, args...);
107
+ }
108
+
109
+ } // namespace
110
+
111
+ // multi_tensor_apply enables horizontal fusion across lists of tensors.
112
+ // For example, whereas you once had a for-loop of a + b = c, where a, b,
113
+ // and c are individual tensors in lists as, bs, and cs, you can now with
114
+ // fewer kernel launches compute as + bs = cs.
115
+ //
116
+ // You can also imagine bs to be a scalar list vs a tensor list.
117
+ //
118
+ // The function below takes in tensor lists, scalars, and a callable and
119
+ // chunks up the computation to launch as few kernels as possible by iterating
120
+ // through every "chunk" in every tensor (thus the nested for loops). In the
121
+ // simplest case, everything gets bundled into just one kernel launch, but
122
+ // due to blocksize constraints, we may need to launch multiple kernels.
123
+ // Each kernel launch is defined by one tensorListMeta construct, which we
124
+ // use to track and reset the necessary metadata for each launch.
125
+ template <int depth, typename scalar_T, typename T, typename... ArgTypes>
126
+ void multi_tensor_apply(
127
+ std::vector<std::vector<at::Tensor>>& tensor_lists,
128
+ at::ArrayRef<Scalar> scalars,
129
+ T callable,
130
+ ArgTypes... args) {
131
+ TORCH_CHECK(
132
+ tensor_lists.size() == depth,
133
+ "Number of tensor lists has to match the depth.");
134
+ const size_t n_tensors = tensor_lists[0].size();
135
+ using scalar_vals_t = typename T::opmath_t;
136
+ TensorListScalarListMetadata<scalar_vals_t, depth> tensorListMeta;
137
+
138
+ int loc_block_info = 0;
139
+ int loc_tensor_info = 0;
140
+ for (size_t t = 0; t < n_tensors; t++) {
141
+ // short-circuit to avoid adding empty tensors to tensorListMeta
142
+ if (tensor_lists[0][t].numel() == 0) {
143
+ continue;
144
+ }
145
+ tensorListMeta.scalar_vals[loc_tensor_info] = scalars[t].to<scalar_T>();
146
+ tensorListMeta.numel_for_tensor[loc_tensor_info] =
147
+ tensor_lists[0][t].numel();
148
+ for (int d = 0; d < depth; d++) {
149
+ tensorListMeta.addresses[d][loc_tensor_info] =
150
+ tensor_lists[d][t].const_data_ptr();
151
+ }
152
+ loc_tensor_info++;
153
+
154
+ // now we enter [chunking territory].
155
+ // we will launch a kernel when EITHER the blocks get filled up OR
156
+ // the tensors get filled up. There will always be at least one block
157
+ // per tensor since the zero-sized ones will not enter the loop, so
158
+ // the nested forloop within represents iterating through the chunks
159
+ // of a single tensor.
160
+ const auto numel = tensor_lists[0][t].numel();
161
+ const auto chunks = numel / kChunkSize + (numel % kChunkSize != 0);
162
+ for (auto chunk = 0; chunk < chunks; chunk++) {
163
+ tensorListMeta.block_to_tensor[loc_block_info] = loc_tensor_info - 1;
164
+ tensorListMeta.block_to_chunk[loc_block_info] = chunk;
165
+ loc_block_info++;
166
+
167
+ // a tensor is not considered full unless all its chunks have been
168
+ // processed
169
+ const bool tensors_full =
170
+ (loc_tensor_info == depth_to_max_tensors_scalarlist[depth - 1] &&
171
+ chunk == chunks - 1);
172
+ const bool blocks_full =
173
+ (loc_block_info == depth_to_max_blocks[depth - 1]);
174
+
175
+ if (tensors_full || blocks_full) {
176
+ multi_tensor_apply_kernel<<<
177
+ loc_block_info,
178
+ kBlockSize,
179
+ 0,
180
+ at::cuda::getCurrentCUDAStream()>>>(
181
+ tensorListMeta, callable, args...);
182
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
183
+
184
+ // Reset.
185
+ loc_block_info = 0;
186
+ // all chunks have already been handled in the kernel
187
+ if (chunk == chunks - 1) {
188
+ loc_tensor_info = 0;
189
+ } else { // blocks were full and tensor chunks remain
190
+ tensorListMeta.numel_for_tensor[0] =
191
+ tensorListMeta.numel_for_tensor[loc_tensor_info - 1];
192
+ tensorListMeta.scalar_vals[0] =
193
+ tensorListMeta.scalar_vals[loc_tensor_info - 1];
194
+ for (int d = 0; d < depth; d++) {
195
+ tensorListMeta.addresses[d][0] =
196
+ tensorListMeta.addresses[d][loc_tensor_info - 1];
197
+ }
198
+ loc_tensor_info = 1;
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ // note: [finishing what we started]
205
+ // if there's remaining work to be done but the tensors/blocks aren't full
206
+ // yet we are at the end, submit the kernel to do the work!
207
+ if (loc_block_info != 0) {
208
+ multi_tensor_apply_kernel<<<
209
+ loc_block_info,
210
+ kBlockSize,
211
+ 0,
212
+ at::cuda::getCurrentCUDAStream()>>>(tensorListMeta, callable, args...);
213
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
214
+ }
215
+ }
216
+
217
+ template <int depth, typename T, typename... ArgTypes>
218
+ void multi_tensor_apply(
219
+ std::vector<std::vector<at::Tensor>>& tensor_lists,
220
+ T callable,
221
+ ArgTypes... args) {
222
+ TORCH_CHECK(
223
+ tensor_lists.size() == depth,
224
+ "Number of tensor lists has to match the depth.");
225
+ const size_t n_tensors = tensor_lists[0].size();
226
+ TensorListMetadata<depth> tensorListMeta;
227
+ tensorListMeta.start_tensor_this_launch = 0;
228
+
229
+ int loc_block_info = 0;
230
+ int loc_tensor_info = 0;
231
+ int processed = 0;
232
+
233
+ for (size_t t = 0; t < n_tensors; t++) {
234
+ // short-circuit to avoid adding empty tensors to tensorListMeta
235
+ if (tensor_lists[0][t].numel() == 0) {
236
+ continue;
237
+ }
238
+ processed++;
239
+ tensorListMeta.numel_for_tensor[loc_tensor_info] =
240
+ tensor_lists[0][t].numel();
241
+ for (int d = 0; d < depth; d++) {
242
+ tensorListMeta.addresses[d][loc_tensor_info] =
243
+ tensor_lists[d][t].const_data_ptr();
244
+ }
245
+ loc_tensor_info++;
246
+
247
+ // see note: [chunking territory].
248
+ const auto numel = tensor_lists[0][t].numel();
249
+ const auto chunks = numel / kChunkSize + (numel % kChunkSize != 0);
250
+ for (auto chunk = 0; chunk < chunks; chunk++) {
251
+ tensorListMeta.block_to_tensor[loc_block_info] = loc_tensor_info - 1;
252
+ tensorListMeta.block_to_chunk[loc_block_info] = chunk;
253
+ loc_block_info++;
254
+
255
+ const bool tensors_full =
256
+ (loc_tensor_info == depth_to_max_tensors[depth - 1] &&
257
+ chunk == chunks - 1);
258
+ const bool blocks_full =
259
+ (loc_block_info == depth_to_max_blocks[depth - 1]);
260
+
261
+ if (tensors_full || blocks_full) {
262
+ multi_tensor_apply_kernel<<<
263
+ loc_block_info,
264
+ kBlockSize,
265
+ 0,
266
+ at::cuda::getCurrentCUDAStream()>>>(
267
+ tensorListMeta, callable, args...);
268
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
269
+
270
+ // Reset.
271
+ loc_block_info = 0;
272
+ if (chunk == chunks - 1) {
273
+ loc_tensor_info = 0;
274
+ tensorListMeta.start_tensor_this_launch = processed;
275
+ } else {
276
+ tensorListMeta.numel_for_tensor[0] =
277
+ tensorListMeta.numel_for_tensor[loc_tensor_info - 1];
278
+ for (int d = 0; d < depth; d++) {
279
+ tensorListMeta.addresses[d][0] =
280
+ tensorListMeta.addresses[d][loc_tensor_info - 1];
281
+ }
282
+ loc_tensor_info = 1;
283
+ tensorListMeta.start_tensor_this_launch = processed - 1;
284
+ }
285
+ }
286
+ }
287
+ }
288
+
289
+ // see note: [finishing what we started]
290
+ if (loc_block_info != 0) {
291
+ multi_tensor_apply_kernel<<<
292
+ loc_block_info,
293
+ kBlockSize,
294
+ 0,
295
+ at::cuda::getCurrentCUDAStream()>>>(tensorListMeta, callable, args...);
296
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
297
+ }
298
+ }
299
+
300
+ template <int depth, typename T, typename... ArgTypes>
301
+ void multi_tensor_apply_for_fused_optimizer(
302
+ std::vector<std::vector<at::Tensor>>& tensor_lists,
303
+ at::TensorList state_steps,
304
+ T callable,
305
+ ArgTypes... args) {
306
+ TORCH_CHECK(
307
+ tensor_lists.size() == depth,
308
+ "Number of tensor lists has to match the depth");
309
+ const auto num_tensors = tensor_lists[0].size();
310
+ FusedOptimizerTensorListMetadata<depth> tensorListMeta;
311
+
312
+ int loc_block_info = 0;
313
+ int loc_tensor_info = 0;
314
+ for (const auto& tensor_index : c10::irange(num_tensors)) {
315
+ // short-circuit to avoid adding empty tensors to tensorListMeta
316
+ if (tensor_lists[0][tensor_index].numel() == 0) {
317
+ continue;
318
+ }
319
+ tensorListMeta.state_steps_addresses[loc_tensor_info] =
320
+ state_steps[tensor_index].const_data_ptr();
321
+ tensorListMeta.numel_for_tensor[loc_tensor_info] =
322
+ tensor_lists[0][tensor_index].numel();
323
+ for (const auto& d : c10::irange(depth)) {
324
+ tensorListMeta.addresses[d][loc_tensor_info] =
325
+ tensor_lists[d][tensor_index].const_data_ptr();
326
+ }
327
+ loc_tensor_info++;
328
+
329
+ // see above note: [chunking territory]
330
+ const auto numel = tensor_lists[0][tensor_index].numel();
331
+ const auto chunks = numel / kChunkSize + (numel % kChunkSize != 0);
332
+ TORCH_CHECK(chunks > -1);
333
+ for (const auto& chunk : c10::irange(chunks)) {
334
+ tensorListMeta.block_to_tensor[loc_block_info] = loc_tensor_info - 1;
335
+ tensorListMeta.block_to_chunk[loc_block_info] = chunk;
336
+ loc_block_info++;
337
+
338
+ const auto tensor_full =
339
+ (loc_tensor_info == depth_to_max_tensors[depth - 1] &&
340
+ chunk == chunks - 1);
341
+ const auto blocks_full = loc_block_info == depth_to_max_blocks[depth - 1];
342
+
343
+ if (tensor_full || blocks_full) {
344
+ multi_tensor_apply_kernel<<<
345
+ loc_block_info,
346
+ kBlockSize,
347
+ 0,
348
+ at::cuda::getCurrentCUDAStream()>>>(
349
+ tensorListMeta, callable, args...);
350
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
351
+
352
+ // Reset.
353
+ loc_block_info = 0;
354
+ if (chunk == chunks - 1) {
355
+ loc_tensor_info = 0;
356
+ } else {
357
+ tensorListMeta.numel_for_tensor[0] =
358
+ tensorListMeta.numel_for_tensor[loc_tensor_info - 1];
359
+ tensorListMeta.state_steps_addresses[0] =
360
+ tensorListMeta.state_steps_addresses[loc_tensor_info - 1];
361
+ for (const auto& d : c10::irange(depth)) {
362
+ tensorListMeta.addresses[d][0] =
363
+ tensorListMeta.addresses[d][loc_tensor_info - 1];
364
+ }
365
+ loc_tensor_info = 1;
366
+ }
367
+ }
368
+ }
369
+ }
370
+
371
+ // see above note: [finishing what we've started]
372
+ if (loc_block_info != 0) {
373
+ multi_tensor_apply_kernel<<<
374
+ loc_block_info,
375
+ kBlockSize,
376
+ 0,
377
+ at::cuda::getCurrentCUDAStream()>>>(tensorListMeta, callable, args...);
378
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
379
+ }
380
+ }
381
+
382
+ } // namespace at::native