Optimization 用AVX指令集优化自适应滤波器

Optimization 用AVX指令集优化自适应滤波器,optimization,filtering,intel,sse,avx,Optimization,Filtering,Intel,Sse,Avx,我正在尝试使用AVX优化自适应滤波代码,AVX的滤波内核可能对每个像素都是随机的(比如0到991) 其对应的C代码如下所示: /*过滤函数*/ 空过滤器() { int size=width*height;//图像大小 float w[992][11];//过滤器内核数组 浮点x[size+10],y[size],filterindex[size];//输入,输出,筛选索引 对于(i=0;i压缩为单值2。>使用零填充。压缩时使用什么填充?像素/系数或更高版本?在第一种情况下,如果过滤器系数ENT

我正在尝试使用AVX优化自适应滤波代码,AVX的滤波内核可能对每个像素都是随机的(比如0到991)

其对应的C代码如下所示:

/*过滤函数*/
空过滤器()
{
int size=width*height;//图像大小
float w[992][11];//过滤器内核数组
浮点x[size+10],y[size],filterindex[size];//输入,输出,筛选索引
对于(i=0;i对于(k=-5,a=0.;k由于每个像素的权重不同,由于必须对过滤器权重进行聚集负载,因此使用AVX一次过滤多个像素时可能不会获得很大的加速。另一种使用相干负载的方法是,使用内部循环,并在加载像素时并行进行8次乘法运算在内存中连续从x开始,并在内存中连续从w过滤权重。由于您有11个权重,这并不理想地映射到AVX寄存器宽度,但您仍会看到加速。然后您可以使用_mm_hadd_ps对结果进行汇总。您可能希望在多个像素上展开循环,以隐藏一些添加延迟。或者,您可以尝试使用_mm_dp_ps dot product指令一起执行乘法和加法,这可能会更快,但延迟更高,因此您需要更多地展开循环


该循环也非常可并行化,因此可能值得考虑在多个线程之间拆分工作。

对于每个输入像素,您可以在两个AVX寄存器中加载11个滤波器系数(第二个寄存器中填充5个零),并以类似方式加载像素:_mm256_load_ps

将这些值成对相乘并相加,得到两个乘积的8和:_mm256_mul_ps,_mm256_fmadd_ps

接下来,您需要使用一系列水平加法将其压缩为单个值,生成4、8和16乘积的总和:_mm_hadd_ps


总计:每个输出像素9条指令。

只有AVX,还是AVX2可用?我认为在这种情况下,使用SIMD将很难获得3倍的改进。只是没有太多的并行性;滤波器内核本身太短,无法通过并行计算卷积的片段获得太多好处,事实上内核在每像素的基础上不同,使得并行计算多个像素变得复杂。您可能能够弥补一些轻微的改进,我认为在这种情况下,向上移动一个级别并搜索算法更改以提高速度将是您的最佳选择。第二个for循环可能不会像您预期的那样工作,因为行
y[i] =(浮动)a、 
不在loop@Learner:只有OP可以决定这一点。当您的实现优化无法使您达到需要提高性能的程度时,您需要查看您的算法,以查看不同的方法是否能在满足您的目标的同时表现得更好。您现在的代码实际上不适合SIMD。Howev呃,它可以很容易地从MIMD中获益(例如使用OpenMP)。您对此感兴趣吗?添加
#pragma omp parallel for private(k,a)
在您循环之前
i
@mathnewport:我确实考虑过使用_-mm\u-hadd\u-ps和_-mm\u-dp\u-ps,但获得的收益微乎其微。即使展开也没有帮助我们。考虑到所有的方法,我们观察到的收益仅为1.7倍左右。而且目前我们也没有寻找使用多线程方法的解决方案。这是非常简单的在这种情况下,你的内存带宽是有限的。你做过分析吗?我用rdtsc()做过分析Vtune也是如此。这种方法没有提供更好的增益,因为下面有两个操作1。>压缩为单值2。>使用零填充。压缩时使用什么填充?像素/系数或更高版本?在第一种情况下,如果过滤器系数ENT存储在[911][16]数组中,数组中填充有零(这将使无关像素消失)。