병렬 프로그래밍

Preview:

Citation preview

병렬프로그래밍:스터디

목차병렬 프로그래밍이란 무엇인가

What is OpenMP?

코드실행

결과에대한설명

컴퓨터 구조, 프로그래밍 모델With Parallel computing

우리는 어쨌거나 프로젝트를 위한 스터디를 합니다

빠르게 나갈 생각이기 때문에질문을많이 하셔야 합니다

소수 인원 프로젝트의 장점을 십분 활용해 주세요

시작하기에 앞서...

병렬 프로그래밍이란무엇인가What is Parallel Programming?

인텔이 한창 클럭으로 장난질 할 때

결국 프레스 캇이라는 희대의 똥망작 탄생

멀티코어의 등장 전

인텔의 클럭 올리기는 성능을 올리기 위한 행위

그런데 성능은 오르지 않았다

AMD는 단일 CPU 칩 안에 연산 유닛 수를 올림

AMD의반격

클럭 올리기

연산 유닛 수를 올림

클럭 상향 : 단일 연산 장치의 성능 올리기멀티코어 : 하나의 하드웨어에 연산 장치의 수 늘리기

Intel의접근법 AMD의 접근법

AMD의 접근법

승자는?

앞으로 많이 듣게 될 말입니다

회로 집적도의 문제나 발열 등물리적인문제로

단일 장치의 성능 향상에는 한계 존재

단일 장치의 성능 향상에는 한계 존재

소프트웨어 프로그래밍은 하드웨어의 모델에서 영향을 받음

병렬은 기본적으로 “다수”를 존재함

다수의연산을 동시에 수행하는 것이 병렬 연산, 이를 제어하는 것이

병렬 프로그래밍

하드웨어의 병렬화에서 병렬 프로그래밍이 대두

What is OpenMPWhy do we use it?

CPU 단에서의 병렬 프로그래밍을 위한 API

병렬 프로그래밍 API 춘추전국시대를 살아남은 몇 안되는 녀석

개발비용과 성능 향상을 따져 본 여러 엔지니어들의 선택을 받음

OpenMP is...

일단 다른 API들에 비해 무지 쉽다는 거

당장 POSIX C Multithread 프로그래밍만 해도 지금의 우리는 접근불가

그나마 직관적인 병렬 프로그래밍이 가능

OpenMP 의 장점1

대중적인 API이니만큼 기업들의 지원도 많은 편

특히 인텔과 AMD라는 든든한 지원군이 존재

OpenMP 의 장점2

대중적인 API이니만큼 다양한 개발환경에서 지원됨

VSCC, Clang/LLVM, GCC, ICC/ICPC 등 다양한 컴파일러에 표준으로 선택

대개 –fopenmp 옵션이나(gcc, clang) –openmp(icc/icpc)

/openmp(VSCC) –framework OpenMP(OS X clang)로 컴파일 가능

OpenMP 의 장점3

코드 실행역시시작은Hello, World!

긴설명필요없는기존 Hello, World in C

source.c:#include <stdio.h>

int main(int argc, char* argv[])

{

printf("Hello, World!");

return 0;

}

살짝변형하면 Hello, World in C-OpenMP

source.c:#include <stdio.h>

int main(int argc, char* argv[])

{

printf("Hello, World!");

return 0;

}

살짝변형하면 Hello, World in C-OpenMP

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

printf("Hello, World!");

return 0;

}

!

살짝변형하면 Hello, World in C-OpenMP

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World!\n");

}

return 0;

}

!!

!

살짝변형하면 Hello, World in C-OpenMP

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

! !

Visual studio에서OpenMP활성화하기

상단 메뉴바

프로젝트(Project)속성(Properties)

구성 속성(Configuration Settings)

C/C++언어(Language)OpenMP지원(OpenMP Support)

예 /openmp(Yes/openmp) 선택

Compiler Directive

ICC: icc –openmp source.c –o helloworld.out

ICPC: icpc –openmp source.c –o helloworld.out

GCC: gcc –fopenmp source.c –o helloworld.out

Clang: clang –fopenmp source.c –o helloworld.out

OS X Clang: clang –framework OpenMP source.c –o helloworld.out

VSCC: cl /openmp source.c

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

일단 결과를 보고 과정을 유추해 보는 것이 순서

결과에 대한 설명

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

유사한 결과가여러 번 나옴

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

유사한 결과가여러 번 나옴

공통된 부분은 여기

Code

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

공통된 부분 확인

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

유사한 결과가여러 번 나옴

달라진 부분은 여기

Code

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

변수 출력부 확인

Code

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

변수 출력부 확인

변수 확인

Code

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

변수 출력부 확인

변수 확인중간 추론: 동일한 함수가 다른 값을 반환

달라진 요인들이 결과의 변화를 초래했을 것

합리적인 추론하기

달라진 요인들이 결과의 변화를 초래했을 것

변수 출력부와 동일한 문자열의 존재와 기능은 확인됨

합리적인 추론하기

달라진 요인들이 결과의 변화를 초래했을 것

변수 출력부와 동일한 문자열의 존재와 기능은 확인됨

아직 해명되지 않은 “반복”을 초래한 것은 아직 해명되지 않은 요소일 것

합리적인 추론하기

Code

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

!!

!

#pragma omp parallel절 안의 내용물은 반복된다

omp_get_thread_num()함수는 다른 값을 매번 반환한다

추론 결과

