use baracuda_kernels_types::OperandDesc;
use crate::fkc::verify::{HostTensor, fill_deterministic, to_bytes};
use crate::jit_adopt::element_kind_to_dtype;
use crate::jit_ingest::VerifyVerdict;
#[cfg(feature = "cuda")]
use crate::pipelined::{PipelinedExecutor, StorageCache};
#[cfg(feature = "cuda")]
use fuel_cuda_backend::{CudaDevice, CudaStorageBytes};
#[cfg(feature = "cuda")]
use fuel_graph::jit::PatternNode;
#[cfg(feature = "cuda")]
use fuel_graph::opt::lower_to_base_map;
#[cfg(feature = "cuda")]
use fuel_graph::registry::{FusedOpId, FusedOpParams};
#[cfg(feature = "cuda")]
use fuel_graph::runtime_fused::emit_region;
#[cfg(feature = "cuda")]
use fuel_graph::topo_order_multi;
#[cfg(feature = "cuda")]
use fuel_graph::{Graph, Node, NodeId, Op};
#[cfg(feature = "cuda")]
use fuel_ir::probe::BackendId;
#[cfg(feature = "cuda")]
use fuel_ir::{DType, Error, Result, Shape};
#[cfg(feature = "cuda")]
use std::sync::{Arc, RwLock};
#[cfg_attr(not(feature = "cuda"), allow(dead_code))]
pub fn admission_probes(operands: &[OperandDesc], seed: u64) -> Vec<Vec<HostTensor>> {
probe_from_operands(operands, seed)
.into_iter()
.chain(special_value_probe_from_operands(operands))
.collect()
}
#[cfg_attr(not(feature = "cuda"), allow(dead_code))]
pub fn combine_probe_verdicts(per_probe: Vec<VerifyVerdict>) -> VerifyVerdict {
if per_probe.is_empty() {
return VerifyVerdict::Fail {
claim: "probe",
detail: "no probes were run, so no claim was verified — an empty probe set \
must never read as a pass"
.to_string(),
};
}
let mut failures: Vec<String> = Vec::new();
let mut inconclusive: Option<(&'static str, String)> = None;
for (i, v) in per_probe.iter().enumerate() {
match v {
VerifyVerdict::Pass => {}
VerifyVerdict::Fail { claim, detail } => {
failures.push(format!("probe {i} ({claim}): {detail}"));
}
VerifyVerdict::Inconclusive { claim, detail } => {
if inconclusive.is_none() {
inconclusive = Some((claim, detail.clone()));
}
}
}
}
if !failures.is_empty() {
return VerifyVerdict::Fail {
claim: "probe_set",
detail: format!(
"{} of {} probes failed: {}",
failures.len(),
per_probe.len(),
failures.join("; ")
),
};
}
if let Some((claim, detail)) = inconclusive {
return VerifyVerdict::Inconclusive { claim, detail };
}
VerifyVerdict::Pass
}
#[cfg_attr(not(feature = "cuda"), allow(dead_code))]
const SPECIAL_F32: [f32; 8] = [
f32::NAN,
f32::INFINITY,
f32::NEG_INFINITY,
0.0,
-0.0,
1.0,
-1.0,
f32::from_bits(1),
];
#[cfg_attr(not(feature = "cuda"), allow(dead_code))]
pub fn special_value_probe_from_operands(operands: &[OperandDesc]) -> Option<Vec<HostTensor>> {
operands
.iter()
.enumerate()
.map(|(i, operand)| {
let rank = operand.rank as usize;
let shape: Vec<usize> = operand.shape[..rank].iter().map(|&d| d as usize).collect();
let extent: usize = shape.iter().product();
let dtype = element_kind_to_dtype(operand.dtype)?;
let is_float = matches!(
dtype,
fuel_ir::DType::F32
| fuel_ir::DType::F64
| fuel_ir::DType::F16
| fuel_ir::DType::BF16
);
let vals: Vec<f32> = if is_float {
let stride = 8usize.saturating_pow(i as u32).max(1);
(0..extent)
.map(|k| SPECIAL_F32[(k / stride) % SPECIAL_F32.len()])
.collect()
} else {
fill_deterministic(extent, 0x5EED_5EC0 ^ (i as u64))
};
let bytes = to_bytes(dtype, &vals)?;
Some(HostTensor {
dtype,
shape,
bytes,
})
})
.collect()
}
#[cfg_attr(not(feature = "cuda"), allow(dead_code))]
pub fn probe_from_operands(operands: &[OperandDesc], seed: u64) -> Option<Vec<HostTensor>> {
operands
.iter()
.enumerate()
.map(|(i, operand)| {
let rank = operand.rank as usize;
let shape: Vec<usize> = operand.shape[..rank].iter().map(|&d| d as usize).collect();
let extent: usize = shape.iter().product();
let dtype = element_kind_to_dtype(operand.dtype)?;
let vals = fill_deterministic(extent, seed ^ (i as u64));
let bytes = to_bytes(dtype, &vals)?;
Some(HostTensor {
dtype,
shape,
bytes,
})
})
.collect()
}
#[cfg(feature = "cuda")]
pub fn reference_output(
decompose: &PatternNode,
probe: &[HostTensor],
out_dtype: DType,
out_shape: Vec<usize>,
device: &CudaDevice,
) -> Result<HostTensor> {
let mut storages: Vec<Arc<RwLock<fuel_memory::Storage>>> = Vec::with_capacity(probe.len());
for t in probe {
let cb = CudaStorageBytes::from_cpu_bytes(device, &t.bytes)?;
storages.push(Arc::new(RwLock::new(fuel_memory::Storage::new(
fuel_memory::BackendStorage::Cuda(cb),
t.dtype,
))));
}
let graph = Arc::new(RwLock::new(Graph::new()));
let (input_ids, sink) = {
let mut g = graph
.write()
.map_err(|_| Error::Msg("reference_output: graph RwLock poisoned".to_string()))?;
let input_ids: Vec<NodeId> = probe
.iter()
.map(|t| {
g.push(Node {
op: Op::Const,
inputs: vec![],
shape: Shape::from_dims(&t.shape),
dtype: t.dtype,
})
})
.collect();
let n_inputs = input_ids.len();
let sink = emit_region(&mut g, decompose, &input_ids, &[]);
for id in n_inputs..=sink.0 {
g.set_target_backend(NodeId(id), BackendId::Cuda);
}
(input_ids, sink)
};
let mut cache = StorageCache::new();
for (id, storage) in input_ids.iter().zip(storages) {
cache.insert(*id, storage);
}
let (out_arc, _layout) = PipelinedExecutor::realize(graph, sink, cache)?;
let bytes = {
let guard = out_arc.read().map_err(|_| {
Error::Msg("reference_output: output storage RwLock poisoned".to_string())
})?;
match &guard.inner {
fuel_memory::BackendStorage::Cuda(c) => c.to_cpu_bytes()?,
#[allow(unreachable_patterns)]
_ => {
return Err(Error::Msg(
"reference_output: realized output storage is not CUDA".to_string(),
));
}
}
};
Ok(HostTensor {
dtype: out_dtype,
shape: out_shape,
bytes,
})
}
#[cfg(feature = "cuda")]
pub fn reference_from_registered_recipe(
claimed_op: FusedOpId,
params: &FusedOpParams,
probe: &[HostTensor],
out_dtype: DType,
out_shape: Vec<usize>,
device: &CudaDevice,
) -> Result<HostTensor> {
let mut storages: Vec<Arc<RwLock<fuel_memory::Storage>>> = Vec::with_capacity(probe.len());
for t in probe {
let cb = CudaStorageBytes::from_cpu_bytes(device, &t.bytes)?;
storages.push(Arc::new(RwLock::new(fuel_memory::Storage::new(
fuel_memory::BackendStorage::Cuda(cb),
t.dtype,
))));
}
let graph = Arc::new(RwLock::new(Graph::new()));
let (input_ids, fused_id) = {
let mut g = graph.write().map_err(|_| {
Error::Msg("reference_from_registered_recipe: graph RwLock poisoned".to_string())
})?;
let input_ids: Vec<NodeId> = probe
.iter()
.map(|t| {
g.push(Node {
op: Op::Const,
inputs: vec![],
shape: Shape::from_dims(&t.shape),
dtype: t.dtype,
})
})
.collect();
let fused_id = g.push(Node {
op: Op::Fused(claimed_op, params.clone()),
inputs: input_ids.clone(),
shape: Shape::from_dims(&out_shape),
dtype: out_dtype,
});
(input_ids, fused_id)
};
let roots = lower_to_base_map(&graph, &[fused_id]);
let sink = *roots.first().ok_or_else(|| {
Error::Msg("reference_from_registered_recipe: lowering returned no roots".to_string())
})?;
{
let mut g = graph.write().map_err(|_| {
Error::Msg("reference_from_registered_recipe: graph RwLock poisoned".to_string())
})?;
for nid in topo_order_multi(&g, &roots) {
if !matches!(g.node(nid).op, Op::Const) {
g.set_target_backend(nid, BackendId::Cuda);
}
}
}
let mut cache = StorageCache::new();
for (id, storage) in input_ids.iter().zip(storages) {
cache.insert(*id, storage);
}
let (out_arc, _layout) = PipelinedExecutor::realize(graph, sink, cache)?;
let bytes = {
let guard = out_arc.read().map_err(|_| {
Error::Msg(
"reference_from_registered_recipe: output storage RwLock poisoned".to_string(),
)
})?;
match &guard.inner {
fuel_memory::BackendStorage::Cuda(c) => c.to_cpu_bytes()?,
#[allow(unreachable_patterns)]
_ => {
return Err(Error::Msg(
"reference_from_registered_recipe: realized output storage is not CUDA"
.to_string(),
));
}
}
};
Ok(HostTensor {
dtype: out_dtype,
shape: out_shape,
bytes,
})
}
#[cfg(test)]
mod tests {
use super::*;
use baracuda_kernels_types::ElementKind;
use fuel_ir::DType;
#[test]
fn a_failure_in_the_last_probe_still_fails_the_candidate() {
let v = combine_probe_verdicts(vec![
VerifyVerdict::Pass,
VerifyVerdict::Fail {
claim: "max_ulp",
detail: "elem 3: NaN vs 1.0".to_string(),
},
]);
match v {
VerifyVerdict::Fail { detail, .. } => {
assert!(
detail.contains("probe 1"),
"the failing probe index is not named in: {detail}"
);
}
other => panic!("a failure in the last probe must fail the candidate, got {other:?}"),
}
}
#[test]
fn an_empty_probe_set_is_a_fail_not_a_pass() {
match combine_probe_verdicts(Vec::new()) {
VerifyVerdict::Fail { claim, .. } => assert_eq!(claim, "probe"),
other => panic!("an empty probe set must not pass; got {other:?}"),
}
}
#[test]
fn inconclusive_survives_a_pass_and_yields_to_a_fail() {
let esc = || VerifyVerdict::Inconclusive {
claim: "max_ulp",
detail: "live reference only".to_string(),
};
let fail = || VerifyVerdict::Fail {
claim: "max_ulp",
detail: "diverged".to_string(),
};
assert!(
matches!(
combine_probe_verdicts(vec![VerifyVerdict::Pass, esc()]),
VerifyVerdict::Inconclusive { .. }
),
"an inconclusive probe must not be swallowed by a passing one"
);
assert!(
matches!(
combine_probe_verdicts(vec![esc(), fail()]),
VerifyVerdict::Fail { .. }
),
"a real failure must outrank an inconclusive in the same set"
);
}
#[test]
#[ignore = "GAP-236 increment 2: fails until the cuda-gated admission call site is wired; run explicitly to see the pending state"]
fn gap_236_the_probe_set_is_actually_consumed() {
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/jit_ingest.rs");
let src =
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("cannot read {path:?}: {e}"));
assert!(
src.contains("(1) Probe synthesis"),
"cannot find the admission block in {path:?} — this scan is looking in the \
wrong place and its verdict below would be meaningless"
);
assert!(
src.contains("admission_probes("),
"`verify_candidate_impl` does not call `admission_probes`, so candidate \
admission still runs on the seeded `[-0.5, 0.5)` fill alone and GAP-236's \
hole is OPEN. `special_value_probe_from_operands` exists and is proven to \
reach the fmaxf-vs-Max divergence, but nothing in production looks at it."
);
}
#[test]
fn gap_236_the_admission_probe_reaches_the_nan_divergence_set() {
#[allow(clippy::if_same_then_else)]
fn fmax_ieee(a: f32, b: f32) -> f32 {
if a.is_nan() {
b
} else if b.is_nan() {
a
} else if a > b {
a
} else {
b
}
}
fn max_prop(a: f32, b: f32) -> f32 {
if a.is_nan() || b.is_nan() {
f32::NAN
} else if a > b {
a
} else {
b
}
}
let od = OperandDesc::new(1, &[64], &[1], ElementKind::F32, 64 * 4);
let mut divergences = 0usize;
let mut specials = 0usize;
let mut scanned = 0usize;
for seed in 0..256u64 {
for probe in admission_probes(&[od, od], seed ^ 0xA11CE) {
let dec = |t: &HostTensor| -> Vec<f32> {
let (chunks, _rest) = t.bytes.as_chunks::<4>();
chunks.iter().map(|c| f32::from_le_bytes(*c)).collect()
};
let (a, b) = (dec(&probe[0]), dec(&probe[1]));
for (&x, &y) in a.iter().zip(b.iter()) {
scanned += 1;
if !x.is_finite() || !y.is_finite() || x == 0.0f32 && x.is_sign_negative() {
specials += 1;
}
if fmax_ieee(x, y).to_bits() != max_prop(x, y).to_bits() {
divergences += 1;
}
}
}
}
assert!(
scanned > 10_000,
"only {scanned} element pairs scanned — the probe builder returned \
nothing and the assertion below would pass or fail for the wrong reason"
);
println!(
"[gap-236] {scanned} element pairs scanned; {specials} non-finite/-0.0 inputs; {divergences} fmaxf-vs-Max divergences reached"
);
assert!(
specials > 0,
"the admission probe set contains no non-finite and no -0.0 input, so whatever produced the divergence count is not the special-value arm"
);
assert!(
divergences > 0,
"GAP-236: across {scanned} element pairs from {} seeds, a NaN-SUPPRESSING \
`fmaxf` and a NaN-PROPAGATING `Max` produced BIT-IDENTICAL results EVERY \
TIME ({specials} non-finite or -0.0 inputs seen). The admission probe \
cannot reach the divergence set, so a candidate that lifts `fmaxf` while \
claiming `Max` agrees with Fuel's reference everywhere the probe can look \
and is admitted. `fill_deterministic` yields `[-0.5, 0.5)`; the entire \
difference between the four min/max ops is `cmp_ne(x, x)`, which no input \
in that range can make true.",
256
);
}
#[test]
fn probe_from_operands_builds_sized_float_inputs() {
let od = OperandDesc::new(1, &[4], &[1], ElementKind::F32, 16);
let p = probe_from_operands(&[od, od], 0x1234).expect("probe");
assert_eq!(p.len(), 2);
assert_eq!(p[0].shape, vec![4]);
assert_eq!(p[0].dtype, DType::F32);
assert_eq!(p[0].bytes.len(), 16);
assert_eq!(
probe_from_operands(&[od, od], 0x1234).unwrap()[0].bytes,
p[0].bytes
); }
#[test]
fn probe_from_operands_rejects_an_unencodable_integer_operand() {
let int_od = OperandDesc::new(1, &[4], &[1], ElementKind::I32, 16);
assert!(
probe_from_operands(&[int_od], 0x1234).is_none(),
"an unencodable-dtype operand must yield None, not a fabricated probe"
);
let f32_od = OperandDesc::new(1, &[4], &[1], ElementKind::F32, 16);
assert!(probe_from_operands(&[f32_od, int_od], 0x1234).is_none());
}
#[cfg(feature = "cuda")]
fn ht_f32(vals: &[f32]) -> HostTensor {
HostTensor {
dtype: DType::F32,
shape: vec![vals.len()],
bytes: bytemuck::cast_slice(vals).to_vec(),
}
}
#[cfg(feature = "cuda")]
fn bytes_to_f32(bytes: &[u8]) -> Vec<f32> {
bytemuck::cast_slice::<u8, f32>(bytes).to_vec()
}
#[cfg(feature = "cuda")]
fn rope_probe(
seq: usize,
head_dim: usize,
base: f64,
) -> (HostTensor, HostTensor, HostTensor, Vec<usize>) {
use fuel_graph::build_rope_tables;
let x_shape = vec![1usize, seq, head_dim];
let x_vals = fill_deterministic(seq * head_dim, 0x5EED_D07);
let (cos, sin) = build_rope_tables(base, 0, seq, head_dim);
let x = HostTensor {
dtype: DType::F32,
shape: x_shape.clone(),
bytes: bytemuck::cast_slice(&x_vals).to_vec(),
};
let cos_t = HostTensor {
dtype: DType::F32,
shape: vec![seq, head_dim],
bytes: bytemuck::cast_slice(&cos).to_vec(),
};
let sin_t = HostTensor {
dtype: DType::F32,
shape: vec![seq, head_dim],
bytes: bytemuck::cast_slice(&sin).to_vec(),
};
(x, cos_t, sin_t, x_shape)
}
#[cfg(feature = "cuda")]
fn expected_rotate_half(
x: &[f32],
cos: &[f32],
sin: &[f32],
seq: usize,
head_dim: usize,
) -> Vec<f32> {
let half = head_dim / 2;
let mut out = vec![0.0f32; seq * head_dim];
for s in 0..seq {
let row = s * head_dim;
for d in 0..head_dim {
let rot = if d < half {
-x[row + d + half]
} else {
x[row + d - half]
};
out[row + d] = x[row + d] * cos[row + d] + rot * sin[row + d];
}
}
out
}
#[test]
#[ignore = "requires a live CUDA device"]
#[cfg(feature = "cuda")]
fn reference_from_registered_recipe_realizes_rotate_half_rope() {
use fuel_cuda_backend::CudaDevice;
use fuel_graph::registry::{FusedOpParams, FusedOps};
let Ok(dev) = CudaDevice::new(0) else {
return fuel_test_support::hardware::skip(
fuel_test_support::hardware::Hardware::Cuda,
fuel_test_support::hardware::Missing::device("CudaDevice::new(0) failed"),
);
};
let (seq, head_dim, base) = (4usize, 8usize, 10000.0f64);
let (x, cos_t, sin_t, x_shape) = rope_probe(seq, head_dim, base);
let x_vals = bytes_to_f32(&x.bytes);
let cos_vals = bytes_to_f32(&cos_t.bytes);
let sin_vals = bytes_to_f32(&sin_t.bytes);
let expected = expected_rotate_half(&x_vals, &cos_vals, &sin_vals, seq, head_dim);
let out = reference_from_registered_recipe(
FusedOps::ROPE,
&FusedOpParams::Rope,
&[x, cos_t, sin_t],
DType::F32,
x_shape,
&dev,
)
.expect("reference_from_registered_recipe should realize the lowered rope base map");
let got = bytes_to_f32(&out.bytes);
assert_eq!(got.len(), expected.len(), "output element count");
for (i, (g, e)) in got.iter().zip(&expected).enumerate() {
assert!(
(g - e).abs() < 1e-4,
"rotate-half rope mismatch at {i}: got {g}, expected {e}"
);
}
}
#[test]
#[ignore = "requires a live CUDA device"]
#[cfg(feature = "cuda")]
fn reference_output_realizes_the_decompose() {
use fuel_cuda_backend::CudaDevice;
use fuel_graph::jit::{OpAttrs, OpTag, PatternNode};
let Ok(dev) = CudaDevice::new(0) else {
return fuel_test_support::hardware::skip(
fuel_test_support::hardware::Hardware::Cuda,
fuel_test_support::hardware::Missing::device("CudaDevice::new(0) failed"),
);
};
let region = PatternNode::Op {
op: OpTag::Add,
attrs: OpAttrs::default(),
operands: vec![
PatternNode::Bind { index: 0 },
PatternNode::Bind { index: 1 },
],
};
let a = ht_f32(&[1.0, 2.0, 3.0, 4.0]);
let b = ht_f32(&[10.0, 20.0, 30.0, 40.0]);
let out = reference_output(®ion, &[a, b], DType::F32, vec![4], &dev).unwrap();
assert_eq!(bytes_to_f32(&out.bytes), vec![11.0, 22.0, 33.0, 44.0]);
}
}