// ExecutionPlan / Device / PrecisionPolicy — how and where a computation runs. #pragma once #include #include #include #include "raid/core/types.hpp" namespace raid { struct Device { std::string name; Backend kind{Backend::cpu}; u64 memory_bytes{0}; int compute_units{0}; // CPU cores or GPU cores (if known) bool unified_memory{true}; bool supports_fp64{true}; // false for every Apple GPU (verified 2026-11-02) u64 max_buffer_bytes{0}; std::string details; nlohmann::json to_json() const; }; struct PrecisionPolicy { Precision requested{Precision::fp64}; /// Maximum reduction length accumulated in FP32 on the GPU before a FP64 CPU combine step. usize fp32_chunk_max{4096}; /// Use compensated (Neumaier) accumulation on GPU partial sums. bool compensated{true}; /// Tolerance (relative) used by auto validation of GPU vs CPU reference. f64 validate_rtol{1e-5}; nlohmann::json to_json() const; }; struct ExecutionPlan { Backend backend{Backend::automatic}; PrecisionPolicy precision{}; bool deterministic{true}; // fixed-order reductions (bitwise reproducible across runs on the same device) unsigned threads{0}; // 0 = all usize chunk_rows{0}; // 0 = automatic u64 max_memory_bytes{0}; // 0 = no explicit bound (device-reported limits still apply) bool allow_fallback{true}; // Metal unsupported → CPU u64 seed{20261102}; nlohmann::json to_json() const; }; } // namespace raid