본문 바로가기
콤퓨타/CUDA

CUDA shared memory와 coalesced memory access

by 어니엉 2013. 2. 20.
728x90

 

[출처 : http://eaglface.blogspot.kr/2008/08/cuda-shared-memory-coalesced-memory.html]

뭔가 새로운 것을 배워나갈때 좋은 방법중에 하나는 잘 만들어진 예제를 참고하는 것이다. CUDA의 경우에는 SDK에 꽤나 좋은 예제가 많아서 배울 때 도움이 많이 된다.

그 중에 Convolution예제는 반드시 봐 두면 좋을 것 같은 예제다. 우선 원래 알고리즘이 매우 직관적이고 Serial implementation이 간단해서 원래 뭐였는지 고민할 필요가 없다는 점이 좋고, CUDA로 대충 구현했을때도 간단히 할 수 있지만 생각보다 속도가 나오지 않으며, 예제의 구현을 따라가면 훨씬 효율적으로 구현할 수 있음을 확인하면서 일반적인 CUDA 구현을 배울 수 있기 때문에 그렇다.

이번 포스트에서 생각해보고자 하는 것은 왜 나이브한 구현이 느려지는지와 shared memory의 사용에 대한 것이다. CUDA를 이용해 GPU를 구동했을 때 빨라지는 것은 거의 thread의 수가 늘어나는 것과 메모리 활용에 달려있다. 가능한 한 많은 thread를 동시에 구동할 수 있게 하는 것과, memory access pattern을 디자인하는 것이 속도 향상을 꾀할 때 필요한 것이다.

thread의 갯수는 거의 알고리즘의 복잡도에 달려있는데 이는 총 thread의 수가 각 thread내에서의 레지스터와 블럭 내의 shared memory사용량에 달려있기 때문이다. 다른 한 가지 요소는 coalesced memory access를 할 수 있는가이다. coalesced memory access는 각 thread가 메모리의 연속된 값에 접근할 때 한꺼번에 가져오거나 쓰는 것을 말하는데, 몇 가지 요구사항이 만족될 때만 이루어진다. 이를 coalescing requirement라고 하는데, 프로그래밍 가이드에 나와있기로는,
1) 각 thread가 32, 64, 128비트(4,8,16바이트) 워드를
2) thread number N인 thread가 (HalfWarpBaseAddress + N)에 접근하고
3) HalfWarpBaseAddress가 16*sizeof(type) 바이트의 주소 구조를 가지는 경우
이다.

그러나 모든 알고리즘이 이런 조건을 만족시킬 수 없으므로 성능은 생각보다 저하된다. 어떤 경우에는 데이터를 먼저 정렬시켜 넘겨줌으로써 가능할 수도 있지만 정렬에도 시간이 걸리며, 가능하지 않은 경우도 많다. 이 같은 경우 shared memory를 버퍼로 사용하여 메모리에 접근하면 눈에 띄는 성능 향상을 얻을 수 있다.

기본적인 아이디어는 각 thread를, 1)데이터 수집, 2) 프로세싱, 3) 데이터 저장 의 세 단계로 만드는 것이다. 데이터 수집단계에서는 필요한 data를 parallel thread를 써서 coalescing access하여 shared memory buffer에 가져오고, 프로세싱 단계에서는 이 데이터를 처리해서 다른 shared memory에 담고, 저장 단계에서는 프로세싱된 데이터를 다시 coalescing access로 global memory에 돌려주는 것이다. 각 단계 사이에 thread동기화를 통해 데이터를 확실히 얻도록 해야 한다. 불필요한 동작이 많은 것 같아 보이지만 메모리 접근횟수가 확실히 줄어들고 shared memory는 매우 빨리 읽고 쓸 수 있기 때문에 더 빠른 구현이 가능해진다. multiplication이나 convolution 예제에서는 이런 데이터 접근에 대해서 상세히 설명하고 있다.

빠른 버퍼를 두어서 데이터 접근 패턴을 바꾸는 것은 반드시 알아두어야 할 테크닉으로 이를 통해서 약 10배의 속도향상을 얻을 수 있다.

다루고 있는 데이터가 4,8,16 바이트가 아닐 경우에는 문제가 약간 복잡해지는데, 이 때는 4,8,16 바이트의 크기를 갖는 char struct를 정의해 두고, type casting을 통해 강제로 읽어들이게 하여 해결해야 한다. 어떤 경우든 인덱싱과 base address요구조건에 신경을 써 줘야만 함에 주의하자.

728x90

댓글