是否可以使用 SSE 对这个嵌套进行矢量化?

Posted

技术标签:

【中文标题】是否可以使用 SSE 对这个嵌套进行矢量化?【英文标题】:Is it possible to vectorize this nested for with SSE? 【发布时间】:2017-03-31 12:49:35 【问题描述】:

我从未为 SSE 优化编写过汇编代码,如果这是一个菜鸟问题,请见谅。在this aritcle 中解释了如何使用条件语句向量化for。但是,我的代码(取自 here)的形式是:

   for (int j=-halfHeight; j<=halfHeight; ++j)
   
      for(int i=-halfWidth; i<=halfWidth; ++i)
      
         const float rx = ofsx + j * a12;
         const float ry = ofsy + j * a22;
         float wx = rx + i * a11;
         float wy = ry + i * a21;
         const int x = (int) floor(wx);
         const int y = (int) floor(wy);
         if (x >= 0 && y >= 0 && x < width && y < height)
         
            // compute weights
            wx -= x; wy -= y;
            // bilinear interpolation
            *out++ =
               (1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x)   + wx * im.at<float>(y,x+1)) +
               (       wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1));
          else 
            *out++ = 0;
         
      
   

因此,据我了解,与链接的文章有几个不同之处:

    这里我们有一个嵌套的 for:我一直在 vectroization 中看到一层 for,从未见过嵌套循环 if 条件基于标量值(x 和 y)而不是数组:如何使链接的示例适应这种情况? out 索引不是基于ij(所以它不是out[i]out[j]):如何以这种方式填充out

特别是我很困惑,因为for 索引总是用作数组索引,而这里用于计算变量,而向量是循环递增的

我正在使用 icpc-O3 -xCORE-AVX2 -qopt-report=5 以及一堆其他优化标志。根据 Intel Advisor 的说法,这不是矢量化的,使用 #pragma omp simd 会生成 warning #15552: loop was not vectorized with "simd"

【问题讨论】:

您使用哪个编译器?您是否确认您的编译器尚未为您自动矢量化? @Jonas 感谢您的评论。请看我更新的问题 很像你之前的问题***.com/questions/43136182/…有什么变化? @RichardCritten 哦,天哪,我完全忘记了那个(你应该明白这让我发疯了),我刚刚删除了它 @RichardCritten 我试着写更多关于它让我更困惑的东西 【参考方案1】:

双线性插值是一个相当棘手的矢量化操作,我不会在您的第一个 SSE 技巧中尝试它。问题是您需要获取的值没有很好地排序。它们有时会重复,有时会被跳过。好消息是,插值图像是一种常见操作,您可能会找到一个预先编写的库来执行此操作,例如 OpenCV

remap() 总是一个不错的选择。只需构建两个数组 wx 和 wy 代表每个像素的分数源位置,然后让remap() 进行插值。

但是,在这种情况下,它看起来像仿射变换。也就是说,分数源像素通过 2x3 矩阵乘法与源像素相关。那是偏移量和 a11/a12/a21/a22 变量。 OpenCV 有这样的变换。在这里阅读:http://docs.opencv.org/3.1.0/d4/d61/tutorial_warp_affine.html

您所要做的就是将输入变量映射为矩阵形式并调用仿射变换。

【讨论】:

非常感谢您的回答。我想我有点理解你解释的过程,但我对如何调用这些函数感到很困惑。我知道这有点不正确,但您能否详细写出解决方案? 你能帮我解决这个问题吗? 我提供的教程非常详细地介绍了这一点。我建议通过教程。如果在那之后您仍有问题,请使用您的新词汇和技能发布一个新问题。 感谢您的评论。说真的,我明白什么是扭曲仿射变换(感谢你的教程),但我仍然对在cv::warpAffine 中翻译上面的代码有疑问。为此,我打开了this 问题。你能不能给个战利品?

以上是关于是否可以使用 SSE 对这个嵌套进行矢量化?的主要内容,如果未能解决你的问题,请参考以下文章

自动矢量化的实际使用?

使用 GCC 强制自动矢量化

是否可以在 numpy 中对这个计算进行矢量化?

使用 SSE 向量化的错误结果

使用 SSE 矢量化在 OpenMP 中将内部循环与残差计算并行化

向量化嵌套循环,其中一个循环变量依赖于另一个