Skip to main content

GPU Coverage Validation

algeon_explain_coverage tells you, before running a query, which parts of it will execute on the GPU and which will stay on the DataFusion CPU path, with a stable reason and remedy for each part that was not selected. It plans the query exactly as execution would, but does not execute it and does not wait for GPU execution capacity.

The answer is not a runtime guarantee. Waiting for GPU capacity, the memory cap for the run, GPU runtime errors, and cuGraph input checks still happen at execution time. Read the returned runtime_caveats whenever the final plan contains GPU work.

SQL surface

On a session with the Algeon native optimizer installed, call the table function with one query string literal:

SELECT row_kind,
gpu_path,
candidate_shape,
reason_code,
remedy_code,
remedy_kind,
remedy,
coverage_json
FROM algeon_explain_coverage('SELECT l_returnflag, sum(l_quantity)
FROM lineitem GROUP BY l_returnflag');

The table function returns one summary row followed by one candidate row per native-planning outcome. The Flight SQL server accepts the same projection without a string-literal escape layer:

EXPLAIN GPU SELECT l_returnflag, sum(l_quantity)
FROM lineitem GROUP BY l_returnflag;

EXPLAIN GPU FORMAT JSON SELECT l_returnflag, sum(l_quantity)
FROM lineitem GROUP BY l_returnflag;

VERBOSE is accepted as the complete row mode. FORMAT JSON uses the same Arrow schema but returns only the summary row, whose coverage_json contains all candidate evidence. EXPLAIN GPU is Flight SQL statement-query syntax; it cannot be prepared or sent to an update endpoint. Both the UDTF and Flight schema carry algeon_datafusion.explain_gpu.schema_version=2 in Arrow schema metadata so clients can identify this shared row contract without inspecting its columns. When planning produces no executable plan, the summary gpu_fragments and cpu_boundaries cells are null, not zero.

ColumnMeaning
query_idFlight SQL query identifier; null for an embedded UDTF call with no server query.
row_kindsummary for final-plan coverage or candidate for one native candidate-selection outcome.
gpu_pathnative, partial_native, cpu, or terminal rejected.
gpu_fragments, cpu_boundariesSummary-row counts for GPU fragments and DataFusion CPU boundaries.
physical_root, post_native_plan_rootSummary-row physical-plan roots. physical_root is the authoritative pre-native root captured by the retained optimizer diagnostics (null when no native optimizer diagnostic exists); post_native_plan_root is the completed executable plan's root.
candidate_shape, candidate_family, outcomeCandidate-row shape, stable shape family, and selection (selected, deferred, not_supported, or not_selected_by_cost). The summary outcome is accepted_replaced, retained_datafusion, or rejected_before_execution.
reason_code, unsupported_categoryStable candidate or terminal-rejection reason and its triage category.
remedy_code, remedy_kind, remedyStable actionable advice for a non-selected candidate. Kinds include user_action, config_action, engine_gap, cudf_rs_gap, and cpu_preferred.
detail_jsonSummary metadata or candidate detail and cost evidence.
coverage_jsonThe complete structured result on the summary row; null on candidate rows.

Validation accepts exactly one query statement. Empty input, multiple statements, non-query statements, and direct or view-indirect recursive calls to algeon_explain_coverage return a structured terminal result.

Final disposition and GPU path

The final disposition is derived by walking the executable final physical plan. It is not inferred from whether an optimizer attempted a native rewrite, and a single candidate outcome never determines it: one report can hold selected and not-supported candidates while the completed plan stays mixed.

Final dispositiongpu_pathMeaning
nativenativeThe planned path contains no known DataFusion CPU execution. GPU fragments and explicit GPU islands are counted together.
mixedpartial_nativeThe same executable plan contains GPU runtime work and at least one DataFusion CPU boundary.
datafusioncpuThe executable plan has no selected GPU runtime node.

rejected is not a final disposition: it is the planning outcome when no executable plan exists, projected as gpu_path=rejected with null fragment/boundary cells. It carries the phase, stable reason_code, and safe detail in coverage_json. Terminal source-resolution failures, an unsupported required GPU island, and a failed final-plan requirement are planning errors. By contrast, an ordinary relational capability miss is not an error: the same query remains executable on the DataFusion baseline and normally has final disposition datafusion.

Candidate outcomes are diagnostics, not the final plan

coverage_json.candidate_outcomes retains relational candidate-selection diagnostics from the native optimizer. Each entry has one of these outcome values:

OutcomeMeaningEvidence
selectedThe candidate was selected for native execution.Candidate shape (detail); reason_code, reason_kind, and category are absent.
deferredSelection is pending producer binding: the candidate waits on unresolved producer facts.Candidate shape (detail) plus the producer-binding reason_code.
not_supportedThe exact relational candidate is outside the native capability contract.reason_code, reason_kind, candidate shape (detail), and category.
not_selected_by_costThe candidate is native-capable, but an enabled preference rule retained the DataFusion plan.The same fields plus cost_evidence projected from native plan-preference facts.

Every candidate carries its stable candidate_family; every non-selected candidate also carries remedy_code, remedy_kind, and human-readable remedy both in its table row and in coverage_json. These are independent from final_disposition. A report can contain candidate diagnostics while the final plan is native because another selected candidate covers the executable path. Conversely, a not_supported or not_selected_by_cost outcome normally produces an executable DataFusion plan, not a rejected result. Candidate outcomes explain selection; final-plan domains describe the completed executable plan.

Validation uses the caller's real planning contract

Validation clones the caller's SessionState. If that state has an Algeon native optimizer rule, the clone receives an isolated copy of the exact optimizer configuration after the cloned DataFusion options are applied. Its completed-plan requirements are copied too. Validation does not install a diagnostic policy and does not plan a second time under another configuration.

coverage_json.validated_under records:

FieldMeaning
native_optimizer_rule_installedWhether the copied session had the native rule.
optimizer_config_sourceinstalled_session_rule or native_rule_absent.
execution_modeThe copied native pipeline mode, when a native rule is present.
final_plan_requirementsRequirements checked against the exact completed plan, such as no_datafusion_cpu.
session_config_fingerprint and optimizer_fingerprintStable comparison stamps for the cloned configuration.
catalog_snapshotsession_state_cloned_at_validation_call; it labels the clone and is not a catalog or table-data fingerprint.

Revalidate after catalog, view, table, or configuration changes. The fingerprints do not claim that source metadata or table contents are unchanged.

Rust surface

The SQL function and Rust API use the same validation primitive:

use algeon_datafusion::{
gpu_coverage::{QueryGpuPlanningOutcome, validate_query},
planner::FinalPlanDisposition,
};

let coverage = validate_query(&ctx, "SELECT count(*) FROM lineitem").await?;

match &coverage.planning_outcome {
QueryGpuPlanningOutcome::Planned(plan) => match plan.disposition() {
FinalPlanDisposition::Native => {}
FinalPlanDisposition::DataFusion | FinalPlanDisposition::Mixed => {
for outcome in &coverage.candidate_outcomes {
eprintln!(
"{} reason_code={} reason_kind={} category={} detail={}",
outcome.selection.as_str(),
outcome.reason_code.as_deref().unwrap_or("absent"),
outcome.reason_kind.map_or("absent", |kind| kind.as_str()),
outcome.category.as_deref().unwrap_or("absent"),
outcome.detail,
);
if let Some(remedy) = outcome.remedy {
eprintln!("{} {}: {}", remedy.code, remedy.kind.as_str(), remedy.guidance);
}
}
}
},
QueryGpuPlanningOutcome::Rejected(rejection) => {
eprintln!("{} {}: {}", rejection.phase.as_str(), rejection.reason_code, rejection.detail);
}
}

println!("{}", coverage.to_json());

The API is async because source planning can perform real I/O. It never executes the returned plan or performs GPU admission.

Runtime caveats

CodeMeaning
runtime_gpu_admission_unknownQuery-service grants are acquired only at execution time and can wait or fail under concurrency; once admitted, each grant is immutable.
device_memory_runtime_unknownAllocation, reservation, and retry outcomes depend on data and concurrency.
native_runtime_failure_has_no_cpu_rescueOnce native GPU execution starts, a native failure is terminal; Algeon does not replay it on CPU.
host_output_materializationQuery output is materialized back to host Arrow outside the GPU-execution promise.
cugraph_runtime_validation_unknowncuGraph seed, personalization, weight, and device-side checks can still fail at runtime.
execution_mode_plan_time_onlyCoverage does not acquire a device grant; capability-first admission and bounded execution happen later for the selected native plan.

Relationship to gpu_validate_call

gpu_validate_call validates one installed GPU function call's named relations and provider-owned options. Its result does not inspect the surrounding physical plan. algeon_explain_coverage inspects the whole planned query, including DataFusion boundaries feeding or consuming an explicit GPU island. Use both when composing graph SQL: validate the function call, then check coverage for the query that will execute.