memcpy是不是最快的?
一般什么样的拷贝方式最快?

解决方案 »

  1.   

    memcpy最后还是调用API吧,CopyMemory?
    可以写个测试代码看一下啊
      

  2.   

    应该是memcpy,因为这个函数,是编译器根据参数动态生成的
      

  3.   

    在很多编译器中,memcpy 是一个 intrinsic 函数,也就是说,这个函数是由编译器实现的。它比 inline 函数更容易被编译时优化。编译器可以根据 memcpy 的参数是常量还是变量做出多种版本,达到最佳的性能。这一点,用 inline 或者 template 的技巧都无法办到。
      

  4.   

    汇编最快咯。不过有什么意义吗?现在主要bottleneck是IO,network。
      

  5.   

    那影响内存拷贝的速度最主要的是机器的什么呢?
    是内存的速度?CPU的速度?总线带宽?I/O?有没有人能系统地介绍一下?
      

  6.   

    应该是内存跟CPU吧,带宽是根本没问题的.你的流量再大都行.
      

  7.   

    不能说什么汇编最快,这是人家编译器优化的技巧,你自己写几行简单指令时回这样写吗:我们看看 VC 对 memcpy 的优化。(所用版本 VC6)void foo(void *d,const void *s)
    {
    memcpy(d,s,1);
    }选性能最优化,生成汇编代码可以看到。代码被优化成:mov eax, DWORD PTR _s$[esp-4]
    mov edx, DWORD PTR _d$[esp-4]
    mov cl, BYTE PTR [eax]
    mov BYTE PTR [edx], cl只是一个字节拷贝,用 cl 寄存器 mov 完成的。把 1 改成 4 后:mov eax, DWORD PTR _s$[esp-4]
    mov edx, DWORD PTR _d$[esp-4]
    mov ecx, DWORD PTR [eax]
    mov DWORD PTR [edx], ecx就变成了一条最普通的 mov 指令。如果是 8 个字节:mov eax, DWORD PTR _s$[esp-4]
    mov ecx, DWORD PTR _d$[esp-4]
    mov edx, DWORD PTR [eax]
    mov DWORD PTR [ecx], edx
    mov eax, DWORD PTR [eax+4]
    mov DWORD PTR [ecx+4], eax就是两条 mov 指令。直到长度是常量 19 还是用 mov 完成的:mov eax, DWORD PTR _s$[esp-4]
    mov ecx, DWORD PTR _d$[esp-4]
    mov edx, DWORD PTR [eax]
    mov DWORD PTR [ecx], edx
    mov edx, DWORD PTR [eax+4]
    mov DWORD PTR [ecx+4], edx
    mov edx, DWORD PTR [eax+8]
    mov DWORD PTR [ecx+8], edx
    mov edx, DWORD PTR [eax+12]
    mov DWORD PTR [ecx+12], edx
    mov dx, WORD PTR [eax+16]
    mov WORD PTR [ecx+16], dx
    mov al, BYTE PTR [eax+18]
    mov BYTE PTR [ecx+18], al长度达到 20 后,就转变成了使用 rep movsdpush esi
    mov esi, DWORD PTR _s$[esp]
    push edi
    mov edi, DWORD PTR _d$[esp+4]
    mov ecx, 5
    rep movsd
    pop edi
    pop esi如果长度并非 4 的整数倍的话,比如复制 23 个字节:push esi
    mov esi, DWORD PTR _s$[esp]
    push edi
    mov edi, DWORD PTR _d$[esp+4]
    mov ecx, 5
    rep movsd
    movsw
    movsb
    pop edi
    pop esi编译器会在后面插入 movsw 和 movsb 。现在我们来看看,memcpy 的长度是变量的情况:void foo(void *d,const void *s,size_t size)
    {
    memcpy(d,s,size);
    } 这次编译器直接调用了 rep movsdmov ecx, DWORD PTR _size$[esp-4]
    push esi
    mov esi, DWORD PTR _s$[esp]
    mov eax, ecx
    push edi
    mov edi, DWORD PTR _d$[esp+4]
    shr ecx, 2
    rep movsd
    mov ecx, eax
    and ecx, 3
    rep movsb
    pop edi
    pop esi因为我们并不知道 size 是否是 4 的整数倍,所以尾巴上用 and ecx,3 / repmovsb 来处理了一下。那么我们能否通知编译器,需要 memcpy 的数据块长度是 4 的倍数呢?答案是可以的。看看编译器怎么编译 memcpy(d,s,size*4);mov ecx, DWORD PTR _size$[esp-4]
    push esi
    mov esi, DWORD PTR _s$[esp]
    push edi
    mov edi, DWORD PTR _d$[esp+4]
    rep movsd
    pop edi
    pop esi非常简洁,不是吗?