From 3adb76894d7076193fd5f2faae4dc079a81aa256 Mon Sep 17 00:00:00 2001 From: nimlgen <138685161+nimlgen@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:13:40 +0300 Subject: [PATCH] validate image=2 float16=1 openpilot benchmark (#6346) * validate image=2 float=16 openpilot * linter * linter2 --- test/external/external_benchmark_openpilot.py | 23 +++++++++++------- ...ab7897cbfa35981e1636fe551e4ce5_float16.npy | Bin 0 -> 26144 bytes 2 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 test/external/openpilot/b1ab7897cbfa35981e1636fe551e4ce5_float16.npy diff --git a/test/external/external_benchmark_openpilot.py b/test/external/external_benchmark_openpilot.py index 0c19c57d..739af653 100644 --- a/test/external/external_benchmark_openpilot.py +++ b/test/external/external_benchmark_openpilot.py @@ -37,15 +37,20 @@ if __name__ == "__main__": ret = next(iter(run_onnx_jit(new_inputs).values())).cast(dtypes.float32).numpy() print(f"jitted: {(time.perf_counter_ns() - st)*1e-6:7.4f} ms") - # validate (only if IMAGE=2 and FLOAT16=0) - if IMAGE.value == 2 and getenv("FLOAT16") == 0: - tinygrad_out = next(iter(run_onnx_jit(new_inputs).values())).cast(dtypes.float32).numpy() - if getenv("SAVE_OUTPUT"): - np.save(Path(__file__).parent / "openpilot" / f"{hashlib.md5(OPENPILOT_MODEL.encode()).hexdigest()}.npy", tinygrad_out) - else: - known_good_out = np.load(Path(__file__).parent / "openpilot" / f"{hashlib.md5(OPENPILOT_MODEL.encode()).hexdigest()}.npy") + suffix = "" + if IMAGE.value < 2: suffix += f"_image{IMAGE.value}" # image=2 has no suffix for compatibility + if getenv("FLOAT16") == 1: suffix += "_float16" + path = Path(__file__).parent / "openpilot" / f"{hashlib.md5(OPENPILOT_MODEL.encode()).hexdigest()}{suffix}.npy" - np.testing.assert_allclose(known_good_out, tinygrad_out, atol=1e-2, rtol=1e-2) - print(colored("outputs validated!", "green")) + # validate if we have records + tinygrad_out = next(iter(run_onnx_jit(new_inputs).values())).cast(dtypes.float32).numpy() + if getenv("SAVE_OUTPUT"): + np.save(path, tinygrad_out) + print(f"saved output to {path}!") + elif path.exists(): + known_good_out = np.load(path) + + np.testing.assert_allclose(known_good_out, tinygrad_out, atol=1e-2, rtol=1e-2) + print(colored("outputs validated!", "green")) else: print(colored("skipping validation", "yellow")) diff --git a/test/external/openpilot/b1ab7897cbfa35981e1636fe551e4ce5_float16.npy b/test/external/openpilot/b1ab7897cbfa35981e1636fe551e4ce5_float16.npy new file mode 100644 index 0000000000000000000000000000000000000000..b8382df3d06f0d7837aa27ddd5638780a2528a8b GIT binary patch literal 26144 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ℑmrge8?PIiJg; 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