avx2와 O2 최적화

2017/02/10

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