Skip to content

Commit 75a2bb8

Browse files
committed
[Fixup] Reflow comments to 120-col budget; drop unit-test reference in program.h
1 parent 15bc142 commit 75a2bb8

7 files changed

Lines changed: 31 additions & 39 deletions

File tree

quadrants/program/program.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,9 @@ Program::AdStackOverflowDiagnosis Program::diagnose_adstack_overflow(uint32_t ta
362362
}
363363
int64_t v = -1;
364364
if (host_resolvable && !expr.nodes.empty()) {
365-
// `evaluate_adstack_size_expr` reads the live SNode state via `SNodeRwAccessorsBank` and
366-
// const-folds the rest in plain C++. `ctx == nullptr` is safe because every leaf we kept
367-
// is host-resolvable; ETS / ETR are the only kinds that touch ctx and we filtered them
368-
// out.
365+
// `evaluate_adstack_size_expr` reads the live SNode state via `SNodeRwAccessorsBank` and const-folds the
366+
// rest in plain C++. `ctx == nullptr` is safe because every leaf we kept is host-resolvable; ETS / ETR
367+
// are the only kinds that touch ctx and we filtered them out.
369368
SizeExprLaunchScope scope;
370369
v = evaluate_adstack_size_expr(expr, const_cast<Program *>(this), nullptr);
371370
}

