|
Neko 1.99.9
A portable framework for high-order spectral element flow simulations
|
#include <stdlib.h>#include <stdint.h>#include <stddef.h>#include <cuda_runtime.h>#include <device/device_config.h>#include "dmma_kernel.h"

Go to the source code of this file.
Classes | |
| struct | dmma_tma_batch_smem |
| struct | opgrad_tma_smem |
| struct | conv1_tma_smem |
| #define DMMA_NG 7 |
Tensor Memory Accelerator (TMA) staging for the fp64 tensor core kernels, Hopper only.
The DMMA kernels in dmma_kernel.h stage an element into shared memory and hand the six tensor contractions to the fp64 tensor cores. What they do not do is overlap the staging with the contractions, and the staging is nearly all of the kernel: at lx = 8 an element is nine cubes of 4 kB – the field u, the seven geometric factors h1 and g11..g23, and the result w – of which the seven factors are 78% of the read traffic and are read in a single pointwise pass that sits between two __syncthreads() with nine multiply-adds per point to hide them behind. Nothing else in the block is running while those 28 kB arrive.
This variant issues that traffic up front, as bulk asynchronous copies on two mbarriers: the cube of u on one, waited on immediately, and the seven factor cubes on the other, waited on only at the pointwise step, so they are in flight underneath the first three contractions. The result cube goes back out the same way, one bulk store instead of DMMA_CUBE scalar ones.
The register-hoisting alternative – read the factors into registers before the contractions rather than into shared memory – is already implemented, in ax_helm_dmma_vector_elem(), and measured a loss on GH200 at lx = 8: the factors cost about sixty registers there and give back more occupancy than the overlap wins. Landing them in shared memory instead is the same hoist without the register bill, which is the argument for spending the shared memory here, and is what this variant is for.
It is not free either. Seven extra cubes take the block from 17.5 kB to 45.5 kB, and on an SM with 228 kB that is five resident blocks rather than the eight it takes to fill the 64 warp limit – 62.5% occupancy against 100%. The bet is that TMA replaces the memory level parallelism that the lost warps were providing: five blocks each with eight bulk copies in flight is 160 kB of outstanding traffic per SM, generated by one thread per block rather than by thousands of LDGs. Whether that bet pays is a measurement, so the variant is a tuner candidate like every other one and is never assumed to win.
Scope: lx == DMMA_P, double precision, sm_90.
The lx bound is what makes the cheap TMA path usable at all. A bulk copy moves a contiguous run of bytes, and at lx == DMMA_P a staged cube is the element's contiguous global chunk – dmma_pack< LX, 1 >::map() reduces to the identity, so the copy needs no addressing beyond a base pointer and a length. Every smaller lx either strides into the padded cube (PPA == 1) or scatters sub-cubes across it (PPA > 1), neither of which a bulk copy can express; those need cp.async.bulk.tensor and a CUtensorMap. That is not merely more work, it is the wrong tool here: a tensor map is built on the host by cuTensorMapEncodeTiled() and bakes in the base pointer, while u and w are Krylov vectors that change on every Ax call, so the descriptors would have to be re-encoded per call inside the solve. And the only lx values that would need it are the packed ones, where DMMA already measures 40% behind the kstep variant. So the tensor path is deliberately not taken.
Definition at line 101 of file dmma_tma_kernel.h.
| #define DMMA_NG_CONV1 13 |
Definition at line 111 of file dmma_tma_kernel.h.
| #define DMMA_NG_OPGRAD 9 |
Definition at line 107 of file dmma_tma_kernel.h.
| #define NEKO_CONV1_TMA_SMEM ((int) sizeof(conv1_tma_smem)) |
Definition at line 401 of file dmma_tma_kernel.h.
| #define NEKO_DMMA_TMA_BATCH_SMEM ((int) sizeof(dmma_tma_batch_smem)) |
Definition at line 295 of file dmma_tma_kernel.h.
| #define NEKO_OPGRAD_TMA_SMEM ((int) sizeof(opgrad_tma_smem)) |
Definition at line 372 of file dmma_tma_kernel.h.
| #define NEKO_TMA_TOOLKIT 0 |
Definition at line 122 of file dmma_tma_kernel.h.
Definition at line 580 of file dmma_tma_kernel.h.
Definition at line 567 of file dmma_tma_kernel.h.
Returns true if the current device has a TMA engine and this build can actually reach it. Result is cached after the first query.
Definition at line 165 of file dmma_tma_kernel.h.