변형과정추적하기

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

printf("Hello, World!");

return 0;

}

! 1:omp.h 헤더 include 하기추가 함수들을 포함시킴

변형과정추적하기

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World!\n");

}

return 0;

}

!!

!

2: omp parallel directive로 printf 함수 구문 감싸기

변형과정추적하기

source.c:#include <stdio.h>

#include <omp.h>

int main(int argc, char* argv[])

{

#pragma omp parallel

{

printf("Hello, World! From thread %d\n“, omp_get_thread_num());

}

return 0;

}

! !3: printf구문이 omp_get_thread_num()함수의반환값 출력하도록 바꾸기

컴퓨터구조, 프로그래밍모델With Parallel computing

어떤 종류의 명령을

어떤 종류의 데이터에 대해 수행하는가

플린 분류에서 아키텍쳐는 크게 4가지로 분류

Single / Multi: 수(단수/복수)

Instruction / Data: 무엇에 대해(작업, 데이터)

결합해서 약어를 만들어 봅시다

SISD: 한 종류의 데이터에 대해 단일한 연산을 수행함(병렬과는 관계 없음)

SIMD: 여러 데이터에 대해 단일한 연산을 수행함(데이터를 분배)

MISD: 동일 데이터에 대해 다양한 연산을 수행함(작업을 분배)

MIMD: 여러 종류의 데이터에 대해 다양한 연산을 수행함(동시에 분배)

오늘 우리가 한 것은?

SISD: 한 종류의 데이터에 대해 단일한 연산을 수행함(병렬과는 관계 없음)

SIMD: 여러 데이터에 대해 단일한 연산을 수행함(데이터를 분배)

MISD: 동일 데이터에 대해 다양한 연산을 수행함(작업을 분배)

MIMD: 여러 종류의 데이터에 대해 다양한 연산을 수행함(동시에 분배)

이는 컴퓨터 구조와,

연산이 실제로 하드웨어에 배분되는 모델을 생각하면

쉽게 이해할 수 있다.

가장 대중적인 모델 SIMD

프로세스 안에서 실행되는 단위 코드 조각

What is thread?

하나의 프로세스는 여러 동작이 결합되어 만들어진다

작업 과정의 어느 부분을 잘라내면 그게 바로 쓰레드그냥 프로세스의 일부분

프로세스 전체의 데이터(변수)는 공유함

정확하진 않지만 쉽게 설명하면...

Process

Process Thread Thread

작업을 관리하기 편하기 때문

미리 작업을 정의해 두고 여러 번 사용하거나

어느 시점까지 대기했다가 필요한 시점/실행가능한 시점에 실행할 수 있기 때문

쓰레드를 만드는 이유?

미리 작업을 정의해 두고 여러 번 사용

OpenMP가쓰레드를 만드는 이유?

미리 작업을 정의해 두고 여러 번 사용

OpenMP가쓰레드를 만드는 이유?

동시에

Process Thread

Thread

Thread

Thread

Process Thread

Thread

Thread

Thread

동시에 여러 작업 수행

프로세스가 특정 지점에서 동시에 여러 스레드를 실행하며 코드가 분기

각각의 스레드가 끝나면 다시 메인 쓰레드가 프로세스의 흐름을 모은다

Fork-Join 모델

OpenMP는 pragma omp 절을 쓰레드로 인식

하드웨어가 최대로 수용 가능한 쓰레드 수, 혹은 환경변수를 인식해 쓰레드 생성

각 쓰레드는 고유 index를 가짐이것이 omp_get_thread_num이 반환하는 값

소프트웨어 모델(스레드)를 하드웨어에 분배

쓰레드를 만들어 둔다 해도 한번에 얼마나 실행 가능한지 알 수 없음

그렇다고 실행 가능시점까지 그냥 대기하면 성능제약 까다로운 부분은 느려짐

성능이 중요한 작업에서는 하드웨어만 봐도 성능 예측 가능한 SIMD가 안전

코드는 하나인데 실행하는 머신은 천차만별

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

결과

Executed in: VSCC 2015, Windows 10 x64, 16GB DDR3, i7 4770K

숫자가 순서대로가 아니다

SIMD에서, 적어도 서로 다른 실행객체에는

순서 의존성이 없어야 함

SIMD에서 중요한 것 하나

실행객체

SIMD에서 중요한 것 하나

실행객체

SIMD에서 중요한 것 하나

: 보통은 쓰레드

Process Thread

Thread

Thread

Thread

동시에 여러 작업 수행

Process Thread

만일순서의존성이존재한다면…

Thread

Thread

Thread

Process Thread

만일순서의존성이존재한다면…

Thread Thread Thread

Thread

Thread

Thread

시간상의이점없음

쓰레드 작업 선행 오버헤드가 먼저 끝난 것을 그냥 먼저 실행

어떤 시점에 누가 먼저 끝날지도 알 수 없고, 수행시간도 매번 차이가 남

공학에서 이렇듯 통제 불가능한 상황에 의해 결과가 달라지는 것을

race condition이라 함

거기다 각 객체 실행 시점은 조금씩 차이남

컴퓨팅은 데이터와 동작 / 단일과 다중에 따라 4가지로 분류

가장 대중적인 병렬 모델은 SIMD

OpenMP는 Fork-Join 모델을 따름

병렬화 되어야 하는 작업은 순서 의존성이 없어야 한다

오늘의 내용정리: