summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-09 19:38:01 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-09 19:38:01 -0400
commit5ba80e14efb595688a3dc3d49c212bc393840513 (patch)
tree87b57ee39eaf0c12603eb1b6f4ea9e0889a20e8e
parente63404cfda97050b9d516232ceb4f918f48edcfc (diff)
Add constant_cycles_kernel benchmark + header split and Makefile
Benchmark supports: => Looping on the GPU for a specified number of iterations => Looping infinitely on the GPU => Logging the sum time (ns and ms) for all iterations to complete Also splits `testbench.h` out of `copy_testbench.h` for use in other benchmarks.
-rw-r--r--Makefile7
-rw-r--r--constant_cycles_kernel.cu56
-rw-r--r--copy_experiments/Makefile3
-rw-r--r--copy_experiments/copy_testbench.h15
-rw-r--r--testbench.h14
5 files changed, 80 insertions, 15 deletions
diff --git a/Makefile b/Makefile
index e81353d..7eaf03d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,9 @@
1.PHONY: copy_experiments 1.PHONY: all copy_experiments
2
3all: constant_cycles_kernel copy_experiments
4
5constant_cycles_kernel: constant_cycles_kernel.cu testbench.h
6 nvcc constant_cycles_kernel.cu -o constant_cycles_kernel
2 7
3copy_experiments: 8copy_experiments:
4 $(MAKE) -C $@ 9 $(MAKE) -C $@
diff --git a/constant_cycles_kernel.cu b/constant_cycles_kernel.cu
new file mode 100644
index 0000000..eda963d
--- /dev/null
+++ b/constant_cycles_kernel.cu
@@ -0,0 +1,56 @@
1/* Copyright 2021-2023 Joshua Bakita
2 * Simple kernel that spins on the GPU for a specified number of iterations,
3 * while tracking and printing the necessary CPU time.
4 */
5#include <time.h>
6#include <stdio.h>
7#include <cuda.h>
8
9#include "testbench.h"
10
11__global__ void loop_on_gpu(unsigned long iters, int *__unused) {
12 for (volatile int i = 0; i < iters; i++) (*__unused)++;
13}
14
15int main(int argc, char **argv) {
16 cudaError_t err;
17 int res, *__unused;
18 struct timespec start, end;
19
20 if (argc != 2) {
21 fprintf(stderr, "Usage: %s <# of millions of iterations, or -1 for infinite>\n",
22 argv[0]);
23 return 1;
24 }
25
26 // Input is multiplied by one million, unless infinite
27 unsigned long num_iters = strtoul(argv[1], NULL, 10);
28 if (num_iters != (unsigned long)(-1))
29 num_iters *= 1000 * 1000;
30
31 // Initialize CUDA and a context (hack)
32 SAFE(cudaMalloc(&__unused, 8));
33
34 // Run iterations on a single thread
35 clock_gettime(CLOCK_MONOTONIC_RAW, &start);
36 loop_on_gpu<<<1,1>>>(num_iters, __unused);
37 SAFE(cudaGetLastError() /* Check successful launch */);
38 SAFE(cudaDeviceSynchronize());
39 clock_gettime(CLOCK_MONOTONIC_RAW, &end);
40
41 // Print detailed timing information
42 long elapsed = timediff(start, end);
43 fprintf(stderr, "Started at %ld ns, ended at %ld ns\n",
44 s2ns(start.tv_sec) + start.tv_nsec, s2ns(end.tv_sec) + end.tv_nsec);
45 fprintf(stderr, "%ld ns (%.2f ms) elapsed\n", elapsed, elapsed / (1000 * 1000.));
46
47 // Verify success (fool optimizer)
48 SAFE(cudaMemcpy(&res, __unused, 8, cudaMemcpyDeviceToHost));
49 // Theoretically this can happen if `__unused` wraps around; maybe for a
50 // very small `long` type, or a very long run. More likely indicates an error.
51 if (!res)
52 fprintf(stderr, "CRITICAL: Zero iterations seem completed. Likely incorrect "
53 "arguments, internal error, or corruption of CUDA internal state.\n");
54
55 return 0;
56}
diff --git a/copy_experiments/Makefile b/copy_experiments/Makefile
index 2358c60..b6b5a38 100644
--- a/copy_experiments/Makefile
+++ b/copy_experiments/Makefile
@@ -1,3 +1,2 @@
1 1copy_contender: copy_contender.cu copy_testbench.h ../testbench.h
2copy_contender: copy_contender.cu copy_testbench.h
3 /usr/local/cuda/bin/nvcc copy_contender.cu -o $@ -lcuda -g 2 /usr/local/cuda/bin/nvcc copy_contender.cu -o $@ -lcuda -g
diff --git a/copy_experiments/copy_testbench.h b/copy_experiments/copy_testbench.h
index e1c4aa5..fed62ba 100644
--- a/copy_experiments/copy_testbench.h
+++ b/copy_experiments/copy_testbench.h
@@ -1,24 +1,15 @@
1/* Copyright 2023 Joshua Bakita 1/* Copyright 2021-2023 Joshua Bakita
2 * Header-only library that provides an ultra-low-overhead GPU timing function, 2 * Header-only library that provides an ultra-low-overhead GPU timing function,
3 * a copy monitoring kernel, and other useful sundries. 3 * a copy monitoring kernel, and other useful sundries.
4 */ 4 */
5#include <stdio.h> 5#include <stdio.h>
6#include <stdint.h> 6#include <stdint.h>
7 7
8#include "../testbench.h"
9
8// 4k pages (4096 bytes) 10// 4k pages (4096 bytes)
9#define PG_SZ 0x1000 11#define PG_SZ 0x1000
10 12
11#define SAFE(x) \
12 if ((err = (cudaError_t)(x)) != 0) { \
13 printf("CUDA error %d! %s\n", err, cudaGetErrorString(err)); \
14 printf("Suspect line: %s\n", #x); \
15 exit(1); \
16 }
17
18#define s2ns(s) ((s)*1000l*1000l*1000l)
19#define ns2ms(s) ((s)/(1000l*1000l))
20#define timediff(start, end) ((s2ns((end).tv_sec) + (end).tv_nsec) - (s2ns((start).tv_sec) + (start).tv_nsec))
21
22// Compiles to 5 inline SASS instructions on sm_52 13// Compiles to 5 inline SASS instructions on sm_52
23static __device__ inline uint64_t gclock64_fast(void) { 14static __device__ inline uint64_t gclock64_fast(void) {
24 uint32_t lo_bits; 15 uint32_t lo_bits;
diff --git a/testbench.h b/testbench.h
new file mode 100644
index 0000000..28d7f77
--- /dev/null
+++ b/testbench.h
@@ -0,0 +1,14 @@
1/* Copyright 2021-2023 Joshua Bakita
2 * Header for miscellaneous experimental helper functions.
3 */
4
5#define SAFE(x) \
6 if ((err = (cudaError_t)(x)) != 0) { \
7 printf("CUDA error %d! %s\n", err, cudaGetErrorString(err)); \
8 printf("Suspect line: %s\n", #x); \
9 exit(1); \
10 }
11
12#define s2ns(s) ((s)*1000l*1000l*1000l)
13#define ns2ms(s) ((s)/(1000l*1000l))
14#define timediff(start, end) ((s2ns((end).tv_sec) + (end).tv_nsec) - (s2ns((start).tv_sec) + (start).tv_nsec))