[t:/]$ 지식_

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









[t:/] is not "technology - root". dawnsea, rss