Definition at line 337 of file dmma_tma_kernel.h.


Definition at line 422 of file dmma_tma_kernel.h.


Whether the device will hand a block each of those allocations. opgrad's is byte for byte the batched axhelm one; conv1's is larger and is queried separately rather than assumed to follow.
Definition at line 417 of file dmma_tma_kernel.h.


Returns true if the current device will hand a block the batched variant's dynamic allocation. Past 48 kB a block only gets shared memory it has explicitly opted into, and the opt-in ceiling is a device attribute rather than a property of the architecture, so it is queried. Cached.
Definition at line 311 of file dmma_tma_kernel.h.


|
inlinestatic |
Definition at line 455 of file dmma_tma_kernel.h.


Compile-time predicate for the LX values the batched variant supports. Same bound as the other two and written out for the same reason, see dmma_tma_vector_lx_supported().
MUST match NEKO_AX_HELM_DMMA_TMA_BATCH_DISPATCH in ax_helm_kernel.h.
Definition at line 435 of file dmma_tma_kernel.h.

|
inlinestatic |
Definition at line 527 of file dmma_tma_kernel.h.


And for cdtp. Same bound, written out per operator for the same reason.
MUST match NEKO_CDTP_DMMA_TMA_DISPATCH in cdtp_kernel.h.
Definition at line 259 of file dmma_tma_kernel.h.

|
inlinestatic |
Definition at line 537 of file dmma_tma_kernel.h.


|
inlinestatic |
Definition at line 483 of file dmma_tma_kernel.h.


The same predicate for the derivative operator, written out for the same reason: an lx its dispatch does not specialise resolves to a no-op that times as free and wins the tuner. Note that the DMMA bound is NOT written out per operator in the same way – dmma_lx_supported() covers every operator whose dispatch specialises 2..DMMA_P, which dudxyz does.
MUST match NEKO_DUDXYZ_DMMA_TMA_DISPATCH in dudxyz_kernel.h.
Definition at line 229 of file dmma_tma_kernel.h.

Compile-time predicate for the LX values the TMA staging supports, see the scope note above: double precision and lx == DMMA_P exactly.
MUST match NEKO_AX_HELM_DMMA_TMA_DISPATCH in ax_helm_kernel.h. An LX the dispatch does not specialise resolves to the no-op primary template, which times as free and wins the tuner comparison – the same trap documented at dmma_vector_lx_supported().
Definition at line 199 of file dmma_tma_kernel.h.

|
inlinestatic |
Definition at line 493 of file dmma_tma_kernel.h.


|
inlinestatic |
Definition at line 511 of file dmma_tma_kernel.h.


And for opgrad and conv1. Same bound, written out per operator for the same reason as above.
MUST match NEKO_OPGRAD_DMMA_TMA_DISPATCH in opgrad_kernel.h and NEKO_CONV1_DMMA_TMA_DISPATCH in conv1_kernel.h.
Definition at line 242 of file dmma_tma_kernel.h.

A bulk copy requires both of its addresses to be 16 byte aligned and its length to be a multiple of 16, and gives no diagnostic when they are not. The length is DMMA_CUBE doubles and the per element offset is a multiple of DMMA_CUBE, so everything rests on the nine pointers the operator is handed: they are whole device_map()ed fields today and so are allocation aligned, but that is a property of every caller rather than of this kernel, and one caller passing an odd element offset would make the copies silently undefined. Cheap enough to check once per tune and fall back.
Definition at line 450 of file dmma_tma_kernel.h.


|
inlinestatic |
Definition at line 469 of file dmma_tma_kernel.h.


The same predicate for the vector operator. Identical to the scalar bound today, and written out anyway rather than aliased: the pair it mirrors, dmma_lx_supported() and dmma_vector_lx_supported(), are not the same, and an lx the vector dispatch does not specialise silently resolves to a no-op that times as free and wins the tuner.
MUST match NEKO_AX_HELM_DMMA_TMA_VECTOR_DISPATCH in ax_helm_kernel.h.
Definition at line 214 of file dmma_tma_kernel.h.

Definition at line 555 of file dmma_tma_kernel.h.

