
대강 생각을 해보니 정말 mmx 를 이용해서 빠르게 연산을 하려면 위와 같이 하는게 가장 빠르겠군요. 다만 레지스터를 많이 쓰고 완전히 asm 코딩을 해야한다는 게 조금 귀찮겠군요. ;)
위의 다이아그램에 있는 과정을 통해 4x4 matrix * 4x4 matrix 의 한 row 씩을 계산해낼 수 있습니다. 대강 계산했을 때 3배 이상의 속도 향상이 있을거라고 예상되던데 과연~
C:
-
#include <stdio .h>
-
-
// A matrix
-
short s1[16] = {
-
1, 2, 3, 4,
-
5, 6, 7, 8,
-
9, 10, 11, 12,
-
13, 14, 15, 16,
-
};
-
-
// Transpose(B matrix)
-
short s2[16] = {
-
17, 21, 25, 29,
-
18, 22, 26, 30,
-
19, 23, 27, 31,
-
20, 24, 28, 32
-
};
-
-
-
// Destination matrix
-
short d[16];
-
-
int j, i;
-
int main( int argc, char** argv ){
-
-
__asm__("movq (s1), %mm0" );
-
__asm__("movq %mm0, %mm1" );
-
__asm__("movq %mm0, %mm2" );
-
__asm__("punpckhdq %mm2, %mm0" );
-
__asm__("punpckldq %mm2, %mm1" );
-
-
__asm__("movq %mm0, %mm6");
-
__asm__("movq %mm1, %mm7");
-
-
__asm__("movq (s2), %mm2" );
-
__asm__("mov $1, %eax" );
-
__asm__("movq s2(,%eax,8), %mm4");
-
-
__asm__("movq %mm2, %mm3" );
-
__asm__("punpckhdq %mm4, %mm2");
-
__asm__("punpckldq %mm4, %mm3");
-
-
__asm__("pmaddwd %mm2, %mm0");
-
__asm__("pmaddwd %mm3, %mm1");
-
-
__asm__("paddw %mm1, %mm0");
-
-
__asm__("movq %mm6, %mm1");
-
__asm__("movq %mm7, %mm2");
-
-
__asm__("mov $2, %eax" );
-
__asm__("movq s2(,%eax,8), %mm3" );
-
__asm__("mov $3, %eax" );
-
__asm__("movq s2(,%eax,8), %mm5");
-
__asm__("movq %mm3, %mm4" );
-
__asm__("punpckhdq %mm5, %mm3");
-
__asm__("punpckldq %mm5, %mm4");
-
-
__asm__("pmaddwd %mm3, %mm1");
-
__asm__("pmaddwd %mm4, %mm2");
-
__asm__("paddw %mm2, %mm1");
-
-
__asm__("packssdw %mm1, %mm0");
-
__asm__("movq %mm0, (d)");
-
-
for( j = 0 ; j <4 ; j++ ){
-
for( i = 0 ; i <4 ; i++ ){
-
fprintf( stderr, "\t%3d", d[j*4+i] );
-
}
-
fprintf( stderr, "\n" );
-
}
-
-
return 0;
-
-
}
코드로 옮기니 위와 같군요. 중간에 실수로 바이트오더를 헷갈려서 연산 결과가 뒤집혔었습니다. 정상적인 결과는 250 260 270 280 이 나와야 하는데 280 270 260 250 이 나와버리더군요. 아아 이거 다시 하고 싶은 작업이 아니네요;
흐흣 그래도 오랫만에 어셈블리 관련된 것들을 생각하고 있는데, 이것도 가끔 하니까 재밌네요. 근데 길어지면 할만하지 않다는거 -_-!
p.s) 전체 연산 코드를 보고 싶으시면 http://mytears.org/resources/mysrc/c/mmx.c 를 보시길 ;)
Tags: asm, matrix, mmx, multiply, optimization, simd
January 14th, 2007 at 1:01 am
아우~ 머리야~~ @_@
January 15th, 2007 at 3:34 pm
헉 -ㅇ- 저거 옴니 그래플로 그린게 더 대단해보이는 =_=;;
January 15th, 2007 at 3:41 pm
jenix// 흐흐 먼저 연습장에 그려놓고 옮긴거라;; 흐흐 하지만 노가다 ㅠ_ㅠ
막상 좀 더 생각해보니 pmaddsw 후에 paddw 를 두 번 해주고 packssdw 는 것도 가능하고, packssdw 를 두 번 해주고 pmaddsw 를 해주는 것도 가능한데 과연 어떤게 더 빠를까 고민이…
아무래도 pack 은 거의 register 내에서의 값 이동 정도밖에는 안되고 add 는 그래도 산술연산이니까 pack 을 두 번 하고 add 를 한 번하는게 더 빠를거 같은데…