一、FFTW简介
FFT(快速傅里叶变换)是数字信号处理的超级经典算法,在量子物理、光谱分析、音视频流信号处理、石油勘探、地震预报、天气预报、概率论、编码理论、医学断层诊断等领域有着广泛的应用。在数学中,傅里叶级数(Fourier series)是把类似波的函数表示成简单正弦波的方式。

快速傅里叶变换的算法有许多,既有FFTW这种开源库,一些芯片企业也针对自家芯片设计FFT优化库,例如Intel的MKL_FFT,华为的KML_FFT。
打住,这里有一个问题? 既然有FFTW这种通用的、开源的还免费的库,为什么芯片公司还要费人费钱去自己搞FFT优化库呢? 通过这篇文章,也许你就会知其一二。 |
FFTW(Fast Fourier Transform in the West)是一款用于快速傅里叶变换(FFT)的开源库,它是自由软件许可证(类似于GPL)下发布的,您可以在其官方网站或代码仓库上找到最新版本的FFTW,然后根据许可证的规定使用它。它可以用于在多种计算平台上进行高效的数值计算。FFTW通过使用预分解算法和缓存技术,可以大大提高FFT的计算速度,与传统的FFT算法相比,可以节省数倍的计算时间。FFTW不仅可以用于科学计算和信号处理,还可以用于图像处理、音频处理等领域。FFTW的优秀性能使其成为许多科学计算和工程应用中不可或缺的工具。官网地址:http://fftw.org/ github地址:https://github.com/FFTW/fftw3
芯片的硬件算力水平
编译器(RISC-V的GCC属于初代版本)
编译选项(尤其是是否启用SIMD加速)
-
操作系统和依赖库等其他因素
gcc版本: 10.2.0
三、安装流程
解压:
ubuntu@perfxlab:~$ tar zxvf fftw-3.3.10.tar.gz
配置:
ubuntu@perfxlab:~/fftw-3.3.10$ ./configure --prefix=/usr/fftw3
安装:
ubuntu@perfxlab:~/fftw-3.3.10$ make install
配置环境变量:
export LD_LIBRARY_PATH=/usr/fftw3/lib:$LD_LIBRARY_PATH
验证是否安装成功:
ubuntu@perfxlab:~/fftw-3.3.10$ fftw-wisdom --version
fftw-wisdom tool for FFTW version 3.3.10.Copyright (c) 2003, 2007-14 Matteo FrigoCopyright (c) 2003, 2007-14 Massachusetts Institute of TechnologyThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <stdio.h>#include <stdlib.h>#include <fftw3.h>int main() {int N = 8; // 信号长度fftw_complex *in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);fftw_complex *out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);fftw_plan plan = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);// 初始化输入信号for (int i = 0; i < N; i++) {in[i][0] = i; // 实部in[i][1] = 0; // 虚部}// 执行傅里叶变换fftw_execute(plan);// 打印结果printf("Input Signal:\n");for (int i = 0; i < N; i++) {printf("%f + %fi\n", in[i][0], in[i][1]);}printf("Transformed Signal:\n");for (int i = 0; i < N; i++) {printf("%f + %fi\n", out[i][0], out[i][1]);}fftw_destroy_plan(plan);fftw_free(in);fftw_free(out);return 0;}
编译代码:
ubuntu@perfxlab:~/cheng$ gcc -o fftw_test testfftw.c -lfftw3 -lm
ubuntu@perfxlab:~/cheng$ ./fftw_testInput Signal:0.000000 + 0.000000i1.000000 + 0.000000i2.000000 + 0.000000i3.000000 + 0.000000i4.000000 + 0.000000i5.000000 + 0.000000i6.000000 + 0.000000i7.000000 + 0.000000iTransformed Signal:28.000000 + 0.000000i-4.000000 + 9.656854i-4.000000 + 4.000000i-4.000000 + 1.656854i-4.000000 + 0.000000i-4.000000 + -1.656854i-4.000000 + -4.000000i-4.000000 + -9.656854i
好了,结果正确,目前已经安装测试完成,可以愉快的使用了。
四、性能测试和对比
下面,我们将基于FFTW的开源项目,对SG2042进行性能评估,并和FT2000做简单对比。
测试代码如下
我们主要测试了FFTW(Fastest Fourier Transform in the West)库中的核心函数fftw_execute的性能。我们通过多次执行fftw_execute函数并取平均值来评估其性能,并将结果以GFlops(每秒十亿次浮点运算数)为单位进行了测量。in_place 、out_place代表是否使用了同一内存。
#include <stdio.h>#include <time.h>#include <fftw3.h>#include <math.h> // 包含math.h以使用log2函数int main() {int signal_lengths[] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}; // 不同信号长度int num_lengths = sizeof(signal_lengths) / sizeof(signal_lengths[0]);for (int i = 0; i < num_lengths; i++) {int N = signal_lengths[i];fftw_complex *in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);fftw_complex *out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);// 填充输入数据 (使用双精度浮点数)for (int j = 0; j < N; j++) {in[j][0] = 1.0; // 实部 (double)in[j][1] = 0.0; // 虚部 (double)}double total_elapsed_time = 0.0;int num_iterations = 20; // 每个长度的信号执行20次// 执行双精度浮点数傅立叶变换fftw_plan plan = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);for (int j = 0; j < num_iterations; j++) {clock_t start_time = clock();fftw_execute(plan);clock_t end_time = clock();double elapsed_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;total_elapsed_time += elapsed_time;}fftw_destroy_plan(plan);double average_time = total_elapsed_time / num_iterations;// 计算FLOPS(每秒浮点运算数)double flops = 5.0 * N * log2(N) / average_time; // 假设FFT算法的复杂度为5*N*log2(N)// 计算GFLOPS(每秒十亿次浮点运算数)double gflops = flops / 1e9;printf("平均FFTW执行时间(长度 %d): %f秒 GFLOPS : %f\n", N, average_time , gflops);fftw_free(in);fftw_free(out);}return 0;}
将fftw_complex改为fftwf_complex,将fftw_plan_dft_1d改为fftwf_plan_dft_1d。
-march=rv64gcv0p7_zfh_xtheadc -mabi=lp64d -mtune=c920 -O3
FT2000 编译选项
-Wall -Wextra -funroll-loops -O3 -DNDEBUG -DNOPEN_HASWELL_OPT
数据类型为float in_place:

数据类型为float out_place:

数据类型为 double in_place:


五、简单总结
将FFTW迁移到RISC-V处理器SG2042上的实验过程还是相对简单,这得益于RISC-V软件生态的不断完善。但同时也依然存在一些问题:
1:从上面的测试结果来看,数据类型为float时, SG2042的表现相对FT2000 有比较明显的差距;数据类型为double时,随着信号长度的增加,性能差距逐渐减小,趋于接近。
2:FFTW目前没有支持RISC-V的Vector版本,仍有极大性能潜力待挖掘。我们或者等待FFTW发行版支持RISC-V;或者有人自研RISC-V FFT优化算法库。回到了文章最开始的问题“既然有FFTW这种通用的、开源的还免费的库,为什么芯片公司还要费人费钱去自己搞FFT优化库呢?”,实际上还有许多类似这样的计算库,存在类似的问题。
全文结束
关于RISC-V公共测试平台

-
加入我们的RISC-V社区
欢迎关注我们,参与进来共建RISC-V软件生态~加入我们的讨论群后,可以向管理员申请免费的64核RISC-V服务器SUDO权限试用账号。
-
发邮件到riscvinfo@perfxlab.com 加入微信讨论群:加iYuta-R2为好友后可拉入群。
加入QQ讨论群:906962594(RVBoards·Only RISC-V)
扫描二维码加群👇

-
RISC-V公共测试云平台系列文章
-
RISC-V公测平台发布 · 我的世界MohistMC
-
RISC-V公测平台发布 · 第一个WEB Server“Hello RISC-V world!” -
RISC-V公测平台发布 ·如何在SG2042上玩转k3s -
“RISC-V成长日记” blog发布,第一个运行在RISC-V服务器上的blog? -
RISC-V公测平台发布:如何在SG2042上玩转OpenMPI -
RISC-V公测平台发布:Compiling The Fedora Linux Kernel Natively on RISC-V -
RISC-V公测平台发布 · Unix Bench完整测试 -
RISC-V公测平台发布 · 使用YCSB测试SG2042上的MySQL性能 -
RISC-V公测平台发布 · 7-zip 测试 -
RISC-V公测平台发布 · CoreMark测试报告 -
RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估 -
RISC-V公测平台发布 · 在SG2042上配置Jupiter+Octave科学计算环境 RISC-V公测平台发布 · 如何在SG2042上玩转 FFTW(本篇)
欢迎投稿,发送至riscvinfo@perfxlab.com