quadrants/program/program.h

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,11 @@ class QD_DLL_EXPORT Program {
235235
// Identity-key for idempotent re-registration. The diagnose path NEVER dereferences this pointer;
236236
// it stores all size-expression data inline (`size_exprs`) so the entry is self-contained and
237237
// immune to lifetime issues from the underlying `AdStackSizingInfo` (LLVM) /
238-
// `AdStackSizingAttribs` (SPIR-V) struct moves. Two structs because LLVM and SPIR-V backends store
239-
// launch-time strides differently (byte-indexed vs element-indexed) and SPIR-V doesn't carry the
240-
// dynamic-range-for fields LLVM needs - unifying them would be a backend-pipeline refactor far
241-
// outside this PR's scope. Inlining `size_exprs` into the registry is the cheapest way to make
242-
// the registry uniform across both backends without touching the launchers' on-the-hot-path
243-
// structs.
238+
// `AdStackSizingAttribs` (SPIR-V) struct moves. Two structs because LLVM and SPIR-V backends store launch-time
239+
// strides differently (byte-indexed vs element-indexed) and SPIR-V doesn't carry the dynamic-range-for fields LLVM
240+
// needs - unifying them would be a backend-pipeline refactor far outside this PR's scope. Inlining `size_exprs`
241+
// into the registry is the cheapest way to make the registry uniform across both backends without touching the
242+
// launchers' on-the-hot-path structs.
244243
struct AdStackSizingInfoEntry {
245244
const void *identity_key{nullptr};
246245
std::string kernel_name;
@@ -253,10 +252,9 @@ class QD_DLL_EXPORT Program {
253252
int task_id_in_kernel,
254253
std::vector<int> allocated_max_sizes,
255254
std::vector<SerializedSizeExpr> size_exprs);
256-
// Refresh just the `size_exprs` snapshot in an existing registry entry. Used by the LLVM launcher
257-
// on the first launch of a task whose codegen-time registration could not capture size_exprs (the
258-
// codegen-time `current_task->ad_stack` had not yet been finalized). No-op for `id == 0` and ids
259-
// outside the registry range.
255+
// Refresh just the `size_exprs` snapshot in an existing registry entry. Used by the LLVM launcher on the first
256+
// launch of a task whose codegen-time registration could not capture size_exprs (the codegen-time
257+
// `current_task->ad_stack` had not yet been finalized). No-op for `id == 0` and ids outside the registry range.
260258
void update_adstack_sizing_info_size_exprs(uint32_t id, std::vector<SerializedSizeExpr> size_exprs);
261259
// Returns a *copy* of the registry entry (not a pointer into the underlying vector) so the caller can
262260
// safely hold the data across operations that might trigger another `register_adstack_sizing_info` and
@@ -278,9 +276,8 @@ class QD_DLL_EXPORT Program {
278276
bool confirmed_invalid_cache{false};
279277
};
280278
AdStackOverflowDiagnosis diagnose_adstack_overflow(uint32_t task_id) const;
281-
// Convenience wrapper retained for the C++ unit test surface that exercises just the message
282-
// formatting; production code uses `diagnose_adstack_overflow` to also act on the confirmed-cause
283-
// signal.
279+
// Convenience wrapper that returns just the message string; production code uses `diagnose_adstack_overflow` to
280+
// also act on the confirmed-cause signal.
284281
std::string diagnose_adstack_overflow_message(uint32_t task_id) const;
285282

286283
/**

quadrants/runtime/cpu/kernel_launcher.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ class KernelLauncher : public LLVM::KernelLauncher {
2121
// serial), so no launch-time gtmp resolution is needed on this backend.
2222
std::vector<AdStackSizingInfo> ad_stacks;
2323
std::vector<std::size_t> num_threads_per_task;
24-
// Per-task snode-write set / arg-write set, copied off `OffloadedTask::snode_writes` /
25-
// `arr_writes` at register time. Used by `launch_llvm_kernel` to bump
26-
// `Program::snode_write_gen_` / `ndarray_data_gen_` before each launch so the per-task adstack
27-
// metadata cache invalidates when this kernel mutates a SNode / ndarray a downstream
24+
// Per-task snode-write set / arg-write set, copied off `OffloadedTask::snode_writes` / `arr_writes` at register
25+
// time. Used by `launch_llvm_kernel` to bump `Program::snode_write_gen_` / `ndarray_data_gen_` before each launch
26+
// so the per-task adstack metadata cache invalidates when this kernel mutates a SNode / ndarray a downstream
2827
// `size_expr` reads.
2928
std::vector<std::vector<int>> snode_writes_per_task;
3029
std::vector<std::vector<int>> arr_writes_per_task;

quadrants/runtime/gfx/runtime.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,9 +1037,8 @@ void GfxRuntime::synchronize() {
10371037
if (prog != nullptr) {
10381038
auto diag = prog->diagnose_adstack_overflow(task_id_val);
10391039
diagnostic = std::move(diag.message);
1040-
// See `LlvmRuntimeExecutor::check_adstack_overflow` for the rationale; only invalidate when
1041-
// the sizer rerun confirmed a stale cache (DLPack-bypass) so a Quadrants pre-pass bug is
1042-
// not silently masked.
1040+
// See `LlvmRuntimeExecutor::check_adstack_overflow` for the rationale; only invalidate when the sizer rerun
1041+
// confirmed a stale cache (DLPack-bypass) so a Quadrants pre-pass bug is not silently masked.
10431042
if (diag.confirmed_invalid_cache) {
10441043
prog->adstack_cache().invalidate_all();
10451044
}

quadrants/runtime/llvm/llvm_adstack_lazy_claim.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -642,11 +642,10 @@ void LlvmRuntimeExecutor::check_adstack_overflow() {
642642
if (flag == 0) {
643643
return;
644644
}
645-
// Drain the companion task-id slot in the same poll. Both slots cleared so the next overflow records
646-
// a fresh identity. `task_id == 0` means the kernel that overflowed pre-dates the registry wiring or
647-
// its `ad_stack.registry_id` was unset for any reason (e.g. a deserialised offline-cache task that has
648-
// not yet been re-registered); the diagnose helper falls through to the generic dual-cause message in
649-
// that case.
645+
// Drain the companion task-id slot in the same poll. Both slots cleared so the next overflow records a fresh
646+
// identity. `task_id == 0` means the kernel that overflowed pre-dates the registry wiring or its
647+
// `ad_stack.registry_id` was unset for any reason (e.g. a deserialised offline-cache task that has not yet been
648+
// re-registered); the diagnose helper falls through to the generic dual-cause message in that case.
650649
uint32_t task_id = 0;
651650
if (adstack_overflow_task_id_host_ptr_ != nullptr) {
652651
int64_t recorded = __atomic_exchange_n(adstack_overflow_task_id_host_ptr_, (int64_t)0, __ATOMIC_RELAXED);
@@ -667,8 +666,8 @@ void LlvmRuntimeExecutor::check_adstack_overflow() {
667666
}
668667
} else {
669668
diagnostic =
670-
"Adstack overflow: a reverse-mode autodiff kernel pushed more elements than the adstack "
671-
"capacity allows.";
669+
"Adstack overflow: a reverse-mode autodiff kernel pushed more elements than the adstack capacity "
670+
"allows.";
672671
}
673672
throw QuadrantsAssertionError(
674673
"Adstack overflow: a reverse-mode autodiff kernel pushed more elements "

tests/cpp/program/test_diagnose_adstack_overflow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ namespace quadrants::lang {
1010
TEST(DiagnoseAdstackOverflow, RegistryAndLookup) {
1111
Program prog(host_arch());
1212

13-
// Two distinct sizing infos. The pointer is just an identity key for `Program::register_*` -
14-
// the test does not deref.
13+
// Two distinct sizing infos. The pointer is just an identity key for `Program::register_*` - the test does not
14+
// deref.
1515
int dummy_a = 0;
1616
int dummy_b = 0;
1717
uint32_t id_a = prog.register_adstack_sizing_info(static_cast<const void *>(&dummy_a), "kernel_a", /*task=*/0,

tests/python/test_adstack.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,10 +1226,9 @@ def test_adstack_overflow_diagnostic_and_auto_recovery():
12261226
# 3. The next reverse launch reads cached `max_size = 2`, pushes 64, overflows. The host poll
12271227
# raises with the enriched diagnostic naming kernel + offload-task index. The raise site
12281228
# ALSO bulk-invalidates the adstack-sizer caches on its way out.
1229-
# 4. The user catches the exception. They do NOT need to manually adjust `ad_stack_size`. On
1230-
# the NEXT reverse launch, the sizer reruns from scratch (cache invalidated), reads the
1231-
# mutated `n[0] = 64`, sizes capacity to 64, and the kernel runs to completion with the
1232-
# correct gradient.
1229+
# 4. The user catches the exception. They do NOT need to manually adjust `ad_stack_size`. On the NEXT reverse
1230+
# launch, the sizer reruns from scratch (cache invalidated), reads the mutated `n[0] = 64`, sizes capacity
1231+
# to 64, and the kernel runs to completion with the correct gradient.
12331232
#
12341233
# This auto-recovery contract is what lets the user's training-loop code recover from a
12351234
# transient cache-staleness window without per-iteration retries: the offending data has
@@ -1286,8 +1285,8 @@ def compute(n_arr: qd.types.ndarray(dtype=qd.i32, ndim=1)):
12861285
# LLVM-CPU the host-eval branch always re-evaluates the size expression per launch via
12871286
# `try_size_expr_cache_hit`, which observes the live ndarray read and self-invalidates on
12881287
# mismatch - that path never raises here, so the second compute.grad call returns cleanly. The
1289-
# `pytest.raises if shortcut else nullcontext` pattern handles both paths uniformly without
1290-
# arch-narrowing the test.
1288+
# `pytest.raises if shortcut else nullcontext` pattern handles both paths uniformly without arch-narrowing the
1289+
# test.
12911290
y[None] = 0.0
12921291
compute(n)
12931292
y.grad[None] = 1.0

0 commit comments

Comments
 (0)