1+ #include < stdio.h>
2+ #include < assert.h>
3+
4+ // Convenience function for checking CUDA runtime API results
5+ // can be wrapped around any runtime API call. No-op in release builds.
6+ inline
7+ cudaError_t checkCuda (cudaError_t result)
8+ {
9+ #if defined(DEBUG) || defined(_DEBUG)
10+ if (result != cudaSuccess) {
11+ fprintf (stderr, " CUDA Runtime Error: %s\n " , cudaGetErrorString (result));
12+ assert (result == cudaSuccess);
13+ }
14+ #endif
15+ return result;
16+ }
17+
18+ template <typename T>
19+ __global__ void offset (T* a, int s)
20+ {
21+ int i = blockDim .x * blockIdx .x + threadIdx .x + s;
22+ a[i] = a[i] + 1 ;
23+ }
24+
25+ template <typename T>
26+ __global__ void stride (T* a, int s)
27+ {
28+ int i = (blockDim .x * blockIdx .x + threadIdx .x ) * s;
29+ a[i] = a[i] + 1 ;
30+ }
31+
32+ template <typename T>
33+ void runTest (int deviceId, int nMB)
34+ {
35+ int blockSize = 256 ;
36+ float ms;
37+
38+ T *d_a;
39+ cudaEvent_t startEvent, stopEvent;
40+
41+ int n = nMB*1024 *1024 /sizeof (T);
42+
43+ // NB: d_a(33*nMB) for stride case
44+ checkCuda ( cudaMalloc (&d_a, n * 33 * sizeof (T)) );
45+
46+ checkCuda ( cudaEventCreate (&startEvent) );
47+ checkCuda ( cudaEventCreate (&stopEvent) );
48+
49+ printf (" Offset, Bandwidth (GB/s):\n " );
50+
51+ offset<<<n/blockSize, blockSize>>> (d_a, 0 ); // warm up
52+
53+ for (int i = 0 ; i <= 32 ; i++) {
54+ checkCuda ( cudaMemset (d_a, 0.0 , n * sizeof (T)) );
55+
56+ checkCuda ( cudaEventRecord (startEvent,0 ) );
57+ offset<<<n/blockSize, blockSize>>> (d_a, i);
58+ checkCuda ( cudaEventRecord (stopEvent,0 ) );
59+ checkCuda ( cudaEventSynchronize (stopEvent) );
60+
61+ checkCuda ( cudaEventElapsedTime (&ms, startEvent, stopEvent) );
62+ printf (" %d, %f\n " , i, 2 *nMB/ms);
63+ }
64+
65+ printf (" \n " );
66+ printf (" Stride, Bandwidth (GB/s):\n " );
67+
68+ stride<<<n/blockSize, blockSize>>> (d_a, 1 ); // warm up
69+ for (int i = 1 ; i <= 32 ; i++) {
70+ checkCuda ( cudaMemset (d_a, 0.0 , n * sizeof (T)) );
71+
72+ checkCuda ( cudaEventRecord (startEvent,0 ) );
73+ stride<<<n/blockSize, blockSize>>> (d_a, i);
74+ checkCuda ( cudaEventRecord (stopEvent,0 ) );
75+ checkCuda ( cudaEventSynchronize (stopEvent) );
76+
77+ checkCuda ( cudaEventElapsedTime (&ms, startEvent, stopEvent) );
78+ printf (" %d, %f\n " , i, 2 *nMB/ms);
79+ }
80+
81+ checkCuda ( cudaEventDestroy (startEvent) );
82+ checkCuda ( cudaEventDestroy (stopEvent) );
83+ cudaFree (d_a);
84+ }
85+
86+ int main (int argc, char **argv)
87+ {
88+ int nMB = 4 ;
89+ int deviceId = 0 ;
90+ bool bFp64 = false ;
91+
92+ for (int i = 1 ; i < argc; i++) {
93+ if (!strncmp (argv[i], " dev=" , 4 ))
94+ deviceId = atoi ((char *)(&argv[i][4 ]));
95+ else if (!strcmp (argv[i], " fp64" ))
96+ bFp64 = true ;
97+ }
98+
99+ cudaDeviceProp prop;
100+
101+ checkCuda ( cudaSetDevice (deviceId) )
102+ ;
103+ checkCuda ( cudaGetDeviceProperties (&prop, deviceId) );
104+ printf (" Device: %s\n " , prop.name );
105+ printf (" Transfer size (MB): %d\n " , nMB);
106+
107+ printf (" %s Precision\n " , bFp64 ? " Double" : " Single" );
108+
109+ if (bFp64) runTest<double >(deviceId, nMB);
110+ else runTest<float >(deviceId, nMB);
111+ }
0 commit comments