test: probe warp_size=64 behavior + kernel 10 warp tiling with WARPSIZE=64 on BI-V100

This commit is contained in:
Claude
2026-08-14 17:02:55 +00:00
parent 1af7e7cf48
commit 11b8a98eea

217
qwen3_6_scripts/probe_warp64.sh Executable file
View File

@@ -0,0 +1,217 @@
#!/bin/bash
# probe_warp64.sh — Verify warp_size=64 behavior on BI-V100
# and test siboehm kernel 10 with WARPSIZE=64
echo "=== 1. Warp behavior probe ==="
cat > /tmp/probe_warp.cu << 'CUDA'
#include <cstdio>
#include <cuda_runtime.h>
__global__ void probe_warp_info() {
if (threadIdx.x == 0) {
printf("warpSize (built-in) = %d\n", warpSize);
}
// Each thread reports its warp ID and lane ID
int warp_id = threadIdx.x / warpSize;
int lane_id = threadIdx.x % warpSize;
// Only first thread of each warp reports
if (lane_id == 0) {
printf(" thread %3d: warp_id=%d, lane_id=%d, warpSize=%d\n",
threadIdx.x, warp_id, lane_id, warpSize);
}
}
__global__ void test_syncwarp_64() {
// Test if __syncwarp with 64-bit mask works
// On NVIDIA: mask is 32-bit (unsigned int)
// On BI-V100 with warp_size=64: need 64-bit mask?
__shared__ int data[128];
int tid = threadIdx.x;
int warp_id = tid / warpSize;
int lane = tid % warpSize;
// Write
data[tid] = tid * 2;
// Try standard __syncwarp()
__syncwarp();
// Read neighbor's data within the warp
int neighbor = (lane + 1) % warpSize + warp_id * warpSize;
int val = data[neighbor];
if (tid == 0) {
printf("__syncwarp() works: thread 0 read thread 1's value = %d (expected 2)\n", val);
}
if (tid == 63) {
printf("__syncwarp() works: thread 63 read thread 0's value = %d (expected 0)\n",
data[warp_id * warpSize]);
}
}
__global__ void test_shfl_down_64() {
int tid = threadIdx.x;
int lane = tid % warpSize;
float val = (float)tid;
// __shfl_down_sync with full mask
// On NVIDIA: mask = 0xFFFFFFFF (32 bits)
// On BI-V100: what mask for 64 threads?
float result = __shfl_down_sync(0xFFFFFFFF, val, 1);
if (tid == 0) {
printf("shfl_down(0xFFFFFFFF, tid=0, delta=1) = %.0f (expected 1.0)\n", result);
}
if (tid == 31) {
printf("shfl_down(0xFFFFFFFF, tid=31, delta=1) = %.0f (expected 32.0 if warp=64, else 31.0)\n", result);
}
if (tid == 32) {
printf("shfl_down(0xFFFFFFFF, tid=32, delta=1) = %.0f (expected 33.0)\n", result);
}
if (tid == 63) {
printf("shfl_down(0xFFFFFFFF, tid=63, delta=1) = %.0f (expected 63.0 if wraps, else 0)\n", result);
}
}
int main() {
printf("--- Warp info (128 threads, 1 block) ---\n");
probe_warp_info<<<1, 128>>>();
cudaDeviceSynchronize();
printf("\n--- __syncwarp test (128 threads) ---\n");
test_syncwarp_64<<<1, 128>>>();
cudaDeviceSynchronize();
printf("\n--- __shfl_down_sync test (64 threads) ---\n");
test_shfl_down_64<<<1, 64>>>();
cudaDeviceSynchronize();
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
printf("\nCUDA error: %s\n", cudaGetErrorString(err));
} else {
printf("\nAll warp probes completed successfully.\n");
}
return 0;
}
CUDA
/usr/local/corex/bin/clang++ --cuda-gpu-arch=ivcore10 --cuda-path=/usr/local/corex \
-I/usr/local/corex/include -L/usr/local/corex/lib64 -lcudart \
/tmp/probe_warp.cu -o /tmp/probe_warp 2>&1
if [ -f /tmp/probe_warp ]; then
echo "Compile: SUCCESS"
/tmp/probe_warp
else
echo "Compile: FAILED"
fi
echo ""
echo "=== 2. Kernel 10 warp tiling compile test (WARPSIZE=64) ==="
cat > /tmp/test_k10_warp64.cu << 'CUDA'
#include <cuda_fp16.h>
#include <cuda_runtime.h>
#include <cstdio>
#define CEIL_DIV(M, N) (((M) + (N)-1) / (N))
// BI-V100 warp size
const int WARPSIZE = 64;
// Minimal kernel 10 structure from siboehm, with WARPSIZE=64
// Just test that the indexing compiles and the launch config is valid
template <const int BM, const int BN, const int BK, const int WM, const int WN,
const int WNITER, const int TM, const int TN, const int NUM_THREADS>
__global__ void __launch_bounds__(NUM_THREADS)
hgemmWarptiling(int M, int N, int K, float alpha,
const __half *A, const __half *B, float beta, __half *C) {
const uint warpIdx = threadIdx.x / WARPSIZE;
const uint warpCol = warpIdx % (BN / WN);
const uint warpRow = warpIdx / (BN / WN);
constexpr uint WMITER = (WM * WN) / (WARPSIZE * TM * TN * WNITER);
constexpr uint WSUBM = WM / WMITER;
constexpr uint WSUBN = WN / WNITER;
const uint threadIdxInWarp = threadIdx.x % WARPSIZE;
const uint threadColInWarp = threadIdxInWarp % (WSUBN / TN);
const uint threadRowInWarp = threadIdxInWarp / (WSUBN / TN);
__shared__ __half As[BM * BK];
__shared__ __half Bs[BK * BN];
// Just write a marker to verify the kernel launched
if (threadIdx.x == 0 && blockIdx.x == 0 && blockIdx.y == 0) {
C[0] = __float2half(42.0f);
}
}
int main() {
// Config adapted for WARPSIZE=64:
// 128 threads = 2 warps of 64
// BM=128, BN=128 → 2 warps need to cover 128x128
// WM=64, WN=128 → 2 warps: (128/128)*(128/64) = 1*2 = 2 warps ✓
const int NUM_THREADS = 128;
const int BM = 128, BN = 128, BK = 16;
const int WM = 64, WN = 128;
const int WNITER = 4;
const int TM = 4, TN = 4;
// Verify constraints
constexpr int NUM_WARPS = NUM_THREADS / 64; // 2
// (BN/WN) * (BM/WM) should == NUM_WARPS
printf("NUM_WARPS=%d, (BN/WN)*(BM/WM)=%d\n", NUM_WARPS, (BN/WN)*(BM/WM));
constexpr int WMITER_check = (WM * WN) / (64 * TM * TN * WNITER);
printf("WMITER=%d\n", WMITER_check);
printf("WSUBM=%d, WSUBN=%d\n", WM/WMITER_check, WN/WNITER);
// Threads in warp: WSUBN/TN * WSUBM/TM should <= 64
int WSUBM = WM / WMITER_check;
int WSUBN = WN / WNITER;
printf("threads_per_warp_check: (WSUBN/TN)*(WSUBM/TM) = %d (need <=64)\n",
(WSUBN/TN) * (WSUBM/TM));
// Allocate tiny test
__half *d_A, *d_B, *d_C;
int M=128, N=128, K=16;
cudaMalloc(&d_A, M*K*sizeof(__half));
cudaMalloc(&d_B, K*N*sizeof(__half));
cudaMalloc(&d_C, M*N*sizeof(__half));
cudaMemset(d_C, 0, M*N*sizeof(__half));
dim3 grid(CEIL_DIV(N, BN), CEIL_DIV(M, BM));
dim3 block(NUM_THREADS);
hgemmWarptiling<BM, BN, BK, WM, WN, WNITER, TM, TN, NUM_THREADS>
<<<grid, block>>>(M, N, K, 1.0f, d_A, d_B, 0.0f, d_C);
cudaDeviceSynchronize();
__half h_c;
cudaMemcpy(&h_c, d_C, sizeof(__half), cudaMemcpyDeviceToHost);
printf("C[0] = %.1f (expected 42.0)\n", __half2float(h_c));
cudaError_t err = cudaGetLastError();
printf("CUDA error: %s\n", cudaGetErrorString(err));
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
return 0;
}
CUDA
/usr/local/corex/bin/clang++ --cuda-gpu-arch=ivcore10 --cuda-path=/usr/local/corex \
-I/usr/local/corex/include -L/usr/local/corex/lib64 -lcudart \
/tmp/test_k10_warp64.cu -o /tmp/test_k10_warp64 2>&1
if [ -f /tmp/test_k10_warp64 ]; then
echo "Compile: SUCCESS"
/tmp/test_k10_warp64
else
echo "Compile: FAILED"
fi