Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
elem_block.h
Go to the documentation of this file.
1#ifndef __MATH_ELEM_BLOCK_H__
2#define __MATH_ELEM_BLOCK_H__
3/*
4 Copyright (c) 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
73#ifndef NEKO_EB_WAVE
74#define NEKO_EB_WAVE NEKO_WAVE_SIZE_UNIFORM
75#endif
76
77/* LDS per CU, and the per workgroup maximum, on CDNA */
78#ifndef NEKO_EB_MAX_LDS
79#define NEKO_EB_MAX_LDS 65536
80#endif
81
82#define NEKO_EB_CANDIDATES 3
83
84template< int LX, int C >
85struct elem_block {
86 static const int waves = 2 << C;
87 static const int fit = (NEKO_EB_WAVE * waves)/(LX * LX);
88 static const int value = (C == 0) ? 1 : (fit > 0 ? fit : 1);
89};
90
91/*
92 * Launch bounds.
93 *
94 * HIP's second argument is MIN_WARPS_PER_EXECUTION_UNIT -- minimum wavefronts
95 * resident per SIMD -- and not CUDA's min blocks per SM. The 3 these kernels
96 * have always carried asks for 3 waves per SIMD, i.e. a 512/3 VGPR budget,
97 * and is kept so that widening the block does not silently change the
98 * register allocation. The first argument must track the real block size:
99 * launching more threads than declared is a launch failure, not a slowdown.
100 */
101#ifndef NEKO_EB_MIN_WAVES_EU
102#define NEKO_EB_MIN_WAVES_EU 3
103#endif
104
105#define NEKO_EB_BOUNDS(NT) __launch_bounds__((NT), NEKO_EB_MIN_WAVES_EU)
106
107/*
108 * Launch geometry helpers. NELV is the element count; the grid is sized so
109 * the tail block is partially filled and clamps, rather than the kernel
110 * returning early -- these kernels have __syncthreads() in the k loop, so an
111 * early return would leave the barrier unmatched.
112 */
113#define NEKO_EB(LX, C) (elem_block<LX, C>::value)
114#define NEKO_EB_NTHRDS(LX, C) dim3((LX), (LX), NEKO_EB(LX, C))
115#define NEKO_EB_NBLCKS(NELV, LX, C) \
116 dim3(((NELV) + NEKO_EB(LX, C) - 1)/NEKO_EB(LX, C), 1, 1)
117#define NEKO_EB_SEL(LX, SEL) \
118 ((SEL) == 0 ? NEKO_EB(LX, 0) : (SEL) == 1 ? NEKO_EB(LX, 1) : NEKO_EB(LX, 2))
119
134#define NEKO_CHUNKS_CANDIDATES 4
135
136/*
137 * Candidate C selects 1024 >> C, i.e. 1024, 512, 256, 128. Candidate 0 is the
138 * historical value, so it is always available as an A/B baseline.
139 *
140 * A heuristic is deliberately avoided here. The best chunk depends on how the
141 * shared memory footprint (which grows as LX^3) caps the resident block count
142 * on the target device, and that differs between architectures -- 164 kB per
143 * SM on A100, 228 kB on H100, 64 kB of LDS per CU on CDNA. Picking by thread
144 * utilisation alone gets it wrong from LX = 6 upward, because once the block
145 * count is capped by shared memory a smaller block simply wastes thread slots.
146 * So all four are instantiated and the tuner measures them.
147 */
148template< int LX, int C >
149struct chunk_block {
150 static const int raw = 1024 >> C;
151 static const int value = (raw >= LX * LX) ? raw : 1024;
152};
153
154#define NEKO_CHUNKS(LX, C) (chunk_block<LX, C>::value)
155#define NEKO_CHUNKS_NTHRDS(LX, C) dim3(NEKO_CHUNKS(LX, C), 1, 1)
156#define NEKO_CHUNKS_SEL(LX, SEL) \
157 ((SEL) == 0 ? NEKO_CHUNKS(LX, 0) : (SEL) == 1 ? NEKO_CHUNKS(LX, 1) : \
158 (SEL) == 2 ? NEKO_CHUNKS(LX, 2) : NEKO_CHUNKS(LX, 3))
159
160#endif // __MATH_ELEM_BLOCK_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)
#define NEKO_EB_WAVE
Definition elem_block.h:74
static const int raw
Definition elem_block.h:141
static const int value
Definition elem_block.h:142
static const int waves
Definition elem_block.h:86
static const int fit
Definition elem_block.h:87
static const int value
Definition elem_block.h:68