본문 바로가기

Research

병렬처리된 thread들은 하드웨어에서 어떻게 처리될까

미완성 버전.. 쓰는 중

 

 

CUDA 프로그래밍 관점의 thread

 CUDA를 기준으로 설명하자면, 프로그래머는 스레드를 일단 묶어줘야할 의무가 있다. 언젠가 알아서 병렬처리를 해줄 수도 있고 워낙 현존하는 라이브러리들이 프로그래머들을 편하게 해주기 때문에 요즘 CUDA프로그래밍의 큰 부담은 없다.

병렬처리 프로그래밍도 여러가지 고려해야할 것이 있겠지만 기본적으로는 병렬처리할 스레드를 묶어주는 것으로 시작된다. CUDA함수를 호출할 때 2차원 기준으로만 본다면 thred block 수와 thread block size로 나뉜다. 좀 더 차원을 복잡하게 하여 자유로운 프로그래밍과 하드웨어에 최적화된 스레드 블록 구성이 가능하지만..그렇게 복잡한 경우에 그냥 라이브러리를 쓰는 것이 좋다고 생각한다... 따라서 대부분 2차원의 thread block 구성이면 될 것 같다.

 CUDA프로그래밍을 하면 알겠지만, thread block은 어떻게 나누느냐가 평소에 큰 차이가 없다...어차피 하드웨어에서도 warp pool 내에서 쌓여있다가 차례대로 그룹단위로 병렬처리된다. 다만 shared memory를 사용할 때 thread block 사용이 중요해진다. 일단 shared memory는 충분한 공간이 아니다. 특히 딥러닝과 같이 대용량 데이터들을 다룰 때 shared memory 공간으로 데이터 fetch를 고속화하는 방식을 사용하기에 벅차다. shared memory 접근 시간은 register 급이기 때문에 thread block 에 속한 thread 사이의 데이터 공유에 매우 유용하지만 한계가 있다.

 

 

하드웨어에서의 thread 처리

 Volta급의 최신 구조에서 방식이 달라졌을 수도 있다. 조금씩 변화하고 있고, 아키텍처별로 왔다갔다 하는게 워낙 많아서...

 기본적으로 Thread Block은 CTA라고도 불리운다. Concurrent Thrad Array라고 해서..용어가 변화한 줄 알았는데 소프트웨어 수준에서는 여전히 Thread block을 쓰는 것 같다... (이하 TB라고 씀)

우리가 작성한 함수는 kernel이라고 불리운다. 이 kernel이 CPU단에서 GPU로 넘어간다. 명령어를 넘기고, GPU의 global memory로 데이터를 넘긴다. 이 kernel 안에 여러 개의 TB가 있고, TB들은 프로세서 유닛인 SM(Streaming Multiprocessor)에 스케줄러에 의해 할당된다. 이 TB는 다른 TB와 독립적이다..따라서 TB간 병렬처리가 가능하다..각 SM에서는 이 TB들을 좀 더 작은 단위로 쪼개서 병렬처리를 수행한다. 따라서 단순히 하나의 SM만 본다면 한 순간의 병렬처리는 32개의 thread만 해당하게 된다. 다만 이러한 SM이 여러 개이고, 워낙 빨리 수행되서 큰 의미에서 병렬적이라고 볼 수 있는 것이다. 

 어쨋건 SM에 있는 core들의 입장에서는 자신들이 1 clock cycle 에서 수행할 수 있는 thread가 동시 32개이므로, 프로그래머 또한 32 배수의 thread 수를 할당해야 한다.

 

 

Shared Memory 사용에 대한 이해

Shared Memory 사용법은 좀 복잡하다. 동작을 이해하지만 CUDA 프로그래밍을 할 때 하드웨어적인 관점과 메모리 공간에 접근하는 스레드 그리고 이것을 어느 순간 동기화해야하는지에 대한 이해가 필요하다... 그렇지 않으면 데이터 값이 잘못 계산된다...

가령 여러 개의 thread block이 자신들의 독립적인 shared memory 공간을 사용한다면 서로 다른 thread block 끼리는 데이터를 공유하지 못한다는 것은 매우 코딩에 있어서 제한적이다..

 

이에 대한건 나중에 다시;