优化SIMD直方图计算

时间:2015-06-21 22:45:27

标签: opencv assembly optimization histogram simd

我研究了一个实现直方图计算的代码,给出了一个opencv结构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快速填充直方图矢量? 提前致谢

1 个答案:

答案 0 :(得分:3)

像杰斯特一样,我很惊讶你的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