Не си го компилирал. Умножението в inner loop-а не е коректно и този код няма да се компилира. Опитваш се да навреш в double променлива резултата от умножението на double с два указателя. Преправих го на:
В отговор на:
a*=m[j]*m[j];
защото предполагам че нещо такова си искал да направиш.
Дизасемблираният код е:
0x0000000000400570 <+0>: movsd (%rdi),%xmm1
0x0000000000400574 <+4>: movsd 0x18(%rdi),%xmm0
0x0000000000400579 <+9>: mulsd %xmm1,%xmm1
0x000000000040057d <+13>: movsd 0x20(%rdi),%xmm2
0x0000000000400582 <+18>: mulsd %xmm0,%xmm1
0x0000000000400586 <+22>: mulsd %xmm0,%xmm1
0x000000000040058a <+26>: movsd 0x30(%rdi),%xmm0
0x000000000040058f <+31>: mulsd %xmm0,%xmm1
0x0000000000400593 <+35>: mulsd %xmm0,%xmm1
0x0000000000400597 <+39>: movsd 0x8(%rdi),%xmm0
0x000000000040059c <+44>: mulsd %xmm0,%xmm0
0x00000000004005a0 <+48>: addsd 0x140(%rip),%xmm1 # 0x4006e8
0x00000000004005a8 <+56>: mulsd %xmm2,%xmm0
0x00000000004005ac <+60>: mulsd %xmm2,%xmm0
0x00000000004005b0 <+64>: movsd 0x38(%rdi),%xmm2
0x00000000004005b5 <+69>: mulsd %xmm2,%xmm0
0x00000000004005b9 <+73>: mulsd %xmm2,%xmm0
0x00000000004005bd <+77>: movsd 0x28(%rdi),%xmm2
0x00000000004005c2 <+82>: addsd %xmm0,%xmm1
0x00000000004005c6 <+86>: movsd 0x10(%rdi),%xmm0
0x00000000004005cb <+91>: mulsd %xmm0,%xmm0
0x00000000004005cf <+95>: mulsd %xmm2,%xmm0
0x00000000004005d3 <+99>: mulsd %xmm2,%xmm0
0x00000000004005d7 <+103>: movsd 0x40(%rdi),%xmm2
0x00000000004005dc <+108>: mulsd %xmm2,%xmm0
0x00000000004005e0 <+112>: mulsd %xmm2,%xmm0
0x00000000004005e4 <+116>: addsd %xmm1,%xmm0
0x00000000004005e8 <+120>: retq
И двата цикъла са напълно unroll-нати, при това и векторизирани. Цялата ти матрица m[3][3] се събира точно в 2 cacheline-а, при това положение няма огромно значение как точно си правело адресните изчисления. За да ги заредиш в регистри и да си правиш сметките само с регистрите (цели 16 64-битови регистри или 8 xmm такива), няма да ти трябва по-малко време. Ако толкова държиш да ускориш нещата, сложи два __mm_prefetch()-а малко преди да викнеш f().
Накрая, единственото което може да подобри нещата според мен е да уредиш по някакъв начин alignment-а на 16 байта за m и да зареждаш стойностите с MOVAPD вместо с MOVSD. Това може и да включва shuffle операции с xmm регистрите и може и да не е добра идея - а може и да е много добра идея, не знам - не можах да излъжа gcc да го направи така или иначе.
И защо не пусна и асемблерния код, който си замислил да е "значително по-бърз"? Имам силни предположения че ще unroll-неш двата цикъла и ще ползваш FPU-то за да ти смята 2 пъти повече операции, отколкото ако ползваш SIMD разширенията, при това по-бавно. Трябваше да го направиш. Всъщност и да benchmark-неш двете нямаше да е зле.
П.П извинявам се, коректно е било, просто тъпия дир.бг поради някаква причина го отрязва :(
Ей ама доста противен тоя дир.бг !!!!Редактирано от gat3way на 11.12.11 14:43.
|