java - 减少FFT的处理时间

标签 java android performance fft

我目前正在为 Android 开发 Java。我尝试实现 FFT 以实现一种频率查看器。

实际上我能够做到这一点,但显示根本不流畅。 我添加了一些跟踪来检查代码每个部分的处理时间,事实是 FFT 需要大约 300 毫秒才能应用于我的复杂数组,该数组拥有 4096 个元素。我需要它花费少于 100 毫秒,因为我的线程(显示频率)每 100 毫秒刷新一次。我减少了初始数组,以便 FFT 结果仅包含 1028 个元素,它可以工作,但结果已被弃用。

有人有想法吗?

我使用了可以在互联网上找到的默认 fft.java 和 Complex.java 类。

仅供引用,我计算 FFT 的代码如下:

int bytesPerSample = 2;
Complex[] x = new Complex[bufferSize/2] ;

for (int index = 0 ; index < bufferReadResult - bytesPerSample + 1; index += bytesPerSample)
{
// 16BITS = 2BYTES

    float asFloat = Float.intBitsToFloat(asInt);


    double sample = 0;
    for (int b = 0; b < bytesPerSample; b++) {
        int v = buffer[index + b];
        if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                v &= 0xFF;
        }
                        sample += v << (b * 8);
     }

    double sample32 = 100 * (sample / 32768.0); // don't know the use of this compute...
    x[index/bytesPerSample] = new Complex(sample32, 0);
}


    Complex[] tx = new Complex[1024]; // size = 2048 

///// reduction of the size of the signal in order to improve the fft traitment time
for (int i = 0; i < x.length/4; i++)
{

    tx[i] = new Complex(x[i*4].re(), 0);

 }

// Signal retrieval thanks to the FFT
fftRes = FFT.fft(tx);

最佳答案

我不懂Java,但你在输入数据和复杂值数组之间进行转换的方式似乎非常复杂。您正在构建两个复杂数据数组,其中只需要一个。

而且,你的复数实值和虚值听起来像是双倍的。这远远超出了你的需求,而且 ARM 在 double 运算上速度非常慢。是否有基于单精度 float 的复杂类?

第三,您通过用零填充复数的虚部来对实际数据执行复数 fft。虽然结果是正确的,但工作量是原来的两倍(除非例程足够聪明来发现这一点,我对此表示怀疑)。如果可能的话,对您的数据执行真正的 fft 并节省一半的时间。

正如西蒙所说,整个问题是避免垃圾收集和内存分配。

此外,您的 FFT 似乎没有准备步骤。这意味着例程 FFT.fft() 每次都在计算复指数。 FFT 计算的最长部分是计算复指数,这很遗憾,因为对于任何给定的 FFT 长度,指数都是常数。它们根本不依赖于您的输入数据。在实时世界中,我们使用 FFT 例程,在程序开始时计算一次指数,然后实际的 fft 本身将该常量数组作为其输入之一。不知道你的FFT类是否可以做类似的事情。

如果您最终确实使用了 FFTW 之类的东西,那么您将不得不习惯于从 Java 调用 C 代码。还要确保您获得支持(我认为)NEON 的版本,NEON 是 ARM 对 SSE、AVX 和 Altivec 的回应。值得仔细阅读他们的发行说明来检查。另外,我强烈怀疑,如果您要求 FFTW 对单精度 float 而不是 double 执行 FFT,FFTW 只能提供显着的加速。

谷歌运气好!

--编辑--

我的意思当然是“祝你好运”。快给我一个真正的键盘,这些触摸屏键盘不可靠......

关于java - 减少FFT的处理时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15734029/

相关文章:

android - Swiftkey 忽略 TextInputEditText 标志 InputType.TYPE_TEXT_FLAG_CAP_WORDS - 不大写

performance - 使用 O(1) 性能初始化 n 个元素数组?

java - Java 中的 Casting 是否有任何运行时成本?

Android Studio 3.0 xml-layout 文件的预览未显示

java - 单击按钮后如何加载下一组元素

java - SSLPeerUnverifiedException 与 httpClient

java - 从 MongoDB 读取数据

android - 如何使用 Jetpack Compose 创建带有溢出菜单的工具栏?

c++ - Eigen:如何加速 += coeffs * coeffs.transpose()

java - Android - 如何将图像存储在已创建的 Firestore 文件夹中