Hal*_*lle 4 c iphone floating-point optimization llvm
我一直在分析我几乎完成的项目,我发现大约四分之三的CPU时间花在了这个IIR过滤器功能上(在目标硬件上大约一秒钟被称为数十万次)所以其他一切运作良好,我想知道它是否可以针对我的特定硬件和软件目标进行优化.我的目标只有iPhone 4和更新版本,只有iOS 4.3及更高版本,只有LLVM 4.x. 如果有收获的话,可能会有一点不精确.
static float filter(const float a, const float *b, const float c, float *d, const int e, const float x)
{
float return_value = 0;
d[0] = x;
d[1] = c * d[0] + a * d[1];
int j;
for (j = 2; j <= e; j++) {
return_value += (d[j] += a * (d[j + 1] - d[j - 1])) * b[j];
}
for (j = e + 1; j > 1; j--) {
d[j] = d[j - 1];
}
return (return_value);
}
Run Code Online (Sandbox Code Playgroud)
关于加速它的任何建议都表示赞赏,如果有可能优化超出默认的编译器优化,也会对您的意见感兴趣.我想知道它是否是NEON SIMD会帮助的东西(这对我来说是新的理由),或者是否可以利用VFP,或者LLVM自动向量化会有所帮助.
我尝试过以下LLVM标志:
-ffast-math(没有显着差异)
-O4(在iPhone 4S上有很大的不同,时间缩短了25%,但我的最低目标设备iPhone 4没有显着差异,改进是我的主要目标)
-O3 -mllvm -unroll-allow-partial -mllvm -unroll-runtime -funsafe-math-optimizations -ffast-math -mllvm -vectorize -mllvm -bb-vectorize-aligned-only(来自Hal Finkel幻灯片的LLVM自动向量化标志:http://llvm.org/devmtg/2012-04-12/Slides/Hal_Finkel.pdf,比Xcode版本目标的默认LLVM优化要慢一些)
打开其他标志,不同的方法,并更改功能.我更愿意单独保留输入和返回类型和值.实际上有一个讨论在这里使用FIR的NEON内在函数:https://pixhawk.ethz.ch/_media/software/optimization/neon_support_in_the_arm_compiler.pdf但我没有足够的经验来成功应用这些信息对我自己的情况.感谢您的任何澄清.
编辑我很抱歉没有早点注意到这一点.在调查了aka.nice的建议之后,我注意到e,a和c传入的值总是相同的值,我在运行时之前知道它们,所以包含这些信息的方法是一个选项.
以下是可以对代码进行的一些转换,以使用vDSP例程.这些转换使用名为T0,T1和T2的各种临时缓冲区.每个都是一个浮点数组,有足够的空间用于e-1元素.
首先,使用临时缓冲区进行计算a * b[j].这会更改原始代码:
for (j = 2; j <= e; j++) {
return_value += (d[j] += a * (d[j + 1] - d[j - 1])) * b[j];
}
Run Code Online (Sandbox Code Playgroud)
至:
vDSP_vsmul(b+2, 1, &a, T0, 1, e-1);
for (j = 2; j <= e; j++)
return_value += (d[j] += (d[j+1] - d[j-1])) * T0[j-2];
Run Code Online (Sandbox Code Playgroud)
然后使用vDSP_vmul计算d[j+1] * T0[j-2]:
vDSP_vsmul(b+2, 1, &a, T0, 1, e-1);
vDSP_vmul(d+3, 1, T0, 1, T1, 1, e-1);
for (j = 2; j <= e; j++)
return_value += (d[j] += T1[j-2] - d[j-1] * T0[j-2];
Run Code Online (Sandbox Code Playgroud)
接下来,将vDSP_vmul提升为vDSP_vma(向量乘法加法)以计算d[j] + d[j+1] * T0[j-2]:
vDSP_vsmul(b+2, 1, &a, T0, 1, e-1);
vDSP_vma(d+3, 1, T0, 1, d+2, 1, T1, 1, e-1);
for (j = 2; j <= e; j++)
return_value += (d[j] = T1[j-2] - d[j-1] * T0[j-2];
Run Code Online (Sandbox Code Playgroud)
我想我会花时间看看是否有任何进步.有一些问题:
j-1和j+1阻止这种情况.手机中的ARM处理器与其他处理器的未对齐数据并不差,但性能因型号而异.以上是我的头脑; 我没有测试过代码.我建议逐个进行转换,以便您可以在每次更改后测试代码并在继续之前识别任何错误.
如果您能找到一个不是IIR的令人满意的过滤器,则可能会有更多的性能优化.