Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
ax_helm.cu
Go to the documentation of this file.
1/*
2 Copyright (c) 2021-2026, The Neko Authors
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16
17 * Neither the name of the authors nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33*/
34
35#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include "ax_helm_kernel.h"
39#include "elem_block_tune.h"
41#include <device/cuda/check.h>
42
43extern "C" {
44 #include <common/neko_log.h>
45}
46
47template < const int>
48int tune(void *w, void *u, void *dx, void *dy, void *dz,
49 void *dxt, void *dyt, void *dzt, void *h1,
50 void *g11, void *g22, void *g33, void *g12,
51 void *g13, void *g23, int *nelv, int *lx,
52 int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel);
53
54template < const int>
55int tune_padded(void *w, void *u, void *dx, void *dy, void *dz,
56 void *dxt, void *dyt, void *dzt, void *h1,
57 void *g11, void *g22, void *g33, void *g12,
58 void *g13, void *g23, int *nelv, int *lx,
59 int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel);
60
61template < const int>
62int tune_vector(void *au, void *av, void *aw, void *u, void *v, void *w,
63 void *dx, void *dy, void *dz, void *h1,
64 void *g11, void *g22, void *g33, void *g12,
65 void *g13, void *g23, int *nelv, int *lx,
66 int *eb_sel, int *nw_sel, int *tw_sel,
67 int *bw_sel);
68
69template < const int>
70int tune_vector_padded(void *au, void *av, void *aw, void *u, void *v, void *w,
71 void *dx, void *dy, void *dz, void *h1,
72 void *g11, void *g22, void *g33, void *g12,
73 void *g13, void *g23, int *nelv, int *lx,
74 int *eb_sel, int *nw_sel, int *tw_sel,
75 int *bw_sel);
76
77extern "C" {
78
82 void cuda_ax_helm(void *w, void *u, void *dx, void *dy, void *dz,
83 void *dxt, void *dyt, void *dzt, void *h1,
84 void *g11, void *g22, void *g33, void *g12,
85 void *g13, void *g23, int *nelv, int *lx) {
86
87 static int autotune[17] = { 0 };
88 /* Elements per block candidate chosen by the autotuner, see
89 elem_block<> in elem_block.h */
90 static int autotune_eb[17] = { 0 };
91 /* chunk candidate chosen for the 1d variant */
92 static int autotune_ch[17] = { 0 };
93 /* warps per block candidate chosen for the dmma variant */
94 static int autotune_nw[17] = { 0 };
95 /* warps per block candidate chosen for the tma staged dmma variant */
96 static int autotune_tw[17] = { 0 };
97
98 const dim3 nblcks_1d((*nelv), 1, 1);
99 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
100
101#define CASE_1D(LX, C) \
102 ax_helm_kernel_1d<real, LX, NEKO_CHUNKS(LX, C)> \
103 <<<nblcks_1d, NEKO_CHUNKS_NTHRDS(LX, C), 0, stream>>> \
104 ((real *) w, (real *) u, \
105 (real *) dx, (real *) dy, (real *) dz, \
106 (real *) dxt, (real *) dyt, (real *) dzt, (real *) h1,\
107 (real *) g11, (real *) g22, (real *) g33, \
108 (real *) g12, (real *) g13, (real *) g23); \
109 CUDA_CHECK(cudaGetLastError());
110
111/* Runtime dispatch onto the tuned chunk candidate */
112#define CASE_1D_SEL(LX, SEL) \
113 switch (SEL) { \
114 case 0: CASE_1D(LX, 0); break; \
115 case 1: CASE_1D(LX, 1); break; \
116 case 2: CASE_1D(LX, 2); break; \
117 default: CASE_1D(LX, 3); break; \
118 }
119
120#define CASE_KSTEP(LX, C) \
121 ax_helm_kernel_kstep<real, LX, NEKO_EB(LX, C)> \
122 <<<NEKO_EB_NBLCKS(*nelv, LX, C), NEKO_EB_NTHRDS(LX, C), 0, stream>>> \
123 ((real *) w, (real *) u, \
124 (real *) dx, (real *) dy, (real *) dz, (real *) h1, \
125 (real *) g11, (real *) g22, (real *) g33, \
126 (real *) g12, (real *) g13, (real *) g23, *nelv); \
127 CUDA_CHECK(cudaGetLastError());
128
129#define CASE_KSTEP_PADDED(LX, C) \
130 ax_helm_kernel_kstep_padded<real, LX, NEKO_EB(LX, C)> \
131 <<<NEKO_EB_NBLCKS(*nelv, LX, C), NEKO_EB_NTHRDS(LX, C), 0, stream>>> \
132 ((real *) w, (real *) u, \
133 (real *) dx, (real *) dy, (real *) dz, (real *) h1, \
134 (real *) g11, (real *) g22, (real *) g33, \
135 (real *) g12, (real *) g13, (real *) g23, *nelv); \
136 CUDA_CHECK(cudaGetLastError());
137
138/* Runtime dispatch onto the tuned elements per block candidate */
139#define CASE_KSTEP_SEL(LX, SEL) \
140 switch (SEL) { \
141 case 0: CASE_KSTEP(LX, 0); break; \
142 case 1: CASE_KSTEP(LX, 1); break; \
143 default: CASE_KSTEP(LX, 2); break; \
144 }
145
146#define CASE_KSTEP_PADDED_SEL(LX, SEL) \
147 switch (SEL) { \
148 case 0: CASE_KSTEP_PADDED(LX, 0); break; \
149 case 1: CASE_KSTEP_PADDED(LX, 1); break; \
150 default: CASE_KSTEP_PADDED(LX, 2); break; \
151 }
152
153#define CASE_DMMA(LX, C) \
154 ax_helm_kernel_dmma<real, LX, NEKO_DMMA_NW(C)> \
155 <<<NEKO_DMMA_NBLCKS(*nelv, LX), NEKO_DMMA_NTHRDS(C), 0, stream>>> \
156 ((real *) w, (real *) u, \
157 (real *) dx, (real *) dy, (real *) dz, (real *) h1, \
158 (real *) g11, (real *) g22, (real *) g33, \
159 (real *) g12, (real *) g13, (real *) g23, *nelv); \
160 CUDA_CHECK(cudaGetLastError());
161
162/* Runtime dispatch onto the tuned warps per block candidate */
163#define CASE_DMMA_SEL(LX, SEL) \
164 switch (SEL) { \
165 case 0: CASE_DMMA(LX, 0); break; \
166 case 1: CASE_DMMA(LX, 1); break; \
167 default: CASE_DMMA(LX, 2); break; \
168 }
169
170/*
171 * The TMA staged dmma variant. Same grid and the same warps per block
172 * candidates as CASE_DMMA -- at the one lx it supports NEKO_DMMA_PACK is 1,
173 * so the grid is nelv blocks -- but it takes no nelv: there is no packed tail
174 * to clamp when a block is exactly an element. See dmma_tma_kernel.h.
175 */
176#define CASE_DMMA_TMA(LX, C) \
177 ax_helm_kernel_dmma_tma<real, LX, NEKO_DMMA_NW(C)> \
178 <<<NEKO_DMMA_NBLCKS(*nelv, LX), NEKO_DMMA_NTHRDS(C), 0, stream>>> \
179 ((real *) w, (real *) u, \
180 (real *) dx, (real *) dy, (real *) dz, (real *) h1, \
181 (real *) g11, (real *) g22, (real *) g33, \
182 (real *) g12, (real *) g13, (real *) g23); \
183 CUDA_CHECK(cudaGetLastError());
184
185/* Runtime dispatch onto the tuned warps per block candidate */
186#define CASE_DMMA_TMA_SEL(LX, SEL) \
187 switch (SEL) { \
188 case 0: CASE_DMMA_TMA(LX, 0); break; \
189 case 1: CASE_DMMA_TMA(LX, 1); break; \
190 default: CASE_DMMA_TMA(LX, 2); break; \
191 }
192
193#define CASE(LX) \
194 case LX: \
195 if(autotune[LX] == 0 ) { \
196 autotune[LX]=tune<LX>( w, u, \
197 dx, dy, dz, \
198 dxt, dyt, dzt,h1, \
199 g11, g22, g33, \
200 g12, g13, g23, nelv, lx, \
201 &autotune_eb[LX], &autotune_ch[LX], \
202 &autotune_nw[LX], &autotune_tw[LX]); \
203 } else if (autotune[LX] == 1 ) { \
204 CASE_1D_SEL(LX, autotune_ch[LX]); \
205 } else if (autotune[LX] == 2 ) { \
206 CASE_KSTEP_SEL(LX, autotune_eb[LX]); \
207 } else if (autotune[LX] == 3 ) { \
208 CASE_DMMA_SEL(LX, autotune_nw[LX]); \
209 } else if (autotune[LX] == 4 ) { \
210 CASE_DMMA_TMA_SEL(LX, autotune_tw[LX]); \
211 } \
212 break
213
214#define CASE_PADDED(LX) \
215 case LX: \
216 if(autotune[LX] == 0 ) { \
217 autotune[LX]=tune_padded<LX>(w, u, \
218 dx, dy, dz, \
219 dxt, dyt, dzt,h1, \
220 g11, g22, g33, \
221 g12, g13, g23,nelv,lx, \
222 &autotune_eb[LX], &autotune_ch[LX], \
223 &autotune_nw[LX], &autotune_tw[LX]); \
224 } else if (autotune[LX] == 1 ) { \
225 CASE_1D_SEL(LX, autotune_ch[LX]); \
226 } else if (autotune[LX] == 2 ) { \
227 CASE_KSTEP_PADDED_SEL(LX, autotune_eb[LX]); \
228 } else if (autotune[LX] == 3 ) { \
229 CASE_DMMA_SEL(LX, autotune_nw[LX]); \
230 } else if (autotune[LX] == 4 ) { \
231 CASE_DMMA_TMA_SEL(LX, autotune_tw[LX]); \
232 } \
233 break
234
235/*
236 * High order cases have no 1d variant to compare against (its shared memory
237 * footprint grows as LX^3), so they are not tuned and keep one element per
238 * block, i.e. candidate 0
239 */
240#define CASE_LARGE(LX) \
241 case LX: \
242 CASE_KSTEP(LX, 0); \
243 break
244
245#define CASE_LARGE_PADDED(LX) \
246 case LX: \
247 CASE_KSTEP_PADDED(LX, 0); \
248 break
249
250 if ((*lx) < 12) {
251 switch(*lx) {
252 CASE(2);
253 CASE(3);
254 CASE_PADDED(4);
255 CASE(5);
256 CASE(6);
257 CASE(7);
258 CASE_PADDED(8);
259 CASE(9);
260 CASE(10);
261 CASE(11);
262 default:
263 {
264 fprintf(stderr, __FILE__ ": size not supported: %d\n", *lx);
265 exit(1);
266 }
267 }
268 }
269 else {
270 switch(*lx) {
271 CASE_LARGE(12);
272 CASE_LARGE(13);
273 CASE_LARGE(14);
274 CASE_LARGE(15);
276 default:
277 {
278 fprintf(stderr, __FILE__ ": size not supported: %d\n", *lx);
279 exit(1);
280 }
281 }
282 }
283 }
284
288 void cuda_ax_helm_vector(void *au, void *av, void *aw,
289 void *u, void *v, void *w,
290 void *dx, void *dy, void *dz,
291 void *dxt, void *dyt, void *dzt,
292 void *h1, void *g11, void *g22,
293 void *g33, void *g12, void *g13,
294 void *g23, int *nelv, int *lx) {
295
296 /* Strategy chosen by the autotuner: 2 kstep, 3 dmma */
297 static int autotune_vec[17] = { 0 };
298 /* elements per block candidate chosen for the kstep variant */
299 static int autotune_vec_eb[17] = { 0 };
300 /* warps per block candidate chosen for the dmma variant */
301 static int autotune_vec_nw[17] = { 0 };
302 /* warps per block candidate chosen for the tma staged dmma variant */
303 static int autotune_vec_tw[17] = { 0 };
304 /* warps per block candidate chosen for the batched tma variant */
305 static int autotune_vec_bw[17] = { 0 };
306
307 const dim3 nblcks_dmma((*nelv), 1, 1);
308 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
309
310/*
311 * The vector kstep variant sweeps the same elements per block candidates as
312 * the scalar one, and the tuner picks between it and the dmma variant. The
313 * vector kernels hold three times the register blocked state -- six T[LX]
314 * arrays rather than two -- and measure at 254-255 registers on sm_90 for
315 * every lx from 8 up, spilling at 10, 12, 14 and 16, so blocking is not
316 * expected to buy much here: it does not change registers per thread, only
317 * threads per block, so it saves the derivative matrix loads and nothing
318 * else. It is swept rather than assumed because that is a measurement, and
319 * because elem_block<>'s thread clamp already keeps every candidate inside
320 * the shared memory budget at every lx.
321 */
322#define CASE_VECTOR_KSTEP(LX, C) \
323 ax_helm_kernel_vector_kstep<real, LX, NEKO_EB(LX, C)> \
324 <<<NEKO_EB_NBLCKS(*nelv, LX, C), NEKO_EB_NTHRDS(LX, C), 0, stream>>> \
325 ((real *) au, (real *) av, (real *) aw, \
326 (real *) u, (real *) v, (real *) w, \
327 (real *) dx, (real *) dy, (real *) dz, \
328 (real *) h1, (real *) g11, (real *) g22, \
329 (real *) g33, (real *) g12, (real *) g13, \
330 (real *) g23, *nelv); \
331 CUDA_CHECK(cudaGetLastError());
332
333#define CASE_VECTOR_KSTEP_PADDED(LX, C) \
334 ax_helm_kernel_vector_kstep_padded<real, LX, NEKO_EB(LX, C)> \
335 <<<NEKO_EB_NBLCKS(*nelv, LX, C), NEKO_EB_NTHRDS(LX, C), 0, stream>>> \
336 ((real *) au, (real *) av, (real *) aw, \
337 (real *) u, (real *) v, (real *) w, \
338 (real *) dx, (real *) dy, (real *) dz, \
339 (real *) h1, (real *) g11, (real *) g22, \
340 (real *) g33, (real *) g12, (real *) g13, \
341 (real *) g23, *nelv); \
342 CUDA_CHECK(cudaGetLastError());
343
344/* Runtime dispatch onto the tuned elements per block candidate */
345#define CASE_VECTOR_KSTEP_SEL(LX, SEL) \
346 switch (SEL) { \
347 case 0: CASE_VECTOR_KSTEP(LX, 0); break; \
348 case 1: CASE_VECTOR_KSTEP(LX, 1); break; \
349 default: CASE_VECTOR_KSTEP(LX, 2); break; \
350 }
351
352#define CASE_VECTOR_KSTEP_PADDED_SEL(LX, SEL) \
353 switch (SEL) { \
354 case 0: CASE_VECTOR_KSTEP_PADDED(LX, 0); break; \
355 case 1: CASE_VECTOR_KSTEP_PADDED(LX, 1); break; \
356 default: CASE_VECTOR_KSTEP_PADDED(LX, 2); break; \
357 }
358
359#define CASE_VECTOR_DMMA(LX, C) \
360 ax_helm_kernel_dmma_vector<real, LX, NEKO_DMMA_NW(C)> \
361 <<<nblcks_dmma, NEKO_DMMA_NTHRDS(C), 0, stream>>> \
362 ((real *) au, (real *) av, (real *) aw, \
363 (real *) u, (real *) v, (real *) w, \
364 (real *) dx, (real *) dy, (real *) dz, \
365 (real *) h1, (real *) g11, (real *) g22, \
366 (real *) g33, (real *) g12, (real *) g13, \
367 (real *) g23); \
368 CUDA_CHECK(cudaGetLastError());
369
370/* Runtime dispatch onto the tuned warps per block candidate */
371#define CASE_VECTOR_DMMA_SEL(LX, SEL) \
372 switch (SEL) { \
373 case 0: CASE_VECTOR_DMMA(LX, 0); break; \
374 case 1: CASE_VECTOR_DMMA(LX, 1); break; \
375 default: CASE_VECTOR_DMMA(LX, 2); break; \
376 }
377
378/* The TMA staged vector variant, same grid and candidates as
379 CASE_VECTOR_DMMA; see dmma_tma_kernel.h */
380#define CASE_VECTOR_DMMA_TMA(LX, C) \
381 ax_helm_kernel_dmma_tma_vector<real, LX, NEKO_DMMA_NW(C)> \
382 <<<nblcks_dmma, NEKO_DMMA_NTHRDS(C), 0, stream>>> \
383 ((real *) au, (real *) av, (real *) aw, \
384 (real *) u, (real *) v, (real *) w, \
385 (real *) dx, (real *) dy, (real *) dz, \
386 (real *) h1, (real *) g11, (real *) g22, \
387 (real *) g33, (real *) g12, (real *) g13, \
388 (real *) g23); \
389 CUDA_CHECK(cudaGetLastError());
390
391/* Runtime dispatch onto the tuned warps per block candidate */
392#define CASE_VECTOR_DMMA_TMA_SEL(LX, SEL) \
393 switch (SEL) { \
394 case 0: CASE_VECTOR_DMMA_TMA(LX, 0); break; \
395 case 1: CASE_VECTOR_DMMA_TMA(LX, 1); break; \
396 default: CASE_VECTOR_DMMA_TMA(LX, 2); break; \
397 }
398
399/*
400 * The batched TMA variant. Unlike every other launch here it carries a dynamic
401 * shared memory allocation -- 54800 B, past the 48 kB a block gets for free --
402 * which the kernel has to opt into once before its first launch; see
403 * ax_helm_dmma_tma_batch_optin(), which is a predictable branch after that.
404 */
405#define CASE_VECTOR_DMMA_TMA_BATCH(LX, C) \
406 (void) ax_helm_dmma_tma_batch_optin<real, LX, NEKO_DMMA_NW(C)>(); \
407 ax_helm_kernel_dmma_tma_batch<real, LX, NEKO_DMMA_NW(C)> \
408 <<<nblcks_dmma, NEKO_DMMA_NTHRDS(C), \
409 NEKO_DMMA_TMA_BATCH_SMEM, stream>>> \
410 ((real *) au, (real *) av, (real *) aw, \
411 (real *) u, (real *) v, (real *) w, \
412 (real *) dx, (real *) dy, (real *) dz, \
413 (real *) h1, (real *) g11, (real *) g22, \
414 (real *) g33, (real *) g12, (real *) g13, \
415 (real *) g23); \
416 CUDA_CHECK(cudaGetLastError());
417
418/* Runtime dispatch onto the tuned warps per block candidate */
419#define CASE_VECTOR_DMMA_TMA_BATCH_SEL(LX, SEL) \
420 switch (SEL) { \
421 case 0: CASE_VECTOR_DMMA_TMA_BATCH(LX, 0); break; \
422 case 1: CASE_VECTOR_DMMA_TMA_BATCH(LX, 1); break; \
423 default: CASE_VECTOR_DMMA_TMA_BATCH(LX, 2); break; \
424 }
425
426#define CASE_VECTOR(LX) \
427 case LX: \
428 if (autotune_vec[LX] == 0 ) { \
429 autotune_vec[LX] = tune_vector<LX>(au, av, aw, u, v, w, \
430 dx, dy, dz, h1, \
431 g11, g22, g33, g12, g13, g23, \
432 nelv, lx, &autotune_vec_eb[LX], \
433 &autotune_vec_nw[LX], \
434 &autotune_vec_tw[LX], \
435 &autotune_vec_bw[LX]); \
436 } else if (autotune_vec[LX] == 2 ) { \
437 CASE_VECTOR_KSTEP_SEL(LX, autotune_vec_eb[LX]); \
438 } else if (autotune_vec[LX] == 3 ) { \
439 CASE_VECTOR_DMMA_SEL(LX, autotune_vec_nw[LX]); \
440 } else if (autotune_vec[LX] == 4 ) { \
441 CASE_VECTOR_DMMA_TMA_SEL(LX, autotune_vec_tw[LX]); \
442 } else if (autotune_vec[LX] == 5 ) { \
443 CASE_VECTOR_DMMA_TMA_BATCH_SEL(LX, autotune_vec_bw[LX]); \
444 } \
445 break
446
447#define CASE_VECTOR_PADDED(LX) \
448 case LX: \
449 if (autotune_vec[LX] == 0 ) { \
450 autotune_vec[LX] = tune_vector_padded<LX>(au, av, aw, u, v, w, \
451 dx, dy, dz, h1, \
452 g11, g22, g33, \
453 g12, g13, g23, \
454 nelv, lx, \
455 &autotune_vec_eb[LX], \
456 &autotune_vec_nw[LX], \
457 &autotune_vec_tw[LX], \
458 &autotune_vec_bw[LX]); \
459 } else if (autotune_vec[LX] == 2 ) { \
460 CASE_VECTOR_KSTEP_PADDED_SEL(LX, autotune_vec_eb[LX]); \
461 } else if (autotune_vec[LX] == 3 ) { \
462 CASE_VECTOR_DMMA_SEL(LX, autotune_vec_nw[LX]); \
463 } else if (autotune_vec[LX] == 4 ) { \
464 CASE_VECTOR_DMMA_TMA_SEL(LX, autotune_vec_tw[LX]); \
465 } else if (autotune_vec[LX] == 5 ) { \
466 CASE_VECTOR_DMMA_TMA_BATCH_SEL(LX, autotune_vec_bw[LX]); \
467 } \
468 break
469
470 switch(*lx) {
471 CASE_VECTOR(2);
472 CASE_VECTOR(3);
474 CASE_VECTOR(5);
475 CASE_VECTOR(6);
476 CASE_VECTOR(7);
478 CASE_VECTOR(9);
479 CASE_VECTOR(10);
480 CASE_VECTOR(11);
481 CASE_VECTOR(12);
482 CASE_VECTOR(13);
483 CASE_VECTOR(14);
484 CASE_VECTOR(15);
486 default:
487 {
488 fprintf(stderr, __FILE__ ": size not supported: %d\n", *lx);
489 exit(1);
490 }
491 }
492 }
493
497 void cuda_ax_helm_vector_part2(void *au, void *av, void *aw,
498 void *u, void *v, void *w,
499 void *h2, void *B, int *n) {
500
501 const dim3 nthrds(1024, 1, 1);
502 const dim3 nblcks(((*n)+1024 - 1)/ 1024, 1, 1);
503 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
504
506 <<<nblcks, nthrds, 0, stream>>> ((real *) au, (real *) av, (real *) aw,
507 (real *) u, (real *) v, (real *) w,
508 (real *) h2, (real *) B, *n);
509 }
510}
511
512template < const int LX >
513int tune(void *w, void *u, void *dx, void *dy, void *dz,
514 void *dxt, void *dyt, void *dzt, void *h1,
515 void *g11, void *g22, void *g33, void *g12,
516 void *g13, void *g23, int *nelv, int *lx,
517 int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel) {
520 int best1 = 0;
523 int best3 = 0;
525 int best4 = 0;
526 const int rounds = neko_tune_rounds();
527 const int iters = neko_tune_iters();
528 const int sweep = neko_eb_sweep();
529 const bool dmma = dmma_lx_supported<LX>() && cuda_have_dmma();
530 /* Whether the pointers are bulk copy aligned is a property of this call
531 rather than of the kernel, so it is checked rather than assumed, see
532 dmma_tma_aligned() in dmma_tma_kernel.h */
533 const bool tma = dmma_tma_lx_supported<LX>() && cuda_have_tma() &&
535 int best = 0;
536 int retval;
537
538 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
540 }
541 for (int c = 0; c < NEKO_CHUNKS_CANDIDATES; c++) {
543 }
544 for (int c = 0; c < NEKO_DMMA_CANDIDATES; c++) {
547 }
548
549 const dim3 nblcks_1d((*nelv), 1, 1);
550 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
551
552 char *env_value = NULL;
553 char neko_log_buf[80];
554
555 env_value=getenv("NEKO_AUTOTUNE");
556
557 sprintf(neko_log_buf, "Autotune Ax helm (lx: %d)", *lx);
559
560 *eb_sel = 0;
561 *ch_sel = 0;
562 *tw_sel = 0;
563
564 if(env_value) {
565 if( !strcmp(env_value,"1D") ) {
568 sprintf(neko_log_buf,"Set by env : 1 (1D, %d chunk)",
572 return 1;
573 } else if( !strcmp(env_value,"KSTEP") ) {
574 const int c = neko_eb_env();
575 *eb_sel = c;
576 CASE_KSTEP_SEL(LX, c);
577 sprintf(neko_log_buf,"Set by env : 2 (KSTEP, %d elem/block)",
578 NEKO_EB_SEL(LX, c));
581 return 2;
582 } else if( !strcmp(env_value,"DMMA") ) {
583 if (dmma) {
584 const int c = neko_dmma_env();
585 *nw_sel = c;
586 CASE_DMMA_SEL(LX, c);
587 sprintf(neko_log_buf,"Set by env : 3 (DMMA, %d warps)",
588 NEKO_DMMA_NW(c));
591 return 3;
592 } else {
593 sprintf(neko_log_buf, "DMMA strategy not available for this config");
595 }
596 } else if( !strcmp(env_value,"DMMA_TMA") ) {
597 if (tma) {
598 const int c = neko_dmma_tma_env();
599 *tw_sel = c;
601 sprintf(neko_log_buf,"Set by env : 4 (DMMA_TMA, %d warps)",
602 NEKO_DMMA_NW(c));
605 return 4;
606 } else {
608 "DMMA_TMA strategy not available for this config");
610 }
611 } else {
612 sprintf(neko_log_buf, "Invalid value set for NEKO_AUTOTUNE");
614 }
615 }
616
619
620 /* Warm every variant before timing anything: each specialisation has to
621 be resident and the clocks at steady state, or whichever variant is
622 timed first is measured on a colder part */
623 for (int i = 0; i < NEKO_TUNE_WARMUP; i++) {
624 CASE_1D(LX, 0);
625 CASE_1D(LX, 1);
626 CASE_1D(LX, 2);
627 CASE_1D(LX, 3);
628 CASE_KSTEP(LX, 0);
629 if (sweep) {
630 CASE_KSTEP(LX, 1);
631 CASE_KSTEP(LX, 2);
632 }
633 if (dmma) {
634 CASE_DMMA(LX, 0);
635 CASE_DMMA(LX, 1);
636 CASE_DMMA(LX, 2);
637 }
638 if (tma) {
639 CASE_DMMA_TMA(LX, 0);
640 CASE_DMMA_TMA(LX, 1);
641 CASE_DMMA_TMA(LX, 2);
642 }
643 }
644
645 /* Interleaved rounds, best time per variant: timing them one after another
646 in a fixed order lets clock drift bias the comparison by position */
647 for (int r = 0; r < rounds; r++) {
653 if (sweep) {
656 }
657 if (dmma) {
661 }
662 if (tma) {
666 }
667 }
668
672
677 *eb_sel = best;
678 *ch_sel = best1;
679 *nw_sel = best3;
680 *tw_sel = best4;
681
682 if (time1[best1] < time2[best]) {
683 retval = 1;
684 } else {
685 retval = 2;
686 }
687
688 /* The dmma variants join the comparison only where they exist, their
689 candidates are left at NEKO_TUNE_INIT otherwise */
690 float tbest = (retval == 1) ? time1[best1] : time2[best];
691
692 if (time3[best3] < tbest) {
693 retval = 3;
694 tbest = time3[best3];
695 }
696 if (time4[best4] < tbest) {
697 retval = 4;
698 }
699
702
703 /* The tuner stands in for a real Ax evaluation, and the variants do not
704 sum in the same order, so leave the output of the chosen kernel in w */
705 if (retval == 1) {
707 } else if (retval == 2) {
709 } else if (retval == 3) {
711 } else {
713 }
714
715 if (retval == 1) {
716 sprintf(neko_log_buf, "Chose : 1 (1D, %d chunk)",
718 } else if (retval == 2) {
719 sprintf(neko_log_buf, "Chose : 2 (KSTEP, %d elem/block)",
721 } else if (retval == 3) {
722 sprintf(neko_log_buf, "Chose : 3 (DMMA, %d warps, %d elem/blk)",
724 } else {
725 sprintf(neko_log_buf, "Chose : 4 (DMMA_TMA, %d warps)",
727 }
730 return retval;
731}
732
733template < const int LX >
734int tune_padded(void *w, void *u, void *dx, void *dy, void *dz,
735 void *dxt, void *dyt, void *dzt, void *h1,
736 void *g11, void *g22, void *g33, void *g12,
737 void *g13, void *g23, int *nelv, int *lx,
738 int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel) {
741 int best1 = 0;
744 int best3 = 0;
746 int best4 = 0;
747 const int rounds = neko_tune_rounds();
748 const int iters = neko_tune_iters();
749 const int sweep = neko_eb_sweep();
750 const bool dmma = dmma_lx_supported<LX>() && cuda_have_dmma();
751 /* Whether the pointers are bulk copy aligned is a property of this call
752 rather than of the kernel, so it is checked rather than assumed, see
753 dmma_tma_aligned() in dmma_tma_kernel.h */
754 const bool tma = dmma_tma_lx_supported<LX>() && cuda_have_tma() &&
756 int best = 0;
757 int retval;
758
759 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
761 }
762 for (int c = 0; c < NEKO_CHUNKS_CANDIDATES; c++) {
764 }
765 for (int c = 0; c < NEKO_DMMA_CANDIDATES; c++) {
768 }
769
770 const dim3 nblcks_1d((*nelv), 1, 1);
771 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
772
773 char *env_value = NULL;
774 char neko_log_buf[80];
775
776 env_value=getenv("NEKO_AUTOTUNE");
777
778 sprintf(neko_log_buf, "Autotune Ax helm (lx: %d)", *lx);
780
781 *eb_sel = 0;
782 *ch_sel = 0;
783 *tw_sel = 0;
784
785 if(env_value) {
786 if( !strcmp(env_value,"1D") ) {
789 sprintf(neko_log_buf,"Set by env : 1 (1D, %d chunk)",
793 return 1;
794 } else if( !strcmp(env_value,"KSTEP") ) {
795 const int c = neko_eb_env();
796 *eb_sel = c;
798 sprintf(neko_log_buf,"Set by env : 2 (KSTEP, %d elem/block)",
799 NEKO_EB_SEL(LX, c));
802 return 2;
803 } else if( !strcmp(env_value,"DMMA") ) {
804 if (dmma) {
805 const int c = neko_dmma_env();
806 *nw_sel = c;
807 CASE_DMMA_SEL(LX, c);
808 sprintf(neko_log_buf,"Set by env : 3 (DMMA, %d warps)",
809 NEKO_DMMA_NW(c));
812 return 3;
813 } else {
814 sprintf(neko_log_buf, "DMMA strategy not available for this config");
816 }
817 } else if( !strcmp(env_value,"DMMA_TMA") ) {
818 if (tma) {
819 const int c = neko_dmma_tma_env();
820 *tw_sel = c;
822 sprintf(neko_log_buf,"Set by env : 4 (DMMA_TMA, %d warps)",
823 NEKO_DMMA_NW(c));
826 return 4;
827 } else {
829 "DMMA_TMA strategy not available for this config");
831 }
832 } else {
833 sprintf(neko_log_buf, "Invalid value set for NEKO_AUTOTUNE");
835 }
836 }
837
840
841 /* Warm every variant before timing anything: each specialisation has to
842 be resident and the clocks at steady state, or whichever variant is
843 timed first is measured on a colder part */
844 for (int i = 0; i < NEKO_TUNE_WARMUP; i++) {
845 CASE_1D(LX, 0);
846 CASE_1D(LX, 1);
847 CASE_1D(LX, 2);
848 CASE_1D(LX, 3);
850 if (sweep) {
853 }
854 if (dmma) {
855 CASE_DMMA(LX, 0);
856 CASE_DMMA(LX, 1);
857 CASE_DMMA(LX, 2);
858 }
859 if (tma) {
860 CASE_DMMA_TMA(LX, 0);
861 CASE_DMMA_TMA(LX, 1);
862 CASE_DMMA_TMA(LX, 2);
863 }
864 }
865
866 /* Interleaved rounds, best time per variant: timing them one after another
867 in a fixed order lets clock drift bias the comparison by position */
868 for (int r = 0; r < rounds; r++) {
874 if (sweep) {
877 }
878 if (dmma) {
882 }
883 if (tma) {
887 }
888 }
889
893
898 *eb_sel = best;
899 *ch_sel = best1;
900 *nw_sel = best3;
901 *tw_sel = best4;
902
903 if (time1[best1] < time2[best]) {
904 retval = 1;
905 } else {
906 retval = 2;
907 }
908
909 /* The dmma variants join the comparison only where they exist, their
910 candidates are left at NEKO_TUNE_INIT otherwise */
911 float tbest = (retval == 1) ? time1[best1] : time2[best];
912
913 if (time3[best3] < tbest) {
914 retval = 3;
915 tbest = time3[best3];
916 }
917 if (time4[best4] < tbest) {
918 retval = 4;
919 }
920
923
924 /* Leave the output of the chosen kernel in w, see tune() */
925 if (retval == 1) {
927 } else if (retval == 2) {
929 } else if (retval == 3) {
931 } else {
933 }
934
935 if (retval == 1) {
936 sprintf(neko_log_buf, "Chose : 1 (1D, %d chunk)",
938 } else if (retval == 2) {
939 sprintf(neko_log_buf, "Chose : 2 (KSTEP, %d elem/block)",
941 } else if (retval == 3) {
942 sprintf(neko_log_buf, "Chose : 3 (DMMA, %d warps, %d elem/blk)",
944 } else {
945 sprintf(neko_log_buf, "Chose : 4 (DMMA_TMA, %d warps)",
947 }
950 return retval;
951}
952
953
954/*
955 * Autotuner for the vector Ax
956 *
957 * The vector operator has no 1d variant, so the sweep is the elements per
958 * block candidates of the kstep variant against the warps per block
959 * candidates of the dmma variant -- the same two dimensions the scalar tuner
960 * sweeps, and the same shape as the HIP vector tuner. See the note at the top
961 * of ax_helm_kernel.h for why blocking is not expected to pay here, and why
962 * it is measured rather than assumed. Sampling follows the scalar tuner:
963 * interleaved rounds, best round per candidate.
964 *
965 * @note The section title has to fit the 30 character header field in
966 * log_section(), which truncates rather than wraps -- hence "Ax vector"
967 * rather than the "Ax helm vector" it reads as.
968 */
969template < const int LX >
970int tune_vector(void *au, void *av, void *aw, void *u, void *v, void *w,
971 void *dx, void *dy, void *dz, void *h1,
972 void *g11, void *g22, void *g33, void *g12,
973 void *g13, void *g23, int *nelv, int *lx,
974 int *eb_sel, int *nw_sel, int *tw_sel,
975 int *bw_sel) {
978 int best2 = 0;
980 int best3 = 0;
982 int best4 = 0;
984 int best5 = 0;
985 const int rounds = neko_tune_rounds();
986 const int iters = neko_tune_iters();
987 const int sweep = neko_eb_sweep();
989 /* Whether the pointers are bulk copy aligned is a property of this call
990 rather than of the kernel, see dmma_tma_vector_aligned() */
993 g11, g22, g33, g12, g13, g23);
994 /* Same pointers, and additionally the device has to grant the block the
995 dynamic allocation, see cuda_have_tma_batch() */
998 g11, g22, g33,
999 g12, g13, g23);
1000 int retval;
1001
1002 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
1003 time2[c] = NEKO_TUNE_INIT;
1004 }
1005 for (int c = 0; c < NEKO_DMMA_CANDIDATES; c++) {
1006 time3[c] = NEKO_TUNE_INIT;
1007 time4[c] = NEKO_TUNE_INIT;
1008 time5[c] = NEKO_TUNE_INIT;
1009 }
1010
1011 const dim3 nblcks_dmma((*nelv), 1, 1);
1012 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
1013
1014 char *env_value = NULL;
1015 char neko_log_buf[80];
1016
1017 env_value=getenv("NEKO_AUTOTUNE");
1018
1019 sprintf(neko_log_buf, "Autotune Ax vector (lx: %d)", *lx);
1021
1022 *nw_sel = 0;
1023 *tw_sel = 0;
1024 *bw_sel = 0;
1025
1026 if(env_value) {
1027 if( !strcmp(env_value,"KSTEP") || !strcmp(env_value,"1D") ) {
1028 /* No 1d variant here, so either pin lands on kstep */
1029 const int c = neko_eb_env();
1030 *eb_sel = c;
1032 sprintf(neko_log_buf,"Set by env : 2 (KSTEP, %d elem/block)",
1033 NEKO_EB_SEL(LX, c));
1036 return 2;
1037 } else if( !strcmp(env_value,"DMMA") ) {
1038 if (dmma) {
1039 const int c = neko_dmma_env();
1040 *nw_sel = c;
1042 sprintf(neko_log_buf,"Set by env : 3 (DMMA, %d warps)",
1043 NEKO_DMMA_NW(c));
1046 return 3;
1047 } else {
1048 sprintf(neko_log_buf, "DMMA strategy not available for this config");
1050 }
1051 } else if( !strcmp(env_value,"DMMA_TMA") ) {
1052 if (tma) {
1053 const int c = neko_dmma_tma_env();
1054 *tw_sel = c;
1056 sprintf(neko_log_buf,"Set by env : 4 (DMMA_TMA, %d warps)",
1057 NEKO_DMMA_NW(c));
1060 return 4;
1061 } else {
1063 "DMMA_TMA strategy not available for this config");
1065 }
1066 } else if( !strcmp(env_value,"DMMA_TMA_BATCH") ) {
1067 if (batch) {
1068 const int c = neko_dmma_tma_env();
1069 *bw_sel = c;
1071 sprintf(neko_log_buf,"Set by env : 5 (DMMA_TMA_BATCH, %d warps)",
1072 NEKO_DMMA_NW(c));
1075 return 5;
1076 } else {
1078 "DMMA_TMA_BATCH strategy not available for this config");
1080 }
1081 } else {
1082 sprintf(neko_log_buf, "Invalid value set for NEKO_AUTOTUNE");
1084 }
1085 }
1086
1089
1090 /* Warm every variant before timing anything, see tune() */
1091 for (int i = 0; i < NEKO_TUNE_WARMUP; i++) {
1093 if (sweep) {
1096 }
1097 if (dmma) {
1098 CASE_VECTOR_DMMA(LX, 0);
1099 CASE_VECTOR_DMMA(LX, 1);
1100 CASE_VECTOR_DMMA(LX, 2);
1101 }
1102 if (tma) {
1106 }
1107 if (batch) {
1111 }
1112 }
1113
1114 for (int r = 0; r < rounds; r++) {
1116 if (sweep) {
1119 }
1120 if (dmma) {
1124 }
1125 if (tma) {
1129 }
1130 if (batch) {
1134 }
1135 }
1136
1137 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
1138 if (time2[c] >= NEKO_TUNE_INIT) { continue; }
1139 sprintf(neko_log_buf, "KSTEP eb=%-4d: %9.2f us/call",
1142 }
1146
1151 *eb_sel = best2;
1152 *nw_sel = best3;
1153 *tw_sel = best4;
1154 *bw_sel = best5;
1155
1156 /* The dmma variants join the comparison only where they exist, their
1157 candidates are left at NEKO_TUNE_INIT otherwise */
1158 float tbest = time2[best2];
1159
1160 retval = 2;
1161 if (time3[best3] < tbest) { retval = 3; tbest = time3[best3]; }
1162 if (time4[best4] < tbest) { retval = 4; tbest = time4[best4]; }
1163 if (time5[best5] < tbest) { retval = 5; }
1164
1167
1168 /* The tuner stands in for a real Ax evaluation, and the variants do not
1169 sum in the same order, so leave the output of the chosen kernel in
1170 au, av and aw */
1171 if (retval == 2) {
1173 sprintf(neko_log_buf, "Chose : 2 (KSTEP, %d elem/block)",
1174 NEKO_EB_SEL(LX, best2));
1175 } else if (retval == 3) {
1177 sprintf(neko_log_buf, "Chose : 3 (DMMA, %d warps, %d elem/blk)",
1179 } else if (retval == 4) {
1181 sprintf(neko_log_buf, "Chose : 4 (DMMA_TMA, %d warps)",
1183 } else {
1185 sprintf(neko_log_buf, "Chose : 5 (DMMA_TMA_BATCH, %d warps)",
1187 }
1190 return retval;
1191}
1192
1193/* Padded variant of tune_vector(), see the note on bank conflicts above */
1194template < const int LX >
1195int tune_vector_padded(void *au, void *av, void *aw, void *u, void *v, void *w,
1196 void *dx, void *dy, void *dz, void *h1,
1197 void *g11, void *g22, void *g33, void *g12,
1198 void *g13, void *g23, int *nelv, int *lx,
1199 int *eb_sel, int *nw_sel, int *tw_sel,
1200 int *bw_sel) {
1203 int best2 = 0;
1205 int best3 = 0;
1207 int best4 = 0;
1209 int best5 = 0;
1210 const int rounds = neko_tune_rounds();
1211 const int iters = neko_tune_iters();
1212 const int sweep = neko_eb_sweep();
1214 /* Whether the pointers are bulk copy aligned is a property of this call
1215 rather than of the kernel, see dmma_tma_vector_aligned() */
1218 g11, g22, g33, g12, g13, g23);
1219 /* Same pointers, and additionally the device has to grant the block the
1220 dynamic allocation, see cuda_have_tma_batch() */
1222 && dmma_tma_vector_aligned(au, av, aw, u, v, w, h1,
1223 g11, g22, g33,
1224 g12, g13, g23);
1225 int retval;
1226
1227 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
1228 time2[c] = NEKO_TUNE_INIT;
1229 }
1230 for (int c = 0; c < NEKO_DMMA_CANDIDATES; c++) {
1231 time3[c] = NEKO_TUNE_INIT;
1232 time4[c] = NEKO_TUNE_INIT;
1233 time5[c] = NEKO_TUNE_INIT;
1234 }
1235
1236 const dim3 nblcks_dmma((*nelv), 1, 1);
1237 const cudaStream_t stream = (cudaStream_t) glb_cmd_queue;
1238
1239 char *env_value = NULL;
1240 char neko_log_buf[80];
1241
1242 env_value=getenv("NEKO_AUTOTUNE");
1243
1244 sprintf(neko_log_buf, "Autotune Ax vector (lx: %d)", *lx);
1246
1247 *nw_sel = 0;
1248 *tw_sel = 0;
1249 *bw_sel = 0;
1250
1251 if(env_value) {
1252 if( !strcmp(env_value,"KSTEP") || !strcmp(env_value,"1D") ) {
1253 /* No 1d variant here, so either pin lands on kstep */
1254 const int c = neko_eb_env();
1255 *eb_sel = c;
1257 sprintf(neko_log_buf,"Set by env : 2 (KSTEP, %d elem/block)",
1258 NEKO_EB_SEL(LX, c));
1261 return 2;
1262 } else if( !strcmp(env_value,"DMMA") ) {
1263 if (dmma) {
1264 const int c = neko_dmma_env();
1265 *nw_sel = c;
1267 sprintf(neko_log_buf,"Set by env : 3 (DMMA, %d warps)",
1268 NEKO_DMMA_NW(c));
1271 return 3;
1272 } else {
1273 sprintf(neko_log_buf, "DMMA strategy not available for this config");
1275 }
1276 } else if( !strcmp(env_value,"DMMA_TMA") ) {
1277 if (tma) {
1278 const int c = neko_dmma_tma_env();
1279 *tw_sel = c;
1281 sprintf(neko_log_buf,"Set by env : 4 (DMMA_TMA, %d warps)",
1282 NEKO_DMMA_NW(c));
1285 return 4;
1286 } else {
1288 "DMMA_TMA strategy not available for this config");
1290 }
1291 } else if( !strcmp(env_value,"DMMA_TMA_BATCH") ) {
1292 if (batch) {
1293 const int c = neko_dmma_tma_env();
1294 *bw_sel = c;
1296 sprintf(neko_log_buf,"Set by env : 5 (DMMA_TMA_BATCH, %d warps)",
1297 NEKO_DMMA_NW(c));
1300 return 5;
1301 } else {
1303 "DMMA_TMA_BATCH strategy not available for this config");
1305 }
1306 } else {
1307 sprintf(neko_log_buf, "Invalid value set for NEKO_AUTOTUNE");
1309 }
1310 }
1311
1314
1315 /* Warm every variant before timing anything, see tune() */
1316 for (int i = 0; i < NEKO_TUNE_WARMUP; i++) {
1318 if (sweep) {
1321 }
1322 if (dmma) {
1323 CASE_VECTOR_DMMA(LX, 0);
1324 CASE_VECTOR_DMMA(LX, 1);
1325 CASE_VECTOR_DMMA(LX, 2);
1326 }
1327 if (tma) {
1331 }
1332 if (batch) {
1336 }
1337 }
1338
1339 for (int r = 0; r < rounds; r++) {
1341 if (sweep) {
1344 }
1345 if (dmma) {
1349 }
1350 if (tma) {
1354 }
1355 if (batch) {
1359 }
1360 }
1361
1362 for (int c = 0; c < NEKO_EB_CANDIDATES; c++) {
1363 if (time2[c] >= NEKO_TUNE_INIT) { continue; }
1364 sprintf(neko_log_buf, "KSTEP eb=%-4d: %9.2f us/call",
1367 }
1371
1376 *eb_sel = best2;
1377 *nw_sel = best3;
1378 *tw_sel = best4;
1379 *bw_sel = best5;
1380
1381 /* The dmma variants join the comparison only where they exist, their
1382 candidates are left at NEKO_TUNE_INIT otherwise */
1383 float tbest = time2[best2];
1384
1385 retval = 2;
1386 if (time3[best3] < tbest) { retval = 3; tbest = time3[best3]; }
1387 if (time4[best4] < tbest) { retval = 4; tbest = time4[best4]; }
1388 if (time5[best5] < tbest) { retval = 5; }
1389
1392
1393 /* Leave the output of the chosen kernel in au, av and aw, see tune() */
1394 if (retval == 2) {
1396 sprintf(neko_log_buf, "Chose : 2 (KSTEP, %d elem/block)",
1397 NEKO_EB_SEL(LX, best2));
1398 } else if (retval == 3) {
1400 sprintf(neko_log_buf, "Chose : 3 (DMMA, %d warps, %d elem/blk)",
1402 } else if (retval == 4) {
1404 sprintf(neko_log_buf, "Chose : 4 (DMMA_TMA, %d warps)",
1406 } else {
1408 sprintf(neko_log_buf, "Chose : 5 (DMMA_TMA_BATCH, %d warps)",
1410 }
1413 return retval;
1414}
#define CASE_DMMA(LX, C)
#define CASE_VECTOR_DMMA(LX, C)
#define CASE_VECTOR(LX)
#define CASE_DMMA_SEL(LX, SEL)
#define CASE_KSTEP_SEL(LX, SEL)
void cuda_ax_helm_vector_part2(void *au, void *av, void *aw, void *u, void *v, void *w, void *h2, void *B, int *n)
Definition ax_helm.cu:497
#define CASE(LX)
#define CASE_1D_SEL(LX, SEL)
int tune_vector(void *au, void *av, void *aw, void *u, void *v, void *w, void *dx, void *dy, void *dz, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx, int *eb_sel, int *nw_sel, int *tw_sel, int *bw_sel)
Definition ax_helm.cu:970
#define CASE_VECTOR_KSTEP(LX, C)
void cuda_ax_helm(void *w, void *u, void *dx, void *dy, void *dz, void *dxt, void *dyt, void *dzt, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx)
Definition ax_helm.cu:82
int tune_padded(void *w, void *u, void *dx, void *dy, void *dz, void *dxt, void *dyt, void *dzt, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx, int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel)
Definition ax_helm.cu:734
#define CASE_PADDED(LX)
void cuda_ax_helm_vector(void *au, void *av, void *aw, void *u, void *v, void *w, void *dx, void *dy, void *dz, void *dxt, void *dyt, void *dzt, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx)
Definition ax_helm.cu:288
#define CASE_KSTEP(LX, C)
#define CASE_KSTEP_PADDED_SEL(LX, SEL)
#define CASE_LARGE(LX)
#define CASE_DMMA_TMA_SEL(LX, SEL)
#define CASE_VECTOR_DMMA_TMA_BATCH(LX, C)
#define CASE_LARGE_PADDED(LX)
#define CASE_VECTOR_KSTEP_PADDED(LX, C)
#define CASE_VECTOR_DMMA_TMA_SEL(LX, SEL)
int tune(void *w, void *u, void *dx, void *dy, void *dz, void *dxt, void *dyt, void *dzt, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx, int *eb_sel, int *ch_sel, int *nw_sel, int *tw_sel)
Definition ax_helm.cu:513
#define CASE_DMMA_TMA(LX, C)
#define CASE_1D(LX, C)
#define CASE_VECTOR_KSTEP_SEL(LX, SEL)
#define CASE_VECTOR_PADDED(LX)
#define CASE_VECTOR_KSTEP_PADDED_SEL(LX, SEL)
#define CASE_VECTOR_DMMA_TMA(LX, C)
#define CASE_KSTEP_PADDED(LX, C)
#define CASE_VECTOR_DMMA_TMA_BATCH_SEL(LX, SEL)
#define CASE_VECTOR_DMMA_SEL(LX, SEL)
int tune_vector_padded(void *au, void *av, void *aw, void *u, void *v, void *w, void *dx, void *dy, void *dz, void *h1, void *g11, void *g22, void *g33, void *g12, void *g13, void *g23, int *nelv, int *lx, int *eb_sel, int *nw_sel, int *tw_sel, int *bw_sel)
Definition ax_helm.cu:1195
__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)
__global__ void T *__restrict__ T *__restrict__ aw
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ w
const int i
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dz
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dx
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ u
__global__ void T *__restrict__ av
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dy
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ v
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ h1
__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__ const T *__restrict__ const T *__restrict__ const T *__restrict__ g23
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ g22
__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__ const T *__restrict__ const T *__restrict__ g13
__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__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const int nelv
__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__ const T *__restrict__ g12
__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__ g33
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ g11
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dyt
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dzt
__global__ void const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ const T *__restrict__ dxt
#define NEKO_CHUNKS_CANDIDATES
Definition elem_block.h:125
#define NEKO_EB_CANDIDATES
Definition elem_block.h:63
#define NEKO_EB_SEL(LX, SEL)
Definition elem_block.h:108
#define NEKO_CHUNKS_SEL(LX, SEL)
Definition elem_block.h:147
#define NEKO_TUNE_TIME(T, LAUNCH, LX, C, ITERS)
static int neko_eb_env()
#define NEKO_TUNE_US(T, ITERS)
static int neko_tune_rounds()
#define NEKO_TUNE_LOG(LX, T1, T2)
#define NEKO_TUNE_INIT
#define NEKO_TUNE_BEST(T, BEST, N)
static int neko_tune_iters()
static int neko_chunks_env()
static int neko_eb_sweep()
#define NEKO_TUNE_WARMUP
double real
#define NEKO_DMMA_CANDIDATES
static bool cuda_have_dmma()
static int neko_dmma_env()
#define NEKO_DMMA_PACK(LX)
#define NEKO_TUNE_LOG_DMMA(LX, T3)
#define NEKO_DMMA_NW(C)
#define NEKO_TUNE_LOG_DMMA_TMA_BATCH(LX, T5)
static bool dmma_tma_aligned(const void *w, const void *u, const void *h1, const void *g11, const void *g22, const void *g33, const void *g12, const void *g13, const void *g23)
static bool dmma_tma_vector_aligned(const void *au, const void *av, const void *aw, const void *u, const void *v, const void *w, const void *h1, const void *g11, const void *g22, const void *g33, const void *g12, const void *g13, const void *g23)
static bool cuda_have_tma_batch()
#define NEKO_TUNE_LOG_DMMA_TMA(LX, T4)
static int neko_dmma_tma_env()
static bool cuda_have_tma()
void log_error(char *msg)
void log_message(char *msg)
void log_end_section()
void log_section(char *msg)