Dzięki wskazówkom @Wibowita powstała nowa wersja:
unsigned int sum(int* numbers, int count)
{
__asm
{
mov esi, numbers
mov ecx, count
shr ecx, 4
mov eax, 0
adding:
prefetchnta [esi + 640]
paddd mm0, [esi ]
paddd mm1, [esi + 8 ]
paddd mm2, [esi + 16]
paddd mm3, [esi + 24]
paddd mm4, [esi + 32]
paddd mm5, [esi + 40]
paddd mm6, [esi + 48]
paddd mm7, [esi + 56]
add esi, 64
loop adding
movd ebx, mm0
add eax, ebx
punpckhdq mm0, mm0
movd ebx, mm0
add eax, ebx
movd ebx, mm1
add eax, ebx
punpckhdq mm1, mm1
movd ebx, mm1
add eax, ebx
movd ebx, mm2
add eax, ebx
punpckhdq mm2, mm2
movd ebx, mm2
add eax, ebx
movd ebx, mm3
add eax, ebx
punpckhdq mm3, mm3
movd ebx, mm3
add eax, ebx
movd ebx, mm4
add eax, ebx
punpckhdq mm4, mm4
movd ebx, mm4
add eax, ebx
movd ebx, mm5
add eax, ebx
punpckhdq mm5, mm5
movd ebx, mm5
add eax, ebx
movd ebx, mm6
add eax, ebx
punpckhdq mm6, mm6
movd ebx, mm6
add eax, ebx
movd ebx, mm7
add eax, ebx
punpckhdq mm7, mm7
movd ebx, mm7
add eax, ebx
emms
}
}
Działa tylko dla ilości elementów podzielnej przez 16.
Dla 102400000 liczb (tak, 390 megabajtów liczb) moja wersja wykonuje się w 28 milisekund, wersja z biblioteki standardowej C++ w 48, a pętla z sumowaniem w 32.
Uroczyście ogłaszam, że nie ma sensu się w to bawić i wystarczyło napisać: cout << accumulate(numbers, numbers + count, 0);
.
edit: dodając prefetch udało się zejść do 26.