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