//general parts #include #include #include #include #include #include #include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include //ROCM parts #include "hip/hip_runtime.h" #include #include "user_benchmark_rocFFT.h" void user_benchmark_rocFFT(bool file_output, FILE* output, rocFFTUserSystemParameters* userParams, int device_id) { hipSetDevice(device_id); const int num_runs = 7; double benchmark_result[2] = { 0,0 };//averaged result = sum(system_size/iteration_time)/num_benchmark_samples uint64_t storageComplexSize=8; switch (userParams->P) { case 0: storageComplexSize = (2 * sizeof(float)); break; case 1: storageComplexSize = (2 * sizeof(double)); break; case 2: storageComplexSize = (2 * 2); break; default: storageComplexSize = (2 * sizeof(float)); break; } uint64_t bufferSize = 0; if (userParams->R2C) { bufferSize = (uint64_t)(storageComplexSize / 2) * (userParams->X + 2) * userParams->Y * userParams->Z * userParams->B; } else { bufferSize = (uint64_t)storageComplexSize * userParams->X * userParams->Y * userParams->Z * userParams->B; } float* buffer_input = (float*)malloc(bufferSize); for (uint64_t i = 0; i < bufferSize/sizeof(float); i++) { buffer_input[i] = (float)(2 * ((float)rand()) / RAND_MAX - 1.0); } for (int n = 0; n < 2; n++) { double run_time[num_runs][2]; for (int r = 0; r < num_runs; r++) { hipfftHandle plan; hipfftHandle plan2; void* dataC; int dims[3]; int FFTdim = 1; if (userParams->Y > 1) FFTdim++; if (userParams->Z > 1) FFTdim++; switch (FFTdim) { case 1: dims[0] = userParams->X; dims[1] = 1; dims[2] = 1; break; case 2: dims[0] = userParams->Y; dims[1] = userParams->X; dims[2] = 1; break; case 3: dims[0] = userParams->Z; dims[1] = userParams->Y; dims[2] = userParams->X; break; } hipMalloc((void**)&dataC, bufferSize); if (hipGetLastError() != hipSuccess) { fprintf(stderr, "ROCM error: Failed to allocate\n"); return; } hipMemcpy(dataC, buffer_input, bufferSize, hipMemcpyHostToDevice); //forward + inverse int iembed[2][3]; int istride[2] = { 1, 1 }; int idist[2] = {bufferSize / userParams->B / storageComplexSize, bufferSize / userParams->B / storageComplexSize}; if (userParams->R2C) idist[0] *= 2; int oembed[2][3]; int ostride[2] = { 1, 1 }; int odist[2] = { bufferSize / userParams->B / storageComplexSize, bufferSize / userParams->B / storageComplexSize }; if (userParams->R2C) odist[1] *= 2; switch (FFTdim) { case 1: iembed[0][0] = (userParams->R2C) ? dims[0] + 2 : dims[0]; oembed[0][0] = (userParams->R2C) ? (dims[0] + 2) / 2 : dims[0]; iembed[1][0] = (userParams->R2C) ? (dims[0] + 2) / 2 : dims[0]; oembed[1][0] = (userParams->R2C) ? dims[0] + 2 : dims[0]; break; case 2: iembed[0][0] = dims[0]; iembed[0][1] = (userParams->R2C) ? dims[1] + 2 : dims[1]; oembed[0][0] = dims[0]; oembed[0][1] = (userParams->R2C) ? (dims[1] + 2) / 2 : dims[1]; iembed[1][0] = dims[0]; iembed[1][1] = (userParams->R2C) ? (dims[1] + 2) / 2 : dims[1]; oembed[1][0] = dims[0]; oembed[1][1] = (userParams->R2C) ? dims[1] + 2 : dims[1]; break; case 3: iembed[0][0] = idist[0]; iembed[0][1] = dims[1]; iembed[0][2] = (userParams->R2C) ? dims[2] + 2 : dims[2]; oembed[0][0] = odist[0]; oembed[0][1] = dims[1]; oembed[0][2] = (userParams->R2C) ? (dims[2] + 2)/2 : dims[2]; iembed[1][0] = idist[0]; iembed[1][1] = dims[1]; iembed[1][2] = (userParams->R2C) ? (dims[2] + 2)/2 : dims[2]; oembed[1][0] = odist[0]; oembed[1][1] = dims[1]; oembed[1][2] = (userParams->R2C) ? dims[2] + 2 : dims[2]; break; } switch (userParams->P) { case 0: if (userParams->R2C){ hipfftPlanMany(&plan, FFTdim, dims, iembed[0], istride[0], idist[0], oembed[0], ostride[0], odist[0], HIPFFT_R2C, userParams->B); hipfftPlanMany(&plan2, FFTdim, dims, iembed[1], istride[1], idist[1], oembed[1], ostride[1], odist[1], HIPFFT_C2R, userParams->B); }else{ hipfftPlanMany(&plan, FFTdim, dims, iembed[0], istride[0], idist[0], oembed[0], ostride[0], odist[0], HIPFFT_C2C, userParams->B); } break; case 1: if (userParams->R2C){ hipfftPlanMany(&plan, FFTdim, dims,iembed[0], istride[0], idist[0], oembed[0], ostride[0], odist[0], HIPFFT_D2Z, userParams->B); hipfftPlanMany(&plan2, FFTdim, dims, iembed[1], istride[1], idist[1], oembed[1], ostride[1], odist[1], HIPFFT_Z2D, userParams->B); }else hipfftPlanMany(&plan, FFTdim, dims, iembed[0], istride[0], idist[0], oembed[0], ostride[0], odist[0], HIPFFT_Z2Z, userParams->B); break; } float totTime = 0; std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now(); for (int i = 0; i < userParams->N; i++) { switch (userParams->P) { case 0: if (userParams->R2C){ hipfftExecR2C(plan, (hipfftReal*) dataC, (hipfftComplex*) dataC); hipfftExecC2R(plan2, (hipfftComplex*) dataC, (hipfftReal*) dataC); }else{ hipfftExecC2C(plan, (hipfftComplex*) dataC, (hipfftComplex*) dataC, -1); hipfftExecC2C(plan, (hipfftComplex*) dataC, (hipfftComplex*) dataC, 1); } break; case 1: if (userParams->R2C){ hipfftExecD2Z(plan, (hipfftDoubleReal*) dataC, (hipfftDoubleComplex*) dataC); hipfftExecZ2D(plan2, (hipfftDoubleComplex*) dataC, (hipfftDoubleReal*) dataC); }else{ hipfftExecZ2Z(plan, (hipfftDoubleComplex*) dataC, (hipfftDoubleComplex*) dataC, -1); hipfftExecZ2Z(plan, (hipfftDoubleComplex*) dataC, (hipfftDoubleComplex*) dataC, 1); } break; } } hipDeviceSynchronize(); std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now(); totTime = (std::chrono::duration_cast(timeEnd - timeSubmit).count() * 0.001) / userParams->N; run_time[r][0] = totTime; if (n > 0) { if (r == num_runs - 1) { double std_error = 0; double avg_time = 0; for (uint64_t t = 2; t < num_runs; t++) { avg_time += run_time[t][0]; } avg_time /= (num_runs-2); for (uint64_t t = 2; t < num_runs; t++) { std_error += (run_time[t][0] - avg_time) * (run_time[t][0] - avg_time); } std_error = sqrt(std_error / (num_runs-2)); if (file_output) fprintf(output, "rocFFT System: %" PRIu64 "x%" PRIu64 "x%" PRIu64 " Batch: %" PRIu64 " Buffer: %" PRIu64 " MB avg_time_per_step: %0.3f ms std_error: %0.3f num_iter: %" PRIu64 " benchmark: %" PRIu64 " scaled bandwidth: %0.1f\n", userParams->X, userParams->Y, userParams->Z, userParams->B, bufferSize / 1024 / 1024, avg_time, std_error, userParams->N, (uint64_t)(((double)bufferSize / 1024) / avg_time), ((double)bufferSize / 1024.0 / 1024.0 / 1.024 * 4 * FFTdim / avg_time)); printf("rocFFT System: %" PRIu64 "x%" PRIu64 "x%" PRIu64 " Batch: %" PRIu64 " Buffer: %" PRIu64 " MB avg_time_per_step: %0.3f ms std_error: %0.3f num_iter: %" PRIu64 " benchmark: %" PRIu64 " scaled bandwidth: %0.1f\n", userParams->X, userParams->Y, userParams->Z, userParams->B, bufferSize / 1024 / 1024, avg_time, std_error, userParams->N, (uint64_t)(((double)bufferSize / 1024) / avg_time), ((double)bufferSize / 1024.0 / 1024.0 / 1.024 * 4 * FFTdim / avg_time)); benchmark_result[0] += ((double)bufferSize / 1024) / avg_time; } } hipfftDestroy(plan); if (userParams->R2C) hipfftDestroy(plan2); hipFree(dataC); hipDeviceSynchronize(); //hipfftComplex* output_rocFFT = (hipfftComplex*)(malloc(sizeof(hipfftComplex) * dims[0] * dims[1] * dims[2])); //hipMemcpy(output_rocFFT, dataC, sizeof(hipfftComplex) * dims[0] * dims[1] * dims[2], hipMemcpyDeviceToHost); //hipDeviceSynchronize(); } } free(buffer_input); }