From b6f24d752db0062cc389fa0ff7564459185f5fe6 Mon Sep 17 00:00:00 2001 From: David Krasowska Date: Mon, 14 Sep 2026 05:35:20 +0200 Subject: [PATCH] rename FUSION_LOOKAHEAD -> QUEUE_ABSORB_LIMIT [regression ci] --- Makefile | 4 ++-- benchmarks/src/config.jl | 2 +- benchmarks/src/tuning.jl | 17 ++++++++++------- benchmarks/test/tests/timings.jl | 2 +- benchmarks/test/tests/tuning.jl | 14 +++++++------- host/detail/queue.cc | 2 +- julia/src/display.jl | 2 +- test/framework.cc | 2 +- test/framework.h | 2 +- 9 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 78c58b6..915ea87 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ JIT_PIPELINE_FALLBACK ?= 0 # how many unique kernels to batch before triggering a JIT compile JIT_BATCH_SIZE ?= 16 # how many pending queue events to scan ahead when looking for fusion candidates -FUSION_LOOKAHEAD ?= 32 +QUEUE_ABSORB_LIMIT ?= 32 # horizontal fusion: max independent parallel chains per kernel pass MAX_HFUSE_CHAINS ?= 9 # vertical fusion: max RPN opcodes per chain (caps how deep chains can be fused) @@ -176,7 +176,7 @@ reconfigure: @echo "PERFETTO_HOME=$(PERFETTO_HOME)" >> $(CONFIG_STAMP) @echo "DEBUG_KEEP_JIT_DIR=$(DEBUG_KEEP_JIT_DIR)" >> $(CONFIG_STAMP) @echo "ENABLE_PROMOTION_REDUCTIONS=$(ENABLE_PROMOTION_REDUCTIONS)" >> $(CONFIG_STAMP) - @echo "FUSION_LOOKAHEAD=$(FUSION_LOOKAHEAD)" >> $(CONFIG_STAMP) + @echo "QUEUE_ABSORB_LIMIT=$(QUEUE_ABSORB_LIMIT)" >> $(CONFIG_STAMP) @echo "ENABLE_OOM_RECOVERY=1" >> $(CONFIG_STAMP) @echo "MAX_HFUSE_CHAINS=$(MAX_HFUSE_CHAINS)" >> $(CONFIG_STAMP) @echo "MAX_VFUSE_OPS=$(MAX_VFUSE_OPS)" >> $(CONFIG_STAMP) diff --git a/benchmarks/src/config.jl b/benchmarks/src/config.jl index 610f7b4..1369467 100644 --- a/benchmarks/src/config.jl +++ b/benchmarks/src/config.jl @@ -112,7 +112,7 @@ struct FusionProfile end const FUSION_BUILD_KNOBS = ( - "FUSION_LOOKAHEAD", + "QUEUE_ABSORB_LIMIT", "MAX_HFUSE_CHAINS", "JIT_BATCH_SIZE", "MAX_VFUSE_OPS", diff --git a/benchmarks/src/tuning.jl b/benchmarks/src/tuning.jl index 8bdf80b..db5ed07 100644 --- a/benchmarks/src/tuning.jl +++ b/benchmarks/src/tuning.jl @@ -1,5 +1,5 @@ const DEFAULT_FUSION_BUILD = Dict( - "FUSION_LOOKAHEAD" => 128, + "QUEUE_ABSORB_LIMIT" => 32, "MAX_HFUSE_CHAINS" => 9, "JIT_BATCH_SIZE" => 16, "MAX_VFUSE_OPS" => 128, @@ -8,7 +8,6 @@ const DEFAULT_FUSION_BUILD = Dict( ) const DEFAULT_FUSION_SEARCH = Dict( - "FUSION_LOOKAHEAD" => [0, 1, 2, 4, 8, 16, 32, 64, 128], # 9 is the ceiling: a tenth chain overflows WRAM at stack depth 3. "MAX_HFUSE_CHAINS" => [1, 2, 4, 6, 8, 9], "JIT_BATCH_SIZE" => [0, 1, 2, 4, 8, 16, 32], @@ -16,7 +15,7 @@ const DEFAULT_FUSION_SEARCH = Dict( ) const CORE_FUSION_KNOBS = ( - "FUSION_LOOKAHEAD", + "QUEUE_ABSORB_LIMIT", "MAX_HFUSE_CHAINS", "JIT_BATCH_SIZE", "MAX_VFUSE_OPS", @@ -72,6 +71,10 @@ function coordinate_descent(seed::Dict{String,Int}, search, passes::Int, for pass in 1:passes changed = false for knob in CORE_FUSION_KNOBS + # A knob with no candidate list is not swept this run: the absorb + # limit is out of the default search but --absorb-limit puts it + # back, so the order here stays canonical either way. + haskey(search, knob) || continue local_build, local_result = best, best_result for candidate in unique([best[knob]; search[knob]]) trial = copy(best) @@ -101,7 +104,7 @@ function tune_usage(io::IO = stdout) --warmup N Override warmup iterations --iterations N Override measured iterations --passes N Maximum coordinate-descent passes - --lookahead N[,N...] FUSION_LOOKAHEAD candidates + --absorb-limit N[,N...] QUEUE_ABSORB_LIMIT candidates --hfuse-chains N[,N...] MAX_HFUSE_CHAINS candidates --jit-batch N[,N...] JIT_BATCH_SIZE candidates --vfuse-ops N[,N...] MAX_VFUSE_OPS candidates @@ -151,7 +154,7 @@ function parse_tune_args(args) options.reset = true options.resume = false elseif arg in ("--dpus", "--elements-per-dpu", "--warmup", "--iterations", - "--passes", "--lookahead", "--hfuse-chains", "--jit-batch", + "--passes", "--absorb-limit", "--hfuse-chains", "--jit-batch", "--vfuse-ops", "--workspace", "--profiles", "--checkpoints", "--timeout", "--build-timeout", "--config") value = option_value(args, index, arg) @@ -167,8 +170,8 @@ function parse_tune_args(args) elseif arg == "--passes" options.passes = parse(Int, value) options.passes > 0 || error("--passes must be positive") - elseif arg == "--lookahead" - options.search["FUSION_LOOKAHEAD"] = nonnegative_list(value) + elseif arg == "--absorb-limit" + options.search["QUEUE_ABSORB_LIMIT"] = nonnegative_list(value) elseif arg == "--hfuse-chains" options.search["MAX_HFUSE_CHAINS"] = int_list(value) elseif arg == "--jit-batch" diff --git a/benchmarks/test/tests/timings.jl b/benchmarks/test/tests/timings.jl index 531ddaf..3ae1650 100644 --- a/benchmarks/test/tests/timings.jl +++ b/benchmarks/test/tests/timings.jl @@ -43,7 +43,7 @@ const SAMPLE_APP_TIME = @test run["min"] == "3.1" @test run["max"] == "3.4" @test [run[knob] for knob in BenchmarkRunner.FUSION_BUILD_KNOBS] == - ["128", "9", "16", "128", "11", "4"] + ["32", "9", "16", "128", "11", "4"] sections = csv_records(BenchmarkRunner.sections_csv(path)) @test length(sections) == 4 diff --git a/benchmarks/test/tests/tuning.jl b/benchmarks/test/tests/tuning.jl index ff3637e..d5be725 100644 --- a/benchmarks/test/tests/tuning.jl +++ b/benchmarks/test/tests/tuning.jl @@ -4,17 +4,17 @@ [1, 2, 4, 6, 8, 9] seed = copy(BenchmarkRunner.DEFAULT_FUSION_BUILD) search = Dict(knob => [value] for (knob, value) in seed) - search["FUSION_LOOKAHEAD"] = [1, 2, 3] + search["QUEUE_ABSORB_LIMIT"] = [1, 2, 3] evaluations = Ref(0) evaluate = build -> begin evaluations[] += 1 - objective = Float64((build["FUSION_LOOKAHEAD"] - 2)^2 + 1) + objective = Float64((build["QUEUE_ABSORB_LIMIT"] - 2)^2 + 1) BenchmarkRunner.TuneResult("ok", objective, [objective], [(1, 1)]) end best, result = BenchmarkRunner.coordinate_descent(seed, search, 3, evaluate) - @test best["FUSION_LOOKAHEAD"] == 2 + @test best["QUEUE_ABSORB_LIMIT"] == 2 @test result.objective == 1.0 @test evaluations[] < 3 * sum(length, values(search)) end @@ -32,7 +32,7 @@ end TOML.print(io, profile) end loaded = BenchmarkRunner.load_fusion_profile(directory, "elementwise") - @test loaded.build["FUSION_LOOKAHEAD"] == 1 + @test loaded.build["QUEUE_ABSORB_LIMIT"] == 1 text = captured_output() do run_cli([ @@ -42,7 +42,7 @@ end ]) end @test occursin("Using fusion profile", text) - @test occursin("FUSION_LOOKAHEAD=1", text) + @test occursin("QUEUE_ABSORB_LIMIT=1", text) end end @@ -65,7 +65,7 @@ end result = BenchmarkRunner.TuneResult("ok", 4.5, [4.5], [(2, 64)]) checkpoint = BenchmarkRunner.load_checkpoint(config, spec, options) @test BenchmarkRunner.record!( - checkpoint, build, result, 1, "FUSION_LOOKAHEAD", 128) + checkpoint, build, result, 1, "QUEUE_ABSORB_LIMIT", 128) resumed = BenchmarkRunner.load_checkpoint( config, spec, BenchmarkRunner.TuneOptions( @@ -103,7 +103,7 @@ end failed = BenchmarkRunner.TuneResult( "runtime_failed", Inf, Float64[], Tuple{Int,Int}[]) BenchmarkRunner.record!(checkpoint, copy(BenchmarkRunner.DEFAULT_FUSION_BUILD), - failed, 1, "FUSION_LOOKAHEAD", 128) + failed, 1, "QUEUE_ABSORB_LIMIT", 128) resumed = BenchmarkRunner.load_checkpoint(config, spec, options) @test isempty(resumed.cache) @test length(resumed.trials) == 1 diff --git a/host/detail/queue.cc b/host/detail/queue.cc index c8c35a9..e36546f 100644 --- a/host/detail/queue.cc +++ b/host/detail/queue.cc @@ -474,7 +474,7 @@ void EventQueue::grow_fusion_batch(const std::shared_ptr& e) { #if PIPELINE if (e->op == Event::OperationType::COMPUTE) { size_t absorbed = 0; - while (absorbed < FUSION_LOOKAHEAD && !operations_.empty()) { + while (absorbed < QUEUE_ABSORB_LIMIT && !operations_.empty()) { auto next = operations_.front(); if (next->op != Event::OperationType::COMPUTE) break; if (!try_fuse(e, next)) break; diff --git a/julia/src/display.jl b/julia/src/display.jl index 21448e1..7e3921d 100644 --- a/julia/src/display.jl +++ b/julia/src/display.jl @@ -77,7 +77,7 @@ function versioninfo(io::IO = stdout) " batch=", cfg("JIT_BATCH_SIZE"))) _field(io, "Build", string(inst("BUILD_TYPE"), ", ", cfg("CXX_STANDARD"), ", ", inst("CXX"))) - _field(io, "Fusion", string("lookahead=", cfg("FUSION_LOOKAHEAD"), + _field(io, "Fusion", string("absorb=", cfg("QUEUE_ABSORB_LIMIT"), " chains=", cfg("MAX_HFUSE_CHAINS"), " ops=", cfg("MAX_VFUSE_OPS"))) _field(io, "Slots", string(MAX_VFUSE_INPUTS, " operands, ", diff --git a/test/framework.cc b/test/framework.cc index aebca3b..e9a0e17 100644 --- a/test/framework.cc +++ b/test/framework.cc @@ -169,7 +169,7 @@ void print_build_config() { << " MAX_VFUSE_OPS=" << MAX_VFUSE_OPS << " MAX_VFUSE_INPUTS=" << MAX_VFUSE_INPUTS << "\n MAX_PIPELINE_STACK_DEPTH=" << MAX_PIPELINE_STACK_DEPTH - << " FUSION_LOOKAHEAD=" << FUSION_LOOKAHEAD + << " QUEUE_ABSORB_LIMIT=" << QUEUE_ABSORB_LIMIT << " BLOCK_SIZE=" << BLOCK_SIZE << " NR_TASKLETS=" << NR_TASKLETS << "\n"; } diff --git a/test/framework.h b/test/framework.h index 86011af..6955472 100644 --- a/test/framework.h +++ b/test/framework.h @@ -217,7 +217,7 @@ constexpr size_t max_reduction_chains() { constexpr size_t max_hfuse_chains() { return (size_t)MAX_HFUSE_CHAINS; } constexpr size_t max_combined_inputs() { return (size_t)MAX_COMBINED_INPUTS; } constexpr size_t max_vfuse_ops() { return (size_t)MAX_VFUSE_OPS; } -constexpr size_t fusion_lookahead() { return (size_t)FUSION_LOOKAHEAD; } +constexpr size_t queue_absorb_limit() { return (size_t)QUEUE_ABSORB_LIMIT; } // Turns a limit into an expected kernel count. constexpr size_t ceil_div(size_t a, size_t b) { return (a + b - 1) / b; }