是否可以用 SSE 将这个嵌套的 for 向量化?
Is it possible to vectorize this nested for with SSE?
我从来没有写过 SSE 优化的汇编代码,如果这是一个菜鸟问题,我很抱歉。在 this aritcle is explained how to vectorize a for
with a conditional statement. However, my code (taken from 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
:我一直在矢量化中看到一级for
,从未见过嵌套循环
- if 条件基于标量值(x 和 y)而不是数组:我如何使链接示例适应这种情况?
out
索引不是基于 i
或 j
(因此它不是 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"
双线性插值是一个相当棘手的矢量化操作,我不会在您的第一个 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
您所要做的就是将输入变量映射到矩阵形式并调用仿射变换。
我从来没有写过 SSE 优化的汇编代码,如果这是一个菜鸟问题,我很抱歉。在 this aritcle is explained how to vectorize a for
with a conditional statement. However, my code (taken from 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
:我一直在矢量化中看到一级for
,从未见过嵌套循环 - if 条件基于标量值(x 和 y)而不是数组:我如何使链接示例适应这种情况?
out
索引不是基于i
或j
(因此它不是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"
双线性插值是一个相当棘手的矢量化操作,我不会在您的第一个 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
您所要做的就是将输入变量映射到矩阵形式并调用仿射变换。