Add MicroCUDA backend, adaptive output wait, wider native K coverage (improve perf)

Shim
- Adaptive output-event wait: sleep to ~120 us before the predicted
  completion (smoothed per wait site), spin near it, back off when late.
  D4R_SHIM_OUTPUT_POLL_US restores a fixed interval.

- Defer the input-marker wait into the worker thread with VRAM interop
  (D4R_SHIM_DEFER_MARKER, default on), taking the host setup off the
  critical path.

MicroCUDA
- Experimental ZLUDA-free backend in wine_nvcuda_bridge, plus
  tools/microcuda and scripts/build_microcuda.sh. Serves accuracy, fast
  and native kernels; unregistered modules fall back to the reference
  path. Unclassified writes invalidate prepared weights.

M kernels
- SWIN_PREP_IDENTITY_AT: key weight prep by allocation identity
  (MicroCUDA); enc3 tube uses it with 8 slots. ZLUDA ignores it.

- dec2 (gfx1101): SWIN_PACKED_RESIDUAL, byte-identical, ~1.6% faster.

- Opt-in gfx12 hardware fp8 conversion (SWIN_FP8_HWCVT), unverified
  on hardware.

Native K translators
- ctile: handle variants that re-materialize the parameter base (mvlo).

- rewrite_output: check live-in registers, not just outputs.

- build.sh: native input covers all 8 flag variants, output the 4 HDR
  "max" variants; depth-tile skip stays mvhi-only.

Tools
- dump_runner and bench_dlss_kernel harness additions.
This commit is contained in:
ayo committed 2026-10-07 15:54:38 -04:00
1 parent 7c60d53cd0
commit a627439025
20 files changed
+2186 -44

No files matched your search

+4 -2
View File
@@ -1,6 +1,8 @@
// fast numerics: intermediate activations f16 (no FP8 re-quantisation), f32 accumulation through GEMM chains
// RX 7700 XT: memory-clause scheduling at the 192 VGPR cap; byte-identical to the default build, gfx1101 only
// d4r-build-flags-gfx1101: -mllvm -misched=gcn-max-memory-clause
// RX 7700 XT: memory-clause scheduling at the 192 VGPR cap; byte-identical to the default build, gfx1101 only.
// SWIN_PACKED_RESIDUAL (residual kept as already-rounded halves until the output projection): byte-identical,
// -1.6% on the captured dec2 launch (0.768 -> 0.756 ms, 3 alternating reps of 100); enc1/enc2/dec1/tube: no gain
// d4r-build-flags-gfx1101: -mllvm -misched=gcn-max-memory-clause -DSWIN_PACKED_RESIDUAL
#define SWIN_NO_Q8
#define SWIN_F32ACC
#ifndef SWIN_MAX_VGPR
+6 -2
View File
@@ -8,9 +8,13 @@
#define SWIN_MLP_R(NW) 2
#endif
// NGX can recycle a weights address for another tube block after feature
// recreation. Address-only caching then serves stale packed weights. Prepare
// each launch; the default single image is sufficient on the launch stream.
// recreation. Address-only caching then serves stale packed weights, so
// d4r_prep_key_at stays 0 (ZLUDA prepares every launch). MicroCUDA instead keys
// preparation by allocation identity (d4r_prep_identity_at): one image per tube
// weight set (6 per evaluation), re-prepared on any free/reallocation or write.
#define SWIN_PREP_KEY_AT 0
#define SWIN_PREP_IDENTITY_AT 1
#define SWIN_PREP_SLOTS 8
#include "swin_block.h"
#ifndef SWIN_NW
#define SWIN_NW 8
+8 -1
View File
@@ -1050,6 +1050,12 @@ __device__ __forceinline__ void swin_block(const CommonParams& p, const TubePara
#ifndef SWIN_PREP_KEY_AT
#define SWIN_PREP_KEY_AT 1 // weights pointer at offset 0; 0 forces preparation on every launch
#endif
#ifndef SWIN_PREP_IDENTITY_AT
// weights pointer at offset (value - 1) for runtimes that key preparation by allocation identity (pointer +
// allocation generation + write epoch: MicroCUDA), never by address alone; 0 = no such key. Runtimes that only
// know d4r_prep_key_at (ZLUDA) ignore it.
#define SWIN_PREP_IDENTITY_AT 0
#endif
// Optional weight-image slots for several weight sets with stable address identity. The ZLUDA
// hook can run prep only for a weights pointer it has not seen (d4r_prep_key_at / d4r_prep_key_slots);
@@ -1090,13 +1096,14 @@ template <int S> __device__ __forceinline__ int prep_slot_claim(uint64_t* keys,
using NAME##_L = SwinLayout<C, NH, NPM, CIN>; \
constexpr int NAME##_S = SWIN_PREP_SLOTS; \
__device__ wslot g_w16[(NAME##_S + 1) * NAME##_L::TOTAL]; \
__device__ uint64_t g_prep_keys[NAME##_S + 1]; \
extern "C" __device__ __attribute__((used)) uint64_t g_prep_keys[NAME##_S + 1] = {}; \
__constant__ SwinDescs<C, NH, NPM, CIN> g_descs = make_descs<C, NH, NPM, CIN>(); \
extern "C" __device__ __attribute__((used)) uint32_t d4r_block_z = NWAVES; \
extern "C" __device__ __attribute__((used)) uint32_t d4r_prep_blocks = (NAME##_L::TOTAL + 127) / 128; \
/* enc3 disables address-only reuse: a recreated feature may recycle a weights address */ \
extern "C" __device__ __attribute__((used)) uint32_t d4r_prep_key_at = SWIN_PREP_KEY_AT; \
extern "C" __device__ __attribute__((used)) uint32_t d4r_prep_key_slots = NAME##_S; \
extern "C" __device__ __attribute__((used)) uint32_t d4r_prep_identity_at = SWIN_PREP_IDENTITY_AT; \
extern "C" __global__ void __launch_bounds__(128) NAME##_prep(PARAMS p) \
{ \
const int idx = blockIdx.x * 128 + threadIdx.x; \
+14
View File
@@ -337,6 +337,20 @@ __device__ __forceinline__ sop lds16(const half_t* p)
// e4m3 bytes of an f16 operand whose values are e4m3 values (K order kept: byte j = element j)
__device__ __forceinline__ gop to_fp8(sop v)
{
#if defined(SWIN_FP8_HWCVT) && defined(__GFX12__)
// Opt-in, UNVERIFIED ON HARDWARE: the values already are e4m3 values (finite, |x| <= 448), so the hardware
// conversion has nothing to round or saturate; byte j = element j as below. Open question before enabling
// it by default: whether e4m3 subnormals (k * 2^-9) survive the gfx12 denormal mode in effect.
uint32_t w[2];
#pragma unroll
for (int j = 0; j < 2; ++j)
{
int packed = __builtin_amdgcn_cvt_pk_fp8_f32((float)v[4 * j], (float)v[4 * j + 1], 0, false);
packed = __builtin_amdgcn_cvt_pk_fp8_f32((float)v[4 * j + 2], (float)v[4 * j + 3], packed, true);
w[j] = (uint32_t)packed;
}
return (u2v){w[0], w[1]};
#endif
uint32_t c[4];
#pragma unroll
for (int j = 0; j < 4; ++j)