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



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

对应的C代码如下:

/* filter function */
    void filter()
{
  int size = width *height;  // image size
  float w[992][11];          // filter kernel array 
  float x[size + 10], y[size], filterindex[size]; // input , output , filter index 
  for (i = 0; i < size; i++) 
  {
    int l;
    /* pick filter: */
    l = filterindex[i];
    /* apply filter */
    for (k = -5, a = 0.; k <= 5; k++)
        a += x[i+k] * w[l][5+k];
        y[i] = (float)a;
  }
}

,

  1. filterindex是一个输入缓冲区,它保存每个像素的过滤器索引(0到991)[周围像素之间没有这些索引的模式]
  2. x为输入,y为输出
  3. w是大小为w[992][2*N_filt + 1]的过滤器内核,其中每个索引初始化为992 set

谁能帮助我如何使用AVX优化以上代码?如果AVX是不可能的,那么请建议任何其他方法来优化3x的目标。

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

将值两两相乘并相加,得到2个乘积的8和:_mm256_mul_ps, _mm256_fmadd_ps。

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

由于每个像素的权重不同,您可能无法获得巨大的加速,因为使用AVX尝试一次过滤多个像素,因为您必须在过滤器权重上做收集负载。另一种使用相干加载的方法是让你的内部循环并行地做8次乘法,因为你在内存中连续地从x加载像素,并在内存中连续地从w过滤权重。因为你有11个权重,这并不理想地映射到AVX寄存器宽度,但你仍然应该看到一个加速。然后可以使用_mm_hadd_ps对结果进行汇总。您可能希望在多个像素上展开循环,以隐藏添加的一些延迟。或者,您可以尝试使用_mm_dp_ps点积指令来同时执行乘法和加法,它可能更快,但延迟更高,因此您需要更多地展开循环。

这个循环也是非常可并行的,所以可能值得考虑将工作拆分到多个线程。

最新更新