私はついにこれの底にたどり着きました(そして、Die in Senteの答えは正しい行にありました、ありがとう)
以下では、dst と src は 512 MByte の std::vector です。Intel 10.1.029 コンパイラと CRT を使用しています。
どちらも64ビット
memcpy(&dst[0],&src[0],dst.size())
と
memcpy(&dst[0],&src[0],N)
ここで、N は以前に宣言されたconst size_t N=512*(1<<20);
call
__intel_fast_memcpy
その大部分は次のもので構成されています。
000000014004ED80 lea rcx,[rcx+40h]
000000014004ED84 lea rdx,[rdx+40h]
000000014004ED88 lea r8,[r8-40h]
000000014004ED8C prefetchnta [rdx+180h]
000000014004ED93 movdqu xmm0,xmmword ptr [rdx-40h]
000000014004ED98 movdqu xmm1,xmmword ptr [rdx-30h]
000000014004ED9D cmp r8,40h
000000014004EDA1 movntdq xmmword ptr [rcx-40h],xmm0
000000014004EDA6 movntdq xmmword ptr [rcx-30h],xmm1
000000014004EDAB movdqu xmm2,xmmword ptr [rdx-20h]
000000014004EDB0 movdqu xmm3,xmmword ptr [rdx-10h]
000000014004EDB5 movntdq xmmword ptr [rcx-20h],xmm2
000000014004EDBA movntdq xmmword ptr [rcx-10h],xmm3
000000014004EDBF jge 000000014004ED80
~2200 MByte/s で実行されます。
しかし、32ビットでは
memcpy(&dst[0],&src[0],dst.size())
通話
__intel_fast_memcpy
その大部分は
004447A0 sub ecx,80h
004447A6 movdqa xmm0,xmmword ptr [esi]
004447AA movdqa xmm1,xmmword ptr [esi+10h]
004447AF movdqa xmmword ptr [edx],xmm0
004447B3 movdqa xmmword ptr [edx+10h],xmm1
004447B8 movdqa xmm2,xmmword ptr [esi+20h]
004447BD movdqa xmm3,xmmword ptr [esi+30h]
004447C2 movdqa xmmword ptr [edx+20h],xmm2
004447C7 movdqa xmmword ptr [edx+30h],xmm3
004447CC movdqa xmm4,xmmword ptr [esi+40h]
004447D1 movdqa xmm5,xmmword ptr [esi+50h]
004447D6 movdqa xmmword ptr [edx+40h],xmm4
004447DB movdqa xmmword ptr [edx+50h],xmm5
004447E0 movdqa xmm6,xmmword ptr [esi+60h]
004447E5 movdqa xmm7,xmmword ptr [esi+70h]
004447EA add esi,80h
004447F0 movdqa xmmword ptr [edx+60h],xmm6
004447F5 movdqa xmmword ptr [edx+70h],xmm7
004447FA add edx,80h
00444800 cmp ecx,80h
00444806 jge 004447A0
~1350 MByte/s のみで動作します。
でも
memcpy(&dst[0],&src[0],N)
ここで、N は事前に宣言さconst size_t N=512*(1<<20);
れており、(32 ビットで) への直接呼び出しにコンパイルされます。
__intel_VEC_memcpy
その大部分は
0043FF40 movdqa xmm0,xmmword ptr [esi]
0043FF44 movdqa xmm1,xmmword ptr [esi+10h]
0043FF49 movdqa xmm2,xmmword ptr [esi+20h]
0043FF4E movdqa xmm3,xmmword ptr [esi+30h]
0043FF53 movntdq xmmword ptr [edi],xmm0
0043FF57 movntdq xmmword ptr [edi+10h],xmm1
0043FF5C movntdq xmmword ptr [edi+20h],xmm2
0043FF61 movntdq xmmword ptr [edi+30h],xmm3
0043FF66 movdqa xmm4,xmmword ptr [esi+40h]
0043FF6B movdqa xmm5,xmmword ptr [esi+50h]
0043FF70 movdqa xmm6,xmmword ptr [esi+60h]
0043FF75 movdqa xmm7,xmmword ptr [esi+70h]
0043FF7A movntdq xmmword ptr [edi+40h],xmm4
0043FF7F movntdq xmmword ptr [edi+50h],xmm5
0043FF84 movntdq xmmword ptr [edi+60h],xmm6
0043FF89 movntdq xmmword ptr [edi+70h],xmm7
0043FF8E lea esi,[esi+80h]
0043FF94 lea edi,[edi+80h]
0043FF9A dec ecx
0043FF9B jne ___intel_VEC_memcpy+244h (43FF40h)
〜2100MByte / sで実行されます(32ビットが何らかの理由で帯域幅に制限されていないことを証明しています).
私自身の memcpy に似た SSE コードが 32 ビット ビルドで同様の ~1300 MB/制限に苦しんでいるという私の主張を撤回します。現在、32 ビットまたは 64 ビットで 2GByte/s を超える問題はありません。(上記の結果のヒントとして)秘訣は、非一時的(「ストリーミング」)ストア(_mm_stream_ps
組み込みなど)を使用することです。
32 ビットのmemcpydst.size()
が最終的により高速なmovnt
バージョンを呼び出さないのは少し奇妙に思われます " "CPUID
実際のデータに近づく前に)しかし、少なくとも私は今観察された動作を理解しています(SysWow64またはH / Wに関連していません)。