Я наконец дошел до сути (ответ Die в Sente был на правильных строчках, спасибо)
Ниже dst и src - это 512 МБайт 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);
Звоните
__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 МБайт / с.
Но на 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 МБайт / с.
ОДНАКО
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)
и работает со скоростью ~ 2100 МБайт / с (и доказательство того, что 32-битная скорость не ограничена).
Я отозвал свое заявление о том, что мой собственный SSE-код, похожий на memcpy, страдает от
аналогично ~ 1300 МБайт / лимит в 32-битных сборках; У меня сейчас нет проблем
получение> 2 ГБ / с на 32 или 64 бита; хитрость (как подсказка вышеупомянутых результатов)
использовать не временные («потоковые») хранилища (например, _mm_stream_ps
встроенные).
Кажется немного странным, что 32-битная "dst.size()
" memcpy в конце концов не работает
вызовите более быструю версию "movnt
" (если вы заходите в memcpy,
невероятное количество CPUID
проверок и эвристической логики, например, сравнение числа
байтов, которые будут скопированы с размером кеша и т. д.
фактические данные) но по крайней мере я понимаю наблюдаемое поведение сейчас (и это
не относится к SysWow64 или H / W).