diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 23:44:06 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 23:44:06 -0400 |
| commit | ccdfc1b2cc31a04110783e96a310f5ed36ca0a9d (patch) | |
| tree | 9ad09926f9d189004c053f442c9c1933d3a49098 /tools/cuda-ab/vecadd_loop.cu | |
| parent | 1dab2b18a6b2bed1354c55822d060a539518806b (diff) | |
| download | open-iov-ccdfc1b2cc31a04110783e96a310f5ed36ca0a9d.tar.gz open-iov-ccdfc1b2cc31a04110783e96a310f5ed36ca0a9d.zip | |
cuda-ab: victory-series coverage battery (8 new clients) + soak runner list
victory_saxpy, victory_reduce (shared+atomics), victory_matmul (tiled
shared), victory_strided, victory_memset2d (pitched), victory_atomics,
victory_streams_events (3 streams + events), victory_math (mixed
int/float/double). Each verifies via readback and prints STATUS OK|FAIL.
soak.sh now runs the full 14-client set (seq or sustained).
Diffstat (limited to 'tools/cuda-ab/vecadd_loop.cu')
| -rw-r--r-- | tools/cuda-ab/vecadd_loop.cu | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/tools/cuda-ab/vecadd_loop.cu b/tools/cuda-ab/vecadd_loop.cu new file mode 100644 index 0000000..bde3d05 --- /dev/null +++ b/tools/cuda-ab/vecadd_loop.cu @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * vecadd_loop.cu - 100 repeated vectorAdd launches, soak-style. + * + * The same three device buffers are reused for 100 identical vadd launches: + * the point is repetition and stability, not new data. Every 10th launch the + * result is copied back and verified element by element against the + * host-computed a+b, so a silent corruption that only appears after many + * launches is caught. + * + * Output lines are stable and greppable: + * + * DEVICE <name> cc=<major>.<minor> sm=<count> mem=<bytes> + * VERIFY launch=<n> bad=<mismatches> + * LOOP launches=100 bad=<mismatches> + * STATUS OK|FAIL + * + * Build with a static CUDA runtime (--cudart=static) so the guest only needs + * the driver's libcuda.so, not a CUDA toolkit installation: + * + * nvcc -O2 --cudart=static -o vecadd_loop vecadd_loop.cu + * + * Then, from the guest: /tmp/vecadd_loop + */ + +#include <cstdio> +#include <cstdlib> +#include <cstdint> +#include <cuda_runtime.h> + +#define NLAUNCH 100 +#define VERIFY_EVERY 10 + +#define CHECK(x) \ + do { \ + cudaError_t e_ = (x); \ + if (e_ != cudaSuccess) { \ + printf("CUDA_ERROR %s at line %d\n", \ + cudaGetErrorString(e_), __LINE__); \ + printf("STATUS FAIL\n"); \ + return 1; \ + } \ + } while (0) + +__global__ void vadd(const float *a, const float *b, float *c, int n) +{ + int i = blockIdx.x * blockDim.x + threadIdx.x; + + if (i < n) + c[i] = a[i] + b[i]; +} + +int main(void) +{ + cudaDeviceProp prop; + const int n = 1 << 15; + size_t bytes = (size_t)n * sizeof(float); + float *h_a, *h_b, *h_c; + float *d_a, *d_b, *d_c; + int bad = 0, i, launch; + + setvbuf(stdout, NULL, _IONBF, 0); + + CHECK(cudaGetDeviceProperties(&prop, 0)); + printf("DEVICE %s cc=%d.%d sm=%d mem=%llu\n", prop.name, + prop.major, prop.minor, prop.multiProcessorCount, + (unsigned long long)prop.totalGlobalMem); + + h_a = (float *)malloc(bytes); + h_b = (float *)malloc(bytes); + h_c = (float *)malloc(bytes); + if (!h_a || !h_b || !h_c) + return 1; + + for (i = 0; i < n; i++) { + h_a[i] = (float)(i % 1000) * 0.5f; + h_b[i] = (float)(i % 997) * 0.25f; + } + + CHECK(cudaMalloc(&d_a, bytes)); + CHECK(cudaMalloc(&d_b, bytes)); + CHECK(cudaMalloc(&d_c, bytes)); + CHECK(cudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice)); + CHECK(cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice)); + + for (launch = 1; launch <= NLAUNCH; launch++) { + vadd<<<(n + 255) / 256, 256>>>(d_a, d_b, d_c, n); + CHECK(cudaGetLastError()); + if (launch % VERIFY_EVERY != 0) + continue; + CHECK(cudaDeviceSynchronize()); + CHECK(cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost)); + { + int vbad = 0; + + for (i = 0; i < n; i++) { + if (h_c[i] != h_a[i] + h_b[i]) + vbad++; + } + printf("VERIFY launch=%d bad=%d\n", launch, vbad); + bad += vbad; + } + } + CHECK(cudaDeviceSynchronize()); + + printf("LOOP launches=%d bad=%d\n", NLAUNCH, bad); + + if (bad != 0) { + printf("STATUS FAIL\n"); + return 1; + } + + printf("STATUS OK\n"); + CHECK(cudaFree(d_a)); + CHECK(cudaFree(d_b)); + CHECK(cudaFree(d_c)); + free(h_a); + free(h_b); + free(h_c); + return 0; +} |
