Skip to main content

derive_backend_caps

Function derive_backend_caps 

Source
pub fn derive_backend_caps(
    backend: BackendId,
    device_location: DeviceLocation,
    table: &KernelBindingTable,
) -> BackendCapabilities
Expand description

FKC cost unification — Part A.

Derive a BackendCapabilities for backend (at device_location) from the kernel binding table. This is the general (any-backend) analogue of default_cpu_caps: instead of a hand-maintained list, it reads the backend’s REGISTERED KERNELS out of the binding table and advertises exactly the (OpKind, DType) pairs those kernels cover.

The (op, dtype) derivation mirrors crate::topology::SystemTopology’s binding_op_coverage: each binding key carries per-operand dtypes (inputs then outputs); the classic (op, dtype) shape takes the OUTPUT dtype — the last entry in the key’s dtype list. Single-dtype keys (most elementwise ops) are unambiguous; multi-dtype keys (e.g. QMatMul [F32, U32, F32]) still produce the consumer-relevant output-dtype entry.

Why this fixes the placement cost model. The placement cost composer (ranker::cost::compute_static_costs) skips any candidate whose backend has no BackendCapabilities in the registry — leaving its static_cost at the default ZERO, so an uncapped GPU candidate prices as free and can spuriously out-rank a real CPU cost. Registering the caps this function derives makes capabilities_for(gpu) return Some, so the GPU candidate’s FLOP/byte cost fn actually runs (see also KernelBindingTable::fill_unset_cost_for_backend, which ensures those kernels carry a non-unknown_cost cost fn).

Alignment / granularity use conservative device defaults (256-byte alignment for GPU buffers — covers CUDA’s 256B and Vulkan’s typical storage-buffer alignment; byte-addressable). Transfer paths advertise the universal HostStaging link back to the CPU so the TransferMatrix can price GPU↔CPU crossings; richer paths (P2P, shared memory) are a future refinement the backend can declare explicitly. Never panics.