Prompt48 commited on
Commit
40e5145
·
verified ·
1 Parent(s): ef96d29

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

Browse files
edit//Qwen3-TTS-test//.venv//Lib//site-packages//torch//include//ATen//native//cuda//SortingRadixSelect.cuh ADDED
@@ -0,0 +1,427 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <ATen/ceil_div.h>
2
+ #include <ATen/cuda/Atomic.cuh>
3
+ #include <ATen/cuda/DeviceUtils.cuh>
4
+ #include <ATen/cuda/AsmUtils.cuh>
5
+ #include <c10/macros/Macros.h>
6
+
7
+ namespace at::native {
8
+
9
+ template <typename scalar_t>
10
+ struct TopKTypeConfig {};
11
+
12
+ template <>
13
+ struct TopKTypeConfig<float> {
14
+ typedef uint32_t RadixType;
15
+
16
+ // Converts a float to an integer representation with the same
17
+ // sorting; i.e., for floats f1, f2:
18
+ // if f1 < f2 then convert(f1) < convert(f2)
19
+ // We use this to enable radix selection of floating-point values.
20
+ // This also gives a relative order for NaNs, but that's ok, as they
21
+ // will all be adjacent
22
+ // neg inf: signbit=1 exp=ff fraction=0 --> radix = 0 00 ff..
23
+ // pos inf: signbit=0 exp=ff fraction=0 --> radix = 1 ff 00..
24
+ // pos nan: signbit=0 exp=ff fraction>0 --> radix = 1 ff x>0
25
+ // neg nan: signbit=1 exp=ff fraction>0 --> radix = 0 00 x<ff...
26
+ static inline __device__ RadixType convert(float v) {
27
+ RadixType x = __float_as_int(v);
28
+ RadixType mask = (x & 0x80000000) ? 0xffffffff : 0x80000000;
29
+
30
+ return (v == v) ? (x ^ mask) : 0xffffffff;
31
+ }
32
+
33
+ static inline __device__ float deconvert(RadixType v) {
34
+ RadixType mask = (v & 0x80000000) ? 0x80000000 : 0xffffffff;
35
+
36
+ return __int_as_float(v ^ mask);
37
+ }
38
+ };
39
+
40
+ template <>
41
+ struct TopKTypeConfig<uint8_t> {
42
+ typedef uint32_t RadixType;
43
+
44
+ static inline __device__ RadixType convert(uint8_t v) {
45
+ return v;
46
+ }
47
+
48
+ static inline __device__ uint8_t deconvert(RadixType v) {
49
+ return v;
50
+ }
51
+ };
52
+
53
+ template <>
54
+ struct TopKTypeConfig<int8_t> {
55
+ typedef uint32_t RadixType;
56
+
57
+ static inline __device__ RadixType convert(int8_t v) {
58
+ return 128u + v;
59
+ }
60
+
61
+ static inline __device__ int8_t deconvert(RadixType v) {
62
+ return v - 128;
63
+ }
64
+ };
65
+
66
+ template <>
67
+ struct TopKTypeConfig<int16_t> {
68
+ typedef uint32_t RadixType;
69
+
70
+ static inline __device__ RadixType convert(int16_t v) {
71
+ static_assert(sizeof(short) == 2, "");
72
+ return 32768u + v;
73
+ }
74
+
75
+ static inline __device__ int16_t deconvert(RadixType v) {
76
+ return v - 32768;
77
+ }
78
+ };
79
+
80
+ template <>
81
+ struct TopKTypeConfig<int32_t> {
82
+ typedef uint32_t RadixType;
83
+
84
+ static inline __device__ RadixType convert(int32_t v) {
85
+ static_assert(sizeof(int) == 4, "");
86
+ return 2147483648u + v;
87
+ }
88
+
89
+ static inline __device__ int32_t deconvert(RadixType v) {
90
+ return v - 2147483648u;
91
+ }
92
+ };
93
+
94
+ template <>
95
+ struct TopKTypeConfig<int64_t> {
96
+ typedef uint64_t RadixType;
97
+
98
+ static inline __device__ RadixType convert(int64_t v) {
99
+ static_assert(sizeof(int64_t) == 8, "");
100
+ return 9223372036854775808ull + v;
101
+ }
102
+
103
+ static inline __device__ int64_t deconvert(RadixType v) {
104
+ return v - 9223372036854775808ull;
105
+ }
106
+ };
107
+
108
+ template <>
109
+ struct TopKTypeConfig<double> {
110
+ typedef uint64_t RadixType;
111
+
112
+ static inline __device__ RadixType convert(double v) {
113
+ RadixType x = __double_as_longlong(v);
114
+ RadixType mask = -((x >> 63)) | 0x8000000000000000;
115
+ return (v == v) ? (x ^ mask) : 0xffffffffffffffff;
116
+ }
117
+
118
+ static inline __device__ double deconvert(RadixType v) {
119
+ RadixType mask = ((v >> 63) - 1) | 0x8000000000000000;
120
+ return __longlong_as_double(v ^ mask);
121
+ }
122
+ };
123
+
124
+ template <>
125
+ struct TopKTypeConfig<at::Half> {
126
+ typedef uint32_t RadixType;
127
+
128
+ static inline __device__ RadixType convert(at::Half v) {
129
+ #if defined(__CUDA_ARCH__) || defined(USE_ROCM)
130
+ RadixType x = __half_as_ushort(v);
131
+ RadixType mask = (x & 0x00008000) ? 0x0000ffff : 0x00008000;
132
+ return (v == v) ? (x ^ mask) : 0xffff;
133
+ #else
134
+ CUDA_KERNEL_ASSERT(false);
135
+ return 0u;
136
+ #endif
137
+ }
138
+
139
+ static inline __device__ at::Half deconvert(RadixType v) {
140
+ #if defined(__CUDA_ARCH__) || defined(USE_ROCM)
141
+ RadixType mask = (v & 0x00008000) ? 0x00008000 : 0x0000ffff;
142
+ return __ushort_as_half(v ^ mask);
143
+ #else
144
+ CUDA_KERNEL_ASSERT(false);
145
+ return static_cast<at::Half>(0);
146
+ #endif
147
+ }
148
+ };
149
+
150
+ template <>
151
+ struct TopKTypeConfig<at::BFloat16> {
152
+ typedef uint32_t RadixType;
153
+
154
+ static inline __device__ RadixType convert(at::BFloat16 v) {
155
+ RadixType x = v.x;
156
+ RadixType mask = (x & 0x00008000) ? 0x0000ffff : 0x00008000;
157
+ return (v == v) ? (x ^ mask) : 0xffff;
158
+ }
159
+
160
+ static inline __device__ at::BFloat16 deconvert(RadixType v) {
161
+ RadixType mask = (v & 0x00008000) ? 0x00008000 : 0x0000ffff;
162
+ at::BFloat16 r;
163
+ r.x = (v ^ mask);
164
+ return r;
165
+ }
166
+ };
167
+
168
+ // This function counts the distribution of all input values in a
169
+ // slice we are selecting by radix digit at `radixDigitPos`, but only
170
+ // those that pass the filter `((v & desiredMask) == desired)`.
171
+ // This produces and broadcasts the seen counts for a single block only.
172
+ // `smem` must have at least `RadixSize` elements.
173
+ template <
174
+ typename scalar_t,
175
+ typename bitwise_t,
176
+ typename index_t,
177
+ typename CountType,
178
+ int RadixSize,
179
+ int RadixBits>
180
+ __device__ void countRadixUsingMask(
181
+ CountType counts[RadixSize],
182
+ CountType* smem,
183
+ bitwise_t desired,
184
+ bitwise_t desiredMask,
185
+ int radixDigitPos,
186
+ index_t sliceSize,
187
+ index_t withinSliceStride,
188
+ const scalar_t* data) {
189
+ // Clear out per-thread counts from a previous round
190
+ #pragma unroll
191
+ for (int i = 0; i < RadixSize; ++i) {
192
+ counts[i] = 0;
193
+ }
194
+
195
+ if (threadIdx.x < RadixSize) {
196
+ smem[threadIdx.x] = 0;
197
+ }
198
+ __syncthreads();
199
+
200
+ // Scan over all the data. Upon a read, the warp will accumulate
201
+ // counts per each digit in the radix using warp voting.
202
+ #if !defined(USE_ROCM)
203
+ // Must be called outside of loop to ensure all threads participate
204
+ unsigned mask = WARP_BALLOT(threadIdx.x < sliceSize);
205
+ #endif
206
+ for (index_t i = threadIdx.x; i < sliceSize;) {
207
+ bitwise_t val =
208
+ TopKTypeConfig<scalar_t>::convert(doLdg(&data[i * withinSliceStride]));
209
+
210
+ bool hasVal = ((val & desiredMask) == desired);
211
+ bitwise_t digitInRadix = at::cuda::Bitfield<bitwise_t>::getBitfield(
212
+ val, radixDigitPos, RadixBits);
213
+
214
+ #pragma unroll
215
+ for (uint32_t j = 0; j < RadixSize; ++j) {
216
+ bool vote = hasVal && (digitInRadix == j);
217
+ #if defined(USE_ROCM)
218
+ counts[j] += __popcll(WARP_BALLOT(vote));
219
+ #else
220
+ counts[j] += __popc(WARP_BALLOT(vote, mask));
221
+ #endif
222
+ }
223
+ i += blockDim.x;
224
+ #if !defined(USE_ROCM)
225
+ mask = WARP_BALLOT(i < sliceSize, mask);
226
+ #endif
227
+ }
228
+
229
+ // Now, for each warp, sum values
230
+ if (at::cuda::getLaneId() == 0) {
231
+ #pragma unroll
232
+ for (uint32_t i = 0; i < RadixSize; ++i) {
233
+ gpuAtomicAddNoReturn(&smem[i], counts[i]);
234
+ }
235
+ }
236
+
237
+ __syncthreads();
238
+
239
+ // For each thread, read in the total counts
240
+ #pragma unroll
241
+ for (uint32_t i = 0; i < RadixSize; ++i) {
242
+ counts[i] = smem[i];
243
+ }
244
+
245
+ __syncthreads();
246
+ }
247
+
248
+ // Over what radix we are selecting values
249
+ constexpr int RADIX_BITS = 2; // digits are base-(2 ^ RADIX_BITS)
250
+ constexpr int RADIX_SIZE = 4; // 2 ^ RADIX_BITS
251
+ constexpr int RADIX_MASK = (RADIX_SIZE - 1);
252
+
253
+ // This finds the unique value `v` that matches the pattern
254
+ // ((v & desired) == desiredMask) in our sorted int format
255
+ template <typename scalar_t, typename bitwise_t, typename index_t>
256
+ __device__ scalar_t findPattern(
257
+ scalar_t* smem,
258
+ const scalar_t* data,
259
+ index_t sliceSize,
260
+ index_t withinSliceStride,
261
+ bitwise_t desired,
262
+ bitwise_t desiredMask) {
263
+ if (threadIdx.x < 2) {
264
+ smem[threadIdx.x] = static_cast<scalar_t>(0);
265
+ }
266
+ __syncthreads();
267
+
268
+ // All threads participate in the loop, in order to sync on the flag
269
+ index_t numIterations =
270
+ round_up(sliceSize, static_cast<index_t>(blockDim.x));
271
+ for (index_t i = threadIdx.x; i < numIterations; i += blockDim.x) {
272
+ bool inRange = (i < sliceSize);
273
+ scalar_t v = inRange ? doLdg(&data[i * withinSliceStride])
274
+ : static_cast<scalar_t>(0);
275
+
276
+ if (inRange &&
277
+ ((TopKTypeConfig<scalar_t>::convert(v) & desiredMask) == desired)) {
278
+ // There should not be conflicts if we are using findPattern,
279
+ // since the result is unique
280
+ smem[0] = static_cast<scalar_t>(1);
281
+ smem[1] = v; // can't use val as the flag, since it could be 0
282
+ }
283
+
284
+ __syncthreads();
285
+
286
+ scalar_t found = smem[0];
287
+ scalar_t val = smem[1];
288
+
289
+ __syncthreads();
290
+
291
+ // Check to see if a thread found the value
292
+ if (found != static_cast<scalar_t>(0)) {
293
+ // all threads return this value
294
+ return val;
295
+ }
296
+ }
297
+
298
+ // should not get here
299
+ CUDA_KERNEL_ASSERT(false);
300
+ return static_cast<scalar_t>(0);
301
+ }
302
+
303
+ // Returns the top-Kth element found in the data using radix selection
304
+ template <typename scalar_t, typename bitwise_t, typename index_t>
305
+ __device__ void radixSelect(
306
+ const scalar_t* data,
307
+ index_t k,
308
+ bool largest,
309
+ index_t sliceSize,
310
+ index_t withinSliceStride,
311
+ int* smem,
312
+ scalar_t* topK) {
313
+ // Per-thread buckets into which we accumulate digit counts in our
314
+ // radix
315
+ int counts[RADIX_SIZE];
316
+
317
+ // We only consider elements x such that (x & desiredMask) == desired
318
+ // Initially, we consider all elements of the array, so the above
319
+ // statement is true regardless of input.
320
+ bitwise_t desired = 0;
321
+ bitwise_t desiredMask = 0;
322
+
323
+ // We are looking for the top kToFind-th element when iterating over
324
+ // digits; this count gets reduced by elimination when counting
325
+ // successive digits
326
+ int kToFind = k;
327
+
328
+ // We start at the most significant digit in our radix, scanning
329
+ // through to the least significant digit
330
+ for (int digitPos = sizeof(scalar_t) * 8 - RADIX_BITS; digitPos >= 0;
331
+ digitPos -= RADIX_BITS) {
332
+ // Count radix distribution for the current position and reduce
333
+ // across all threads
334
+ countRadixUsingMask<
335
+ scalar_t,
336
+ bitwise_t,
337
+ index_t,
338
+ int,
339
+ RADIX_SIZE,
340
+ RADIX_BITS>(
341
+ counts,
342
+ smem,
343
+ desired,
344
+ desiredMask,
345
+ digitPos,
346
+ sliceSize,
347
+ withinSliceStride,
348
+ data);
349
+
350
+ auto found_unique = [&](int i, int count) -> bool {
351
+ /* All threads have the same value in counts here, so all */
352
+ /* threads will return from the function. */
353
+ if (count == 1 && kToFind == 1) {
354
+ /* There is a unique answer. */
355
+ desired = at::cuda::Bitfield<bitwise_t>::setBitfield(
356
+ desired, i, digitPos, RADIX_BITS);
357
+ desiredMask = at::cuda::Bitfield<bitwise_t>::setBitfield(
358
+ desiredMask, RADIX_MASK, digitPos, RADIX_BITS);
359
+
360
+ /* The answer is now the unique element v such that: */
361
+ /* (v & desiredMask) == desired */
362
+ /* However, we do not yet know what the actual element is. We */
363
+ /* need to perform a search through the data to find the */
364
+ /* element that matches this pattern. */
365
+ *topK = findPattern<scalar_t, bitwise_t, index_t>(
366
+ (scalar_t*)smem,
367
+ data,
368
+ sliceSize,
369
+ withinSliceStride,
370
+ desired,
371
+ desiredMask);
372
+ return true;
373
+ }
374
+ return false;
375
+ };
376
+ auto found_non_unique = [&](int i, int count) -> bool {
377
+ if (count >= kToFind) {
378
+ desired =
379
+ at::cuda::Bitfield<bitwise_t>::setBitfield(
380
+ desired, i, digitPos, RADIX_BITS);
381
+ desiredMask = at::cuda::Bitfield<bitwise_t>::setBitfield(
382
+ desiredMask, RADIX_MASK, digitPos, RADIX_BITS);
383
+
384
+ /* The top-Kth element v must now be one such that: */
385
+ /* (v & desiredMask == desired) */
386
+ /* but we haven't narrowed it down; we must check the next */
387
+ /* least-significant digit */
388
+ return true;
389
+ }
390
+ kToFind -= count;
391
+ return false; // continue the loop
392
+ };
393
+
394
+ // All threads participate in the comparisons below to know the
395
+ // final result
396
+ if (largest) {
397
+ // Process in descending order
398
+ #pragma unroll
399
+ for (int i = RADIX_SIZE - 1; i >= 0; --i) {
400
+ int count = counts[i];
401
+ if (found_unique(i, count)) {
402
+ return;
403
+ }
404
+ if (found_non_unique(i, count)) {
405
+ break;
406
+ }
407
+ }
408
+ } else {
409
+ // Process in ascending order
410
+ #pragma unroll
411
+ for (int i = 0; i < RADIX_SIZE; ++i) {
412
+ int count = counts[i];
413
+ if (found_unique(i, count)) {
414
+ return;
415
+ }
416
+ if (found_non_unique(i, count)) {
417
+ break;
418
+ }
419
+ }
420
+ }
421
+ } // end digitPos for
422
+
423
+ // There is no unique result, but there is a non-unique result
424
+ // matching `desired` exactly
425
+ *topK = TopKTypeConfig<scalar_t>::deconvert(desired);
426
+ }
427
+ } // namespace at::native