Execute native Windows K DLSS and validate real transformer weights
This commit is contained in:
1 parent
a0c36a6d6f
commit
5592b7a921
20 files changed
+948
-54
No files matched your search
@@ -38,6 +38,9 @@ int main(int argc, char** argv)
|
||||
start();
|
||||
try {
|
||||
Args args(argc, argv);
|
||||
uint64_t identity = 0xcbf29ce484222325ull;
|
||||
for (const char* c = ptx; *c; ++c) identity = (identity ^ uint8_t(*c)) * 0x100000001b3ull;
|
||||
std::printf("PTX_IDENTITY kernel=d4r_ptx_pattern fnv1a64=%016llx\n", static_cast<unsigned long long>(identity));
|
||||
if (args.cuda_dll.empty()) throw std::runtime_error("--cuda-dll is required (absolute ZLUDA nvcuda.dll path)");
|
||||
if (args.context != "primary" && args.context != "created") throw std::runtime_error("context must be primary or created");
|
||||
// Require the real HIP architecture, then match the CUDA device by PCI identity.
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Validate every RGBA16F diagnostic frame against another complete pipeline."""
|
||||
import argparse
|
||||
import math
|
||||
import pathlib
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
|
||||
def main(args):
|
||||
frames = sorted(args.reference.glob('output-*.rgba16f'))
|
||||
if not frames:
|
||||
raise RuntimeError('Reference contains no frames')
|
||||
for path in frames:
|
||||
actual = args.actual / path.name
|
||||
if not actual.is_file():
|
||||
raise RuntimeError(f'Missing output frame {path.name}')
|
||||
reference = np.fromfile(path, np.float16)
|
||||
output = np.fromfile(actual, np.float16)
|
||||
if reference.size != output.size or reference.size != args.width * args.height * 4:
|
||||
raise RuntimeError(f'Output size mismatch for {path.name}')
|
||||
if not np.isfinite(reference).all() or not np.isfinite(output).all():
|
||||
raise RuntimeError(f'NaN/Inf in {path.name}')
|
||||
x = reference.reshape(-1, 4)[:, :3].astype(np.float64)
|
||||
y = output.reshape(-1, 4)[:, :3].astype(np.float64)
|
||||
error = np.abs(x - y)
|
||||
rms = float(np.sqrt(np.mean(error ** 2)))
|
||||
peak = max(1., float(np.abs(x).max()))
|
||||
psnr = math.inf if rms == 0 else 20 * math.log10(peak / rms)
|
||||
outliers = float(np.mean(error > .01 * peak))
|
||||
print(f'FRAME_REFERENCE name={path.name} max_abs={error.max():.9g} '
|
||||
f'max_rel={(error / np.maximum(np.abs(x), .001)).max():.9g} rms={rms:.9g} psnr_db={psnr:.6g} '
|
||||
f'fraction_over_1pct={outliers:.9g}')
|
||||
if psnr < args.min_psnr or error.max() > .025 * peak or outliers > .0001:
|
||||
raise RuntimeError(f'Complete pipeline mismatch in {path.name}')
|
||||
print(f'PASS FRAME_REFERENCE frames={len(frames)} finite=1 min_psnr_db={args.min_psnr}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--reference', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--actual', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--width', type=int, default=512)
|
||||
parser.add_argument('--height', type=int, default=288)
|
||||
parser.add_argument('--min-psnr', type=float, default=60.)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
main(args)
|
||||
except Exception as error:
|
||||
print(f'FAIL FRAME_REFERENCE {error}', file=sys.stderr)
|
||||
raise SystemExit(5)
|
||||
@@ -0,0 +1,95 @@
|
||||
"""Compare real K captures with the upstream CPU PTX interpreter.
|
||||
|
||||
The local DLL and captures remain private. Only numerical metrics are public.
|
||||
Use this independent reference to audit the NumPy model's reduction uncertainty.
|
||||
"""
|
||||
import argparse
|
||||
import math
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||
REFERENCE = pathlib.Path(__file__).resolve().parent / 'reference'
|
||||
if not (REFERENCE / 'ptxsim.py').exists():
|
||||
REFERENCE = ROOT / 'kernels/tools'
|
||||
sys.path.insert(0, str(REFERENCE))
|
||||
import pwin_model as pm
|
||||
pm.NORM_FRAGMENT_ORDER = True
|
||||
import pwin_check as pc
|
||||
import ptxsim
|
||||
from extract_dlss_ptx import fatbins, ptx_entries
|
||||
|
||||
|
||||
def metrics(label, expected, actual):
|
||||
expected = expected.astype(np.float64)
|
||||
actual = actual.astype(np.float64)
|
||||
if not np.isfinite(expected).all() or not np.isfinite(actual).all():
|
||||
raise RuntimeError(f'{label} contains NaN/Inf')
|
||||
error = np.abs(expected - actual)
|
||||
peak = max(1., float(np.abs(expected).max()))
|
||||
maximum = float(error.max())
|
||||
relative = float((error / np.maximum(np.abs(expected), .001)).max())
|
||||
rms = float(np.sqrt(np.mean(error ** 2)))
|
||||
psnr = math.inf if rms == 0 else 20 * math.log10(peak / rms)
|
||||
print(f'{label} max_abs={maximum:.9g} max_rel={relative:.9g} rms={rms:.9g} '
|
||||
f'peak={peak:.9g} psnr_db={psnr:.6g}', flush=True)
|
||||
return maximum, peak, psnr
|
||||
|
||||
|
||||
def validate(args):
|
||||
name = f'dltss_pwin_{args.layer}_layer'
|
||||
dump = pm.Dump(str(args.capture_dir))
|
||||
if dump.kernel != name:
|
||||
raise RuntimeError('Capture kernel does not match requested layer')
|
||||
native = pc.Outputs(dump, str(args.native_dir))
|
||||
candidates = []
|
||||
for bx, by in pc.windows(dump.grid, 12):
|
||||
model = pc.model_window(dump, args.layer, bx, by)
|
||||
expected, actual = pc.stored(dump, native, args.layer, bx, by, *model)
|
||||
difference = float(np.abs(expected.astype(np.float64) - actual.astype(np.float64)).max())
|
||||
candidates.append((difference, bx, by, model, expected, actual))
|
||||
selected = sorted(candidates, key=lambda c: (-c[0], c[1], c[2]))[:args.windows]
|
||||
pattern = re.compile(rb'\.entry\s+' + name.encode() + rb'\s*\(')
|
||||
sources = [source.rstrip(b'\0') for _, fatbin in fatbins(args.dlss_dll.read_bytes())
|
||||
for source in ptx_entries(fatbin) if pattern.search(source)]
|
||||
if not sources:
|
||||
raise RuntimeError('Local DLSS DLL does not contain the captured kernel')
|
||||
args.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
path = args.output_dir / (name + '.ptx')
|
||||
path.write_bytes(sources[-1])
|
||||
for _, bx, by, model, numpy_expected, actual in selected:
|
||||
_, memory, steps = ptxsim.run_block(str(path), name, str(args.capture_dir), (bx, by, 0))
|
||||
reference_output = pc.Outputs.__new__(pc.Outputs)
|
||||
reference_output.d = dump
|
||||
reference_output.allocs = {identifier: (base, data) for identifier, base, data
|
||||
in zip(memory.ids, memory.bases, memory.data)}
|
||||
_, expected = pc.stored(dump, reference_output, args.layer, bx, by, *model)
|
||||
print(f'PTX_REFERENCE layer={args.layer} window={bx},{by} statements={steps}', flush=True)
|
||||
maximum, peak, psnr = metrics('PTX_VS_NATIVE', expected, actual)
|
||||
metrics('PTX_VS_NUMPY', expected, numpy_expected)
|
||||
# Half reductions and approximate reciprocal/rsqrt are not bit-exact
|
||||
# across ISAs. Bound both the worst element and total error explicitly.
|
||||
if maximum > max(.001, .005 * peak) or psnr < 60:
|
||||
raise RuntimeError('Native layer differs from independent PTX reference')
|
||||
print(f'PASS K_PTX_REFERENCE layer={args.layer} windows={len(selected)} nan_inf=0', flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--layer', choices=list(pc.LAYERS), required=True)
|
||||
parser.add_argument('--capture-dir', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--native-dir', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--dlss-dll', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--output-dir', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--windows', type=int, default=2)
|
||||
args = parser.parse_args()
|
||||
if args.windows < 1:
|
||||
parser.error('--windows must be positive')
|
||||
try:
|
||||
validate(args)
|
||||
except Exception as error:
|
||||
print(f'FAIL K_PTX_REFERENCE {error}', file=sys.stderr)
|
||||
raise SystemExit(5)
|
||||
@@ -18,7 +18,8 @@ if not (REFERENCE / 'pwin_check.py').exists():
|
||||
REFERENCE = ROOT / 'kernels/tools'
|
||||
sys.path.insert(0, str(REFERENCE))
|
||||
import pwin_model as pm
|
||||
from pwin_check import LAYERS, model_window, Outputs, stored
|
||||
pm.NORM_FRAGMENT_ORDER = True
|
||||
from pwin_check import LAYERS, model_window, Outputs, stored, windows
|
||||
|
||||
|
||||
def generate(layer, directory):
|
||||
@@ -113,10 +114,14 @@ def generate(layer, directory):
|
||||
print(f'PASS K_FIXTURE kernel={layer} weights={weight_bytes} public_synthetic=1')
|
||||
|
||||
|
||||
def validate(layer, directory, output):
|
||||
def validate(layer, directory, output, window_count=1, real_capture=False):
|
||||
dump = pm.Dump(str(directory))
|
||||
model, extra = model_window(dump, layer, 0, 0)
|
||||
expected, actual = stored(dump, Outputs(dump, str(output)), layer, 0, 0, model, extra)
|
||||
outputs = Outputs(dump, str(output))
|
||||
pairs = []
|
||||
for bx, by in windows(dump.grid, window_count):
|
||||
model, extra = model_window(dump, layer, bx, by)
|
||||
pairs.append(stored(dump, outputs, layer, bx, by, model, extra))
|
||||
expected, actual = (np.concatenate(values) for values in zip(*pairs))
|
||||
if not np.isfinite(expected).all() or not np.isfinite(actual).all():
|
||||
raise RuntimeError('K replay contains NaN/Inf or unwritten output')
|
||||
difference = np.abs(actual.astype(np.float64) - expected.astype(np.float64))
|
||||
@@ -127,7 +132,11 @@ def validate(layer, directory, output):
|
||||
psnr = math.inf if not rms else 20 * math.log10(peak / rms)
|
||||
print(f'K_REPLAY_REFERENCE kernel={layer} elements={actual.size} max_abs={maximum:.9g} '
|
||||
f'max_rel={relative:.9g} rms={rms:.9g} psnr_db={psnr:.6g}')
|
||||
if maximum > .001 or psnr < 60:
|
||||
# Bound ISA approximate reciprocal/rsqrt and matrix accumulation differences;
|
||||
# require the independent PTX reference gate for every real-weight layer.
|
||||
absolute_limit = max(.001, .005 * peak) if real_capture else .001
|
||||
print(f'K_REPLAY_LIMIT windows={len(pairs)} max_abs_limit={absolute_limit:.9g} min_psnr_db=60 real_capture={int(real_capture)}')
|
||||
if maximum > absolute_limit or psnr < 60:
|
||||
worst = int(difference.argmax())
|
||||
raise RuntimeError(f'K mismatch at {worst}: reference={expected[worst]}, gpu={actual[worst]}')
|
||||
print(f'PASS K_REPLAY_REFERENCE kernel={layer} architecture=gfx1201 nan_inf=0')
|
||||
@@ -139,6 +148,8 @@ if __name__ == '__main__':
|
||||
parser.add_argument('--layer', choices=list(LAYERS), required=True)
|
||||
parser.add_argument('--fixture-dir', type=pathlib.Path, required=True)
|
||||
parser.add_argument('--output-dir', type=pathlib.Path)
|
||||
parser.add_argument('--windows', type=int, default=1)
|
||||
parser.add_argument('--real-capture', action='store_true')
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
if args.mode == 'generate':
|
||||
@@ -146,7 +157,9 @@ if __name__ == '__main__':
|
||||
else:
|
||||
if not args.output_dir:
|
||||
parser.error('validate requires --output-dir')
|
||||
validate(args.layer, args.fixture_dir, args.output_dir)
|
||||
if args.windows < 1:
|
||||
parser.error('--windows must be positive')
|
||||
validate(args.layer, args.fixture_dir, args.output_dir, args.windows, args.real_capture)
|
||||
except Exception as error:
|
||||
print(f'FAIL K_REPLAY {error}', file=sys.stderr)
|
||||
raise SystemExit(5)
|
||||
@@ -121,7 +121,7 @@ int main(int argc, char** argv)
|
||||
cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize");
|
||||
cuda.check(cuda.cuCtxSetCurrent(nullptr), "cuCtxSetCurrent(NULL)");
|
||||
cuda.check(cuda.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2"); context = nullptr;
|
||||
std::printf("PASS NGX_INIT architecture=gfx1201 sr_available=1 transformer_executed=0\n");
|
||||
std::printf("PASS NGX_INIT architecture=gfx1201 sr_available=1 transformer_validation=pending\n");
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL NGX_INIT %s\n", e.what());
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
// No host SDK, CRT, or device library dependency. Compiled only for gfx1201.
|
||||
extern "C" __attribute__((global)) void d4r_ptx_pattern(
|
||||
unsigned int* output, unsigned int count, unsigned int seed)
|
||||
{
|
||||
const unsigned int i = __builtin_amdgcn_workgroup_id_x() * 128u +
|
||||
__builtin_amdgcn_workitem_id_x();
|
||||
if (i < count)
|
||||
output[i] = (i * 1664525u + seed) ^ 0xa5a55a5au;
|
||||
}
|
||||
|
||||
extern "C" __attribute__((global)) void d4r_probe_pattern(
|
||||
unsigned int* output, unsigned int count, unsigned int seed)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user