diff options
| -rw-r--r-- | measure_launch_oh.cu | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/measure_launch_oh.cu b/measure_launch_oh.cu index 981448a..0a253a2 100644 --- a/measure_launch_oh.cu +++ b/measure_launch_oh.cu | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | /* Copyright 2024 Joshua Bakita | 1 | /* Copyright 2024 Joshua Bakita |
| 2 | * Simple kernel that clocks how long a kernel launch takes to the GPU. | 2 | * Simple kernel that clocks how long a kernel launch takes to the GPU. |
| 3 | * Prints samples to stdout and summary statistics to stderr. | 3 | * Prints samples to stdout and summary statistics to stderr. |
| 4 | * | ||
| 5 | * For best results, pin to a CPU core and redirect interrupts. | ||
| 4 | */ | 6 | */ |
| 5 | #include <time.h> | 7 | #include <time.h> |
| 8 | #include <sched.h> | ||
| 6 | #include <stdio.h> | 9 | #include <stdio.h> |
| 7 | #include <stdint.h> | 10 | #include <stdint.h> |
| 8 | #include <unistd.h> | 11 | #include <unistd.h> |
| @@ -14,7 +17,7 @@ __global__ void flag_on_gpu(volatile int *flag) { | |||
| 14 | } | 17 | } |
| 15 | 18 | ||
| 16 | // Get launch overhead | 19 | // Get launch overhead |
| 17 | long measure_launch_overhead() { | 20 | long measure_launch_overhead(bool first_run) { |
| 18 | volatile int *barrier; | 21 | volatile int *barrier; |
| 19 | struct timespec start, end; | 22 | struct timespec start, end; |
| 20 | SAFE(cudaHostAlloc(&barrier, sizeof(*barrier), cudaHostAllocMapped)); | 23 | SAFE(cudaHostAlloc(&barrier, sizeof(*barrier), cudaHostAllocMapped)); |
| @@ -24,6 +27,9 @@ long measure_launch_overhead() { | |||
| 24 | while (!*barrier) continue; | 27 | while (!*barrier) continue; |
| 25 | clock_gettime(CLOCK_MONOTONIC_RAW, &end); | 28 | clock_gettime(CLOCK_MONOTONIC_RAW, &end); |
| 26 | SAFE(cudaDeviceSynchronize()); | 29 | SAFE(cudaDeviceSynchronize()); |
| 30 | if (first_run) | ||
| 31 | fprintf(stderr, "(%d) First launch completed at CLOCK_MONOTONIC_RAW = %ld ns\n", | ||
| 32 | getpid(), time2ns(end)); | ||
| 27 | return timediff(start, end); | 33 | return timediff(start, end); |
| 28 | } | 34 | } |
| 29 | 35 | ||
| @@ -44,13 +50,18 @@ int main(int argc, char **argv) { | |||
| 44 | SAFE(cudaMalloc(&__unused, 8)); | 50 | SAFE(cudaMalloc(&__unused, 8)); |
| 45 | 51 | ||
| 46 | // Run once to ensure the kernel is compiled | 52 | // Run once to ensure the kernel is compiled |
| 47 | time = measure_launch_overhead(); | 53 | time = measure_launch_overhead(true); |
| 48 | fprintf(stderr, "(%d) %ld ns (%.2f ms) warmup launch overhead\n", getpid(), | 54 | fprintf(stderr, "(%d) %ld ns (%.2f ms) warmup launch overhead\n", getpid(), |
| 49 | time, ns2ms((double)time)); | 55 | time, ns2ms((double)time)); |
| 50 | 56 | ||
| 51 | // Time several kernel launches | 57 | // Time several kernel launches |
| 52 | for (i = 0; i < num_iters; i++) { | 58 | for (i = 0; i < num_iters; i++) { |
| 53 | time = measure_launch_overhead(); | 59 | // We're measuring on the order of microseconds. Make sure the |
| 60 | // kernel scheduler does not interrupt us during a timing | ||
| 61 | // iteration by explicitly invoking it here. | ||
| 62 | sched_yield(); | ||
| 63 | // Measure overhead | ||
| 64 | time = measure_launch_overhead(false); | ||
| 54 | cumulative_time += time; | 65 | cumulative_time += time; |
| 55 | // Print one sample per line | 66 | // Print one sample per line |
| 56 | fprintf(stdout, "%ld\n", time); | 67 | fprintf(stdout, "%ld\n", time); |
