Download code/bench/bench_latency_nirnay.py from nandukmelath/nirnay: direct link, hf CLI and curl.
- Browser
- Download file 4.23 kB
-
https://huggingface.co/nandukmelath/nirnay/resolve/main/code/bench/bench_latency_nirnay.py
- Command line
-
hf download hf://nandukmelath/nirnay/code/bench/bench_latency_nirnay.py
-
curl -L -o bench_latency_nirnay.py https://huggingface.co/nandukmelath/nirnay/resolve/main/code/bench/bench_latency_nirnay.py
4.23 kB
| """Nirnay CPU latency on this machine with the exact Laya latency workload | |
| (see bench_latency_laya.py). Writes bench/results/nirnay_latency.json. | |
| Reports both regimes honestly: | |
| cold_schema question/option encodings NOT cached (first call with a new schema) | |
| warm schema cached (every later call with the same questions; the normal case) | |
| python bench\\bench_latency_nirnay.py [model_dir] | |
| """ | |
| import json | |
| import os | |
| import sys | |
| import time | |
| import numpy as np | |
| import psutil | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| ROOT = os.path.dirname(HERE) | |
| sys.path.insert(0, ROOT) | |
| sys.path.insert(0, HERE) | |
| from bench_latency_laya import STATE_EN, qs # noqa: E402 (identical workload) | |
| import nirnay # noqa: E402 | |
| OUT = os.path.join(HERE, "results", "nirnay_latency%s.json" % (("_" + os.environ["BENCH_TAG"]) if os.environ.get("BENCH_TAG") else "")) | |
| def timed(fn, warmup=2, reps=10): | |
| for _ in range(warmup): | |
| fn() | |
| ts = [] | |
| for _ in range(reps): | |
| t = time.perf_counter() | |
| fn() | |
| ts.append((time.perf_counter() - t) * 1000) | |
| return {"p50_ms": round(float(np.percentile(ts, 50)), 2), "p95_ms": round(float(np.percentile(ts, 95)), 2), | |
| "mean_ms": round(float(np.mean(ts)), 2), "min_ms": round(float(np.min(ts)), 2)} | |
| def main(): | |
| model_dir = sys.argv[1] if len(sys.argv) > 1 else os.path.join(ROOT, "models", "nirnay-v1") | |
| threads = [int(x) for x in os.environ.get("BENCH_THREADS", "1,4,8,16").split(",")] | |
| proc = psutil.Process() | |
| rss0 = proc.memory_info().rss | |
| t = time.perf_counter() | |
| m = nirnay.load(model_dir, threads=max(threads)) | |
| load_ms = round((time.perf_counter() - t) * 1000, 1) | |
| res = {"meta": {"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "cpu": "2x Xeon E5-2630 v3 (HP Z840)", | |
| "model": m.name, "model_dir": model_dir}, | |
| "cold_load_ms": load_ms, "rss_delta_mb": round((proc.memory_info().rss - rss0) / 2**20, 1), | |
| "disk_mb": round(sum(os.path.getsize(os.path.join(model_dir, f)) for f in os.listdir(model_dir)) / 2**20, 1), | |
| "by_threads": {}} | |
| print("%s loaded in %.0f ms (+%.0f MB RSS, %.0f MB on disk, backend %s)" % ( | |
| m.name, load_ms, res["rss_delta_mb"], res["disk_mb"], m.backend)) | |
| res["backend"] = m.backend | |
| import torch | |
| for th in threads: | |
| m = nirnay.load(model_dir, threads=th) # ONNX Runtime fixes its thread pool per session | |
| torch.set_num_threads(th) | |
| per = {} | |
| for n in (1, 5, 10, 50): | |
| q = qs(n) | |
| def cold(): | |
| m.cache.d.clear() | |
| m.predict(STATE_EN, q) | |
| r_cold = timed(cold) | |
| r_warm = timed(lambda: m.predict(STATE_EN, q)) | |
| per["%d_questions" % n] = {"warm": r_warm, "cold_schema": r_cold, | |
| "ms_per_question_warm": round(r_warm["p50_ms"] / n, 3)} | |
| print(" threads=%2d %2dq warm p50 %7.2f ms (p95 %7.2f) cold-schema p50 %7.2f ms" % | |
| (th, n, r_warm["p50_ms"], r_warm["p95_ms"], r_cold["p50_ms"]), flush=True) | |
| res["by_threads"][str(th)] = per | |
| # throughput: many states, same questions (predict_batch) | |
| m = nirnay.load(model_dir, threads=8) | |
| torch.set_num_threads(8) | |
| states = [{"ticket": {"subject": "Case %d" % i, "messages": [{"from": "customer", "text": STATE_EN["ticket"]["messages"][0]["text"][: 80 + 3 * i]}]}} | |
| for i in range(64)] | |
| q10 = qs(10) | |
| m.predict_batch(states[:4], q10) | |
| t = time.perf_counter() | |
| m.predict_batch(states, q10) | |
| el = time.perf_counter() - t | |
| res["throughput_10q"] = {"states": len(states), "seconds": round(el, 3), | |
| "decisions_per_s": round(len(states) * 10 / el, 1), | |
| "states_per_s": round(len(states) / el, 1)} | |
| print(" throughput: %.0f decisions/s (%.1f states/s, 10 questions each)" % | |
| (res["throughput_10q"]["decisions_per_s"], res["throughput_10q"]["states_per_s"])) | |
| res["peak_rss_mb"] = round(proc.memory_info().rss / 2**20, 1) | |
| os.makedirs(os.path.dirname(OUT), exist_ok=True) | |
| json.dump(res, open(OUT, "w"), indent=2) | |
| print("wrote", OUT) | |
| if __name__ == "__main__": | |
| main() | |