我正在寻找可以处理 8 位实数到复数转换(大小为 65K)的 FFT 引擎。对此的需求是加速实时信号处理引擎。它目前受到 8 位 -> FP32 和 FP32 -> 8 位转换的限制,以及实际的 FFT 受内存带宽限制(我们目前正在使用 FFTW)。
我认为 Spiral 项目可能能够做到这一点http://spiral.net,但他们网页上似乎唯一可用的代码是用于单次或双次转换。
任何人都知道可以做到这一点的任何 C 或 C++ 库吗?
有时我遇到了同样的问题。我的数据帧的 FFTW 在 14 毫秒内执行(向前、一些计算和向后),而直接字节(或短)到浮点数组的转换需要 12-19 毫秒。所以我制作了 SSE 函数来将字节转换为浮点数(每个周期 4 个元素),并且获得了显着的速度增益 - 现在转换在 2.2-5 毫秒内完成。
如果您的编译器可以使用自动向量化,请先尝试。
如果没有,请使用内在函数编写简单的转换函数。
我使用过内联汇编程序(MOVD、PUNPCKLBW、PUNPCKLWD、CVTDQ2PS、MOVAPS 命令序列)。
procedure BytesToSingles(Src, Dst: Pointer; Count: Integer);
asm
//EAX = Src pointer to byte array
//EDX = Dst pointer to float array !!! 16 byte-aligned !!!
//ECX = Count (multiple of four)
SHR ECX, 2 // 4 elements per cycle
JZ @@Exit
PXOR XMM7, XMM7 // zeros
@@Cycle:
MOVD XMM1, [EAX] // load 4 bytes
PUNPCKLBW XMM1, XMM7 // unpack to words
PUNPCKLWD XMM1, XMM7 // words to int32
CVTDQ2PS XMM0, XMM1 // convert integers to 4 floats
MOVAPS [EDX], XMM0 // store 4 floats to destination array
ADD EAX, 4 // move array pointers
ADD EDX, 16
LOOP @@Cycle
@@Exit:
end;
请注意,正如 Paul R 在评论中所写,对 8 位数据的 FFT 实现会遇到数值错误问题。
您不想在定点进行所有处理。您的数据将在该大小的 FFT 中变成糊状。从技术上讲,您可以使用 32 位定点并保留所有动态,但您仍然必须转换数据,并且它会比使用浮点数慢(您标记了 SSE,所以我假设您在具有 FPU 的英特尔机器上) . 我的意见基于我创建Kissfft的工作
而是专注于加快类型转换。我没有运行 MBo 的汇编代码,但它看起来是正确的方法。我认为展开可能会使其更快。
如果您不习惯汇编,请改用 SSE2 编译器内部函数。它会一样快(假设编译器不错),它会让你的代码更具可读性和可维护性。 这个答案会给你大部分你需要的东西。