[기술] GPU와 CUDA (8) - 공유 메모리

공유 메모리 공유 메모리 사용 방법은 크게 세 가지 케이스로 구분한다. L1 캐시: 자주 사용되는 데이터를 직접 분류, 관리하기 어려운 경우 사용자 관리 캐시 1: 개발자가 커널 내 알고리즘의 데이터 접근 패턴을 파악 후, 직접 제어 사용자 관리 캐시 2: 자주 사용하는 데이터의 전역 메모리 접근을 줄이기 위함 스레드 간 공유 메모리와 L1 캐시 활용 방법 공유 메모리 (Shared Memory) 역할 및 특징: 공유 메모리는 각 블록 내 모든 스레드가 접근할 수 있는 고속 메모리 공간이다....

[기술] GPU와 CUDA (7) - CUDA 기반 행렬 곱셈

CUDA 기반 행렬 곱셈 행렬 연산은 CUDA 연산에 가장 어울리는 문제이다. 따라서 행렬 곱셈을 GPU에서 수행하는 방법을 이해한다. 스레드 레이아웃 설정 대규모 행렬 곱을 위한 CUDA 프로그램을 위해 스레드 레이아웃을 먼저 결정해야 한다. 어떻게 레이아웃 기준을 잡아야 할까? 두 가지 경우를 생각할 수 있다. 데이터를 읽는 행렬 A, B 기준 결과가 저장되는 행렬 C 기준 C = AB 이 행렬 연산에서 C의 (row, col) 값 계산을 위해서는 A(row, k) B (k, col) 원소들을 불러와야 한다....

[기술] GPU와 CUDA (6) - CUDA 실행 모델

GPU 아키텍처 SM: 스트리밍 멀티프로세서 하나의 GPU는 SM이라는 물리적 구조를 여러 개 포함한다. SM은 여러 CUDA 코어를 가진 연산 장치다. Fermi 아키텍처는 하나의 SM에 32개의 CUDA 코어를 가지고 있다. SM에는 CUDA 코어말고 레지스터, 공유 메모리, L1 캐시 등이 포함된다. CUDA 코어 CUDA 코어는 GPU의 가장 기본이 되는 프로세싱 유닛이다. 코어 안에는 FP 연산기, INT 연산기 등이 있으며, CUDA 프로그램의 동작 단위가 스레드이므로, 스레드 1개에 CUDA 코어 1개가 할당된다. CUDA 스레드 계층과 GPU 하드웨어 간단한 요약 1 스레드 = 1 코어 32개 스레드가 모여 1개의 워프이다....

[기술] GPU와 CUDA (5) - 스레드 레이아웃

스레드 레이아웃 스레드 레이아웃 결정 앞서 CUDA 커널의 레이아웃은 그리드와 블록의 형태로 결정한다고 하였다. 구체적으로 다음의 과정을 따른다. 블록 형태 결정 (즉, 스레드를 어떻게 배치할껀지 결정) 데이터의 크기 및 블록 형태에 따라 그리드 형태 결정 블록 형태는 커널의 알고리즘 특성과 GPU 환경을 고려하여야 한다. 이때 레지스터, 공유 메모리 크기 등도 고려해야 할 요소이다. 큰 벡터의 합을 연산하는 CUDA 커널 (2) 벡터 차원이 1,024보다 크면 블록을 여러 개 지정해야 한다. 하나의 블록이었다면, 각 스레드가 벡터의 첫 번째 원소부터 담당하여 연산한다....

[기술] GPU와 CUDA (4) - CUDA 연산 구조

CUDA 스레드 계층 스레드 CUDA 스레드 계층에서 가장 작은 단위는 스레드이다. 따라서 CUDA 연산을 수행하거나, 코어를 사용하는 기본 단위이다. 커널 호출 시, CUDA 커널 코드는 모든 스레드에 공유된다. 각 스레드는 커널을 독립적으로 실행한다. 워프 CUDA 스레드 계층의 두 번째 계층은 워프이다. 워프는 32개 스레드를 하나로 묶은 단위이다. 중요한 점은 워프는 디바이스에서 하나의 제어 장치에 의해 제어된다. GPU의 SIMT 구조에서 멀티 스레드 단위가 바로 워프이다. 이 말은 1개의 명령어에 의해 32개 스레드가 동시에 움직이는 것을 의미한다....

[기술] GPU와 CUDA (3) - CPU와 GPU의 벡터 합 연산

벡터 합을 구하는 호스트 프로그램 #include <stdio.h> #inlcude <stdlib.h> #include <string.h> #define NUM_DATA 1024 int main(void) { int* a, * b, * c; int memSize = sizeof(int) * NUM_DATA a = new int[NUM_DATA]; memset(a, 0, memSize); b = new int[NUM_DATA]; memset(b, 0, memSize); c = new int[NUM_DATA]; memset(c, 0, memSize); for (int i = 0; i < NUM_DATA; i++) { a[i] = rand() % 10; b[i] = rand() % 10; } for (int i = 0; i < NUM_DATA; i++) { c[i] = a[i] + b[i]; } delete[] a; delete[] b; delete[] c; } 벡터 합을 구하는 디바이스 프로그램 #include "cuda_runtime....

[기술] GPU와 CUDA (2) - CPU와 GPU 통신

호스트와 디바이스 호스트 호스트는 일반적으로 CPU를 의미한다. 따라서 호스트 코드는 CPU에서 실행되는 코드를 의미한다. 또한 호스트 메모리는 CPU가 사용하는 시스템 메모리이다. (DRAM) 디바이스 디바이스는 일반적으로 GPU를 의미한다. 따라서 디바이스 코드는 GPU에서 실행되는 코드를 의미한다. 또한 디바이스 코드는 GPU가 사용하는 GPU 메모리이다. CUDA 프로그램 CUDA 프로그램은 호스트 코드와 디바이스 코드로 구성된다. 프로그램 실행 시 처음 호출되는 코드는 CPU에서 프로세스를 할당하기 때문에, 호스트 코드가 통상 같이 있다. CUDA 프로그램에서 호스트 코드는 gcc와 같은 컴파일러로, 디바이스 코드는 NVCC 컴파일러로 컴파일한다....

[기술] GPU와 CUDA (1) - GPU의 연산 개념

GPU에 관하여 GPU는 방대한 수학 연산을 가속하기 위해 설계된 전자 회로이다. GPU는 CPU에 비해 수천 개의 작은 코어(모델 및 사용 목적에 따라 다름)를 가지고 있기 때문에 GPU 아키텍처는 병렬 처리에 최적화되어 있다. GPU는 여러 작업을 동시에 처리할 수 있으며 그래픽 및 수학적 워크로드에서 더 빠르다. GPU vs CPU GPU vs CPU 기본적인 GPU 구조 Flynn’s Taxanomy 플린의 분류법은 스탠포드 대학교의 마이클 J. 플린이 컴퓨터 아키텍처를 분류한 것이다. 플린의 분류법의 기본 개념은 간단하다....