【问题标题】:Optimizing SIMD histogram calculation优化 SIMD 直方图计算
【发布时间】:2015-09-07 07:41:54
【问题描述】:

我编写了一个代码,该代码在给定直方图的 opencv struct IplImage * 和缓冲区 unsigned int * 的情况下实现直方图计算。我还是 SIMD 的新手,所以我可能没有充分利用指令集提供的全部潜力。

histogramASM:
xor rdx, rdx
xor rax, rax
mov eax, dword [imgPtr + imgWidthOffset]
mov edx, dword [imgPtr + imgHeightOffset]
mul rdx                                     
mov rdx, rax                                ; rdx = Image Size
mov r10, qword [imgPtr + imgDataOffset]     ; r10 = ImgData

NextPacket: 
mov rax, rdx
movdqu  xmm0, [r10 + rax - 16]
mov rcx,16                               ; 16 pixels/paq

PacketLoop:
pextrb  rbx, xmm0, 0                ; saving the pixel value on rbx
shl rbx,2
inc dword [rbx + Hist]
psrldq  xmm0,1
loop    PacketLoop

sub rdx,16
cmp rdx,0
jnz NextPacket
ret

在 C 上,我会运行这些代码以获得相同的结果。

imgSize = (img->width)*(img->height);
pixelData = (unsigned char *) img->imageData;

for(i = 0; i < imgSize; i++)
{
    pixel = *pixelData; 
    hist[pixel]++;
    pixelData++;
}

但两者所花费的时间(在我的计算机中使用 rdtsc() 测量)仅比 SIMD 的汇编程序好 1.5 倍。有没有办法优化上面的代码,用SIMD快速填充直方图向量? 提前致谢

【问题讨论】:

  • 这看起来不太好使用 simd,我很惊讶你竟然得到了这么多的改进。至于优化,至少可以将shl rbx, 2 合并到inc dword [rbx*4 + Hist] 中,也不需要cmp rdx, 0loop 指令也应该避免。
  • 谢谢。刚刚修改了那个。我也很难过,因为我对汇编方式没有那么有经验。但它必须在 asm 上。
  • 相关:微小的直方图(如 4 个桶)可以使用 count[0] += (arr[i] == 0),您可以使用 SIMD 打包比较对其进行矢量化 - Micro Optimization of a 4-bucket histogram of a large array or list

标签: opencv assembly optimization histogram simd


【解决方案1】:

像 Jester 一样,我很惊讶您的 SIMD 代码有任何显着改进。你编译的 C 代码是不是开启了优化?

我可以提出的另一个建议是展开您的 Packetloop 循环。这是一个相当简单的优化,将每次“迭代”的指令数量减少到只有两条:

pextrb  ebx, xmm0, 0
inc dword [ebx * 4 + Hist]
pextrb  ebx, xmm0, 1
inc dword [ebx * 4 + Hist]
pextrb  ebx, xmm0, 2
inc dword [ebx * 4 + Hist]
...
pextrb  ebx, xmm0, 15
inc dword [ebx * 4 + Hist]

如果你使用的是 NASM,你可以使用 %rep 指令来节省一些输入:

%assign pixel 0
%rep 16
    pextrb  rbx, xmm0, pixel
    inc dword [rbx * 4 + Hist]
%assign pixel pixel + 1
%endrep

【讨论】:

  • 哇,非常感谢。这实际上将其提高了近 5 倍。必须清楚地避免循环指令。编辑:移除 mov rcx, 16 的效果提高了 5 倍以上。
猜你喜欢
  • 2019-09-27
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 2012-11-08
  • 2022-01-11
  • 1970-01-01
相关资源
最近更新 更多