Execute gfx1201 K enc2 and generalize layer reference diagnostics

This commit is contained in:
Codex committed 2026-09-30 14:40:49 +03:00
1 parent 1b5d4c9db7
commit 2dea066d6a
7 files changed
+90 -51

No files matched your search

+21 -13
View File
@@ -29,19 +29,24 @@ add_custom_command(OUTPUT "${wmma_object}"
-o "${wmma_object}" -o "${wmma_object}"
DEPENDS tools/windows/wmma_gfx1201.hip kernels/common/wmma_backend.h VERBATIM) DEPENDS tools/windows/wmma_gfx1201.hip kernels/common/wmma_backend.h VERBATIM)
add_custom_target(d4r_wmma_code_object ALL DEPENDS "${wmma_object}") add_custom_target(d4r_wmma_code_object ALL DEPENDS "${wmma_object}")
# Compile-only K port smoke test. This object is intentionally not installed as # These K objects stay in experimental/k, outside the ZLUDA native override
# a native override until its transformer outputs pass the K reference/replay. # directory, until each layer and then the complete network pass replay.
set(k_enc1_object "${CMAKE_CURRENT_BINARY_DIR}/dltss_pwin_enc1_layer_gfx1201.hsaco") set(k_objects)
add_custom_command(OUTPUT "${k_enc1_object}" foreach(layer enc1 enc2)
set(k_object "${CMAKE_CURRENT_BINARY_DIR}/dltss_pwin_${layer}_layer_gfx1201.hsaco")
add_custom_command(OUTPUT "${k_object}"
COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=gfx1201 COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=gfx1201
--offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64 --offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64
-nogpuinc -nogpulib -O2 -DD4R_DEVICE_ONLY_MINIMAL -nogpuinc -nogpulib -O2 -DD4R_DEVICE_ONLY_MINIMAL
"${CMAKE_CURRENT_SOURCE_DIR}/kernels/k/dltss_pwin_enc1_layer.hip" "${CMAKE_CURRENT_SOURCE_DIR}/kernels/k/dltss_pwin_${layer}_layer.hip"
-o "${k_enc1_object}" -o "${k_object}"
DEPENDS kernels/k/dltss_pwin_enc1_layer.hip kernels/k/pwin_layer.h DEPENDS kernels/k/dltss_pwin_${layer}_layer.hip kernels/k/pwin_layer.h
kernels/k/pwin_common.h kernels/common/wmma_backend.h kernels/k/pwin_common.h kernels/common/wmma_backend.h
kernels/common/hip_device_minimal.h VERBATIM) kernels/common/hip_device_minimal.h VERBATIM)
add_custom_target(d4r_k_gfx1201_compile ALL DEPENDS "${k_enc1_object}") list(APPEND k_objects "${k_object}")
install(FILES "${k_object}" DESTINATION experimental/k)
endforeach()
add_custom_target(d4r_k_gfx1201_compile ALL DEPENDS ${k_objects})
foreach(probe hip_gfx1201_probe gfx12_wmma_probe k_module_probe cuda_driver_probe d3d12_hip_interop_probe hip_stream_lifecycle_probe ngx_cuda_init_probe) foreach(probe hip_gfx1201_probe gfx12_wmma_probe k_module_probe cuda_driver_probe d3d12_hip_interop_probe hip_stream_lifecycle_probe ngx_cuda_init_probe)
add_executable(d4r_${probe} tools/windows/${probe}.cpp) add_executable(d4r_${probe} tools/windows/${probe}.cpp)
target_compile_definitions(d4r_${probe} PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__) target_compile_definitions(d4r_${probe} PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__)
@@ -97,9 +102,8 @@ add_dependencies(d4r_gfx12_wmma_probe d4r_wmma_code_object)
add_dependencies(d4r_k_module_probe d4r_k_gfx1201_compile) add_dependencies(d4r_k_module_probe d4r_k_gfx1201_compile)
install(FILES "${probe_object}" DESTINATION bin) install(FILES "${probe_object}" DESTINATION bin)
install(FILES "${wmma_object}" DESTINATION bin) install(FILES "${wmma_object}" DESTINATION bin)
install(FILES "${k_enc1_object}" DESTINATION experimental/k)
install(FILES scripts/windows/test-windows-rdna4.ps1 DESTINATION .) install(FILES scripts/windows/test-windows-rdna4.ps1 DESTINATION .)
install(FILES tools/windows/k_enc1_validate.py DESTINATION .) install(FILES tools/windows/k_layer_validate.py DESTINATION .)
install(FILES kernels/tools/pwin_model.py DESTINATION reference) install(FILES kernels/tools/pwin_model.py DESTINATION reference)
install(FILES docs/windows-rdna4-port.md DESTINATION docs) install(FILES docs/windows-rdna4-port.md DESTINATION docs)
include(CTest) include(CTest)
@@ -109,9 +113,13 @@ set_tests_properties(hip_gfx1201 PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201"
add_test(NAME gfx12_wmma COMMAND d4r_gfx12_wmma_probe add_test(NAME gfx12_wmma COMMAND d4r_gfx12_wmma_probe
--hip-root "${D4R_HIP_ROOT}" --module "${wmma_object}" --iterations 16) --hip-root "${D4R_HIP_ROOT}" --module "${wmma_object}" --iterations 16)
set_tests_properties(gfx12_wmma PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;wmma") set_tests_properties(gfx12_wmma PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;wmma")
add_test(NAME k_enc1_execution COMMAND d4r_k_module_probe foreach(layer enc1 enc2)
--hip-root "${D4R_HIP_ROOT}" --module "${k_enc1_object}") add_test(NAME k_${layer}_execution COMMAND d4r_k_module_probe
set_tests_properties(k_enc1_execution PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;k_execution") --hip-root "${D4R_HIP_ROOT}"
--module "${CMAKE_CURRENT_BINARY_DIR}/dltss_pwin_${layer}_layer_gfx1201.hsaco"
--kernel-name ${layer})
set_tests_properties(k_${layer}_execution PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;k_execution")
endforeach()
add_test(NAME d3d12_hip_interop COMMAND d4r_d3d12_hip_interop_probe add_test(NAME d3d12_hip_interop COMMAND d4r_d3d12_hip_interop_probe
--hip-root "${D4R_HIP_ROOT}" --module "${probe_object}" --iterations 32) --hip-root "${D4R_HIP_ROOT}" --module "${probe_object}" --iterations 32)
set_tests_properties(d3d12_hip_interop PROPERTIES TIMEOUT 120 LABELS "hardware;interop") set_tests_properties(d3d12_hip_interop PROPERTIES TIMEOUT 120 LABELS "hardware;interop")
+2 -2
View File
@@ -8,8 +8,8 @@ It is an experiment. It has been tested on one GPU in a handful of games, it dep
**Windows / RDNA4 development:** the `windows-rdna4` branch adds native Windows **Windows / RDNA4 development:** the `windows-rdna4` branch adds native Windows
gfx1201 HIP/ZLUDA diagnostics, validated D3D12/HIP interop, an NGX init probe, gfx1201 HIP/ZLUDA diagnostics, validated D3D12/HIP interop, an NGX init probe,
and a CPU-checked gfx12 WMMA backend. The first K `enc1` kernel executes on and a CPU-checked gfx12 WMMA backend. K `enc1` and `enc2` execute on
gfx1201 and matches the existing numpy model on a synthetic nonzero fixture. gfx1201 and match the existing numpy model on synthetic nonzero fixtures.
The remaining K/M kernels and Windows game runtime are still in progress. The remaining K/M kernels and Windows game runtime are still in progress.
Build commands, hardware results and remaining Build commands, hardware results and remaining
porting gates are in [docs/windows-rdna4-port.md](docs/windows-rdna4-port.md). porting gates are in [docs/windows-rdna4-port.md](docs/windows-rdna4-port.md).
+17 -7
View File
@@ -7,8 +7,8 @@ This is a work log for an implementation in progress, not a claim of DLSS suppor
## Milestone and gates ## Milestone and gates
Current milestone: M1/M2/M4/M5 passed; NGX init + DLSS CUDA capability discovery Current milestone: M1/M2/M4/M5 passed; NGX init + DLSS CUDA capability discovery
passed with the user's DLLs. M6 is in progress: the first K `enc1` prep and passed with the user's DLLs. M6 is in progress: K `enc1` and `enc2` prep and
transformer run on gfx1201 and pass a synthetic nonzero numpy reference check. transformers run on gfx1201 and pass synthetic nonzero numpy reference checks.
Do not integrate NGX until the integer PTX workload is stable on the real GPU. Do not integrate NGX until the integer PTX workload is stable on the real GPU.
| Gate | Status | | Gate | Status |
@@ -19,7 +19,7 @@ Do not integrate NGX until the integer PTX workload is stable on the real GPU.
| M3: Windows NGX initialization and simple DLSS path | Init + SR capabilities PASS; Evaluate/transformer pending | | M3: Windows NGX initialization and simple DLSS path | Init + SR capabilities PASS; Evaluate/transformer pending |
| M4: D3D12 / HIP external memory and fence round trip | PASS with TheRock; stable 7.2 has mapped-view leak | | M4: D3D12 / HIP external memory and fence round trip | PASS with TheRock; stable 7.2 has mapped-view leak |
| M5: independently validated gfx12 WMMA backend | PASS: raw + legacy adapter, 16 cases, max abs/relative error 0 | | M5: independently validated gfx12 WMMA backend | PASS: raw + legacy adapter, 16 cases, max abs/relative error 0 |
| M6: K layers, full transformer and image validation | Partial: `enc1` executes, nonzero fixture matches reference; other layers/full network pending | | M6: K layers, full transformer and image validation | Partial: `enc1`/`enc2` execute and match nonzero references; other layers/full network pending |
| M7: M FP16-equivalent baseline and full transformer | Pending | | M7: M FP16-equivalent baseline and full transformer | Pending |
| M8: standalone Windows D3D12 NGX harness | Pending | | M8: standalone Windows D3D12 NGX harness | Pending |
| M9: OptiScaler integration, profiling, installation | Pending | | M9: OptiScaler integration, profiling, installation | Pending |
@@ -137,13 +137,13 @@ different inputs; max absolute and relative errors were both zero.
`kernels/k/pwin_common.h` now calls the tested adapter. The Windows device-only `kernels/k/pwin_common.h` now calls the tested adapter. The Windows device-only
compiler uses `kernels/common/hip_device_minimal.h`, exposing only public compiler uses `kernels/common/hip_device_minimal.h`, exposing only public
Clang AMDGPU work-item/grid/barrier builtins and HIP-compatible qualifiers; Clang AMDGPU work-item/grid/barrier builtins and HIP-compatible qualifiers;
the ordinary Linux HIP include path remains. CMake builds `enc1` for gfx1201 the ordinary Linux HIP include path remains. CMake builds `enc1`/`enc2` for gfx1201
into `experimental/k/` and verifies that HIP loads both prep and transformer into `experimental/k/` and verifies that HIP loads both prep and transformer
entry points. The `k_module_probe` now launches prep and transformer. The entry points. The `k_module_probe` now launches prep and transformer. The
identity fixture verifies all 4096 full-resolution and 1024 merged FP16 values identity fixture verifies all 4096 full-resolution and 1024 merged FP16 values
bitwise. A second fixture enables nonzero V projections, position-only bitwise. A second fixture enables nonzero V projections, position-only
attention, Wo, MLP/GELU and patch merge; it checks finite values and a patch attention, Wo, MLP/GELU and patch merge; it checks finite values and a patch
identity, then saves all inputs/outputs for `k_enc1_validate.py`. That script identity, then saves all inputs/outputs for `k_layer_validate.py`. That script
runs the existing `pwin_model.py` and measures max absolute/relative error and runs the existing `pwin_model.py` and measures max absolute/relative error and
PSNR. The code object remains in `experimental/k/`, outside ZLUDA's override PSNR. The code object remains in `experimental/k/`, outside ZLUDA's override
path, until the other K layers and real captured weights/activations pass. path, until the other K layers and real captured weights/activations pass.
@@ -259,7 +259,7 @@ One command adds the local NGX initialization gate after eight diagnostics:
powershell -NoProfile -File scripts/windows/test-windows-rdna4.ps1 -RuntimeProfile therock -NgxCore "C:/Users/Administrator/d4r/_nvngx.dll" -DlssDll "C:/Users/Administrator/d4r/nvngx_dlss.dll" powershell -NoProfile -File scripts/windows/test-windows-rdna4.ps1 -RuntimeProfile therock -NgxCore "C:/Users/Administrator/d4r/_nvngx.dll" -DlssDll "C:/Users/Administrator/d4r/nvngx_dlss.dll"
``` ```
Success requires all nine tests, including `PASS K_REFERENCE` and Success with the two local NGX DLLs requires all eleven tests, including both `PASS K_REFERENCE` checks and
`PASS NGX_INIT ... sr_available=1`. The NGX probe still reports `PASS NGX_INIT ... sr_available=1`. The NGX probe still reports
`transformer_executed=0`: the standalone K launch has not been integrated into `transformer_executed=0`: the standalone K launch has not been integrated into
DLSS. On NGX failure, CUDA trace and NVAPI query DLSS. On NGX failure, CUDA trace and NVAPI query
@@ -279,7 +279,7 @@ cmake --install build/windows-rdna4 --prefix dist/windows-rdna4-diagnostics
The one-command diagnostic runner is also installed at The one-command diagnostic runner is also installed at
`dist/windows-rdna4-diagnostics/test-windows-rdna4.ps1`. It requires the selected `dist/windows-rdna4-diagnostics/test-windows-rdna4.ps1`. It requires the selected
HIP SDK and ZLUDA directory; the developer setup auto-discovers local defaults. HIP SDK and ZLUDA directory; the developer setup auto-discovers local defaults.
Success: exit 0, all five tests passed in `summary.json`, `PASS HIP`, `PASS CUDA`, Success: exit 0, every selected test passed in `summary.json`, `PASS HIP`, `PASS CUDA`,
`PASS INTEROP_LIFETIME` and `PASS INTEROP` in stdout. Failure: send the **single printed ZIP path**; it contains `PASS INTEROP_LIFETIME` and `PASS INTEROP` in stdout. Failure: send the **single printed ZIP path**; it contains
stdout/stderr, timeout/exception exit code, DLL paths/versions/hashes, driver/OS stdout/stderr, timeout/exception exit code, DLL paths/versions/hashes, driver/OS
inventory and a minidump for an unhandled exception. Upstream trace is attempted inventory and a minidump for an unhandled exception. Upstream trace is attempted
@@ -351,6 +351,16 @@ Reference dependency: pinned local NumPy `2.4.6` on Python 3.11, installed by
`setup-windows-tools.ps1` into `.tools/python/vendor` (not the game runtime). `setup-windows-tools.ps1` into `.tools/python/vendor` (not the game runtime).
This is a synthetic one-layer check, not proof of complete K or DLSS output. This is a synthetic one-layer check, not proof of complete K or DLSS output.
2026-09-29 M6 second kernel: `enc2` exercises nonzero Q/K/V, learned attention
and softmax, Wo, MLP/GELU and patch merge on gfx1201. Full output max absolute
error `3.81469727e-06`, max relative error `0.00166893` (denominator floor
`1e-3`), PSNR `130.39 dB`; merged output max absolute error `3.81469727e-06`,
PSNR `132.49 dB`. All 4096 full and 1536 merged elements written, no NaN/Inf.
Both layers pass 32 identity iterations and the nonzero numpy reference.
Bundle `test-results/m6-k-enc2-final.zip`: 11/11 gates PASS. CTest: 8/8 PASS.
The generic probe/reference runner selects `--kernel-name enc1|enc2`; both
objects remain under `experimental/k` and are not used as DLSS overrides yet.
Stable HIP SDK 7.2 compiler caveat: its `-O2` code object for `enc1` produces Stable HIP SDK 7.2 compiler caveat: its `-O2` code object for `enc1` produces
NaN already on the identity fixture (first element `0xfe00` instead of NaN already on the identity fixture (first element `0xfe00` instead of
`0xbc00`). Its `-O1` object also miscomputes the identity fixture; `-O0` `0xbc00`). Its `-O1` object also miscomputes the identity fixture; `-O0`
+14 -10
View File
@@ -101,7 +101,8 @@ try {
$files = @((Join-Path $HipRoot 'bin/amdhip64_7.dll'), $comgr, $files = @((Join-Path $HipRoot 'bin/amdhip64_7.dll'), $comgr,
(Join-Path $ZludaRoot 'nvcuda.dll'), (Join-Path $PackageRoot 'bin/probe_gfx1201.hsaco'), (Join-Path $ZludaRoot 'nvcuda.dll'), (Join-Path $PackageRoot 'bin/probe_gfx1201.hsaco'),
(Join-Path $PackageRoot 'bin/wmma_gfx1201.hsaco'), (Join-Path $PackageRoot 'bin/wmma_gfx1201.hsaco'),
(Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc1_layer_gfx1201.hsaco')) (Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc1_layer_gfx1201.hsaco'),
(Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc2_layer_gfx1201.hsaco'))
if ($NgxCore -or $DlssDll) { if ($NgxCore -or $DlssDll) {
if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' } if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' }
if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) { if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) {
@@ -127,16 +128,19 @@ try {
$wmmaOk = Invoke-Probe 'gfx12-wmma' (Join-Path $bin 'd4r_gfx12_wmma_probe.exe') @( $wmmaOk = Invoke-Probe 'gfx12-wmma' (Join-Path $bin 'd4r_gfx12_wmma_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'wmma_gfx1201.hsaco'), '--iterations', "$Iterations") '--hip-root', $HipRoot, '--module', (Join-Path $bin 'wmma_gfx1201.hsaco'), '--iterations', "$Iterations")
if (!$wmmaOk) { throw 'gfx12 WMMA layout validation failed; refusing to mark K/M readiness.' } if (!$wmmaOk) { throw 'gfx12 WMMA layout validation failed; refusing to mark K/M readiness.' }
$kFixture = Join-Path $OutputDirectory 'k-enc1-fixture'
$kModuleOk = Invoke-Probe 'k-enc1-gpu' (Join-Path $bin 'd4r_k_module_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc1_layer_gfx1201.hsaco'),
'--fixture-dir', $kFixture, '--iterations', "$Iterations")
if (!$kModuleOk) { throw 'K enc1 GPU execution failed; see the k-enc1-gpu logs.' }
$pythonCommand = Get-Command python -ErrorAction SilentlyContinue $pythonCommand = Get-Command python -ErrorAction SilentlyContinue
if (!$pythonCommand) { throw 'Python 3.11+ with NumPy 2.4.6 is needed for the K reference check; run setup-windows-tools.ps1.' } if (!$pythonCommand) { throw 'Python 3.11+ with NumPy 2.4.6 is needed for K reference checks; run setup-windows-tools.ps1.' }
$kReferenceOk = Invoke-Probe 'k-enc1-reference' $pythonCommand.Source @( foreach ($layer in @('enc1', 'enc2')) {
(Join-Path $PackageRoot 'k_enc1_validate.py'), '--fixture-dir', $kFixture) $kFixture = Join-Path $OutputDirectory "k-$layer-fixture"
if (!$kReferenceOk) { throw 'K enc1 output differs from pwin_model.py; see the k-enc1-reference logs.' } $kModuleOk = Invoke-Probe "k-$layer-gpu" (Join-Path $bin 'd4r_k_module_probe.exe') @(
'--hip-root', $HipRoot,
'--module', (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_gfx1201.hsaco"),
'--kernel-name', $layer, '--fixture-dir', $kFixture, '--iterations', "$Iterations")
if (!$kModuleOk) { throw "K $layer GPU execution failed; see the k-$layer-gpu logs." }
$kReferenceOk = Invoke-Probe "k-$layer-reference" $pythonCommand.Source @(
(Join-Path $PackageRoot 'k_layer_validate.py'), '--kernel-name', $layer, '--fixture-dir', $kFixture)
if (!$kReferenceOk) { throw "K $layer output differs from pwin_model.py; see the k-$layer-reference logs." }
}
$cudaOk = $true $cudaOk = $true
foreach ($context in @('primary', 'created')) { foreach ($context in @('primary', 'created')) {
$ok = Invoke-Probe "cuda-$context" (Join-Path $bin 'd4r_cuda_driver_probe.exe') @( $ok = Invoke-Probe "cuda-$context" (Join-Path $bin 'd4r_cuda_driver_probe.exe') @(
+2
View File
@@ -90,6 +90,7 @@ struct Args {
std::string nvapi_dll; std::string nvapi_dll;
std::string ngx_abi = "driver"; std::string ngx_abi = "driver";
std::string fixture_dir; std::string fixture_dir;
std::string kernel_name = "enc1";
unsigned iterations = 32; unsigned iterations = 32;
int device = -1; int device = -1;
Args(int argc, char** argv) { Args(int argc, char** argv) {
@@ -108,6 +109,7 @@ struct Args {
else if (key == "--nvapi-dll") nvapi_dll = value; else if (key == "--nvapi-dll") nvapi_dll = value;
else if (key == "--ngx-abi") ngx_abi = value; else if (key == "--ngx-abi") ngx_abi = value;
else if (key == "--fixture-dir") fixture_dir = value; else if (key == "--fixture-dir") fixture_dir = value;
else if (key == "--kernel-name") kernel_name = value;
else if (key == "--iterations") { else if (key == "--iterations") {
size_t end = 0; size_t end = 0;
iterations = static_cast<unsigned>(std::stoul(value, &end)); iterations = static_cast<unsigned>(std::stoul(value, &end));
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Compare a real gfx1201 K enc1 launch with the existing numpy K reference.""" """Compare real gfx1201 K enc1/enc2 launches with the existing numpy reference."""
import argparse import argparse
import math import math
import pathlib import pathlib
@@ -57,21 +57,24 @@ def compare(name, actual, expected):
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--fixture-dir", required=True, type=pathlib.Path) parser.add_argument("--fixture-dir", required=True, type=pathlib.Path)
parser.add_argument("--kernel-name", choices=("enc1", "enc2"), default="enc1")
args = parser.parse_args() args = parser.parse_args()
folder = args.fixture_dir folder = args.fixture_dir
params = SyntheticParams(folder) params = SyntheticParams(folder)
output_channels = 96 if args.kernel_name == "enc2" else 64
reference_full, reference_merged = pwin_encoder( reference_full, reference_merged = pwin_encoder(
params, 0, 0, H=2, C=64, COUT=64, posattn=True) params, 0, 0, H=2, C=64, COUT=output_channels,
posattn=args.kernel_name == "enc1")
actual_full = np.fromfile(folder / "full.bin", np.float16).reshape(64, 64) actual_full = np.fromfile(folder / "full.bin", np.float16).reshape(64, 64)
actual_merged = np.fromfile(folder / "merged.bin", np.float16).reshape(16, 64) actual_merged = np.fromfile(folder / "merged.bin", np.float16).reshape(16, output_channels)
full_abs, full_psnr = compare("full", actual_full, reference_full) full_abs, full_psnr = compare("full", actual_full, reference_full)
merged_abs, merged_psnr = compare("merged", actual_merged, reference_merged) merged_abs, merged_psnr = compare("merged", actual_merged, reference_merged)
# Initial acceptance for the synthetic nonzero FP16 fixture. Tighten this # Initial acceptance for the synthetic nonzero FP16 fixture. Tighten this
# after each K stage has been compared on captured DLSS weights/activations. # after each K stage has been compared on captured DLSS weights/activations.
if full_abs > 0.001 or full_psnr < 60.0 or merged_abs > 0.001 or merged_psnr < 60.0: if full_abs > 0.001 or full_psnr < 60.0 or merged_abs > 0.001 or merged_psnr < 60.0:
raise RuntimeError("K enc1 numerical mismatch against pwin_model.py") raise RuntimeError(f"K {args.kernel_name} numerical mismatch against pwin_model.py")
print("PASS K_REFERENCE architecture=gfx1201 kernel=enc1 nonzero_weights=1 " print(f"PASS K_REFERENCE architecture=gfx1201 kernel={args.kernel_name} "
"transformer_executed=1 nan_inf=0") "nonzero_weights=1 transformer_executed=1 nan_inf=0")
if __name__ == "__main__": if __name__ == "__main__":
+25 -13
View File
@@ -43,24 +43,29 @@ int main(int argc, char** argv)
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t properties{}; hipDeviceProp_t properties{};
hip.select_gfx1201(args.device, properties); hip.select_gfx1201(args.device, properties);
if (args.kernel_name != "enc1" && args.kernel_name != "enc2")
throw std::runtime_error("--kernel-name must be enc1 or enc2");
const bool enc2 = args.kernel_name == "enc2";
const std::string entry = "dltss_pwin_" + args.kernel_name + "_layer";
hipModule_t module = nullptr; hipModule_t module = nullptr;
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(K enc1)"); hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(K)");
struct Cleanup { struct Cleanup {
HipApi& hip; hipModule_t module; HipApi& hip; hipModule_t module;
~Cleanup() { if (module) (void)hip.hipModuleUnload(module); } ~Cleanup() { if (module) (void)hip.hipModuleUnload(module); }
} cleanup{hip, module}; } cleanup{hip, module};
hipFunction_t prep = nullptr, transformer = nullptr; hipFunction_t prep = nullptr, transformer = nullptr;
hip.check(hip.hipModuleGetFunction(&prep, module, "dltss_pwin_enc1_layer_prep"), "K enc1 prep"); hip.check(hip.hipModuleGetFunction(&prep, module, (entry + "_prep").c_str()), "K prep");
hip.check(hip.hipModuleGetFunction(&transformer, module, "dltss_pwin_enc1_layer"), "K enc1 transformer"); hip.check(hip.hipModuleGetFunction(&transformer, module, entry.c_str()), "K transformer");
if (!prep || !transformer) throw std::runtime_error("Null K entry point"); if (!prep || !transformer) throw std::runtime_error("Null K entry point");
// Identity fixture: all projection, MLP and patch-merge weights are zero. // Identity fixture: all projection, MLP and patch-merge weights are zero.
// G1/G2 are one. The full transformer must return its input through its // G1/G2 are one. The full transformer must return its input through its
// residual path and the merged output must be zero. Every stage launches. // residual path and the merged output must be zero. Every stage launches.
constexpr size_t full_elements = 8u * 8u * 64u; constexpr size_t full_elements = 8u * 8u * 64u;
constexpr size_t merged_elements = 4u * 4u * 64u; const size_t output_channels = enc2 ? 96u : 64u;
constexpr size_t weight_bytes = 149504u; const size_t merged_elements = 4u * 4u * output_channels;
constexpr size_t prep_items = 256u * 16u + 1024u; const size_t weight_bytes = enc2 ? 166080u : 149504u;
const size_t prep_items = (enc2 ? 288u : 256u) * 16u + 1024u;
std::vector<uint8_t> weights(weight_bytes, 0); std::vector<uint8_t> weights(weight_bytes, 0);
auto set_half = [&](size_t byte, uint16_t bits) { auto set_half = [&](size_t byte, uint16_t bits) {
weights.at(byte) = static_cast<uint8_t>(bits); weights.at(byte) = static_cast<uint8_t>(bits);
@@ -119,8 +124,8 @@ int main(int argc, char** argv)
return 5; return 5;
} }
} }
std::printf("PASS K_IDENTITY architecture=gfx1201 iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n", std::printf("PASS K_IDENTITY architecture=gfx1201 kernel=%s iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n",
args.iterations, full_elements, merged_elements); args.kernel_name.c_str(), args.iterations, full_elements, merged_elements);
// Exercise nonzero V projection, position-only attention and Wo GEMMs. // Exercise nonzero V projection, position-only attention and Wo GEMMs.
// The generated data is saved for comparison with pwin_model.py. // The generated data is saved for comparison with pwin_model.py.
@@ -135,6 +140,12 @@ int main(int argc, char** argv)
constexpr size_t qkv = 128u, head = 12288u, bias = 24704u, wo = 41216u; constexpr size_t qkv = 128u, head = 12288u, bias = 24704u, wo = 41216u;
constexpr size_t w1 = 49664u, w2 = 82944u, pm = 115712u; constexpr size_t w1 = 49664u, w2 = 82944u, pm = 115712u;
for (unsigned k = 0; k < 32u; ++k) { for (unsigned k = 0; k < 32u; ++k) {
if (enc2) {
set_matrix(qkv, k, k, 1024u); // head 0 Q
set_matrix(qkv + 2048u, k, k, 1024u); // head 0 K
set_matrix(qkv + head + 2048u * 3u, k, k, 1024u); // head 1 Q
set_matrix(qkv + head + 2048u * 4u, k, k, 1024u); // head 1 K
}
set_matrix(qkv + 2048u * 2u, k, k, 1024u); // head 0 V <- input 0:32 set_matrix(qkv + 2048u * 2u, k, k, 1024u); // head 0 V <- input 0:32
set_matrix(qkv + head + 2048u * 5u, k, k, 1024u); // head 1 V <- input 32:64 set_matrix(qkv + head + 2048u * 5u, k, k, 1024u); // head 1 V <- input 32:64
set_matrix(wo, k, k, 1024u); // head 0 Wo -> output 0:32 set_matrix(wo, k, k, 1024u); // head 0 Wo -> output 0:32
@@ -181,9 +192,10 @@ int main(int argc, char** argv)
for (unsigned mt = 0; mt < 16u; ++mt) { for (unsigned mt = 0; mt < 16u; ++mt) {
const unsigned my = mt >> 2, mx = mt & 3u; const unsigned my = mt >> 2, mx = mt & 3u;
const size_t full_base = (8u * (2u * my) + 2u * mx) * 64u; const size_t full_base = (8u * (2u * my) + 2u * mx) * 64u;
for (unsigned channel = 0; channel < 64u; ++channel) { for (unsigned channel = 0; channel < output_channels; ++channel) {
const size_t i = mt * 64u + channel; const size_t i = mt * output_channels + channel;
if (merged[i] != full[full_base + channel]) const uint16_t expected = channel < 64u ? full[full_base + channel] : 0u;
if (merged[i] != expected)
throw std::runtime_error("K patch merge identity mismatch at " + std::to_string(i)); throw std::runtime_error("K patch merge identity mismatch at " + std::to_string(i));
} }
} }
@@ -201,8 +213,8 @@ int main(int argc, char** argv)
save("full.bin", full.data(), full.size() * sizeof(uint16_t)); save("full.bin", full.data(), full.size() * sizeof(uint16_t));
save("merged.bin", merged.data(), merged.size() * sizeof(uint16_t)); save("merged.bin", merged.data(), merged.size() * sizeof(uint16_t));
} }
std::printf("PASS K_NONZERO architecture=gfx1201 changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n", std::printf("PASS K_NONZERO architecture=gfx1201 kernel=%s changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n",
changed, full.size(), merged.size(), !args.fixture_dir.empty()); args.kernel_name.c_str(), changed, full.size(), merged.size(), !args.fixture_dir.empty());
return 0; return 0;
} catch (const std::exception& error) { } catch (const std::exception& error) {
std::fprintf(stderr, "FAIL K_MODULE %s\n", error.what()); std::fprintf(stderr, "FAIL K_MODULE %s\n", error.what());