"""GPU diagnosis only: reuse the browser's exact FP32 model and normalized inputs.""" import argparse from collections import defaultdict import hashlib import json from pathlib import Path import tempfile import time import numpy as np import onnxruntime as ort def main(): parser = argparse.ArgumentParser() parser.add_argument('--model', type=Path, required=True) parser.add_argument('--input', type=Path, required=True, help='Browser-exported little-endian float32 .f32 file') parser.add_argument('--provider', choices=['cuda', 'tensorrt'], default='cuda') parser.add_argument('--iterations', type=int, default=200) parser.add_argument('--views', type=int, choices=range(1, 5), default=1) parser.add_argument('--output', type=Path, default=Path('rtmw3d-native-comparison.json')) args = parser.parse_args() provider = {'cuda': 'CUDAExecutionProvider', 'tensorrt': 'TensorrtExecutionProvider'}[args.provider] if provider not in ort.get_available_providers(): raise RuntimeError(f'{provider} is unavailable; no CPU performance substitute is allowed') if not 12 <= args.iterations <= 1000: raise ValueError('iterations must be between 12 and 1000') data = np.fromfile(args.input, dtype=' 0 for name, total in provider_times.items()): raise RuntimeError('No GPU provider nodes were observed in the native profile') ordered = sorted(times) with args.model.open('rb') as file: digest = hashlib.sha256() for chunk in iter(lambda: file.read(1024 * 1024), b''): digest.update(chunk) result = {'schema': 'rtmw3d-native-comparison/v1', 'onnxruntime': ort.__version__, 'modelSha256': digest.hexdigest(), 'requestedProvider': provider, 'views': args.views, 'metrics': {'p50Ms': ordered[int((len(ordered) - 1) * .5)], 'p95Ms': ordered[int((len(ordered) - 1) * .95)], 'aggregateFPS': len(times) / wall * 1000, 'perInputFPS': len(times) / wall * 1000 / args.views, 'actualInferences': len(times), 'wallMs': wall, 'sessionTimesMs': times}, 'separateProfile': {'providerMilliseconds': dict(provider_times), 'topNodes': sorted(nodes, key=lambda n: -n['milliseconds'])[:30]}, 'notes': ['Diagnostic path only; production remains browser-based', 'Same three normalized browser inputs; upload, inference and CPU output retrieval included', 'CPU fallback nodes are disclosed in the separate profile', 'No video, tensor contents, landmark coordinates or device identity are included in this report']} args.output.write_text(json.dumps(result, indent=2) + '\n', encoding='utf-8') print(json.dumps({'output': str(args.output), 'metrics': result['metrics'] | {'sessionTimesMs': None}}, indent=2)) if __name__ == '__main__': main()