-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
548 lines (470 loc) · 29.1 KB
/
Copy pathMakefile
File metadata and controls
548 lines (470 loc) · 29.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
# ============================================================================
# Makefile — MARS (Memory for Autonomous Real-time Systems)
#
# A GPU-resident multimodal memory substrate for real-time AI systems.
#
# Targets:
# make Build everything (engine, validate, latency_bench, demos)
# make engine Build the interactive benchmark CLI
# make validate Build the JSON-emitting validation harness
# make latency Build the deadline-aware latency benchmark
# make server Build the JSON-line REPL engine server
# make demos Build all four application demonstrators
# make tests Build and run host-only unit tests (no GPU required)
# make check Run the validation harness and save to results.json
# make run Run the interactive CLI at a default size
# make clean Remove all build artifacts
# make info Print nvcc version and GPU info (for vast.ai verify)
#
# Demo-specific targets (each runs at its natural sensor rate):
# make demo-av ./demos/av_perception/demo (60 Hz, 1 ms target)
# make demo-robot ./demos/robot_episodic/demo (1 kHz, 1 ms target)
# make demo-ar ./demos/ar_spatial/demo (90 Hz, 5 ms target)
# make demo-voice ./demos/voice_agent/demo (30 Hz, 20 ms target)
# make demo-embodied ./demos/embodied_scene/demo (kids-ball multimodal)
# make bench-kids-mars GPU N-sweep JSON (requires nvcc + GPU)
# make bench-kids-export Write results/kids_corpus_10k.bin (no GPU)
# make bench-kids-baselines FAISS on corpus bin (faiss-gpu + numpy)
#
# Latency benchmark presets (match the four application demonstrators):
# make bench-av ./latency_bench 60 1.0 600 2400
# make bench-robot ./latency_bench 1000 1.0 10000 6000
# make bench-ar ./latency_bench 90 5.0 4500 20000
# make bench-voice ./latency_bench 30 20.0 900 3000
#
# Sustained long-running benchmarks (real-world duration):
# make bench-sustained Run all four 30-second sustained tests
# make bench-av-30s AV perception, 30s real-time, 5K memories
# make bench-robot-15s Humanoid control, 15s real-time, 10K memories
# make bench-ar-30s AR/VR headset, 30s real-time, 50K memories
# make bench-voice-30s Voice agent, 30s real-time, 10K memories
#
# Scaling stress test (sweep corpus sizes):
# make bench-scale 60 Hz × 15s at N = 1K, 5K, 10K, 20K, 50K
#
# Requirements:
# CUDA Toolkit 11.8+, nvcc in PATH
# NVIDIA GPU with compute capability 7.0+
# C++17 host compiler (gcc 9+, clang 10+)
#
# For tests target only: just g++, no CUDA, no GPU.
# ============================================================================
NVCC ?= nvcc
CXX ?= g++
CXXFLAGS := -std=c++17 -O3 -Iinclude
DEMO_INC := -Iinclude -Idemos/common
GENCODE := -gencode arch=compute_70,code=sm_70 \
-gencode arch=compute_80,code=sm_80 \
-gencode arch=compute_86,code=sm_86 \
-gencode arch=compute_89,code=sm_89
NVCCFLAGS := $(CXXFLAGS) $(GENCODE) --expt-relaxed-constexpr
# ─── Source files ────────────────────────────────────────────────────
GRAPH_OBJS := src/cuda_graph_capture.o
WMMA_OBJS := src/wmma_similarity.o
COMMON_OBJS := src/memory_graph.o src/memory_cuda.o $(GRAPH_OBJS)
ENGINE_OBJS := $(COMMON_OBJS) $(WMMA_OBJS) src/main.o
VALIDATE_OBJS := $(COMMON_OBJS) src/validate.o
CMNG_OBJS := src/cmng_build.o src/cmng_search.o
LATENCY_OBJS := $(COMMON_OBJS) $(CMNG_OBJS) $(WMMA_OBJS) src/latency_bench.o
PERSIST_OBJS := src/persistence.o
SERVER_OBJS := $(COMMON_OBJS) $(PERSIST_OBJS) $(WMMA_OBJS) src/engine_server.o
TILED_OBJS := src/tiled_query.o src/memory_graph.o
DEMO_NAMES := av_perception robot_episodic ar_spatial voice_agent embodied_scene
DEMO_BINS := $(foreach d,$(DEMO_NAMES),demos/$(d)/demo)
KIDS_SWEEP := demos/embodied_scene/bench_kids_sweep
# ─── Primary targets ─────────────────────────────────────────────────
.PHONY: all engine validate latency server demos tests run check clean info paper
.PHONY: demo-av demo-robot demo-ar demo-voice demo-embodied
.PHONY: bench-kids-mars bench-kids-export bench-kids-baselines bench-kids-sweep-bin
.PHONY: bench-av bench-robot bench-ar bench-voice
.PHONY: bench-sustained bench-av-30s bench-robot-15s bench-ar-30s bench-voice-30s
.PHONY: bench-scale bench-large bench-fp16 bench-cmng bench-mars bench-ablation bench-ablation-quick
.PHONY: bench-av-keepalive bench-av-30s-keepalive
.PHONY: bench-graph bench-wmma bench-tiled
all: engine validate latency server demos $(KIDS_SWEEP)
engine: memory_engine
validate: validate
latency: latency_bench
server: engine_server
demos: $(DEMO_BINS)
# ─── Binary rules ────────────────────────────────────────────────────
memory_engine: $(ENGINE_OBJS)
$(NVCC) $(NVCCFLAGS) -lcublas -o $@ $^
validate: $(VALIDATE_OBJS)
$(NVCC) $(NVCCFLAGS) -lcublas -o validate $^
latency_bench: $(LATENCY_OBJS)
$(NVCC) $(NVCCFLAGS) -lcublas -o latency_bench $^
engine_server: $(SERVER_OBJS)
$(NVCC) $(NVCCFLAGS) -lcublas -o engine_server $^
bench_tiled: $(TILED_OBJS) src/bench_tiled.o
$(NVCC) $(NVCCFLAGS) -lcublas -o bench_tiled $^
# Each demo builds from its demo.cu + common objects + frame_timer.h
demos/%/demo: demos/%/demo.cu $(COMMON_OBJS) demos/common/frame_timer.h include/memory_cuda.cuh include/memory_graph.h
$(NVCC) $(NVCCFLAGS) $(DEMO_INC) -lcublas -o $@ $< $(COMMON_OBJS)
# Kids-ball embodied scene: GPU sweep benchmark (separate entry point)
$(KIDS_SWEEP): demos/embodied_scene/bench_kids_sweep.cu $(COMMON_OBJS) include/memory_cuda.cuh include/memory_graph.h
$(NVCC) $(NVCCFLAGS) $(DEMO_INC) -lcublas -o $@ $< $(COMMON_OBJS)
bench-kids-sweep-bin: $(KIDS_SWEEP)
bench-kids-mars: $(KIDS_SWEEP)
@mkdir -p results
$(KIDS_SWEEP) results/kids_ball_mars_sweep.json
# Coarse grid over episode_same_boost at fixed N; writes step_*.json + SUMMARY under dir
bench-kids-iterate: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_default
$(KIDS_SWEEP) --boost-grid 0,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.5 \
--iterate-n 10000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_default
# Second-stage refine around prior optimum (~0.25) at N=10k
bench-kids-iterate-refine: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine
$(KIDS_SWEEP) --boost-grid 0.20,0.22,0.24,0.26,0.28,0.30 \
--iterate-n 10000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine
# Same refine grid but pick best by (composite - penalty * wall_p99_ms)
bench-kids-iterate-refine-latency: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_latency
$(KIDS_SWEEP) --boost-grid 0.20,0.22,0.24,0.26,0.28,0.30 \
--iterate-n 10000 --iterate-probes 256 --iterate-wall-ms-penalty 1.0 \
--iterate-steps-dir results/iteration_steps/make_refine_latency
# Third pass: include 0.25 between 0.24 and 0.26 (saved hardware: vast_a100_refine3/)
bench-kids-iterate-refine-micro: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 10000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro
# Same micro-grid at larger N (matches multi-N sweep corpus sizes; run on GPU)
bench-kids-iterate-refine-micro-20k: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_20k
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 20000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_20k
bench-kids-iterate-refine-micro-50k: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_50k
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 50000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_50k
# 100k / 250k / 500k: same micro-grid as 10k–50k (one NSN build per make invocation).
bench-kids-iterate-refine-micro-100k: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_100k
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 100000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_100k
bench-kids-iterate-refine-micro-250k: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_250k
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 250000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_250k
bench-kids-iterate-refine-micro-500k: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_500k
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 500000 --iterate-probes 256 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_500k
# 1M nodes (~3 GiB FP32 embeddings + NSN + query ctx): needs a high-VRAM GPU (e.g. A100 40GB+).
# 128 probes/boost to keep wall time tractable; raise with --iterate-probes if you need tighter stats.
bench-kids-iterate-refine-micro-1m: $(KIDS_SWEEP)
@mkdir -p results/iteration_steps/make_refine_micro_1m
$(KIDS_SWEEP) --boost-grid 0.23,0.24,0.245,0.25,0.255,0.26 \
--iterate-n 1000000 --iterate-probes 128 \
--iterate-steps-dir results/iteration_steps/make_refine_micro_1m
# Fill ~40 GiB VRAM (default): N from scripts/kids_ball_max_n_vram.py (≈13.2M nodes @ 768-D).
# Requires comparable host DRAM (~38+ GiB embeddings during corpus build). Override: VRAM_GIB=80 make ...
VRAM_GIB ?= 40
bench-kids-vram-max-smoke: $(KIDS_SWEEP)
@N=$$(python3 scripts/kids_ball_max_n_vram.py --vram-gib $(VRAM_GIB) --reserve-mib 768 --print-n); \
mkdir -p results/iteration_steps/make_vram_max_smoke; \
echo "bench-kids-vram-max-smoke: VRAM_GIB=$(VRAM_GIB) N=$$N (see scripts/kids_ball_max_n_vram.py)"; \
$(KIDS_SWEEP) --boost-grid 0.24 --iterate-n $$N --iterate-probes 4 \
--iterate-steps-dir results/iteration_steps/make_vram_max_smoke
bench-kids-export: $(KIDS_SWEEP)
@mkdir -p results
$(KIDS_SWEEP) --dump-only results/kids_corpus_10k.bin 10000 768
bench-kids-baselines:
@python3 scripts/bench_kids_ball_faiss.py --corpus results/kids_corpus_10k.bin | tee results/kids_ball_faiss.json
# ─── Object file rules ───────────────────────────────────────────────
src/persistence.o: src/persistence.cpp include/persistence.h include/memory_graph.h
$(CXX) $(CXXFLAGS) -c $< -o $@
src/%.o: src/%.cpp include/memory_graph.h
$(NVCC) $(NVCCFLAGS) -x cu -c $< -o $@
src/%.o: src/%.cu include/memory_graph.h include/memory_cuda.cuh
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/cmng_build.o: src/cmng_build.cu include/cmng.cuh include/memory_cuda.cuh
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/cmng_search.o: src/cmng_search.cu include/cmng.cuh include/memory_cuda.cuh
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/cuda_graph_capture.o: src/cuda_graph_capture.cu include/cuda_graph_capture.h include/memory_cuda.cuh
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/wmma_similarity.o: src/wmma_similarity.cu include/wmma_similarity.cuh include/memory_cuda.cuh
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/tiled_query.o: src/tiled_query.cu include/tiled_query.h
$(NVCC) $(NVCCFLAGS) -c $< -o $@
src/bench_tiled.o: src/bench_tiled.cu include/tiled_query.h
$(NVCC) $(NVCCFLAGS) -c $< -o $@
# ─── Tests (host-only, NO CUDA NEEDED) ───────────────────────────────
tests:
$(CXX) -std=c++17 -Iinclude -O2 -o tests/run_tests \
src/memory_graph.cpp src/persistence.cpp src/memory_budget.cpp src/streaming.cpp tests/test_memory_graph.cpp
./tests/run_tests
# ─── Convenience run targets ─────────────────────────────────────────
run: memory_engine
./memory_engine 4000 2000 2000 768
check: validate
@mkdir -p results
./validate 100 768 | tee results/results.json
@echo ""
@echo "═══════════════════════════════════════════════════════════"
@echo " Validation complete. Results written to results/results.json"
@echo "═══════════════════════════════════════════════════════════"
# Demo runs (each at its natural sensor rate + deadline target)
demo-av: demos/av_perception/demo
./demos/av_perception/demo
demo-robot: demos/robot_episodic/demo
./demos/robot_episodic/demo
demo-ar: demos/ar_spatial/demo
./demos/ar_spatial/demo
demo-voice: demos/voice_agent/demo
./demos/voice_agent/demo
demo-embodied: demos/embodied_scene/demo
./demos/embodied_scene/demo
# Latency benchmark presets (rate, budget_ms, frames, corpus)
bench-av: latency_bench
@mkdir -p results
./latency_bench 60 1.0 600 2400 | tee results/bench_av.json
bench-robot: latency_bench
@mkdir -p results
./latency_bench 1000 1.0 10000 6000 | tee results/bench_robot.json
bench-ar: latency_bench
@mkdir -p results
./latency_bench 90 5.0 4500 20000 | tee results/bench_ar.json
bench-voice: latency_bench
@mkdir -p results
./latency_bench 30 20.0 900 3000 | tee results/bench_voice.json
# Keepalive variants (prevent GPU clock-state drops at low sensor rates)
bench-av-keepalive: latency_bench
@mkdir -p results
./latency_bench 60 1.0 600 2400 --keepalive | tee results/bench_av_keepalive.json
bench-av-30s-keepalive: latency_bench
@mkdir -p results
./latency_bench 60 1.0 1800 5000 --keepalive | tee results/sustained_av_30s_keepalive.json
# ─── Paper (requires tectonic: brew install tectonic) ────────────
paper:
cd paper && tectonic --reruns 3 main.tex
@echo " ✓ paper/main.pdf rebuilt"
# ─── Diagnostics ─────────────────────────────────────────────────────
info:
@echo "NVCC: $(NVCC)"
@$(NVCC) --version 2>/dev/null | tail -1 || echo " (nvcc not found)"
@echo "CXX: $(CXX)"
@$(CXX) --version 2>/dev/null | head -1 || echo " (g++ not found)"
@echo "GPU(s):"
@nvidia-smi --query-gpu=name,compute_cap,memory.total --format=csv,noheader 2>/dev/null || echo " (nvidia-smi not found)"
# ─── Sustained long-running benchmarks ────────────────────────────────
# Real-world durations: 15-30 seconds of wall-clock time at sensor rate.
# These stress-test thermal throttling, memory allocator pressure, and
# OS scheduling interference that short runs may not expose.
bench-av-30s: latency_bench
@mkdir -p results
@echo "══════════ AV Perception — 30s sustained ══════════"
./latency_bench 60 1.0 1800 5000 | tee results/sustained_av_30s.json
bench-robot-15s: latency_bench
@mkdir -p results
@echo "══════════ Robot Episodic — 15s sustained ══════════"
./latency_bench 1000 1.0 15000 10000 | tee results/sustained_robot_15s.json
bench-ar-30s: latency_bench
@mkdir -p results
@echo "══════════ AR/VR Spatial — 30s sustained ══════════"
./latency_bench 90 5.0 2700 50000 | tee results/sustained_ar_30s.json
bench-voice-30s: latency_bench
@mkdir -p results
@echo "══════════ Voice Agent — 30s sustained ══════════"
./latency_bench 30 20.0 900 10000 | tee results/sustained_voice_30s.json
bench-sustained: bench-av-30s bench-robot-15s bench-ar-30s bench-voice-30s
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " All sustained benchmarks complete."
@echo " Results in results/ folder"
@echo "═══════════════════════════════════════════════════"
# ─── Scaling stress test ─────────────────────────────────────────────
# Sweep corpus sizes at a fixed 60 Hz rate for 15 seconds (900 frames).
# Shows how latency scales with working-set size.
bench-scale: latency_bench
@mkdir -p results
@echo "══════════ Scaling: N=1K ══════════"
./latency_bench 60 1.0 900 1000 | tee results/scale_1k.json
@echo "══════════ Scaling: N=5K ══════════"
./latency_bench 60 1.0 900 5000 | tee results/scale_5k.json
@echo "══════════ Scaling: N=10K ══════════"
./latency_bench 60 1.0 900 10000 | tee results/scale_10k.json
@echo "══════════ Scaling: N=20K ══════════"
./latency_bench 60 1.0 900 20000 | tee results/scale_20k.json
@echo "══════════ Scaling: N=50K ══════════"
./latency_bench 60 1.0 900 50000 | tee results/scale_50k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " Scaling sweep complete."
@echo " Results in results/ folder"
@echo "═══════════════════════════════════════════════════"
# ─── Large corpus scaling (v4 FP16 + CUDA graph) ────────────────────
# Tests how the system scales from 50K to 2M memories with FP16 enabled.
# Use --fp16 --graph for maximum performance at large N.
bench-large: latency_bench
@mkdir -p results
@echo "══════════ Large: N=50K (FP16+Graph) ══════════"
./latency_bench 60 5.0 300 50000 --fp16 --graph | tee results/large_50k.json
@echo "══════════ Large: N=100K (FP16+Graph) ══════════"
./latency_bench 60 5.0 300 100000 --fp16 --graph | tee results/large_100k.json
@echo "══════════ Large: N=200K (FP16+Graph) ══════════"
./latency_bench 60 10.0 300 200000 --fp16 --graph | tee results/large_200k.json
@echo "══════════ Large: N=500K (FP16+Graph) ══════════"
./latency_bench 60 20.0 300 500000 --fp16 --graph | tee results/large_500k.json
@echo "══════════ Large: N=1M (FP16+Graph) ══════════"
./latency_bench 60 50.0 100 1000000 --fp16 --graph | tee results/large_1m.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " Large corpus sweep complete."
@echo "═══════════════════════════════════════════════════"
# ─── FP16 vs FP32 A/B comparison ───────────────────────────────────
# Same workload (60 Hz, 10K, 15s) with and without FP16.
bench-fp16: latency_bench
@mkdir -p results
@echo "══════════ FP32 baseline (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 | tee results/fp32_10k.json
@echo "══════════ FP16 (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 --fp16 | tee results/fp16_10k.json
@echo "══════════ FP16+Graph (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 --fp16 --graph | tee results/fp16_graph_10k.json
@echo "══════════ FP32 baseline (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 | tee results/fp32_50k.json
@echo "══════════ FP16 (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 --fp16 | tee results/fp16_50k.json
@echo "══════════ FP16+Graph (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 --fp16 --graph | tee results/fp16_graph_50k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " FP16 A/B comparison complete."
@echo "═══════════════════════════════════════════════════"
# ─── CMNG graph ANN benchmarks (v5) ──────────────────────────────────
# Greedy beam search on cross-modal navigable graph.
# Compares CMNG vs brute-force at various corpus sizes.
bench-cmng: latency_bench
@mkdir -p results
@echo "══════════ CMNG N=10K ══════════"
./latency_bench 60 1.0 300 10000 --cmng | tee results/cmng_10k.json
@echo "══════════ CMNG N=50K ══════════"
./latency_bench 60 5.0 300 50000 --cmng | tee results/cmng_50k.json
@echo "══════════ CMNG N=100K ══════════"
./latency_bench 60 5.0 300 100000 --cmng | tee results/cmng_100k.json
@echo "══════════ CMNG N=200K ══════════"
./latency_bench 60 10.0 300 200000 --cmng | tee results/cmng_200k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " CMNG benchmark sweep complete."
@echo "═══════════════════════════════════════════════════"
# ─── MARS benchmark: cuBLAS similarity + CUB radix-sort top-K ────────
# Targets FAISS-competitive latency via elimination of the top-K bottleneck.
# Sweeps N = 2.4K, 10K, 20K, 50K to show scaling.
bench-mars: latency_bench
@mkdir -p results
@echo "══════════ MARS N=2.4K (AV perception) ══════════"
./latency_bench 60 1.0 600 2400 --mars | tee results/mars_2400.json
@echo "══════════ MARS N=10K ══════════"
./latency_bench 60 1.0 600 10000 --mars | tee results/mars_10k.json
@echo "══════════ MARS N=20K ══════════"
./latency_bench 60 5.0 600 20000 --mars | tee results/mars_20k.json
@echo "══════════ MARS N=50K ══════════"
./latency_bench 60 5.0 300 50000 --mars | tee results/mars_50k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " MARS benchmark sweep complete."
@echo " Results in results/mars_*.json"
@echo "═══════════════════════════════════════════════════"
# ─── Ablation study (NSN topology contribution) ─────────────────────
# Tests 6 hypotheses about NSN design choices.
# Each variant runs at 60 Hz × 300 frames with --recall to measure
# recall@10 and cross-modal hit rate alongside latency.
#
# Variants:
# full — all 5 NSN phases, h=2 (baseline)
# no_bridges — phases 1-4 only (no cross-modal edges)
# no_hubs — phases 1,2,4,5 (no hub supernodes)
# flat — no graph, brute-force top-K only (h=0)
# h0 — full NSN but BFS disabled (h=0)
# h1 — full NSN, 1-hop BFS
# h3 — full NSN, 3-hop BFS
#
# Output: results/ablation_*.json (one file per variant × corpus size)
.PHONY: bench-ablation
bench-ablation: latency_bench
@mkdir -p results/ablation
@echo "══════════ NSN Ablation Study ══════════"
@for N in 2000 5000 10000 50000; do \
for variant in full no_bridges no_hubs flat h0 h1 h3; do \
echo "── $$variant N=$$N ──"; \
./latency_bench 60 99.0 300 $$N --recall --ablate $$variant \
| tee results/ablation/$${variant}_$${N}.json; \
done; \
done
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " Ablation study complete. Results in results/ablation/"
@echo " Parse with: python3 scripts/parse_ablation.py"
@echo "═══════════════════════════════════════════════════"
# Quick ablation at small N (for testing, ~2 min)
bench-ablation-quick: latency_bench
@mkdir -p results/ablation
@for variant in full no_bridges no_hubs flat h0 h1 h3; do \
echo "── $$variant N=5000 ──"; \
./latency_bench 60 99.0 200 5000 --recall --ablate $$variant \
| tee results/ablation/$${variant}_5000.json; \
done
# ─── CUDA Graph capture A/B comparison ──────────────────────────────
bench-graph: latency_bench
@mkdir -p results
@echo "══════════ No Graph (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 | tee results/no_graph_10k.json
@echo "══════════ With Graph (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 --graph | tee results/graph_10k.json
@echo "══════════ No Graph (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 | tee results/no_graph_50k.json
@echo "══════════ With Graph (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 --graph | tee results/graph_50k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " CUDA Graph A/B comparison complete."
@echo "═══════════════════════════════════════════════════"
# ─── WMMA tensor-core A/B comparison ─────────────────────────────────
bench-wmma: latency_bench
@mkdir -p results
@echo "══════════ FP32 scalar (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 | tee results/fp32_scalar_10k.json
@echo "══════════ FP16 scalar (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 --fp16 | tee results/fp16_scalar_10k.json
@echo "══════════ FP16 WMMA (N=10K) ══════════"
./latency_bench 60 1.0 900 10000 --fp16 --wmma | tee results/fp16_wmma_10k.json
@echo "══════════ FP32 scalar (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 | tee results/fp32_scalar_50k.json
@echo "══════════ FP16 scalar (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 --fp16 | tee results/fp16_scalar_50k.json
@echo "══════════ FP16 WMMA (N=50K) ══════════"
./latency_bench 60 5.0 900 50000 --fp16 --wmma | tee results/fp16_wmma_50k.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " WMMA tensor-core A/B comparison complete."
@echo "═══════════════════════════════════════════════════"
# ─── Tiled out-of-core benchmark (100M+ corpus) ─────────────────────
bench-tiled: bench_tiled
@mkdir -p results
@echo "══════════ Tiled: N=10M ══════════"
./bench_tiled 10000000 768 5000000 5 | tee results/tiled_10m.json
@echo "══════════ Tiled: N=50M ══════════"
./bench_tiled 50000000 768 5000000 3 | tee results/tiled_50m.json
@echo "══════════ Tiled: N=100M ══════════"
./bench_tiled 100000000 768 5000000 3 | tee results/tiled_100m.json
@echo ""
@echo "═══════════════════════════════════════════════════"
@echo " Tiled out-of-core benchmark complete."
@echo "═══════════════════════════════════════════════════"
clean:
rm -f src/*.o
rm -f memory_engine validate latency_bench engine_server bench_tiled
rm -f $(DEMO_BINS) $(KIDS_SWEEP)
rm -f tests/run_tests