通过添加指针进行复制时可能出现缓存未命中



我想知道是否有人能说明这里发生了什么,以及可能的解决方案建议。

使用VS2010 ulimate c++win7 x64。英特尔i5-3570@3.4ghz,8GB内存。

我有一段代码运行缓慢,这让我很惊讶,因为它实际上并没有做太多。至少我是这么想的。因此,使用一些老派的计时技术,我将问题缩小到简单的内存添加和复制。使用混合源代码和程序集的选项来调试输出,我得到了。。。

byte* pback = (byte*)m_pBackbuffer;
000007FEF5661A5E  mov         rdx,qword ptr [rbx+0CA800h]  
000007FEF5661A65  mov         ebp,eax  
byte* pout = (byte*)pSamplebuffer;
while(i--){
000007FEF5661A67  test        esi,esi  
000007FEF5661A69  je          AVNOnScreenRenderer::MergeBackbufferToOutputSample+70h (7FEF5661A80h)  
000007FEF5661A6B  nop         dword ptr [rax+rax]  
    *pout++ = (*pback++ + *pout);
000007FEF5661A70  movzx       ecx,byte ptr [rdx]  
000007FEF5661A73  inc         rdi  
000007FEF5661A76  inc         rdx  
000007FEF5661A79  add         byte ptr [rdi-1],cl  
000007FEF5661A7C  dec         esi  
000007FEF5661A7E  jne         AVNOnScreenRenderer::MergeBackbufferToOutputSample+60h (7FEF5661A70h) 

这一小段代码大约需要100毫秒才能完成。

其中,删除+指针运算将代码速度降低到0毫秒-使用此代码:

byte* pback = (byte*)m_pBackbuffer;
000007FEF5661A5E  mov         r8,qword ptr [rbx+0CA800h]  
000007FEF5661A65  mov         ebp,eax  
byte* pout = (byte*)pSamplebuffer;
while(i--){
000007FEF5661A67  test        edi,edi  
000007FEF5661A69  je          AVNOnScreenRenderer::MergeBackbufferToOutputSample+71h (7FEF5661A81h)  
000007FEF5661A6B  nop         dword ptr [rax+rax]  
    *pout++ = (*pback++);// + *pout);
000007FEF5661A70  movzx       ecx,byte ptr [r8]  
000007FEF5661A74  inc         rsi  
000007FEF5661A77  inc         r8  
000007FEF5661A7A  dec         edi  
000007FEF5661A7C  mov         byte ptr [rsi-1],cl  
000007FEF5661A7F  jne         AVNOnScreenRenderer::MergeBackbufferToOutputSample+60h (7FEF5661A70h) 

起初我预计会有很小的时间消耗,但随着时间的增加。起初我以为这是因为我读写到了同一个内存地址,即循环中的*pout变量,但后来我创建了另一个缓冲区来写,并重新排列了一些部分以使用其他变量,但问题仍然存在。当我删除+时,问题就消失了。

请一些聪明的人帮我解决这个问题好吗。

ps这里有一个用另一个缓冲区重新排列代码的例子。。。

byte* pback = (byte*)m_pBackbuffer;
byte* pout = (byte*)m_pOutbuffer;
while(i--){
    int b = *pback;
    int s = *pSamplebuffer;
    int o = b;//b + s;
    *pout = o;
}

您确定上面打印的程序集等于您在最后执行的代码吗?智能编译器应该用简单的memcpy替换第二个版本,从而从本质上加快代码的速度。这种优化对于第一个代码片段是不可能的。

根据缓冲区的大小,遍历每个元素并应用add操作确实会消耗一些时间。

最新更新