intel 제공 api를 쓸 것인가, gcc 기능을 쓸 것인가 테스트를 해보고 있었지만..
gcc -o t3 -O2 -ftree-vectorize -fopt-info-vec t3.c -march=haswell
이렇게 하면 지가 최적화 한 부분을 보여주고 그냥 최적화 해준다. 벡터화 한 부분은 note로 콘솔에 보여준다. 이것으로 확인하면 된다.
vmovdqu 0(%r13,%rax), %ymm0
addq $32, %rax
vmovdqu %ymm0, -32(%rax)
cmpq $100000000, %rax
jne .L3
원래 c코드는 int *의 루프였다. 그런데 4바이트 단위의 루프를 컴파일러가 깨버리고 32바이트 단위로 최적화했다. 즉 256 비트 크기인 ymm에 얼라인 시켜 버린 것이다. 쩐다..
어제 내가 썼던 글은 무효가 된다.
그렇다면 단순 루프만 그렇게 된 것은 아닐까? 스칼라를 더한 연산을 해보니 마찬가지로 최적화가 된다. 물론 C 코드상에서 벡터 = 벡터 + 벡터 방식의 구문을 쓸 수는 없다.
벡터의 합을 구해보니 헐..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <immintrin.h>
typedef int v4si __attribute__ ((vector_size (16)));
#define CC 100000000
int main(int argc, char *argv[])
{
int i;
int *k, *kp;
int *q, *qp;
int *l, *lp;
k = malloc(4 * CC);
q = malloc(4 * CC);
l = malloc(4 * CC);
kp = k;
lp = l;
srand( time( NULL));
for(i = 0; i < CC; i++) {
*kp++ = rand();
*lp++ = rand() % 20;
}
kp = k;
qp = q;
lp = l;
// memcpy(q, k, 4 * CC);
for(i = 0; i < CC; i++) {
*qp++ = *kp++ + *lp++;
}
printf("%d, %d, %d\n", k[CC - 1], q[CC - 1], l[CC - 1]);
free(k);
free(q);
free(l);
}
이 코드에서... 벡터 덧셈을 256비트 단위로 하고 있다.
vpaddd 0(%r13,%rax), %ymm1, %ymm0
vmovdqu %ymm0, (%r14,%rax)
addq $32, %rax
cmpq $400000000, %rax
jne .L3
실로 멋진 최적화다...
다음 문서를 참조한다.
https://www.linuxplumbersconf.org/2016/ocw/system/presentations/3795/original/GCC.pdf