|
12 | 12 | pub mod async_mem; |
13 | 13 | pub mod cluster; |
14 | 14 | pub mod dsmem; |
| 15 | +// Green Contexts (CUDA 12.4+) — cudarc only exposes `CUgreenCtx` and its FFI |
| 16 | +// functions behind these version features (matching NVIDIA's own |
| 17 | +// introduction of the API in CUDA 12.4). Gating this at compile time, not |
| 18 | +// just at runtime via `check_hopper_support()` below, so the crate still |
| 19 | +// builds on any CUDA Toolkit older than 12.4 — which otherwise fails to |
| 20 | +// compile at all, on any GPU, regardless of architecture. |
| 21 | +#[cfg(any( |
| 22 | + feature = "cuda-12040", |
| 23 | + feature = "cuda-12050", |
| 24 | + feature = "cuda-12060", |
| 25 | + feature = "cuda-12080", |
| 26 | + feature = "cuda-12090", |
| 27 | + feature = "cuda-13000", |
| 28 | + feature = "cuda-13010", |
| 29 | + feature = "cuda-13020" |
| 30 | +))] |
15 | 31 | pub mod green_ctx; |
16 | 32 | pub mod lifecycle; |
17 | 33 | pub mod tma; |
@@ -43,3 +59,97 @@ pub const MAX_PORTABLE_CLUSTER_SIZE: u32 = 8; |
43 | 59 |
|
44 | 60 | /// Maximum cluster size on Blackwell (B200). |
45 | 61 | pub const MAX_BLACKWELL_CLUSTER_SIZE: u32 = 16; |
| 62 | + |
| 63 | +#[cfg(test)] |
| 64 | +mod pascal_compat_tests { |
| 65 | + //! Confirms Hopper-only feature checks degrade gracefully (return an |
| 66 | + //! `Err`/`false`, not a panic or UB) on pre-Hopper hardware, now that the |
| 67 | + //! compile-time gating fix above lets this module build at all on CUDA |
| 68 | + //! Toolkits older than 12.4. Requires real GPU hardware — run with: |
| 69 | + //! cargo test -p ringkernel-cuda --features cuda -- --ignored pascal_compat |
| 70 | + use super::*; |
| 71 | + use crate::device::CudaDevice; |
| 72 | + |
| 73 | + #[test] |
| 74 | + #[ignore] // Requires CUDA hardware |
| 75 | + fn pascal_compat_check_hopper_support_degrades_gracefully() { |
| 76 | + let device = CudaDevice::new(0).expect("Failed to create device"); |
| 77 | + let (major, minor) = device.compute_capability(); |
| 78 | + println!("Device compute capability: {major}.{minor}"); |
| 79 | + |
| 80 | + let result = check_hopper_support(&device); |
| 81 | + if major < 9 { |
| 82 | + assert!( |
| 83 | + result.is_err(), |
| 84 | + "check_hopper_support returned Ok on pre-Hopper hardware" |
| 85 | + ); |
| 86 | + } else { |
| 87 | + assert!(result.is_ok()); |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + #[test] |
| 92 | + #[ignore] // Requires CUDA hardware |
| 93 | + fn pascal_compat_supports_cluster_launch_degrades_gracefully() { |
| 94 | + let device = CudaDevice::new(0).expect("Failed to create device"); |
| 95 | + let (major, _) = device.compute_capability(); |
| 96 | + |
| 97 | + let supported = supports_cluster_launch(&device); |
| 98 | + if major < 9 { |
| 99 | + assert!( |
| 100 | + !supported, |
| 101 | + "supports_cluster_launch returned true on pre-Hopper hardware" |
| 102 | + ); |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + #[test] |
| 107 | + #[ignore] // Requires CUDA hardware |
| 108 | + fn pascal_compat_dsmem_degrades_gracefully() { |
| 109 | + let device = CudaDevice::new(0).expect("Failed to create device"); |
| 110 | + let (major, _) = device.compute_capability(); |
| 111 | + |
| 112 | + let available = dsmem::is_dsmem_available(&device, 4); |
| 113 | + if major < 9 { |
| 114 | + assert!( |
| 115 | + !available, |
| 116 | + "is_dsmem_available returned true on pre-Hopper hardware" |
| 117 | + ); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + #[test] |
| 122 | + #[ignore] // Requires CUDA hardware |
| 123 | + fn pascal_compat_cluster_size_degrades_to_one() { |
| 124 | + let device = CudaDevice::new(0).expect("Failed to create device"); |
| 125 | + let (major, _) = device.compute_capability(); |
| 126 | + |
| 127 | + let max_cluster = cluster::query_max_cluster_size(&device, std::ptr::null_mut()) |
| 128 | + .expect("query_max_cluster_size should not error"); |
| 129 | + if major < 9 { |
| 130 | + assert_eq!( |
| 131 | + max_cluster, 1, |
| 132 | + "query_max_cluster_size did not degrade to 1 on pre-Hopper hardware" |
| 133 | + ); |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + #[test] |
| 138 | + #[ignore] // Requires CUDA hardware |
| 139 | + fn pascal_compat_cooperative_groups_still_available() { |
| 140 | + // Cooperative groups (grid.sync()) have a lower floor (CC 6.0+, |
| 141 | + // Pascal) than Hopper-specific features (CC 9.0+) — confirms the |
| 142 | + // gating logic distinguishes per-feature floors correctly, rather |
| 143 | + // than treating "not Hopper" as "nothing works". |
| 144 | + let device = CudaDevice::new(0).expect("Failed to create device"); |
| 145 | + let (major, _) = device.compute_capability(); |
| 146 | + |
| 147 | + let coop = device.supports_cooperative_groups(); |
| 148 | + if major >= 6 { |
| 149 | + assert!( |
| 150 | + coop, |
| 151 | + "supports_cooperative_groups returned false on CC 6.0+ hardware" |
| 152 | + ); |
| 153 | + } |
| 154 | + } |
| 155 | +} |
0 commit comments