c++ - 有效地移动整个内存块

标签 c++ memory

在执行 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/

相关文章:

c++ - 对字符串数组进行排序会导致段错误

c++ - 如何阻止 `/Gm-` 从 CMake 传递给 clang_cl.exe

c++ - 还有几个 SWIG 警告

java - 当 JVM 在运行时内存不足时会发生什么?

使用位域比较 C 中的结构

php - 多次插入时出现内存不足错误

c++ - 使用 libgit2 执行 Git Pull

c++ - c++ 删除内存

linux - 以低延迟访问 PCI 内存条 (Linux)

javascript - 在 Eclipse 中结合 c++ 和 javascript 开发