use fuel_cuda_backend::CudaDevice;
use fuel_ir::dispatch::OpKind;
use fuel_ir::probe::BackendId;
use fuel_ir::{DType, Error, Layout, Result};
use std::sync::{Arc, RwLock};
use crate::dispatch::{cuda_input, cuda_output, read_storage, write_storage};
use crate::fkc::lower::LinkRegistry;
use crate::kernel::{KernelRef, OpParams};
use fuel_memory::Storage;
use super::{
CudaInvoker, HostTensor, LedgerRecord, ProbeInputs, VerificationLedger, VerifyError,
VerifyOutcome, fill_deterministic, verify_bit_stability,
};
const ROPE_APPLY_CONTRACT: &str =
include_str!("../../../../docs/kernel-contracts/cuda/rope-apply.fkc.md");
macro_rules! rope_apply_wrapper {
($wrapper_name:ident, $driver:path) => {
pub(crate) fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 3 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 3 inputs (x, cos, sin) + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer_count, seq, head_dim) = match params {
OpParams::Rope {
outer_count,
seq,
head_dim,
} => (*outer_count, *seq, *head_dim),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Rope, got {:?}"
),
other,
))
.bt())
}
};
let x_guard = read_storage(&inputs[0])?;
let cos_guard = read_storage(&inputs[1])?;
let sin_guard = read_storage(&inputs[2])?;
let mut out_guard = write_storage(&outputs[0])?;
let x_cuda = cuda_input(&x_guard)?;
let cos_cuda = cuda_input(&cos_guard)?;
let sin_cuda = cuda_input(&sin_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$driver(
x_cuda,
cos_cuda,
sin_cuda,
outer_count,
seq,
head_dim,
out_cuda,
)
}
};
}
rope_apply_wrapper!(
rope_apply_f32,
fuel_cuda_backend::baracuda::attention::rope_apply_f32_into
);
rope_apply_wrapper!(
rope_apply_f16,
fuel_cuda_backend::baracuda::attention::rope_apply_f16_into
);
rope_apply_wrapper!(
rope_apply_bf16,
fuel_cuda_backend::baracuda::attention::rope_apply_bf16_into
);
rope_apply_wrapper!(
rope_apply_f64,
fuel_cuda_backend::baracuda::attention::rope_apply_f64_into
);
struct RopeApplyLinkRegistry;
impl LinkRegistry for RopeApplyLinkRegistry {
fn resolve_primitive(&self, symbol: &str) -> Option<KernelRef> {
match symbol {
"baracuda_kernels_rope_apply_f32" => Some(rope_apply_f32 as KernelRef),
"baracuda_kernels_rope_apply_f16" => Some(rope_apply_f16 as KernelRef),
"baracuda_kernels_rope_apply_bf16" => Some(rope_apply_bf16 as KernelRef),
"baracuda_kernels_rope_apply_f64" => Some(rope_apply_f64 as KernelRef),
_ => None,
}
}
fn resolve_fused(&self, _symbol: &str) -> Option<KernelRef> {
None
}
}
const PROBE_OUTER_COUNT: usize = 1;
const PROBE_SEQ: usize = 2;
const PROBE_HEAD_DIM: usize = 4;
fn to_bytes(dt: DType, vals: &[f32]) -> Option<Vec<u8>> {
Some(match dt {
DType::F32 => bytemuck::cast_slice(vals).to_vec(),
DType::F64 => {
let v: Vec<f64> = vals.iter().map(|&x| x as f64).collect();
bytemuck::cast_slice(&v).to_vec()
}
DType::BF16 => {
let v: Vec<half::bf16> = vals.iter().map(|&x| half::bf16::from_f32(x)).collect();
bytemuck::cast_slice(&v).to_vec()
}
DType::F16 => {
let v: Vec<half::f16> = vals.iter().map(|&x| half::f16::from_f32(x)).collect();
bytemuck::cast_slice(&v).to_vec()
}
_ => return None,
})
}
fn ht(dt: DType, shape: Vec<usize>, vals: &[f32]) -> Option<HostTensor> {
Some(HostTensor {
dtype: dt,
shape,
bytes: to_bytes(dt, vals)?,
})
}
fn rope_apply_probe(dt: DType, seed: u64) -> Option<ProbeInputs> {
let (outer, seq, head_dim) = (PROBE_OUTER_COUNT, PROBE_SEQ, PROBE_HEAD_DIM);
let half = head_dim / 2;
let x = ht(
dt,
vec![outer * seq * head_dim],
&fill_deterministic(outer * seq * head_dim, seed),
)?;
let cos = ht(
DType::F32,
vec![seq * half],
&fill_deterministic(seq * half, seed ^ 0x1111),
)?;
let sin = ht(
DType::F32,
vec![seq * half],
&fill_deterministic(seq * half, seed ^ 0x2222),
)?;
Some(vec![x, cos, sin])
}
fn rope_apply_kernel_name(dt: DType) -> Option<&'static str> {
match dt {
DType::F32 => Some("rope_apply_f32"),
DType::F16 => Some("rope_apply_f16"),
DType::BF16 => Some("rope_apply_bf16"),
DType::F64 => Some("rope_apply_f64"),
_ => None,
}
}
fn verified_at_string() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let secs = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
format!("epoch:{secs}")
}
pub fn run_fkc_verify_harness(
kernels: &[&str],
force: bool,
) -> std::result::Result<VerificationLedger, VerifyError> {
let provider = crate::fkc::import_bundle_str(ROPE_APPLY_CONTRACT, &RopeApplyLinkRegistry)
.map_err(|e| VerifyError::Backend(format!("rope-apply contract import failed: {e}")))?;
let mut table = crate::kernel::KernelBindingTable::new();
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(&mut table, &mut fused)
.map_err(|e| VerifyError::Backend(format!("rope-apply contract register failed: {e}")))?;
let mut ledger =
VerificationLedger::from_records(VerificationLedger::embedded().records().to_vec());
let device =
CudaDevice::new(0).map_err(|e| VerifyError::Backend(format!("no CUDA device: {e}")))?;
for (op, dtypes, backend, entry) in table.iter_entries() {
if op != OpKind::Rope || backend != BackendId::Cuda {
continue;
}
let Some(dt) = dtypes.first().copied() else {
continue;
};
let Some(name) = rope_apply_kernel_name(dt) else {
continue;
};
if !kernels.contains(&name) {
continue;
}
if !force
&& ledger.has_pass(
BackendId::Cuda,
dtypes,
entry.kernel_revision_hash,
"bit_stable_on_same_hardware",
)
{
continue;
}
let dt_salt: u64 = match dt {
DType::F32 => 0x1,
DType::F16 => 0x2,
DType::BF16 => 0x3,
DType::F64 => 0x4,
_ => 0x0,
};
let seed = 0x2545_F491_4F6C_DD1D_u64 ^ dt_salt.wrapping_mul(0x9E37_79B9_7F4A_7C15);
let Some(probe) = rope_apply_probe(dt, seed) else {
continue;
};
let out_shape = vec![PROBE_OUTER_COUNT * PROBE_SEQ * PROBE_HEAD_DIM];
let inv = CudaInvoker::new(device.clone(), dt, out_shape).with_params(OpParams::Rope {
outer_count: PROBE_OUTER_COUNT,
seq: PROBE_SEQ,
head_dim: PROBE_HEAD_DIM,
});
let attempt = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
verify_bit_stability(&inv, entry, std::slice::from_ref(&probe), 16)
}));
let (result, evidence) = match attempt {
Ok(Ok(VerifyOutcome::Pass)) => (
"pass",
serde_json::json!({ "repeat_calls": 16, "harness": "task-4.6/rope_apply_harness" }),
),
Ok(Ok(VerifyOutcome::Fail { detail })) => {
("fail", serde_json::json!({ "detail": detail }))
}
Ok(Ok(VerifyOutcome::NoReference)) => ("no_reference", serde_json::Value::Null),
Ok(Err(e)) => (
"fail",
serde_json::json!({ "invoke_error": format!("{e:?}") }),
),
Err(_) => ("fail", serde_json::json!({ "panic": true })),
};
ledger.upsert(LedgerRecord {
kernel_ref: name.to_string(),
backend: "Cuda".to_string(),
dtypes: dtypes.iter().map(|d| format!("{d:?}")).collect(),
kernel_revision_hash: entry.kernel_revision_hash,
claim: "bit_stable_on_same_hardware".to_string(),
result: result.to_string(),
verified_at: verified_at_string(),
protocol_version: 1,
evidence,
});
}
Ok(ledger)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore = "requires a live CUDA device + --features cuda"]
fn fkc_verify_rope_apply_writes_a_pass_ledger_entry() {
let ledger = run_fkc_verify_harness(&["rope_apply_f32"], true).expect("harness runs");
assert!(ledger.records().iter().any(|r| {
r.kernel_ref == "rope_apply_f32"
&& r.backend == "Cuda"
&& r.claim == "bit_stable_on_same_hardware"
&& r.result == "pass"
}));
super::super::ledger::write_merged_ledger(ledger.records());
}
}