Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
math_kernel.h
Go to the documentation of this file.
1#ifndef __MATH_MATH_KERNEL_H__
2#define __MATH_MATH_KERNEL_H__
3/*
4 Copyright (c) 2021-2026, The Neko Authors
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13
14 * Redistributions in binary form must reproduce the above
15 copyright notice, this list of conditions and the following
16 disclaimer in the documentation and/or other materials provided
17 with the distribution.
18
19 * Neither the name of the authors nor the names of its
20 contributors may be used to endorse or promote products derived
21 from this software without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35*/
36
37#include "wave.h"
38
42template< typename T >
44 const T c,
45 const int n) {
46
47 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
48 const int str = blockDim.x * gridDim.x;
49
50 for (int i = idx; i < n; i += str) {
51 a[i] = c * a[i];
52 }
53}
54
58template< typename T >
60 T * __restrict__ b,
61 int * __restrict__ mask,
62 const int n,
63 const int n_mask) {
64
65 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
66 const int str = blockDim.x * gridDim.x;
67
68 for (int i = idx; i < n_mask; i += str) {
69 a[i] = b[mask[i+1]-1];
70 }
71}
72
76template< typename T >
78 T * __restrict__ b,
79 int * __restrict__ mask,
80 const int n,
81 const int n_mask) {
82
83 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
84 const int str = blockDim.x * gridDim.x;
85
86 for (int i = idx; i < n_mask; i += str) {
87 a[i] = b[mask[i]];
88 }
89}
90
92void face_gather_nonlinear_index(int *index, const int idx, const int lx,
93 const int ly, const int lz) {
94 const int idx2 = idx - 1;
95 index[3] = idx2 / (lx * ly * lz);
96 index[2] = (idx2 - (lx * ly * lz) * index[3]) / (lx * ly);
97 index[1] = (idx2 - (lx * ly * lz) * index[3] - (lx * ly) * index[2]) / lx;
98 index[0] = (idx2 - (lx * ly * lz) * index[3] - (lx * ly) * index[2]) -
99 lx * index[1];
100 index[0]++;
101 index[1]++;
102 index[2]++;
103 index[3]++;
104}
105
107int face_gather_idx(const int i, const int j, const int k, const int l,
108 const int n1, const int n2, const int nf) {
109 return ((i) + (n1) * (((j) - 1) + (n2) * (((k) - 1) + (nf) * (((l) - 1))))) - 1;
110}
111
115template< typename T >
117 const T * __restrict__ b,
118 const int * __restrict__ mask,
119 const int * __restrict__ facet,
120 const int n1,
121 const int n2,
122 const int lx,
123 const int ly,
124 const int lz,
125 const int n_mask) {
126 int index[4];
127
128 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
129 const int str = blockDim.x * gridDim.x;
130
131 for (int m = idx; m < n_mask; m += str) {
132 const int f = facet[m + 1];
133 face_gather_nonlinear_index(index, mask[m + 1], lx, ly, lz);
134
135 switch (f) {
136 case 1:
137 case 2:
138 a[m] = b[face_gather_idx(index[1], index[2], f, index[3], n1, n2, 6)];
139 break;
140 case 3:
141 case 4:
142 a[m] = b[face_gather_idx(index[0], index[2], f, index[3], n1, n2, 6)];
143 break;
144 case 5:
145 case 6:
146 a[m] = b[face_gather_idx(index[0], index[1], f, index[3], n1, n2, 6)];
147 break;
148 }
149 }
150}
151
155template< typename T >
157 T * __restrict__ b,
158 int * __restrict__ mask,
159 const int n,
160 const int n_mask) {
161
162 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
163 const int str = blockDim.x * gridDim.x;
164
165 for (int i = idx; i < n_mask; i += str) {
166 a[mask[i+1]-1] = b[i];
167 }
168}
169
173template< typename T >
175 T * __restrict__ b,
176 int * __restrict__ mask,
177 const int n,
178 const int n_mask) {
179
180 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
181 const int str = blockDim.x * gridDim.x;
182
183 for (int i = idx; i < n_mask; i += str) {
184 a[mask[i]] = b[i];
185 }
186}
187
192#define MASKED_ATOMIC_RED_BLOCK 256
193
197template< typename T >
199 T * __restrict__ b,
200 int * __restrict__ mask,
201 const int n,
202 const int n_mask) {
203
206
207 const int lane = threadIdx.x % NEKO_WAVE_SIZE;
208 const int str = MASKED_ATOMIC_RED_BLOCK * gridDim.x;
209
210 bins[threadIdx.x] = 0.0;
211
212 /* Stride over whole blocks, so every thread reaches every barrier and
213 every lane every shuffle; lanes past the end carry no target */
215 base += str) {
216
217 if (threadIdx.x == 0)
220 const int kbase = bins_base;
221
222 const int i = base + threadIdx.x;
223 int key = -1;
224 T val = 0.0;
225 if (i < n_mask) {
226 key = mask[i + 1] - 1;
227 val = b[i];
228 }
229
230 /* A run starts where the target changes and ends in the lane before
231 the next run's head. The ballot is 64 bits wide at either wavefront
232 size, with the upper half zero at wave32. */
233 const int key_prev = __shfl_up(key, 1);
234 const bool head = (lane == 0) || (key != key_prev);
235 const unsigned long long heads = __ballot(head);
236
237 if (heads == (~0ull >> (64 - NEKO_WAVE_SIZE))) {
238 /* No two neighbouring lanes share a target, so there is nothing to
239 combine: scatter directly, as a plain atomic kernel would. The
240 ballot is the same in every lane, so the branch is
241 wavefront-uniform. */
242 if (key >= 0)
243 unsafeAtomicAdd(&a[key], val);
244 }
245 else {
246 const unsigned long long next = heads & ~((2ull << lane) - 1ull);
247 const int run_end = next ? __ffsll(next) - 2 : NEKO_WAVE_SIZE - 1;
248
249 /* Segmented suffix sum, the head ends up with the sum of its run */
250#pragma unroll
251 for (int off = 1; off < NEKO_WAVE_SIZE; off *= 2) {
252 const T tmp = __shfl_down(val, off);
253 if (lane + off <= run_end)
254 val += tmp;
255 }
256
257 if (head && key >= 0) {
258 const int s = key - kbase;
259 if (s >= 0 && s < MASKED_ATOMIC_RED_BLOCK)
260 atomicAdd(&bins[s], val);
261 else
262 unsafeAtomicAdd(&a[key], val);
263 }
264 }
266
267 /* Flush the bins and clear them for the next stride; the barrier at
268 the top of the loop orders this against the next accumulation */
269 const T sum = bins[threadIdx.x];
270 if (sum != (T) 0.0) {
272 bins[threadIdx.x] = 0.0;
273 }
274 }
275}
276
280template< typename T >
282 T * __restrict__ b,
283 int * __restrict__ mask,
284 const int n,
285 const int n_mask) {
286
287 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
288 const int str = blockDim.x * gridDim.x;
289
290 for (int i = idx; i < n_mask; i += str) {
291 a[mask[i+1]-1] = b[mask[i+1]-1];
292 }
293}
294
298template< typename T >
300 T * __restrict__ b,
301 int * __restrict__ mask,
302 const int n,
303 const int n_mask) {
304
305 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
306 const int str = blockDim.x * gridDim.x;
307
308 for (int i = idx; i < n_mask; i += str) {
309 a[mask[i]] = b[mask[i]];
310 }
311}
312
316template< typename T >
318 const T c,
319 const int n,
320 int* __restrict__ mask,
321 const int n_mask) {
322
323 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
324 const int str = blockDim.x * gridDim.x;
325
326 for (int i = idx; i < n_mask; i += str) { a[mask[i]] = c; }
327}
328
332template< typename T >
334 T * __restrict__ b,
335 const T c,
336 const int n) {
337
338 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
339 const int str = blockDim.x * gridDim.x;
340
341 for (int i = idx; i < n; i += str) {
342 a[i] = c * b[i];
343 }
344}
345
349template< typename T >
351 const T c,
352 const int n) {
353
354 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
355 const int str = blockDim.x * gridDim.x;
356
357 for (int i = idx; i < n; i += str) {
358 a[i] = c / a[i];
359 }
360}
361
365template< typename T >
367 T * __restrict__ b,
368 const T c,
369 const int n) {
370
371 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
372 const int str = blockDim.x * gridDim.x;
373
374 for (int i = idx; i < n; i += str) {
375 a[i] = c / b[i];
376 }
377}
378
382template< typename T >
384 const T c,
385 const int n) {
386
387 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
388 const int str = blockDim.x * gridDim.x;
389
390 for (int i = idx; i < n; i += str) {
391 a[i] = a[i] + c;
392 }
393}
394
398template< typename T >
400 T * __restrict__ b,
401 const T c,
402 const int n) {
403
404 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
405 const int str = blockDim.x * gridDim.x;
406
407 for (int i = idx; i < n; i += str) {
408 a[i] = b[i] + c;
409 }
410}
411
415template< typename T >
417 const T min_val,
418 const T max_val,
419 const int n) {
420
421 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
422 const int str = blockDim.x * gridDim.x;
423 const T l = max_val - min_val;
424
425 for (int i = idx; i < n; i += str) {
426 a[i] = min_val + fmod(fmod(a[i] - min_val, l) + l, l);
427 }
428}
429
433template< typename T >
435 const int n) {
436
437 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
438 const int str = blockDim.x * gridDim.x;
439
440 for (int i = idx; i < n; i += str) {
441 a[i] = sqrt(a[i]);
442 }
443}
444
448template< typename T >
450 const T * __restrict__ a,
451 const T p,
452 const int n) {
453
454 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
455 const int str = blockDim.x * gridDim.x;
456
457 for (int i = idx; i < n; i += str) {
458 ap[i] = pow(a[i], p);
459 }
460}
461
465template< typename T >
467 const T c,
468 const int n) {
469
470 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
471 const int str = blockDim.x * gridDim.x;
472
473 for (int i = idx; i < n; i += str) {
474 a[i] = c;
475 }
476}
477
481template< typename T >
483 const T * __restrict__ b,
484 const int n) {
485
486 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
487 const int str = blockDim.x * gridDim.x;
488
489 for (int i = idx; i < n; i += str) {
490 a[i] = b[i];
491 }
492}
493
497template< typename T >
499 const T * __restrict__ b,
500 const int n) {
501
502 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
503 const int str = blockDim.x * gridDim.x;
504
505 for (int i = idx; i < n; i += str) {
506 a[i] = a[i] + b[i];
507 }
508}
509
513template< typename T >
515 const T * __restrict__ b,
516 const T * __restrict__ c,
517 const int n) {
518
519 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
520 const int str = blockDim.x * gridDim.x;
521
522 for (int i = idx; i < n; i += str) {
523 a[i] = b[i] + c[i];
524 }
525}
526
530template< typename T >
532 const T * __restrict__ b,
533 const T * __restrict__ c,
534 const T * __restrict__ d,
535 const int n) {
536
537 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
538 const int str = blockDim.x * gridDim.x;
539
540 for (int i = idx; i < n; i += str) {
541 a[i] = b[i] + c[i] + d[i];
542 }
543}
544
548template< typename T >
550 const T * __restrict__ b,
551 const T c1,
552 const int n) {
553
554 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
555 const int str = blockDim.x * gridDim.x;
556
557 for (int i = idx; i < n; i += str) {
558 a[i] = c1 * a[i] + b[i];
559 }
560}
561
565template< typename T >
567 const T ** p,
568 const T * alpha,
569 const int p_cur,
570 const int n) {
571
572 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
573 const int str = blockDim.x * gridDim.x;
574
575
576 for (int i = idx; i < n; i+= str) {
577 T tmp = 0.0;
578 for (int j = 0; j < p_cur; j ++) {
579 tmp += p[j][i]*alpha[j];
580 }
581 x[i] += tmp;
582 }
583}
584
588template< typename T >
590 const T * __restrict__ b,
591 const T c1,
592 const int n) {
593
594 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
595 const int str = blockDim.x * gridDim.x;
596
597 for (int i = idx; i < n; i += str) {
598 a[i] = a[i] + c1 * b[i];
599 }
600}
601
605template< typename T >
607 const T * __restrict__ b,
608 const T c1,
609 const int n) {
610
611 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
612 const int str = blockDim.x * gridDim.x;
613
614 for (int i = idx; i < n; i += str) {
615 a[i] = a[i] + c1 * (b[i] * b[i]);
616 }
617}
618
622template< typename T >
624 const T * __restrict__ b,
625 const T * __restrict__ c,
626 const T c1,
627 const T c2,
628 const int n) {
629
630 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
631 const int str = blockDim.x * gridDim.x;
632
633 for (int i = idx; i < n; i += str) {
634 a[i] = c1 * b[i] + c2 * c[i];
635 }
636}
637
641template< typename T >
643 const T * __restrict__ b,
644 const T * __restrict__ c,
645 const T * __restrict__ d,
646 const T c1,
647 const T c2,
648 const T c3,
649 const int n) {
650
651 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
652 const int str = blockDim.x * gridDim.x;
653
654 for (int i = idx; i < n; i += str) {
655 a[i] = c1 * b[i] + c2 * c[i] + c3 * d[i];
656 }
657}
658
662template< typename T >
664 const T * __restrict__ b,
665 const T * __restrict__ c,
666 const T * __restrict__ d,
667 const T * __restrict__ e,
668 const T c1,
669 const T c2,
670 const T c3,
671 const T c4,
672 const int n) {
673
674 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
675 const int str = blockDim.x * gridDim.x;
676
677 for (int i = idx; i < n; i += str) {
678 a[i] = a[i] + c1 * b[i] + c2 * c[i] + c3 * d[i] + c4 * e[i];
679 }
680}
681
685template< typename T >
687 const int n) {
688
689 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
690 const int str = blockDim.x * gridDim.x;
691 const T one = 1.0;
692
693 for (int i = idx; i < n; i += str) {
694 a[i] = one / a[i];
695 }
696}
697
701template< typename T >
703 const T * __restrict__ b,
704 const int n) {
705
706 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
707 const int str = blockDim.x * gridDim.x;
708
709 for (int i = idx; i < n; i += str) {
710 a[i] = a[i] / b[i];
711 }
712}
713
717template< typename T >
719 const T * __restrict__ b,
720 const T * __restrict__ c,
721 const int n) {
722
723 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
724 const int str = blockDim.x * gridDim.x;
725
726 for (int i = idx; i < n; i += str) {
727 a[i] = b[i] / c[i];
728 }
729}
730
734template< typename T >
736 const T * __restrict__ b,
737 const int n) {
738
739 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
740 const int str = blockDim.x * gridDim.x;
741
742 for (int i = idx; i < n; i += str) {
743 a[i] = a[i] * b[i];
744 }
745}
746
750template< typename T >
752 const T * __restrict__ b,
753 const T * __restrict__ c,
754 const int n) {
755
756 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
757 const int str = blockDim.x * gridDim.x;
758
759 for (int i = idx; i < n; i += str) {
760 a[i] = b[i] * c[i];
761 }
762}
763
767template< typename T >
769 const T * __restrict__ b,
770 const T * __restrict__ c,
771 const int n) {
772
773 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
774 const int str = blockDim.x * gridDim.x;
775
776 for (int i = idx; i < n; i += str) {
777 a[i] = a[i] - b[i] * c[i];
778 }
779}
780
784template< typename T >
786 const T * __restrict__ b,
787 const int n) {
788
789 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
790 const int str = blockDim.x * gridDim.x;
791
792 for (int i = idx; i < n; i += str) {
793 a[i] = a[i] - b[i];
794 }
795}
796
800template< typename T >
802 const T * __restrict__ b,
803 const T * __restrict__ c,
804 const int n) {
805
806 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
807 const int str = blockDim.x * gridDim.x;
808
809 for (int i = idx; i < n; i += str) {
810 a[i] = b[i] - c[i];
811 }
812}
813
817template< typename T >
819 const T * __restrict__ b,
820 const T * __restrict__ c,
821 const int n) {
822
823 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
824 const int str = blockDim.x * gridDim.x;
825
826 for (int i = idx; i < n; i += str) {
827 a[i] = a[i] + b[i] * c[i];
828 }
829
830}
831
835template< typename T >
837 const T * __restrict__ b,
838 const T * __restrict__ c,
839 const T * __restrict__ d,
840 const int n) {
841
842 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
843 const int str = blockDim.x * gridDim.x;
844
845 for (int i = idx; i < n; i += str) {
846 a[i] = a[i] + b[i] * c[i] * d[i];
847 }
848
849}
850
854template< typename T >
856 const T * __restrict__ b,
857 const T * __restrict__ c,
858 const T s,
859 const int n) {
860
861 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
862 const int str = blockDim.x * gridDim.x;
863
864 for (int i = idx; i < n; i += str) {
865 a[i] = a[i] + s * b[i] * c[i];
866 }
867
868}
869
873template< typename T >
875 const T * __restrict__ u1,
876 const T * __restrict__ u2,
877 const T * __restrict__ u3,
878 const T * __restrict__ v1,
879 const T * __restrict__ v2,
880 const T * __restrict__ v3,
881 const int n) {
882
883 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
884 const int str = blockDim.x * gridDim.x;
885
886 for (int i = idx; i < n; i += str) {
887 dot[i] = u1[i] * v1[i] + u2[i] * v2[i] + u3[i] * v3[i];
888 }
889
890}
891
895template< typename T >
897 T * __restrict__ u2,
898 T * __restrict__ u3,
899 const T * __restrict__ v1,
900 const T * __restrict__ v2,
901 const T * __restrict__ v3,
902 const T * __restrict__ w1,
903 const T * __restrict__ w2,
904 const T * __restrict__ w3,
905 const int n) {
906
907 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
908 const int str = blockDim.x * gridDim.x;
909
910 for (int i = idx; i < n; i += str) {
911 u1[i] = v2[i]*w3[i] - v3[i]*w2[i];
912 u2[i] = v3[i]*w1[i] - v1[i]*w3[i];
913 u3[i] = v1[i]*w2[i] - v2[i]*w1[i];
914 }
915}
916
926template< typename T>
928#if NEKO_WAVE_SIZE == 64
929 val += __shfl_down(val, 32);
930#endif
931 val += __shfl_down(val, 16);
932 val += __shfl_down(val, 8);
933 val += __shfl_down(val, 4);
934 val += __shfl_down(val, 2);
935 val += __shfl_down(val, 1);
936 return val;
937}
938
942template< typename T>
944#if NEKO_WAVE_SIZE == 64
945 val = max(val, __shfl_down(val, 32));
946#endif
947 val = max(val, __shfl_down(val, 16));
948 val = max(val, __shfl_down(val, 8));
949 val = max(val, __shfl_down(val, 4));
950 val = max(val, __shfl_down(val, 2));
951 val = max(val, __shfl_down(val, 1));
952 return val;
953}
954
958template< typename T>
960#if NEKO_WAVE_SIZE == 64
961 val = min(val, __shfl_down(val, 32));
962#endif
963 val = min(val, __shfl_down(val, 16));
964 val = min(val, __shfl_down(val, 8));
965 val = min(val, __shfl_down(val, 4));
966 val = min(val, __shfl_down(val, 2));
967 val = min(val, __shfl_down(val, 1));
968 return val;
969}
970
974template< typename T >
975__global__ void reduce_kernel(T * bufred, const int n) {
976
977 T sum = 0;
978 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
979 const int str = blockDim.x * gridDim.x;
980 for (int i = idx; i<n ; i += str)
981 {
982 sum += bufred[i];
983 }
984
985 __shared__ T shared[64];
986 unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
987 unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
988
990 if (lane == 0)
991 shared[wid] = sum;
993
994 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
995 if (wid == 0)
997
998 if (threadIdx.x == 0)
999 bufred[blockIdx.x] = sum;
1000}
1001
1005template< typename T >
1006__global__ void reduce_max_kernel(T * bufred, const T ninf, const int n) {
1007
1008 T max_val = ninf;
1009 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1010 const int str = blockDim.x * gridDim.x;
1011 for (int i = idx; i<n ; i += str)
1012 {
1013 max_val = max(max_val, bufred[i]);
1014 }
1015
1016 __shared__ T shared[64];
1017 unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1018 unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1019
1021 if (lane == 0)
1022 shared[wid] = max_val;
1023 __syncthreads();
1024
1026 if (wid == 0)
1028
1029 if (threadIdx.x == 0)
1030 bufred[blockIdx.x] = max_val;
1031}
1032
1036template< typename T >
1037__global__ void reduce_min_kernel(T * bufred, const T pinf, const int n) {
1038
1039 T min_val = pinf;
1040 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1041 const int str = blockDim.x * gridDim.x;
1042 for (int i = idx; i<n ; i += str)
1043 {
1044 min_val = min(min_val, bufred[i]);
1045 }
1046
1047 __shared__ T shared[64];
1048 unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1049 unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1050
1052 if (lane == 0)
1053 shared[wid] = min_val;
1054 __syncthreads();
1055
1057 if (wid == 0)
1059
1060 if (threadIdx.x == 0)
1061 bufred[blockIdx.x] = min_val;
1062}
1063
1068template< typename T_acc >
1070 const int n,
1071 const int j
1072 ) {
1073 __shared__ T_acc buf[1024] ;
1074 const int idx = threadIdx.x;
1075 const int y= blockIdx.x;
1076 const int step = blockDim.x;
1077
1078 buf[idx]=0;
1079 for (int i=idx ; i<n ; i+=step)
1080 {
1081 buf[idx] += bufred[i*j + y];
1082 }
1083 __syncthreads();
1084
1085 int i = 512;
1086 while (i != 0)
1087 {
1088 if(threadIdx.x < i && (threadIdx.x + i) < n )
1089 {
1090 buf[threadIdx.x] += buf[threadIdx.x + i] ;
1091 }
1092 i = i>>1;
1093 __syncthreads();
1094 }
1095
1096 bufred[y] = buf[0];
1097}
1098
1102template< typename T >
1104 const T * b,
1105 const T * c,
1106 T * buf_h,
1107 const int n) {
1108
1109 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1110 const int str = blockDim.x * gridDim.x;
1111
1112 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1113 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1114
1115 __shared__ T shared[64];
1116 T sum = 0.0;
1117 for (int i = idx; i < n; i+= str) {
1118 sum += a[i] * b[i] * c[i];
1119 }
1120
1122 if (lane == 0)
1123 shared[wid] = sum;
1124 __syncthreads();
1125
1126 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
1127 if (wid == 0)
1129
1130 if (threadIdx.x == 0)
1131 buf_h[blockIdx.x] = sum;
1132}
1133
1137template< typename T, typename T_acc >
1139 const T * b,
1140 const T * c,
1141 T_acc * buf_h,
1142 const int n) {
1143
1144 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1145 const int str = blockDim.x * gridDim.x;
1146
1147 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1148 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1149
1151 T_acc sum = 0.0;
1152 for (int i = idx; i < n; i+= str) {
1153 sum += static_cast<T_acc>(a[i] * b[i] * c[i]);
1154 }
1155
1157 if (lane == 0)
1158 shared[wid] = sum;
1159 __syncthreads();
1160
1161 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
1162 if (wid == 0)
1164
1165 if (threadIdx.x == 0)
1166 buf_h[blockIdx.x] = sum;
1167}
1168
1172template< typename T, typename T_acc >
1174 const T ** b,
1175 const T * c,
1176 T_acc * buf_h,
1177 const int j,
1178 const int n) {
1179
1180 const int idx = blockIdx.x * blockDim.y + threadIdx.y;
1181 const int str = blockDim.y * gridDim.x;
1182 const int y = threadIdx.x;
1183
1184 __shared__ T_acc buf[1024];
1185 T_acc tmp = 0;
1186 if(y < j){
1187 for (int i = idx; i < n; i+= str) {
1188 tmp += static_cast<T_acc>(a[i] * b[threadIdx.x][i] * c[i]);
1189 }
1190 }
1191
1192 buf[threadIdx.y*blockDim.x+y] = tmp;
1193 __syncthreads();
1194
1195 int i = blockDim.y>>1;
1196 while (i != 0) {
1197 if (threadIdx.y < i) {
1198 buf[threadIdx.y*blockDim.x +y] += buf[(threadIdx.y + i)*blockDim.x+y];
1199 }
1200 __syncthreads();
1201 i = i>>1;
1202 }
1203 if (threadIdx.y == 0) {
1204 if( y < j) {
1205 buf_h[j*blockIdx.x+y] = buf[y];
1206 }
1207 }
1208}
1209
1213template< typename T, typename T_acc >
1215 const T * b,
1216 T_acc * buf_h,
1217 const int n) {
1218
1219 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1220 const int str = blockDim.x * gridDim.x;
1221
1222 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1223 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1224
1226 T_acc sum = 0.0;
1227 for (int i = idx; i < n; i+= str) {
1228 sum += static_cast<T_acc>(a[i] * b[i]);
1229 }
1230
1232 if (lane == 0)
1233 shared[wid] = sum;
1234 __syncthreads();
1235
1236 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
1237 if (wid == 0)
1239
1240 if (threadIdx.x == 0)
1241 buf_h[blockIdx.x] = sum;
1242
1243}
1244
1248template< typename T, typename T_acc >
1250 const T * b,
1251 T_acc * buf_h,
1252 const int n) {
1253
1254 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1255 const int str = blockDim.x * gridDim.x;
1256
1257 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1258 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1259
1261 T_acc sum = 0.0;
1262 for (int i = idx; i < n; i+= str) {
1263 sum += static_cast<T_acc>(pow(a[i] - b[i], 2.0));
1264 }
1265
1267 if (lane == 0)
1268 shared[wid] = sum;
1269 __syncthreads();
1270
1271 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
1272 if (wid == 0)
1274
1275 if (threadIdx.x == 0)
1276 buf_h[blockIdx.x] = sum;
1277
1278}
1279
1283template< typename T, typename T_acc >
1285 T_acc * buf_h,
1286 const int n) {
1287
1288 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1289 const int str = blockDim.x * gridDim.x;
1290
1291 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1292 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1293
1295 T_acc sum = 0;
1296 for (int i = idx; i<n ; i += str)
1297 {
1298 sum += static_cast<T_acc>(a[i]);
1299 }
1300
1302 if (lane == 0)
1303 shared[wid] = sum;
1304 __syncthreads();
1305
1306 sum = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : 0;
1307 if (wid == 0)
1309
1310 if (threadIdx.x == 0)
1311 buf_h[blockIdx.x] = sum;
1312
1313}
1314
1318template< typename T >
1320 const T ninf,
1321 T * buf_h,
1322 const int n) {
1323
1324 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1325 const int str = blockDim.x * gridDim.x;
1326
1327 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1328 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1329
1330 __shared__ T shared[64];
1331 T max_val = ninf;
1332 for (int i = idx; i<n ; i += str)
1333 {
1334 max_val = max(max_val, a[i]);
1335 }
1336
1338 if (lane == 0)
1339 shared[wid] = max_val;
1340 __syncthreads();
1341
1343 if (wid == 0)
1345
1346 if (threadIdx.x == 0)
1347 buf_h[blockIdx.x] = max_val;
1348
1349}
1350
1355template< typename T >
1357 T * buf_h,
1358 const int n) {
1359
1360 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1361 const int str = blockDim.x * gridDim.x;
1362
1363 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1364 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1365
1366 __shared__ T shared[64];
1367 T max_val = T(0);
1368 for (int i = idx; i<n ; i += str)
1369 {
1370 max_val = max(max_val, fabs(a[i]));
1371 }
1372
1374 if (lane == 0)
1375 shared[wid] = max_val;
1376 __syncthreads();
1377
1378 max_val = (threadIdx.x < blockDim.x / NEKO_WAVE_SIZE) ? shared[lane] : T(0);
1379 if (wid == 0)
1381
1382 if (threadIdx.x == 0)
1383 buf_h[blockIdx.x] = max_val;
1384
1385}
1386
1390template< typename T >
1392 const T pinf,
1393 T * buf_h,
1394 const int n) {
1395
1396 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1397 const int str = blockDim.x * gridDim.x;
1398
1399 const unsigned int lane = threadIdx.x % NEKO_WAVE_SIZE;
1400 const unsigned int wid = threadIdx.x / NEKO_WAVE_SIZE;
1401
1402 __shared__ T shared[64];
1403 T min_val = pinf;
1404 for (int i = idx; i<n ; i += str)
1405 {
1406 min_val = min(min_val, a[i]);
1407 }
1408
1410 if (lane == 0)
1411 shared[wid] = min_val;
1412 __syncthreads();
1413
1415 if (wid == 0)
1417
1418 if (threadIdx.x == 0)
1419 buf_h[blockIdx.x] = min_val;
1420
1421}
1422
1426template< typename T >
1428 const int n) {
1429
1430 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1431 const int str = blockDim.x * gridDim.x;
1432
1433 for (int i = idx; i < n; i += str) {
1434 a[i] = fabs(a[i]);
1435 }
1436}
1437
1438// ========================================================================== //
1439// Kernels for the point-wise operations
1440
1445template <typename T>
1446__global__ void
1447 pwmax_vec2_kernel(T* __restrict__ a, const T* __restrict__ b, const int n) {
1448
1449 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1450 const int str = blockDim.x * gridDim.x;
1451
1452 for (int i = idx; i < n; i += str) a[i] = max(a[i], b[i]);
1453}
1454
1459template <typename T>
1461 T* __restrict__ a, const T* __restrict__ b, const T* __restrict__ c,
1462 const int n) {
1463
1464 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1465 const int str = blockDim.x * gridDim.x;
1466
1467 for (int i = idx; i < n; i += str) a[i] = max(b[i], c[i]);
1468}
1469
1474template <typename T>
1475__global__ void pwmax_sca2_kernel(T* __restrict__ a, const T c, const int n) {
1476
1477 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1478 const int str = blockDim.x * gridDim.x;
1479
1480 for (int i = idx; i < n; i += str) a[i] = max(a[i], c);
1481}
1482
1487template <typename T>
1489 T* __restrict__ a, const T* __restrict b, const T c, const int n) {
1490
1491 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1492 const int str = blockDim.x * gridDim.x;
1493
1494 for (int i = idx; i < n; i += str) a[i] = max(b[i], c);
1495}
1496
1501template <typename T>
1502__global__ void
1503 pwmin_vec2_kernel(T* __restrict__ a, const T* __restrict__ b, const int n) {
1504
1505 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1506 const int str = blockDim.x * gridDim.x;
1507
1508 for (int i = idx; i < n; i += str) a[i] = min(a[i], b[i]);
1509}
1510
1515template <typename T>
1517 T* __restrict__ a, const T* __restrict__ b, const T* __restrict__ c,
1518 const int n) {
1519
1520 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1521 const int str = blockDim.x * gridDim.x;
1522
1523 for (int i = idx; i < n; i += str) a[i] = min(b[i], c[i]);
1524}
1525
1530template <typename T>
1531__global__ void pwmin_sca2_kernel(T* __restrict__ a, const T c, const int n) {
1532
1533 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1534 const int str = blockDim.x * gridDim.x;
1535
1536 for (int i = idx; i < n; i += str) a[i] = min(a[i], c);
1537}
1538
1543template <typename T>
1545 T* __restrict__ a, const T* __restrict b, const T c, const int n) {
1546
1547 const int idx = blockIdx.x * blockDim.x + threadIdx.x;
1548 const int str = blockDim.x * gridDim.x;
1549
1550 for (int i = idx; i < n; i += str) a[i] = min(b[i], c);
1551}
1552
1553#endif // __MATH_MATH_KERNEL_H__
__global__ void ale_add_kinematics_kernel(const int n, T *__restrict__ wx, T *__restrict__ wy, T *__restrict__ wz, const T *__restrict__ x_ref, const T *__restrict__ y_ref, const T *__restrict__ z_ref, const T *__restrict__ phi, const T *__restrict__ x, const T *__restrict__ y, const T *__restrict__ z, const kinematics_params_t kin_params)
const int i
const int e
const int j
__syncthreads()
__global__ void const T *__restrict__ x
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ w3
__global__ void addcol4_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T *__restrict__ d, const int n)
__global__ void cwrap_kernel(T *__restrict__ a, const T min_val, const T max_val, const int n)
__global__ void pwmin_vec3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void reduce_kernel(T *bufred, const int n)
__global__ void cdiv2_kernel(T *__restrict__ a, T *__restrict__ b, const T c, const int n)
__global__ void invcol2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void add2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void add4s3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T *__restrict__ d, const T c1, const T c2, const T c3, const int n)
__inline__ __device__ T reduce_warp(T val)
__global__ void masked_scatter_copy_aligned_kernel(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
__global__ void masked_atomic_reduction_kernel(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int m)
__global__ void pwmax_vec3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void glsc2_kernel(const T *a, const T *b, T_acc *buf_h, const int n)
__global__ void addcol3s2_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T s, const int n)
__global__ void cfill_mask_kernel(T *__restrict__ a, const T c, const int size, int *__restrict__ mask, const int mask_size)
__global__ void cdiv_kernel(T *__restrict__ a, const T c, const int n)
__global__ void masked_copy_kernel_aligned(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
__global__ void face_masked_gather_copy_kernel(T *__restrict__ a, const T *__restrict__ b, const int *__restrict__ mask, const int *__restrict__ facet, const int n1, const int n2, const int lx, const int ly, const int lz, const int n_mask)
__global__ void masked_gather_copy_aligned_kernel(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
Definition math_kernel.h:78
__global__ void pwmax_sca2_kernel(T *__restrict__ a, const T c, const int n)
__device__ __forceinline__ void face_gather_nonlinear_index(int *index, const int idx, const int lx, const int ly, const int lz)
Definition math_kernel.h:93
__global__ void reduce_max_kernel(T *bufred, const T ninf, const int n)
__global__ void pwmin_vec2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void add3s2_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T c1, const T c2, const int n)
__inline__ __device__ T reduce_max_warp(T val)
__global__ void glsum_kernel(const T *a, T_acc *buf_h, const int n)
__global__ void add2s1_kernel(T *__restrict__ a, const T *__restrict__ b, const T c1, const int n)
__device__ __forceinline__ int face_gather_idx(const int i, const int j, const int k, const int l, const int n1, const int n2, const int nf)
__global__ void add5s4_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T *__restrict__ d, const T *__restrict__ e, const T c1, const T c2, const T c3, const T c4, const int n)
#define MASKED_ATOMIC_RED_BLOCK
__global__ void masked_gather_copy_kernel(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
Definition math_kernel.h:59
__global__ void add2s2_many_kernel(T *__restrict__ x, const T **p, const T *alpha, const int p_cur, const int n)
__global__ void glsc3_many_kernel(const T *a, const T **b, const T *c, T_acc *buf_h, const int j, const int n)
__global__ void pwmax_vec2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void cmult_kernel(T *__restrict__ a, const T c, const int n)
Definition math_kernel.h:43
__global__ void addcol3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void pwmin_sca3_kernel(T *__restrict__ a, const T *__restrict b, const T c, const int n)
__global__ void pwmax_sca3_kernel(T *__restrict__ a, const T *__restrict b, const T c, const int n)
__global__ void power_kernel(T *__restrict__ ap, const T *__restrict__ a, const T p, const int n)
__global__ void col2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void masked_copy_kernel_0(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
__global__ void sqrt_inplace_kernel(T *__restrict__ a, const int n)
__global__ void col3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void sub2_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
__global__ void glmin_kernel(const T *a, const T pinf, T *buf_h, const int n)
__global__ void cmult2_kernel(T *__restrict__ a, T *__restrict__ b, const T c, const int n)
__global__ void pwmin_sca2_kernel(T *__restrict__ a, const T c, const int n)
__global__ void sub3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void glsubnorm2_kernel(const T *a, const T *b, T_acc *buf_h, const int n)
__global__ void glsc3_reduce_kernel(T_acc *bufred, const int n, const int j)
__global__ void add2s2_kernel(T *__restrict__ a, const T *__restrict__ b, const T c1, const int n)
__global__ void vdot3_kernel(T *__restrict__ dot, const T *__restrict__ u1, const T *__restrict__ u2, const T *__restrict__ u3, const T *__restrict__ v1, const T *__restrict__ v2, const T *__restrict__ v3, const int n)
__global__ void invcol1_kernel(T *__restrict__ a, const int n)
__global__ void add3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void glmax_kernel(const T *a, const T ninf, T *buf_h, const int n)
__global__ void vlsc3_kernel(const T *a, const T *b, const T *c, T *buf_h, const int n)
__global__ void add4_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const T *__restrict__ d, const int n)
__global__ void cfill_kernel(T *__restrict__ a, const T c, const int n)
__global__ void masked_scatter_copy_kernel(T *__restrict__ a, T *__restrict__ b, int *__restrict__ mask, const int n, const int n_mask)
__global__ void glsc3_kernel(const T *a, const T *b, const T *c, T_acc *buf_h, const int n)
__global__ void reduce_min_kernel(T *bufred, const T pinf, const int n)
__global__ void vcross_kernel(T *__restrict__ u1, T *__restrict__ u2, T *__restrict__ u3, const T *__restrict__ v1, const T *__restrict__ v2, const T *__restrict__ v3, const T *__restrict__ w1, const T *__restrict__ w2, const T *__restrict__ w3, const int n)
__global__ void addsqr2s2_kernel(T *__restrict__ a, const T *__restrict__ b, const T c1, const int n)
__global__ void cadd2_kernel(T *__restrict__ a, T *__restrict__ b, const T c, const int n)
__global__ void absval_kernel(T *__restrict__ a, const int n)
__global__ void invcol3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void subcol3_kernel(T *__restrict__ a, const T *__restrict__ b, const T *__restrict__ c, const int n)
__global__ void cadd_kernel(T *__restrict__ a, const T c, const int n)
__global__ void glamax_kernel(const T *a, T *buf_h, const int n)
__inline__ __device__ T reduce_min_warp(T val)
__global__ void copy_kernel(T *__restrict__ a, const T *__restrict__ b, const int n)
Object for handling masks in Neko.
Definition mask.f90:34
#define max(a, b)
Definition tensor.cu:40
#define NEKO_WAVE_SIZE
Definition wave.h:119