问题简介
使用oneMKL工具,对FFT算法进行加速与优化。
- 调用oneMKL相应API函数,产生2048 * 2048个随机单精度实数。
- 产生的随机数据作为输入,实现两维Real to complex FFT参考代码。
- 产生的随机数据作为输入,调用oneMKLAPI计算两维Real to complex FFT。
- 结果正确性验证,对3和4计算的两维FFT输出数据进行全数据比对(允许适当精度误差),输出“结果正确”或“结果不正确”信息。
- 平均性能数据比对(比如运行1000次),输出FFT参考代码平均运行时间和oneMKLFFT平均运行时间。
环境配置
代码环境通过以下几步完成配置:
- 下载安装visual studio 2022
- 从Intel官网下载OneAPI Base并安装
代码实现
核心代码部分,包括随机数生成、FFTW计算、MKL计算及数据正确性验证。
首先生成随机数:
VSLStreamStatePtr stream;
vslNewStream(&stream, VSL_BRNG_MT19937, 1);
vsRngUniform(VSL_RNG_METHOD_UNIFORM_STD, stream, N * M, input_data, 0.0f, 1.0f);
之后进行FFTW计算:
fftwf_plan fftw_plan = fftwf_plan_dft_r2c_2d(N, M, input_data, fftw_result, FFTW_ESTIMATE);
auto start_time = std::chrono::high_resolution_clock::now();
fftwf_execute(fftw_plan);
auto end_time = std::chrono::high_resolution_clock::now();
double execution_time = std::chrono::duration<double, std::micro>(end_time - start_time).count();
以及MKL计算:
DftiCreateDescriptor(&handle, DFTI_SINGLE, DFTI_REAL, 2, s0);
DftiSetValue(handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
DftiSetValue(handle, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
DftiSetValue(handle, DFTI_INPUT_STRIDES, s1);
DftiSetValue(handle, DFTI_OUTPUT_STRIDES, s2);
DftiCommitDescriptor(handle);
auto start_time = std::chrono::high_resolution_clock::now();
DftiComputeForward(handle, input_data, mkl_result);
auto end_time = std::chrono::high_resolution_clock::now();
double execution_time = std::chrono::duration<double, std::micro>(end_time - start_time).count();
最后进行数据正确性验证:
bool compareResults(const MKL_Complex8* mkl_result, const fftwf_complex* fftw_result, const int SIZE) {
const double epsilon = 1e-5;
for (size_t j = 0; j < SIZE; ++j) {
if (fabs(mkl_result[j].real - fftw_result[j][0]) > epsilon || fabs(mkl_result[j].imag - fftw_result[j][1]) > epsilon) {
return false;
}
}
return true;
}
运行结果
代码运行结果如下,1000次循环的结果全部正确,MKL的平均运行时间短于FFTW。