2. 발표자 소개 - 김정현
• 해커 16기
• 2007년 경희대 졸업(02학번)
• 2009년 서울대 석사
• 2015년 현재 서울대 컴퓨터공학부 박사과정
• 관심분야
• 컴퓨터 구조, 병렬 컴퓨팅, 컴파일러
3. 목차
• 전통적인 프로세서의 성능 향상 기법
• 멀티 코어의 출현
• 병렬 컴퓨팅이란?
• 병렬 프로그래밍 모델
• GPGPU
• CUDA/OpenCL
• 병렬 컴퓨팅의 한계
• 병렬 프로그래밍 시 유의사항
• 요약
4. 전통적인 프로세서의 속도 향상 기법
• 프로세서의 주파수를 높임
• 주파수
• 프로세서가 한 명령어를 수행하는데 필요한 주기
• 1GHz 프로세서: 1개의 명령을 1나노초에 처리
• 소프트웨어의 수정 없이 성능이 향상됨
• 1GHz 프로세서를 2GHz 프로세서로 업그레이드하면?
• 대략 2배의 성능향상
5. Intel Processor Clock Speed(MHz)
http://people.cs.clemson.edu/~mark/330links.html
주파수가 더 이상
증가하지 않음
6. 멀티 코어의 출현
• 주파수 증가가 멈춘 이유?
• 하드웨어의 한계
• 주파수를 올리면 그에 따라 발열이 올라감
• CPU fan만으로는 제어 불가능한 발열량 발생
• 하지만 CPU 집적도는 계속하여 향상됨
• 동일한 면적에 더 많은 트랜지스터를 넣을 수 있음
• 이 공간을 어떻게 활용하지?
• 멀티 코어!
7. 멀티 코어란?
• 프로세서
• CPU 칩을 의미
• 코어
• CPU 칩 안에서 계산을 담당하는 주체
• 멀티 코어?
• 여러 개의 코어가 하나의 프로세서에 집적됨
9. 병렬 컴퓨팅이란?
• Parallel Computing
• 동시에 다수의 계산을 수행하는 방법
• 예제
• 1부터 100까지의 합을 여러 개의 코어가 나누어 계산
• 1~50까지 코어 0이 계산
• 51~100까지 코어 1이 계산
10. 왜 병렬 컴퓨팅이 필요한가?
• 다수의 코어를 가진 현대 컴퓨터
• 데스크톱 프로세서
• 모바일 프로세서
• 다수의 코어를 효과적으로 이용하는 방법?
• 다수의 프로그램을 동시에 실행
• 하나의 큰 프로그램을 여러 개로 분할하여 동시에 실행
11. 다수의 프로그램을 동시에 실행
• 웹 브라우저는 코어 0에서 실행
• 엑셀 프로그램은 코어 1에서 실행
• 파워포인트 프로그램은 코어 2에서 실행
• 단점?
• 위의 프로그램들은 모두 사용자의 입력을 기다리는 프로그램
• 일반적으로 사용자는 한 시점에 하나의 프로그램만을 이용
• 세 프로그램이 하나의 프로세서에서 실행되어도 유저는 감지하지 못함
12. 하나의 큰 프로그램을 분할
• 많은 계산을 요구하는 프로그램?
• 게임
• 원소가 10만 개인 두 배열의 곱셈
• 어떻게 분할하나?
• 게임
• 네트워킹 담당 부분
• 물리 엔진 계산 부분
• UI 렌더링
• 곱셈
• 10만개를 각 코어별로 나누어 계산
Task parallelism
(태스크 병렬화)
Data parallelism
(데이터 병렬화)
13. 병렬 프로그래밍 모델?
• CPU를 위한 병렬 프로그래밍 모델
• pthreads
• OpenMP
• MPI
• Intel Threading Building Blocks
• GPU를 위한 병렬 프로그래밍 모델
• CUDA
• OpenCL
14. GPGPU
• General-purpose computing on graphics processing units
• GPU의 목적
• 모니터에 각 픽셀들의 색을 결정
• 이를 위해 다수의 코어가 존재함
• NVIDIA GTX960의 경우 1024개의 CUDA 코어가 있음
• 이렇게 많은 코어를 계산용으로 활용할 순 없을까?
• GPGPU의 탄생
• 초기의 프로그래밍 모델: OpenGL이나 DirectX를 이용
• 계산 전용 프로그래밍 모델의 등장
• CUDA/OpenCL
16. OpenCL
• Open Computing Language
• Khronos Group에서 제안/관리
• 공개된 무료 표준
• CPU, GPU, FPGA등 다양한 계산이 가능한 프로세서에서 동작
가능
• 하드웨어 벤더가 OpenCL SDK를 제공해야 함
• https://www.khronos.org/opencl/
17. 병렬 컴퓨팅의 한계
• 프로그래머에 따라 프로그램의 실행 속도가 크게 다를 수 있음
• 더 좋은 프로세서로 업그레이드
• 소프트웨어의 성능 향상은 기대하기 힘듦
• 주파수는 정체, 코어의 수가 증가
• 어떻게 병렬화를 할 것인가?
18. 병렬화 방법
• 태스크 병렬화(Task parallelism)
• 게임의 각 부분을 각 코어가 담당하도록 구현
• 데이터 병렬화(Data parallelism)
• 전체 데이터를 N등분 하여 각 코어에게 할당
19. 암달의 법칙(Amdahl‘s law)
• 멀티 코어를 이용한 프로그램의 성능 향상은 순차적으로 진행
하는 부분에 의해 결정됨
병렬화 영역
(Parallel portion)
27. thread0 thread1
임계 구역(Critical Section)
Load x→reg
Inc reg
Store reg→x
thread0
Load x→reg
Inc reg
Store reg→x
thread1
Load x→reg (0)
Inc reg (1)
Store reg→x (1)
Load x→reg (0)
Inc reg (1)
Store reg→x (1)
x = 1
원하는 결과: x=2
28. 임계 구역(Critical Section)
Lock(s)
Load x→reg
Inc reg
Store reg→x
Unlock(s)
thread0
Lock(s)
Load x→reg
Inc reg
Store reg→x
Unlock(s)
thread1
thread0 thread1
Load x→reg (0)
Inc reg (1)
Store reg→x (1)
x = 2
Lock(s)
Unlock(s)
Load x→reg (1)
Inc reg (2)
Store reg→x (2)
Lock(s)
Unlock(s)
Critical section
29. 성능 - 어느 것이 더 빠를까?
구현 1
int idx=my_id*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
구현 2
int idx=my_id;
for(i=0; i<N/2; i++) {
C[idx] = A[idx] * B[idx];
idx+=2;
}
30. 구현 1
Thread 0
int idx=0*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
Thread 1
int idx=1*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
2
N=16
2
4
A
B
C
*
=
31. 구현 2
Thread 0
int idx=0;
for(i=0; i<N/2; i++) {
C[idx] = A[idx] * B[idx];
idx+=2;
}
Thread 1
int idx=1;
for(i=0; i<N/2; i++) {
C[idx] = A[idx] * B[idx];
idx+=2;
}
2
N=16
2
4
A
B
C
*
=
32. 성능 - 어느 것이 더 빠를까?
구현 1
int idx=my_id*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
구현 2
int idx=my_id;
for(i=0; i<N/2; i++) {
C[idx] = A[idx] * B[idx];
idx+=2;
}
33. 구현 1 – 더 빠르다!
Thread 0
int idx=0*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
Thread 1
int idx=1*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
2
N=16
2
4
A
B
C
*
=
34. 빠른 이유?
• 캐시(Cache)
• 캐시의 특성
• 시간적 지역성 (Temporal locality)
• 한 번 접근 한 곳에 또 접근함
• 공간적 지역성 (Spatial locality)
• 이전에 접근한 곳 근처를 접근함
• 캐시 접근의 단위
• 캐시 블록(라인)
• 64 Byte
35. 구현 1
Thread 0
int idx=0*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
Thread 1
int idx=1*N/2;
for(i=0; i<N/2; ++i) {
C[idx] = A[idx] * B[idx];
idx++;
}
2
N=16
2
4
A
B
C
*
=