feat(test): add kernel qualification coverage for GDN, MoE, and DeepSeek4 - #687
feat(test): add kernel qualification coverage for GDN, MoE, and DeepSeek4#687Graffioh wants to merge 2 commits into
Conversation
f210518 to
e5a77b2
Compare
|
@cubic-dev-ai review this PR |
@Graffioh I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 9 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
671d031 to
a74b046
Compare
There was a problem hiding this comment.
4 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="server/test/kernel_qualification.h">
<violation number="1" location="server/test/kernel_qualification.h:143">
P2: When a qualification produces no output or no metrics, `evaluate` reports a pass because `std::all_of` is true for an empty range. Reject empty comparisons and empty metric lists before declaring a case passed, otherwise missing measurements can produce a false-positive qualification.</violation>
</file>
<file name="server/test/test_kernel_qualification_core.cpp">
<violation number="1" location="server/test/test_kernel_qualification_core.cpp:73">
P3: The precision assertion is too weak to detect loss of double precision. Match the complete expected serialized value so reduced-precision JSON output fails the regression test.</violation>
</file>
<file name="server/test/test_kernel_qualification_gdn.cpp">
<violation number="1" location="server/test/test_kernel_qualification_gdn.cpp:162">
P2: The allocation guards do not surround the in-place `state` buffer, so a state-region overwrite can corrupt adjacent tensors without either guard failing. Place sentinels directly around each guarded allocation, or use a guarded backing buffer for the state and output regions.</violation>
<violation number="2" location="server/test/test_kernel_qualification_gdn.cpp:308">
P2: When the initialized GPU cannot provide the grouped-column specialization, this contract reports `fail` and exits nonzero rather than `unsupported`. Detect the device capability before qualification and return an unsupported case, or register this test only for devices with the required route.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| result.status = result.route.matched && | ||
| std::all_of(result.metrics.begin(), result.metrics.end(), | ||
| [](const Metric & metric) { return metric.passed; }) | ||
| ? Status::pass |
There was a problem hiding this comment.
P2: When a qualification produces no output or no metrics, evaluate reports a pass because std::all_of is true for an empty range. Reject empty comparisons and empty metric lists before declaring a case passed, otherwise missing measurements can produce a false-positive qualification.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/test/kernel_qualification.h, line 143:
<comment>When a qualification produces no output or no metrics, `evaluate` reports a pass because `std::all_of` is true for an empty range. Reject empty comparisons and empty metric lists before declaring a case passed, otherwise missing measurements can produce a false-positive qualification.</comment>
<file context>
@@ -0,0 +1,257 @@
+ result.status = result.route.matched &&
+ std::all_of(result.metrics.begin(), result.metrics.end(),
+ [](const Metric & metric) { return metric.passed; })
+ ? Status::pass
+ : Status::fail;
+ if (!result.route.matched) {
</file context>
| ggml_context * context = ggml_init(params); | ||
| if (!context) return result; | ||
|
|
||
| ggml_tensor * guard_before = |
There was a problem hiding this comment.
P2: The allocation guards do not surround the in-place state buffer, so a state-region overwrite can corrupt adjacent tensors without either guard failing. Place sentinels directly around each guarded allocation, or use a guarded backing buffer for the state and output regions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/test/test_kernel_qualification_gdn.cpp, line 162:
<comment>The allocation guards do not surround the in-place `state` buffer, so a state-region overwrite can corrupt adjacent tensors without either guard failing. Place sentinels directly around each guarded allocation, or use a guarded backing buffer for the state and output regions.</comment>
<file context>
@@ -0,0 +1,390 @@
+ ggml_context * context = ggml_init(params);
+ if (!context) return result;
+
+ ggml_tensor * guard_before =
+ ggml_new_tensor_1d(context, GGML_TYPE_F32, GUARD_ELEMENTS);
+ ggml_tensor * q = ggml_new_tensor_4d(
</file context>
| const PathRun candidate = run_path(backend, inputs, initial_state, true); | ||
| ggml_backend_cuda_set_graphs_disabled_override(previous_graphs_disabled); | ||
|
|
||
| const bool route_matched = reference.computed && candidate.computed && |
There was a problem hiding this comment.
P2: When the initialized GPU cannot provide the grouped-column specialization, this contract reports fail and exits nonzero rather than unsupported. Detect the device capability before qualification and return an unsupported case, or register this test only for devices with the required route.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/test/test_kernel_qualification_gdn.cpp, line 308:
<comment>When the initialized GPU cannot provide the grouped-column specialization, this contract reports `fail` and exits nonzero rather than `unsupported`. Detect the device capability before qualification and return an unsupported case, or register this test only for devices with the required route.</comment>
<file context>
@@ -0,0 +1,390 @@
+ const PathRun candidate = run_path(backend, inputs, initial_state, true);
+ ggml_backend_cuda_set_graphs_disabled_override(previous_graphs_disabled);
+
+ const bool route_matched = reference.computed && candidate.computed &&
+ reference.scalar_launches == N_STEPS &&
+ reference.grouped_launches == 0 &&
</file context>
| REQUIRE_TRUE( | ||
| json.find("1.2345678901234567e-12") != std::string::npos); | ||
| REQUIRE_TRUE( | ||
| json.find("9.87654321098765") != std::string::npos); |
There was a problem hiding this comment.
P3: The precision assertion is too weak to detect loss of double precision. Match the complete expected serialized value so reduced-precision JSON output fails the regression test.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/test/test_kernel_qualification_core.cpp, line 73:
<comment>The precision assertion is too weak to detect loss of double precision. Match the complete expected serialized value so reduced-precision JSON output fails the regression test.</comment>
<file context>
@@ -0,0 +1,74 @@
+ REQUIRE_TRUE(
+ json.find("1.2345678901234567e-12") != std::string::npos);
+ REQUIRE_TRUE(
+ json.find("9.87654321098765") != std::string::npos);
+}
</file context>
What this adds
pass,fail, andunsupportedstates, CTest-compatible exit codes, and a stablelucebox.kernel_qualification.v1JSON report.Scope
This draft covers ggml-level kernel correctness and dispatch proof. It is separate from #636, which owns model and release qualification through profiles, baselines, evidence, reports, and dashboards.
The runner follows the useful shape of llama.cpp's
tests/test-backend-ops.cpp: deterministic inputs, reference and candidate execution, non-finite rejection, and explicit tolerances. Lucebox also checks state changes, allocation guards, route counters, and unsupported hardware.The current contracts are representative, not a model-by-model test matrix. GDN covers the recurrent kernel used by the Qwen and speculative paths. The MoE and DeepSeek4 contracts cover one focused optimized route each.
What remains
mainhas Qwen 3.5 and Qwen 3.6 paths, but no Qwen 3.8 backend. This PR does not claim Qwen 3.8 model coverage.Local validation
Passed on the CPU-only macOS host:
git diff --check.Not run here:
The draft stays open until the remote GPU runners are available and these checks pass.