diff --git a/crates/ml-core/build.rs b/crates/ml-core/build.rs index 22c156cd3..ad5a0afaa 100644 --- a/crates/ml-core/build.rs +++ b/crates/ml-core/build.rs @@ -29,6 +29,7 @@ fn main() { println!("cargo:rerun-if-changed={}", common_header_path.display()); // Detect GPU architecture from env or default to sm_80 + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}"); diff --git a/crates/ml-dqn/build.rs b/crates/ml-dqn/build.rs index 74486d572..853c774a7 100644 --- a/crates/ml-dqn/build.rs +++ b/crates/ml-dqn/build.rs @@ -21,7 +21,13 @@ fn main() { println!("cargo:rerun-if-changed={}", common_header_path.display()); - // Detect GPU architecture from env or default to sm_80 + // Detect GPU architecture from env or default to sm_80. + // CRITICAL: pair env::var() with rerun-if-env-changed per + // pearl_build_rs_rerun_if_env_changed, otherwise sccache + cubin caches + // hit-on-SHA across arch changes (e.g., SM 89 L40S → SM 90 H100), and + // training fails at runtime with CUDA_ERROR_NO_BINARY_FOR_GPU on rmsnorm + // cubin load (commit 0371d6a76 on H100, post-Class-B chain). + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}"); diff --git a/crates/ml-ensemble/build.rs b/crates/ml-ensemble/build.rs index 654739587..90a92d514 100644 --- a/crates/ml-ensemble/build.rs +++ b/crates/ml-ensemble/build.rs @@ -13,6 +13,7 @@ fn main() { let kernel_dir = Path::new("src"); // Detect GPU architecture from env or default to sm_80 + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}"); diff --git a/crates/ml-explainability/build.rs b/crates/ml-explainability/build.rs index 51c1765d0..799dbf628 100644 --- a/crates/ml-explainability/build.rs +++ b/crates/ml-explainability/build.rs @@ -13,6 +13,7 @@ fn main() { let kernel_dir = Path::new("src"); // Detect GPU architecture from env or default to sm_80 (matches crates/ml/build.rs). + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}"); diff --git a/crates/ml-ppo/build.rs b/crates/ml-ppo/build.rs index 1da83cbe8..6c044ccb2 100644 --- a/crates/ml-ppo/build.rs +++ b/crates/ml-ppo/build.rs @@ -29,6 +29,7 @@ fn main() { println!("cargo:rerun-if-changed={}", common_header_path.display()); // Detect GPU architecture from env or default to sm_80 + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}"); diff --git a/crates/ml-supervised/build.rs b/crates/ml-supervised/build.rs index dd1f05508..ef2abb27e 100644 --- a/crates/ml-supervised/build.rs +++ b/crates/ml-supervised/build.rs @@ -25,6 +25,7 @@ fn main() { let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); // Detect GPU architecture from env or default to sm_80 (L40S / A100). + println!("cargo:rerun-if-env-changed=CUDA_COMPUTE_CAP"); let cuda_compute_cap = std::env::var("CUDA_COMPUTE_CAP").unwrap_or_else(|_| "80".to_string()); let arch = format!("sm_{cuda_compute_cap}");