// // Program to solve Laplace equation on a regular 3D grid // #include #include #include #include #include //////////////////////////////////////////////////////////////////////// // define kernel block size //////////////////////////////////////////////////////////////////////// #define BLOCK_X 32 #define BLOCK_Y 4 //////////////////////////////////////////////////////////////////////// // include kernel function //////////////////////////////////////////////////////////////////////// #include //////////////////////////////////////////////////////////////////////// // declaration, forward //////////////////////////////////////////////////////////////////////// extern "C" void Gold_laplace3d(int NX, int NY, int NZ, float* h_u1, float* h_u2); void printHelp(void); //////////////////////////////////////////////////////////////////////// // Main program //////////////////////////////////////////////////////////////////////// int main(int argc, char **argv){ // 'h_' prefix - CPU (host) memory space int NX, NY, NZ, REPEAT, bx, by, i, j, k, ind, pitch; size_t pitch_bytes; float *h_u1, *h_u2, *h_u3, *h_foo, err; unsigned int hTimer; // 'd_' prefix - GPU (device) memory space float *d_u1, *d_u2, *d_foo; // check command line inputs if(cutCheckCmdLineFlag( argc, (const char**)argv, "help")) { printHelp(); return 1; } if( cutGetCmdLineArgumenti( argc, (const char**)argv, "nx", &NX) ) { if( NX <= 99 ) { printf("Illegal argument - nx must be greater than 99\n"); return -1; } } else NX = 100; if( cutGetCmdLineArgumenti( argc, (const char**)argv, "ny", &NY) ) { if( NY <= 99 ) { printf("Illegal argument - ny must be greater than 99\n"); return -1; } } else NY = 100; if( cutGetCmdLineArgumenti( argc, (const char**)argv, "nz", &NZ) ) { if( NZ <= 99 ) { printf("Illegal argument - nz must be greater than 99\n"); return -1; } } else NZ = 100; if( cutGetCmdLineArgumenti( argc, (const char**)argv, "repeat", &REPEAT) ) { if( REPEAT <= 0 ) { printf("Illegal argument - repeat must be greater than zero\n"); return -1; } } else REPEAT = 1; printf("\nGrid dimensions: %d x %d x %d\n", NX, NY, NZ); // initialise card and timer int deviceCount; CUDA_SAFE_CALL_NO_SYNC(cudaGetDeviceCount(&deviceCount)); if (deviceCount == 0) { fprintf(stderr, "There is no device.\n"); exit(EXIT_FAILURE); } int dev; for (dev = 0; dev < deviceCount; ++dev) { cudaDeviceProp deviceProp; CUDA_SAFE_CALL_NO_SYNC(cudaGetDeviceProperties(&deviceProp, dev)); if (deviceProp.major >= 1) break; } if (dev == deviceCount) { fprintf(stderr, "There is no device supporting CUDA.\n"); exit(EXIT_FAILURE); } else CUDA_SAFE_CALL(cudaSetDevice(dev)); CUT_SAFE_CALL( cutCreateTimer(&hTimer) ); // allocate memory for arrays h_u1 = (float *)malloc(sizeof(float)*NX*NY*NZ); h_u2 = (float *)malloc(sizeof(float)*NX*NY*NZ); h_u3 = (float *)malloc(sizeof(float)*NX*NY*NZ); CUDA_SAFE_CALL( cudaMallocPitch((void **)&d_u1, &pitch_bytes, sizeof(float)*NX, NY*NZ) ); CUDA_SAFE_CALL( cudaMallocPitch((void **)&d_u2, &pitch_bytes, sizeof(float)*NX, NY*NZ) ); pitch = pitch_bytes/sizeof(float); // initialise u1 for (k=0; k>>(NX, NY, NZ, pitch, d_u1, d_u2); d_foo = d_u1; d_u1 = d_u2; d_u2 = d_foo; // swap d_u1 and d_u3 CUDA_SAFE_CALL( cudaThreadSynchronize() ); CUT_CHECK_ERROR("GPU_laplace3d execution failed\n"); } CUT_SAFE_CALL( cutStopTimer(hTimer) ); printf("\n%dx GPU_laplace3d: %f (ms) \n", REPEAT, cutGetTimerValue(hTimer)); CUT_SAFE_CALL( cutResetTimer(hTimer) ); // Read back GPU results CUT_SAFE_CALL( cutStartTimer(hTimer) ); CUDA_SAFE_CALL( cudaMemcpy2D(h_u2, sizeof(float)*NX, d_u1, pitch_bytes, sizeof(float)*NX, NY*NZ, cudaMemcpyDeviceToHost) ); CUT_SAFE_CALL( cutStopTimer(hTimer) ); printf("\nCopy u2 to host: %f (ms) \n", cutGetTimerValue(hTimer)); CUT_SAFE_CALL( cutResetTimer(hTimer) ); // print out corner of array /* for (k=0; k<3; k++) { for (j=0; j<8; j++) { for (i=0; i<8; i++) { ind = i + j*NX + k*NX*NY; printf(" %5.2f ", h_u2[ind]); } printf("\n"); } printf("\n"); } */ // Gold treatment CUT_SAFE_CALL( cutResetTimer(hTimer) ); CUT_SAFE_CALL( cutStartTimer(hTimer) ); for (int i = 1; i <= REPEAT; ++i) { Gold_laplace3d(NX, NY, NZ, h_u1, h_u3); h_foo = h_u1; h_u1 = h_u3; h_u3 = h_foo; // swap h_u1 and h_u3 } CUT_SAFE_CALL( cutStopTimer(hTimer) ); printf("\n%dx Gold_laplace3d: %f (ms) \n \n", REPEAT, cutGetTimerValue(hTimer)); // print out corner of array /* for (k=0; k<3; k++) { for (j=0; j<8; j++) { for (i=0; i<8; i++) { ind = i + j*NX + k*NX*NY; printf(" %5.2f ", h_u1[ind]); } printf("\n"); } printf("\n"); } */ // error check err = 0.0; for (k=0; k