有幸参加了 Intel 组织的 oneAPI 黑客松大赛,使用 oneMKL 提供的接口,对 FFT 计算进行了加速,特此记录。
代码库
https://github.com/jywhy6/oneapi_hackathon
安装依赖
oneMKL
- 下载最新版本 Intel® oneAPI Math Kernel Library (oneMKL)
- 在安装目录下找到并运行
setvars.bat
以一键配置 oneMKL 环境变量
CMake
- CMake 是一个开源的跨平台自动化构建系统
- 从 2021.3 版本起,oneMKL 支持 CMake(详见开发者指南)
- 从官网下载并安装最新版本(Latest Release)的 CMake,并勾选添加到系统
PATH
的选项
vcpkg
- vcpkg 是微软开发的 C 和 C++ 库管理器
- 建议跟随官方 GitHub 仓库的指南安装 vcpkg
FFTW
- FFTW 是一个傅立叶变换库,支持 C、Fortran 等语言
- oneMKL 提供了无需修改源码的 FFTW 加速接口
- 成功安装 vcpkg 后,执行
vcpkg install fftw3:x64-windows
命令安装 64 位 Windows 版本的 FFTW 库
构建
- 打开终端,进入源码目录
- 执行
mkdir build
、cd build
命令,创建并进入build
目录 - 执行
cmake -S .. -B . -D CMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_TOOLCHAIN_FILE="{PATH_TO_VCPKG}/scripts/buildsystems/vcpkg.cmake"
命令,生成 64 位项目文件- 请将
{PATH_TO_VCPKG}
替换为您的 vcpkg 安装路径
- 请将
- 执行
cmake --build . --config Release
命令,使用Release
配置构建项目
- 执行
运行测试
- (在
build
目录)执行ctest -C Release
命令,将自动依次运行以下四个程序,并输出测试结果random_number_generator
,使用MT19937
算法,生成2048 * 2048
个在[0, 1)
区间内均匀分布的伪随机单精度浮点数(种子由源码中#define SEED
设置),并将结果输出至rand.txt
fftw3_onemkl
,读取rand.txt
作为输入,使用 oneMKL 提供的 FFTW 加速接口,执行 1000 次二维的实数到复数的傅立叶变换(单精度浮点数),将计算结果输出至result_fftw3_onemkl.txt
,并打印平均执行时长fftw3_original
,读取rand.txt
作为输入,使用原版 FFTW 接口,执行 1000 次二维的实数到复数的傅立叶变换(单精度浮点数),将计算结果输出至result_fftw3_original.txt
,并打印平均执行时长compare
,读取fftw3_onemkl
和fftw3_original
输出的结果,并分别计算实部和虚部的平均误差值,当两者平均误差值都小于 0.0001 时测试通过,否则测试失败
测试结果
如下图所示,可打开
build/Testing/Temporary/LastTest.log
查看详细的测试结果实部和虚部的平均误差值都小于 0.0001,测试通过(有趣的是,我尝试替换了几次随机数种子,最后得到的平均误差值都是 0.000085)
oneMKL 提供的 FFTW 加速接口平均执行时间 0.012634 秒,原版 FFTW 接口平均执行时间 0.025977 秒,使用 oneMKL,计算速度高达原版的 205.61%
oneMKL 使用体验
个人感觉 oneMKL 使用起来还是有一定难度(主要在构建配置上),但只要学习安装目录下的样例代码,再多读读官方文档,还是能比较快做一个 DEMO 出来的。
令我非常惊喜的是,使用 oneMKL 提供的 FFTW 加速接口完全不需要改动源码,只需链接 oneMKL,这极大降低了开发者的接口学习负担(本项目也充分利用了这一特性,用一份代码生成两个不同程序)。