在执行 sobel 操作后,我有以下代码:
short* tempBufferVert = new short[width * height];
ippiFilterSobelVertBorder_8u16s_C1R(pImg, width, tempBufferVert, width * 2, dstSize, IppiMaskSize::ippMskSize3x3, IppiBorderType::ippBorderConst, 0, pBufferVert);
for (int i = 0; i < width * height; i++)
tempBufferVert[i] >>= 2;
令人沮丧的是,位移位是所有操作中耗时最长的,IPP sobel 经过优化,运行速度比我愚蠢的位移位更快。我如何优化位移位,或者是否有 IPP 或其他选项(AVX?)在整个内存上执行位移位(但属于短符号, >>= 在 Visual Studio 实现中执行)
最佳答案
C++ 优化器在基于迭代器的循环中比在索引循环中执行得更好。
这是因为编译器可以假设地址算法在索引溢出时是如何工作的。为了在数组中使用索引时做出相同的假设,您必须碰巧为索引选择正确的数据类型。
类次代码可以表示为:
void shift(short* first, short* last, int bits)
{
while (first != last) {
*first++ >>= bits;
}
}
int test(int width, int height)
{
short* tempBufferVert = new short[width * height];
shift(tempBufferVert, tempBufferVert + (width * height), 2);
}
将(启用正确的优化)矢量化:https://godbolt.org/g/oJ8Boj
注意循环的中间是如何变成的:
.L76:
vmovdqa ymm0, YMMWORD PTR [r9+rdx]
add r8, 1
vpsraw ymm0, ymm0, 2
vmovdqa YMMWORD PTR [r9+rdx], ymm0
add rdx, 32
cmp rsi, r8
ja .L76
lea rax, [rax+rdi*2]
cmp rcx, rdi
je .L127
vzeroupper
关于c++ - 有效地移动整个内存块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41715961/