ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 포인터 에일리어스(Pointer Alias)
    프로그래밍/기록, 개념, 용어 2015. 2. 4. 21:20
    반응형

    포인터 에일리어스(Pointer Alias)


    두 개 이상의 포인터 변수가 같은 메모리 위치를 담고 있을 때 그 포인터들을 에일리어스(alias)라고 부른다.

    컴파일러 입장에선 모든 포인터 변수가 서로의 에일리어스 일 수도 있다 생각하는 것이 안전하다.



    포인터 에일리어스 발생 가능성이 높은 코드


    void any_func( int* a, int* b )

    {

      *b = *b + *a;

      *a = *a + 2;
    }


    포인터 a, b가 에일리어스 상태가 아니라면 a의 값은 한 번만 로딩되면 된다. 

    에일리어스일 경우에는 포인터 b가 지칭하는 값에 대한 수정이 a가 지칭하는 값에 대한 수정일 수 있으므로 a의 값이 두 번 로딩되어야 한다.



    포인터 에일리어싱이 가능한 코드


    void func( int* a, int* b )
    {

      (*a)++;

      (*b)++;
    }


    위 코드가 컴파일 되면 아래와 같이 된다.


    포인터 에일리어스가 가능한 상태에서 컴파일된 코드


    ld [$o0], %o5 ! Load *a

    add %o5, %o5 ! Increment

    st %05, [%o0] ! Store *a // 첫 번째 변수 저장

    ld [%01], %o4 ! Load *b // 두 번째 변수 읽어들임

    add $o4, 1, $o3 ! Increment

    st %o3, [%o1] ! Store *b


    포인터 에일리어싱 때문에 포인터 변수 b가 가리키는 주소에서 값을 읽기(load) 전에 포인터 변수 a가 가리키는 주소에 값을 써야한다(store)


    다음은 포인터 에일리어싱이 없는 경우이다.


    포인터 에일리어싱 문제가 없는 코드

    void func( int* a )
    {

      a[0]++;

      a[1]++;
    }


    위 코드가 컴파일 되면 이와 같이 된다.


    포인터 에일리어싱 없이 컴파일된 코드


    ld [%o0], %o5 ! Load a[0]

    ld [%o0+4], %o4 !Load a[1] // 두 번째 변수를 load

    add %o5, 1, %o5 ! Increment 

    st %o5, [%o0] ! Store a[0] // 첫 번째 변수 저장

    add %o4, 1, %o3 ! Increment

    st %o3, [%o1] ! Store a[1]


    두 메모리 작업에 에일리어싱이 없다는 사실을 컴파일러가 알 수 있으므로, 

    명령어 순서를 바꿔 메모리 읽기를 앞으로 당겨 메모리 접근 지연의 영향을 줄일 수 있다.


    restrict 키워드


    restrict 키워드는 출력값으로 쓰이는 포인터(destination!)는 인자로 같은 요소를 가리키지 않을 것이란걸 컴파일러에게 알려주는 것으로, 

    컴파일러는 이 통지를 믿고 최적화 과정을 수행하게 된다. 이 키워드는 C에서는 표준이지만 C++에선 표준이 아니다.


    이런 부분이 없을 거라는걸 알려주는 키워드...!


    int arr[5];


    any_task(&arr[0], &arr[4], 5);


    최적화를 컴파일러가 메모리 에일리어싱이 될지 안 될지를 명확하게 알 수 있도록 하자.

    반응형
Designed by Tistory.