From 4c2a39ed55b867eb2ef12bd5c0ba252c512d573d Mon Sep 17 00:00:00 2001 From: Musa Mahmood Date: Sat, 17 Oct 2026 21:32:06 -0400 Subject: [PATCH] [0.1.28] gpu-bench: OCR's GPU memory budget in the results What the engine measured its runs to need (detector MB fixed + per megapixel, recognizer per 1000 line-pixels), the limit at the end, and budget_waits, the runs that waited for GPU memory, in the stages. --- check_targets.jai | 2 +- first.jai | 2 +- tools/gpu_bench/gpu_bench.jai | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/check_targets.jai b/check_targets.jai index 51b722e..b6dfa3d 100644 --- a/check_targets.jai +++ b/check_targets.jai @@ -47,7 +47,7 @@ APP_NAME :: "mcap"; APP_FOLDER_NAME :: "mcap"; GIT_BRANCH :: "check"; GIT_HASH :: "-"; -VERSION :: "0.1.27"; +VERSION :: "0.1.28"; BUILD_DATE :: "-"; DEBUG :: true; COMPILE_TESTS :: true; diff --git a/first.jai b/first.jai index 2eff64f..9e7544e 100644 --- a/first.jai +++ b/first.jai @@ -8,7 +8,7 @@ APP_NAME :: "mcap"; APP_FOLDER_NAME :: "mcap"; APP_BUNDLE_IDENTIFIER :: "com.example.mcap"; -VERSION :: "0.1.27"; +VERSION :: "0.1.28"; // Where everything goes: bin/, or bin-headless/ for builds made with no_crash_dialog, so automated // builds never write over the ones you run by hand. build_directory := "bin"; diff --git a/tools/gpu_bench/gpu_bench.jai b/tools/gpu_bench/gpu_bench.jai index 16f0d4e..c5f4c62 100644 --- a/tools/gpu_bench/gpu_bench.jai +++ b/tools/gpu_bench/gpu_bench.jai @@ -151,6 +151,7 @@ Run :: struct { stages: string; // where the time went, per item batch: s64; gpu: Gpu_Stats; + budget: string; // OCR on the GPU: what its memory budget measured (modules/OCR/budget.jai), or "" trace: [..] string; // the GPU's memory above the baseline, MB, after each step: load:812 first:1020 warm1:... pass1:.../peak... explanation: string; // why a GPU run is on the CPU } @@ -322,6 +323,10 @@ run_task :: (task: *Task, prefer_gpu: bool, corpus: *Corpus) -> Run { if prefer_gpu && !ocr_gpu run.explanation = copy_string(ocr_why); run.provider = sprint("%", ocr_provider(engine.ocr)); run.batch = engine.ocr.rec_batch; + b := engine.ocr.budget; + if b.enabled run.budget = sprint("detector %+% MB/MP, recognizer %+% MB per 1000 line-px", FF(b.det_fixed / MEGABYTE, 0), FF(b.det_per_pixel * 1_000_000 / MEGABYTE, 0), + FF(b.rec_fixed / MEGABYTE, 0), FF(b.rec_per_column * 1000 / MEGABYTE, 1)); + else if engine.ocr.provider == .CUDA run.budget = "off (the arena could not be measured)"; } case .LABELS; #through; case .LABELS_TEXT; @@ -457,7 +462,8 @@ run_task :: (task: *Task, prefer_gpu: bool, corpus: *Corpus) -> Run { per := cast(float64) max(run.items * options.repeats, 1) * 1000; if task.kind == .OCR { s := ocr_stats(engine.ocr); - run.stages = sprint("detect:%,orient:%,recognize:%", FF(s.detect_us / per, 2), FF(s.orientation_us / per, 2), FF(s.recognize_us / per, 2)); + run.stages = sprint("detect:%,orient:%,recognize:%,budget_waits:%", FF(s.detect_us / per, 2), FF(s.orientation_us / per, 2), FF(s.recognize_us / per, 2), s.budget_waits); + if engine.ocr.budget.enabled run.budget = sprint("%; limit % MB at the end", run.budget, FF(engine.ocr.budget.limit / MEGABYTE, 0)); } else if task.kind == .SEGMENT { s := engine.segment.stats; run.stages = sprint("prepare:%,model:%,post:%", FF(s.prepare_us / per, 2), FF(s.model_us / per, 2), FF(s.post_us / per, 2)); @@ -501,6 +507,7 @@ print_run :: (task: *Task, run: Run) { if run.megapixels print(", % megapixels/s", FF(run.megapixels / m.median, 1)); print("\n"); if run.stages print(" per %, summed over threads (ms): %\n", run.unit, run.stages); + if run.budget print(" GPU memory budget: %\n", run.budget); if run.gpu.samples print(" GPU: % MB more memory at the peak, % percent busy, % W, % MHz, up to % C\n", FF(run.gpu.peak_mb - run.gpu.baseline_mb, 0), FF(run.gpu.util_sum / run.gpu.samples, 0), FF(run.gpu.power_sum / run.gpu.samples, 0), FF(run.gpu.clock_sum / run.gpu.samples, 0), FF(run.gpu.temperature_max, 0)); @@ -671,6 +678,8 @@ hash_file_cached :: (path: string) -> string { return hash; } +MEGABYTE :: 1024.0 * 1024; + seconds_since :: (start: Apollo_Time) -> float64 { return to_float64_seconds(current_time_monotonic() - start); }