2626#include < cuda_runtime.h>
2727#include < functional>
2828
29+ #ifndef SGEMM_HAS_WMMA_TARGET
30+ #define SGEMM_HAS_WMMA_TARGET 0
31+ #endif
32+
2933// ============================================================================
3034// WMMA Tile Dimensions
3135// ============================================================================
@@ -48,6 +52,7 @@ using tensor_core::WMMA_N;
4852 * 检查当前设备是否支持 Tensor Core (sm_70+)
4953 */
5054inline bool tensorCoresAvailable () { return DeviceInfoCache::instance ().hasTensorCores (); }
55+ inline constexpr bool tensorCoreFastPathCompiled () { return SGEMM_HAS_WMMA_TARGET != 0 ; }
5156
5257/* *
5358 * 检查给定维度是否适合 Tensor Core 加速
@@ -100,24 +105,9 @@ nullFallback(const float *, const float *, float *, int, int, int, cudaStream_t
100105// Tensor Core Compute - 纯 WMMA 计算路径
101106// ============================================================================
102107
103- // WMMA is only available on sm_70+
104- #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 700
108+ // WMMA is only emitted when the configured target architectures include sm_70+.
109+ #if SGEMM_HAS_WMMA_TARGET
105110#include < mma.h>
106- #endif
107-
108- /* *
109- * FP32 → FP16 转换内核
110- */
111- __global__ void float_to_half_kernel (const float *__restrict__ input, half *__restrict__ output,
112- int size) {
113- int idx = blockIdx .x * blockDim .x + threadIdx .x ;
114- if (idx < size) {
115- output[idx] = __float2half (input[idx]);
116- }
117- }
118-
119- // WMMA kernel is only available on sm_70+
120- #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 700
121111
122112/* *
123113 * 纯 Tensor Core WMMA 计算内核
@@ -132,6 +122,7 @@ __global__ void float_to_half_kernel(const float *__restrict__ input, half *__re
132122__global__ void tensor_core_sgemm_kernel_fp16 (const half *__restrict__ A,
133123 const half *__restrict__ B, float *__restrict__ C,
134124 int M, int K, int N) {
125+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
135126 int warpM = blockIdx .y ;
136127 int warpN = blockIdx .x ;
137128
@@ -159,6 +150,14 @@ __global__ void tensor_core_sgemm_kernel_fp16(const half *__restrict__ A,
159150 }
160151
161152 nvcuda::wmma::store_matrix_sync (C + aRow * N + bCol, c_frag, N, nvcuda::wmma::mem_row_major);
153+ #else
154+ (void )A;
155+ (void )B;
156+ (void )C;
157+ (void )M;
158+ (void )K;
159+ (void )N;
160+ #endif
162161}
163162
164163/* *
@@ -179,13 +178,24 @@ inline void launch_tensor_core_sgemm_fp16_fast_path(const half *A, const half *B
179178}
180179
181180#else
182- // Stub implementations for older architectures (will not be called)
181+ // Stub implementations when no WMMA-capable target was configured.
183182inline void launch_tensor_core_sgemm_fp16_fast_path (const half *, const half *, float *, int , int ,
184183 int , cudaStream_t) {
185- // This function should never be called on pre-sm_70 GPUs
184+ throw CudaError ( " Tensor Core fast path was not compiled for the configured CUDA architectures " );
186185}
187186#endif
188187
188+ /* *
189+ * FP32 → FP16 转换内核
190+ */
191+ __global__ void float_to_half_kernel (const float *__restrict__ input, half *__restrict__ output,
192+ int size) {
193+ int idx = blockIdx .x * blockDim .x + threadIdx .x ;
194+ if (idx < size) {
195+ output[idx] = __float2half (input[idx]);
196+ }
197+ }
198+
189199/* *
190200 * 纯 WMMA 计算路径入口(FP16 输入)
191201 *
@@ -198,9 +208,13 @@ inline void launch_tensor_core_sgemm_fp16(const half *A, const half *B, float *C
198208 return ;
199209 }
200210
211+ if (!tensorCoreFastPathCompiled ()) {
212+ throw CudaError (" launch_tensor_core_sgemm_fp16 requires a build that targets sm_70+" );
213+ }
214+
201215 if (!tensorCoresAvailable () || !tensorCoreDimensionsSupported (M, K, N)) {
202- throw CudaError (" launch_tensor_core_sgemm_fp16 requires sm_70+ and dimensions aligned "
203- " to 16" );
216+ throw CudaError (
217+ " launch_tensor_core_sgemm_fp16 requires runtime sm_70+ support and dimensions aligned to 16" );
204218 }
205219
206220 launch_tensor_core_sgemm_fp16_fast_path (A, B, C, M, K, N, stream);
@@ -235,7 +249,8 @@ inline void launch_tensor_core_sgemm_with_fallback(const float *A, const float *
235249 }
236250
237251 // Fallback 路径:设备或维度不支持 Tensor Core
238- if (!tensorCoresAvailable () || !tensorCoreDimensionsSupported (M, K, N)) {
252+ if (!tensorCoreFastPathCompiled () || !tensorCoresAvailable () ||
253+ !tensorCoreDimensionsSupported (M, K, N)) {
239254 fallback (A, B, C, M, K, N, stream);
240255 return ;
241256 }
@@ -283,7 +298,8 @@ inline void launch_tensor_core_sgemm_with_fallback(const float *A, const float *
283298inline void launch_tensor_core_sgemm_with_fallback (const float *A, const float *B, float *C, int M,
284299 int K, int N, const FallbackKernel &fallback,
285300 cudaStream_t stream = 0 ) {
286- launch_tensor_core_sgemm_with_fallback (A, B, C, M, K, N, fallback, stream);
301+ launch_tensor_core_sgemm_with_fallback<const FallbackKernel &>(A, B, C, M, K, N, fallback,
302+ stream);
287303}
288304
289305// ============================================================================
0 commit comments