[0.1.38] 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.
This commit is contained in:
Musa Mahmood 2026-10-17 21:32:06 -04:00
parent 8b76e506f3
commit 68ab91b03c
3 changed files with 12 additions and 3 deletions

View File

@ -52,7 +52,7 @@ APP_NAME :: "mcap";
APP_FOLDER_NAME :: "mcap";
GIT_BRANCH :: "check";
GIT_HASH :: "-";
VERSION :: "0.1.37";
VERSION :: "0.1.38";
BUILD_DATE :: "-";
DEBUG :: true;
COMPILE_TESTS :: true;

View File

@ -8,7 +8,7 @@ APP_NAME :: "mcap";
APP_FOLDER_NAME :: "mcap";
APP_BUNDLE_IDENTIFIER :: "com.example.mcap";
VERSION :: "0.1.37";
VERSION :: "0.1.38";
// 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";

View File

@ -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);
}