계층적 메모리 접근 최적화

 

무슨말이가?

그거슨, GPU에는 여러 메모리가 있는데, 그 메모리들을 빠른 순서대로 사용한다는 의미로

 

속도순으로 나열하면

레지스터 = 공유메모리 > 상수메모리 > 텍스쳐메모리 > 전역메모리 > 지역메모리

 

요런 형태로, 레지스터가 가장 빠르고 레지스터와 비슷한 접근속도를 갖는것이 바로 공유메모리

우리는 어떻게 하면 이 레지스터와 공유메모리에서 계산을 할 것인가를 생각해야한다.

 

그렇지만, 무조건 접근 메모리를 빠른 메모리를 사용한다고해서 빠르기만 한 것도 아니다.

 

빠른 메모리를 사용했는데도 느린 예를 보여드리겠습니다,

 

뱅크충돌 : 스레드가 동시에 같은 뱅크영역을 접근하려할 때 발생하는 문제

               동시에 같은 영역을 접근하려 했기 때문에, 스레드는 한번에 메모리에 접근하지 못한다

               때문에 같은 뱅크영역의 충돌이 발생하지 않게 순차적으로 접근한다

               병렬프로세스에서 순차적으로 접근하는 현상이 발생하기 때문에 전체적으로 속도가

               느려지는 충돌현상이다.

 

공유메모리 : 4바이트 간격으로 16개의 뱅크로 구성, 64바이트마다 이런 패턴 반복

요 그림은 두개의 스레드가 동시에 같은 뱅크를 접근하는 현상이다.

이럴 경우 겹치는 두 스레드가 병렬이 아닌 순차처리를 하게 된다.

 

위의 표는 3840x3840개의 데이터에 대해 공유메모리 사용 시 

뱅크충돌이 발생하는 경우(BankConflict) : 각 하프워프 당 16번의 뱅크 충돌(일부러 실험환경 조성)

뱅크충돌이 발생하지 않는 경우(NoBankConflict) : 걍 충돌이 없는 상황

공유메모리 사용부분을 제외한 전역메모리 접근 시간 (NoSharedRead)

warp serialize는 뱅크충돌의 발생여부를 보여주는 것으로 553391번의 충돌이 일어났다는 것을 보여준다. 

 

 

 

트랜잭션 : 전역 메모리를 읽어오는 단위영역

               트랜잭션 크기 이외의 메모리 영역을 더 참조해야하는 스레드가 존재할 경우

               메모리 트랜잭션 횟수가 증가한다.

 

전역메모리 접근 시 하프워프 스레드가 읽고자 하는 전체 메모리 영역의 크기를 통해 메모리 트랜잭션이 발생한다.

하프워프 단위의 스레드가 되도록 조밀한 메모리 영역을 참조하고자 할 경우 트랜잭션의 횟수는 적게 발생하고, 위와 같은 충돌현상은 줄어들 것이다.

 

그래서, 한번의 트랜잭션으로 전역메모리 접근이 완료될 경우 최적의 성능을 보인다.

이렇게 한번의 트랜잭션으로 메모리 접근이 이루어질 수 있도록 메모리 접근 설계를 해야한다.

 

CUDA Compute Capability 1.2 이상의 GPU에서 전역메모리 접근은 하프워프 단위의 모든 스레드가 하나의 세그먼트를 참조하면 하나의 트랜잭션으로 합쳐진다.

그리고 전송되는 메모리 단위는 전역 메모리의 크기에 따라 달라진다.

 

전송메모리 결정 : 트랜잭션이 발생하는 전역메모리의 단위영역 시작주소는 세그먼트의 배수로 결정

                         최종적으로 128/64/32 바이트 단위영역을 기준으로 하프워프가 필요로하는

                         최소, 최대 범위의 메모리주소를 참조하여 최소한의 단위영역을 결정한다.

 



전송 메모리 결정의 예

 - 하프워프 스레드가 전부 32바이트의 단위에서만 메모리 참조를 할 경우

 - 32바이트 단위 메모리 트랜잭션이 한번만 발생

 - 참조하고자 하는 전역 메모리가 2048바이트 영역 내에 흩어져 있을 경우

  * 128바이트의 트랜잭션(한 세그먼트)이 최대 16번 발생하여 상당한 성능 저하 초래 (위 그림)

 - 한 세그먼트에 한 전역메모리가 스레드로 접근

Posted by 긍정왕오킹