Kim Seon Deok

[CUDA] ch2. CUDA Memory Management - Shared memory & Texture memory & Registers 본문

CUDA Programming

[CUDA] ch2. CUDA Memory Management - Shared memory & Texture memory & Registers

seondeok 2023. 12. 18. 05:20

 

 

 

Shared memory 

shared memory는 CUDA memory hierarchy에서 User-Managed cache로써 역할을 수행한다.

user가 global memory에서 data를 coalesce한 방식으로 read/write하고, user가 control 할 수 있는 cache처럼 작동하는 memory를 제공한다. 

 

- shared memory는 같은 block 내의 thread에게만 visible하다. -> 같은 block 내의 thread끼리만 memory access를 공유

- 같은 block 내 thread들은 result를 공유할 수 있기 때문에, redundant한 계산을 줄일 수 있다.

- shared memory와 CPU cache는 비슷하다. CPU cache는 explicit하게 관리되지 않는 반면 shared memory는 user에 의해 explict하게 manage될 수 있다.

- shared memory는 global memory보다 latency가 낮고 bandwidth가 높다.

 

 

 

shared memory의 내부 구성

Bank conflicts and its effect on shared memory

 

shared memory는 bandwidth를 높이기 위해 bank로 구성되어 있다.

- 각 bank는 cycle 당 1개의 address를 처리할 수 있다. -> shared memory는 bank 갯수만큼 simultaneous하게 access가 가능하다

- Volta 아키텍쳐의 경우, shared memory에 4byte-wide의 32개의 bank가 들어있다.

 

shared memory 내부에 array가 저장된 모습

 

하나의 배열이 shared memory에 저장될 때, 인접한 4-byte word는 bank에 연속적으로 저장된다.

 

 

  • Bank conflict가 발생하지 않는 경우

1 warp 내 32개의 thread가 shared memory의 서로 다른 bank에 각각 액세스

 

  • Bank conflict가 발생하는 경우

1 warp 내 32개의 thread중 일부가 shared memory의 같은 bank에 random하게 액세스

 

 

 

Texture cache

- read-only cache는 kernel 실행 중 변경되지 않는 read-only data를 저장하는 데 적합하다.

- 다른 cache로의 load를 줄여 성능을 향상시키는 역할을 한다.

- GPU에서 Read-only data는 grid 내 모든 thread에서 visible하다.

- CPU는 해당 data에 대해 read 및 write 권한이 모두 있다.

- const __restrict__ 로 read-only data를 표현

- __ldg 로 texture cache를 통한 로딩을 수행

 

Read-only data는 주로 warp가 동일한 address/data를 read하도록 요구될 때 사용된다.

이를 통해 각 clock period 당 모든 thread에 대해 data request가 이루어진다. 

또한 texture cache는 같은 warp 내 thread들이 2D 및 3D locality를 가진 texture address에서 data를 read할 때 성능이 향상되는 경향이 있기 때문에 image scailing과 같은 image process algorithm에 유용하다.

 

 

 

 

 

Register

GPU는 CPU에 비해 충분한 갯수의 register를 갖고 있다. 그렇기 때문에 register에 data의 대부분을 저장할 수 있고 context switching을 통해서 latency를 줄일 수 있다. 따라서 register를 optimal하게 만드는 것이 중요하다.

하나의 SM에는 고정된 register set이 있다.

 

register spill

CUDA compiler는 각 thread 당 최적의 register 갯수를 찾는다.

local variable이나 intermediate value가 많아서 register 갯수가 부족해지는 경우 data는 local memory(L1/L2 cache 혹은 lower level memory)로 이동한다. 따라서 불필요한 local variable을 많이 선언하지 않는 것이 권장된다.

 

 

- register는 per-thead로 single thread의 scope를 갖고 있다.

- grid에서 실행되는 모든 thread에 대해 변수의 private copy가 생성되고, copy에 대해 thread가 액세스하게 된다. 단 다른 thread의 private한 variable에는 액세스할 수 없다. 

- kernel의 일부로 선언된 local variable과 intermediate value를 저장한다.

 

 

 

 

 

 

Comments