GreyGeek
GreyGeek

Reputation: 948

What are the condition for the compiler to reduce std::copy to memcpy (memmove)

According to some post here ( Efficiency of std::copy vs memcpy , ) std::copy is supposed to be reduce to memcpy/memmove on a pod type. i am trying to test that but i cant replicate the result.

I am using visual studio 2010 and I tried all optimization levels

struct pod_  
{ 
        unsigned int v1 ,v2 ,v3 ;
} ;

typedef pod_ T ;
static_assert(std::is_pod<pod_>::value, "Struct must be a POD type");


const unsigned int size = 20*1024*1024 / sizeof(T);
std::vector<T> buffer1(size) ;
std::vector<T> buffer2((size)) ;

And i tried this :

std::copy(buffer1.begin(),buffer1.end(),&buffer2[0]);
0030109C  mov         esi,dword ptr [esp+14h]  
003010A0  mov         ecx,dword ptr [esp+18h]  
003010A4  mov         edi,dword ptr [esp+24h]  
003010A8  mov         eax,esi  
003010AA  cmp         esi,ecx  
003010AC  je          main+8Eh (3010CEh)  
003010AE  mov         edx,edi  
003010B0  sub         edx,esi  
003010B2  mov         ebx,dword ptr [eax]  
003010B4  mov         dword ptr [edx+eax],ebx  
003010B7  mov         ebx,dword ptr [eax+4]  
003010BA  mov         dword ptr [edx+eax+4],ebx  
003010BE  mov         ebx,dword ptr [eax+8]  
003010C1  mov         dword ptr [edx+eax+8],ebx  
003010C5  add         eax,0Ch  
003010C8  cmp         eax,ecx  
003010CA  jne         main+72h (3010B2h)  
003010CC  xor         ebx,ebx  

casting to a primitive type seems to work.

    std::copy((char *)&buffer1[0],(char *)&buffer1[buffer1.size() - 1],(char *)&buffer2[0]);
003010CE  sub         ecx,esi  
003010D0  mov         eax,2AAAAAABh  
003010D5  imul        ecx  
003010D7  sar         edx,1  
003010D9  mov         eax,edx  
003010DB  shr         eax,1Fh  
003010DE  add         eax,edx  
003010E0  lea         eax,[eax+eax*2]  
003010E3  lea         ecx,[eax*4-0Ch]  
003010EA  push        ecx  
003010EB  push        esi  
003010EC  push        edi  
003010ED  call        dword ptr [__imp__memmove (3020B0h)]  
003010F3  add         esp,0Ch 

Upvotes: 2

Views: 508

Answers (1)

James Kanze
James Kanze

Reputation: 153957

The "answer" in the thread you post is wrong. Generally, I would expect std::copy to be more efficient than memcpy or memmove (because it is more specialized) for POD types. Whether this is the case when using iterators depends on the compiler, but any optimization does depend on the compiler being able to "see through" the iterators. Depending on the compiler and the implementation of the library, this may not be possible.

Note too that your test code has undefined behavior. One of the requirements for using std::copy (and memcpy) is that the destination is not in the range of the source ([first,last) for std::copy, [source,source+n) for memcpy). If the source and the destination overlap, the behavior is undefined.

Upvotes: 1

Related Questions