diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2024-02-26 20:29:25 -0500 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2024-02-26 20:29:25 -0500 |
| commit | 340457bd5dae3624d4c92a02b84fb8206c0348a9 (patch) | |
| tree | 561baa1d81e9a41b48066f547435e43613106bc4 /measure_launch_oh.cu | |
| parent | 5c65954998591bc61a4138024ba4895bed64a8a6 (diff) | |
Add measure_launch_oh benchmark and make target
Benchmark supports:
=> Warms up the GPU and kernel code before sampling
=> Uses a flag in zero-copy memory to track when a kernel begins
=> Outputs summary statistics to stderr, and sample data to stdout
Diffstat (limited to 'measure_launch_oh.cu')
| -rw-r--r-- | measure_launch_oh.cu | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/measure_launch_oh.cu b/measure_launch_oh.cu new file mode 100644 index 0000000..981448a --- /dev/null +++ b/measure_launch_oh.cu | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | /* Copyright 2024 Joshua Bakita | ||
| 2 | * Simple kernel that clocks how long a kernel launch takes to the GPU. | ||
| 3 | * Prints samples to stdout and summary statistics to stderr. | ||
| 4 | */ | ||
| 5 | #include <time.h> | ||
| 6 | #include <stdio.h> | ||
| 7 | #include <stdint.h> | ||
| 8 | #include <unistd.h> | ||
| 9 | |||
| 10 | #include "testbench.h" | ||
| 11 | |||
| 12 | __global__ void flag_on_gpu(volatile int *flag) { | ||
| 13 | *flag = 1; | ||
| 14 | } | ||
| 15 | |||
| 16 | // Get launch overhead | ||
| 17 | long measure_launch_overhead() { | ||
| 18 | volatile int *barrier; | ||
| 19 | struct timespec start, end; | ||
| 20 | SAFE(cudaHostAlloc(&barrier, sizeof(*barrier), cudaHostAllocMapped)); | ||
| 21 | *barrier = 0; | ||
| 22 | clock_gettime(CLOCK_MONOTONIC_RAW, &start); | ||
| 23 | flag_on_gpu<<<100,100>>>(barrier); | ||
| 24 | while (!*barrier) continue; | ||
| 25 | clock_gettime(CLOCK_MONOTONIC_RAW, &end); | ||
| 26 | SAFE(cudaDeviceSynchronize()); | ||
| 27 | return timediff(start, end); | ||
| 28 | } | ||
| 29 | |||
| 30 | int main(int argc, char **argv) { | ||
| 31 | int *__unused, i; | ||
| 32 | unsigned long num_iters; | ||
| 33 | long time; | ||
| 34 | long double cumulative_time = 0; | ||
| 35 | |||
| 36 | if (argc != 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { | ||
| 37 | fprintf(stderr, "Usage: %s [# of samples]\n", argv[0]); | ||
| 38 | return 1; | ||
| 39 | } | ||
| 40 | |||
| 41 | num_iters = strtoul(argv[1], NULL, 10); | ||
| 42 | |||
| 43 | // Initialize CUDA and a context (hack) | ||
| 44 | SAFE(cudaMalloc(&__unused, 8)); | ||
| 45 | |||
| 46 | // Run once to ensure the kernel is compiled | ||
| 47 | time = measure_launch_overhead(); | ||
| 48 | fprintf(stderr, "(%d) %ld ns (%.2f ms) warmup launch overhead\n", getpid(), | ||
| 49 | time, ns2ms((double)time)); | ||
| 50 | |||
| 51 | // Time several kernel launches | ||
| 52 | for (i = 0; i < num_iters; i++) { | ||
| 53 | time = measure_launch_overhead(); | ||
| 54 | cumulative_time += time; | ||
| 55 | // Print one sample per line | ||
| 56 | fprintf(stdout, "%ld\n", time); | ||
| 57 | } | ||
| 58 | |||
| 59 | fprintf(stderr, "(%d) %.0Lf ns (%.2Lf ms) average launch overhead\n", getpid(), | ||
| 60 | cumulative_time / num_iters, ns2ms(cumulative_time / num_iters)); | ||
| 61 | return 0; | ||
| 62 | } | ||
