c++ - 是否可以在计算中对串行依赖项使用 SIMD,例如指数移动平均滤波器?
问题描述
我正在处理我的音频应用程序中不同参数的多个(独立)指数移动平均1 极滤波器,目的是在音频速率下平滑每个参数值:
for (int i = 0; i < mParams.GetSize(); i++) {
mParams.Get(i)->SmoothBlock(blockSize);
}
...
inline void SmoothBlock(int blockSize) {
double inputA0 = mValue * a0;
for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
mSmoothedValues[sampleIndex] = z1 = inputA0 + z1 * b1;
}
}
我想利用 CPUSIMD
指令,并行处理它们,但我不确定如何实现这一点。
事实上,z1
是递归的:考虑到“以前的值”,不能“打包”双数组,对吧?
也许有办法正确组织不同过滤器的数据并并行处理它们?
欢迎任何提示或建议!
请注意:我没有多个信号路径。任何参数代表(唯一)处理信号的不同控制。假设我有一个 sin 信号:参数 1 将影响增益,参数 2 音高,参数 3 滤波器截止,参数 4 声像等等。
解决方案
您有一个特殊情况,输入信号是Heaviside step function。您希望获得对此函数的过滤器响应,称为Step response。这种情况下的递归可以被消除。首先,让我们展开几个步骤的递归。
z[1] = in + z[0]*b
z[2] = in + z[1]*b = in + (in + z[0]*b)*b = in*(1 + b) + z[0]*b^2
z[3] = in + z[2]*b = in*(1 + b + b^2) + z[0]*b^3
z[4] = in + z[3]*b = in*(1 + b + b^2 + b^3) + z[0]*b^4
从最后一个方程:
z[1] = in*(1 + b + b^2 + b^3) + z[-3]*b^4
z[2] = in*(1 + b + b^2 + b^3) + z[-2]*b^4
z[3] = in*(1 + b + b^2 + b^3) + z[-1]*b^4
z[4] = in*(1 + b + b^2 + b^3) + z[0]*b^4
现在很容易以矢量化形式重写它。
in' = {in, in, in, in};
z' = in' * (1 + b + b^2 + b^3) + z'*b^4
其中“'”表示向量或单个 SIMD 寄存器。现在很容易将其翻译成 immintrin 指令。请注意,现在您不能更改任何样本的输入值,但有时可以更改四个样本的倍数。
此外,您可以将两个或多个 SIMD 寄存器表示为一个向量,并进一步扩展递归。由于更好的管道利用率,这将提高性能,但不要过度使用,否则您将没有足够的寄存器。
推荐阅读
- java - Java - 下拉组件显示
- tensorflow - Theano / Pytorch / Tensorflow 可以自动计算以下梯度吗?
- python - 稀疏张量上的行或元素选择
- git-merge - 我希望选定的文本文件在合并时充当二进制文件
- django - 带有 Django REST 框架的 RBAC
- python-3.x - “此 python 中不包含 SSL 支持”Anaconda-python3-smtplib
- kohana-3 - Kohana 3 - 将模型保存到数据库中,关系为 belongs_to
- asp.net-mvc - ASP MVC Identity 2 让用户成为“用户”角色
- ruby-on-rails - Ruby - LoadError:无法加载此类文件 - ../credentials_go_in_var_lib/credentials
- java - 如何在 Keystore 中找到证书