通过同学介绍参加了23年度由东方地球物理公司举办的东方杯 Intel OneAPI黑客松比赛。下面分享一下此次的参赛过程和感受。
背景介绍 & 问题简介
oneAPI 就是这样一个跨架构编程模型,它在构建各种创新解决方案时拥有巨大潜力。利用 oneMKL(oneAPI Math Kernel Library)等工具对数学工程问题进行加速与优化。
这次的赛题主要围绕着OneAPI的数学库OneMKL进行,赛题内容是调用OneMKL数学库的相关接口,实现 FFT变换,并和开源的fftw3库进行正确性与速度两方面的对比。
测试流程
1.下载64位fftw3并解压:FFTW Installation on Windows
2.启动VS 2022 -X64 Native Tools Commond Prompt for VS 2022
3.通过cd命令跳转到fftw3库文件解压目录
4.输入如下命令生成对应的lib库:
lib /machine:x64 /def:libfftw3-3.def
lib /machine:x64 /def:libfftw3l-3.def
lib /machine:x64 /def:libfftw3f-3.def
5.在编译器VS2022社区版中安装Windows版本的Get Intel® oneAPI Math Kernel Library (oneMKL):Get Intel® oneAPI Math Kernel Library
6.新建项目:HKS_Project
7.右键项目进入“属性”,依次修改可执行文件目录、包含目录、库目录
8.在“属性”、“链接器”中点击输入,修改以下附加依赖项:
mkl_intel_ilp64.lib
mkl_intel_thread.lib
mkl_core.lib
libiomp5md.lib
9.在“属性”中,选择 C/C++ 下“常规”,在附加包含目录中添加 fftw64 的路径
10.在“属性”、“链接器”中点击输入,添加附加依赖项(步骤4生成的lib文件):
libfftw3-3.lib
libfftw3f-3.lib
libfftw3l-3.lib
11.将 fftw64 中的libfftw3-3.dll 、libfftw3f-3.dll、libfftw3l-3.dll文件复制到当前项目中
12.在VS 2022编译器中运行项目:“开始执行(不调试)”
部分代码展示
- (1)随机数生成器函数
// 创建随机数生成器函数
void random_numbers(float* standardized_numbers, const MKL_INT scale) {
VSLStreamStatePtr stream;
vslNewStream(&stream, VSL_BRNG_MT19937, 777);
vsRngUniform(VSL_RNG_METHOD_UNIFORM_STD_ACCURATE, stream, scale, standardized_numbers, 0.0, 1.0);
vslDeleteStream(&stream);
}
(2)onemkl_fft执行傅里叶变换
DFTI_DESCRIPTOR_HANDLE hand = NULL;
for (int i = 0; i < 1000; i++) {
char version[DFTI_VERSION_LENGTH];
DftiGetValue(0, DFTI_VERSION, version);
status = DftiCreateDescriptor(&hand, DFTI_SINGLE, DFTI_REAL, 2, N);
status = DftiSetValue(hand, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
status = DftiSetValue(hand, DFTI_CONJUGATE_EVEN_STORAGE,
DFTI_COMPLEX_COMPLEX);
status = DftiSetValue(hand, DFTI_INPUT_STRIDES, rs);
status = DftiSetValue(hand, DFTI_OUTPUT_STRIDES, cs);
status = DftiCommitDescriptor(hand);
status = DftiComputeForward(hand, real_data, cmplx_data);
}
(3)fftw3执行傅里叶变换
// fftw3执行傅里叶变换
for (int i = 0; i < 1000; i++) {
plan = fftwf_plan_dft_r2c_2d(NUM3, NUM3, in, out, FFTW_ESTIMATE);
fftwf_execute(plan);
}
(4)结果正确性检验
// 结果正确性检验
for (int i = 0; i < (NUM3 / 2 + 1) * NUM3;++i) {
if (abs(cmplx_data[i].real - out[i][0])> variable1) {
std::cout << "out[" << i << "]:" << abs(cmplx_data[i].real - out[i][0]) << std::endl;
std::cout << "out[" << i << "]:" << "结果不正确" << std::endl;
}
}
总结
通过此次比赛,了解并上手操作OneMKL库,虽然只是进行一些简单的FFT变换,但是经体验到了OneApi强大之处。后续会继续探索OneApi的其他领域的用途。