本文记录笔者参加英特尔oneAPI黑客松比赛的环境调试、代码编写、结果分析及参赛心得。
环境配置:使用Visual Studio2022 + oneMKL
在oneMKL安装过程中,选择VS2022作为IDE;
安装完毕后,在VS2022中,在属性管理器中Debug|x64中添加MKL项,Use oneMKL改为Parallel,VC++目录项中,设置
可执行文件目录:
C:\Program Files (x86)\Intel\oneAPI\mkl\2023.2.0\bin\intel64;$(ExecutablePath)
包含目录:
C:\Program Files (x86)\Intel\oneAPI\mkl\2023.2.0\include;$(IncludePath)
库目录:
C:\ProgramFiles(x86)\Intel\oneAPI\mkl\2023.2.0\lib\intel64;C:\Program Files (x86)\Intel\oneAPI\compiler\2023.2.0\windows\compiler\lib\intel64_win;$(LibraryPath)
链接器输入的附加依赖项:
mkl_intel_ilp64.lib;mkl_intel_thread.lib;mkl_core.lib;libiomp5md.lib;%(AdditionalDependencies)
至此,环境配置完成。
代码逻辑:
在main函数中先生成2048*2048大小的随机数,分别调用fftw3以及oneMKL实现单精度浮点数的FFT,通过比较虚实部的方式对比结果,以上过程重复实现1000次,从而计算所用的平均时间。
int main()
{
auto start = chrono::high_resolution_clock::now();
auto end = chrono::high_resolution_clock::now();
chrono::duration<double> duration = end - start;
double time1 = 0, time2 = 0;
int right = 0;
for (int TIME = 0; TIME < tot_times; ++TIME) {
generate();
start = chrono::high_resolution_clock::now();
fft_by_fftw3();
end = chrono::high_resolution_clock::now();
duration = end - start;
time1 += duration.count();
start = chrono::high_resolution_clock::now();
fft_by_mkl();
end = chrono::high_resolution_clock::now();
duration = end - start;
time2 += duration.count();
bool equal = true;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N / 2 + 1; ++j) {
if (abs(fftwOutput[i * (N / 2 + 1)][j * 2] - mklOutput[i * N + j].real()) > 0.001)
equal = false;
if (abs(fftwOutput[i * (N / 2 + 1)][j * 2 + 1] - mklOutput[i * N + j].imag()) > 0.001)
equal = false;
}
}
if (equal)
right++;
}
fftw_free(fftwOutput);
cout << "Accuracy:" << right << " / 1000" << endl;
cout << "FFTW3_avg_time: " << time1 / tot_times << endl;
cout << "MKL_avg_time: " << time2 / tot_times << endl;
return 0;
}
运行方法及结果对比:
代码中分别使用fftw3和oneMKL实现2048*2048单精度FFT,并反复运行一千次,计算平均时长;在正确性方面,分别比较二者结果数组的实部和虚部,相差小于0.001视为相等,经过测试后正确率为1000/1000,平均每次FFT运行时长:FFTW3:0.0159s,oneMKL:0.0073s,可以发现,oneMKL在FFT运算上的平均时长明显小于FFTW3,性能上有将近一倍的提升。