728x90

시간 측정

- time ./실행파일명

ex. time ./13_serial_loop.x

- 13_serial_loop는 순차 프로그램, 15_parallel_for 작업분할지시자를 사용한 병렬 프로그램

 -> 20번 루프돌리는 동안 13은 0.045s 가 걸렸으나 15는 0.029s가 소요

 

 

atomic을 사용하는 경우

- 동기화를 위해 하나의 스레드만 사용하도록 막음

 => 병렬 처리의 성능을 크게 낮춤

* ciritical은 함수 범위 atomic은 한 줄연산 범위

 

 

 

reduction

- #pragma omp for reduction (+:sum)

 => 각 스래드들끼리 local sum을 구해서 다 더해라

 * atomic 처럼 한 스레드마다 다 돌떄까지 기다리지 않음. 단 전체가 로컬 sum을 구하도록 기다림

- sum이 shared 변수 -> 내부적으로 private처럼 처리

 

 

 

 

 

300x250
728x90

동기화 루틴

- #pragma omp critical 

 => 한 스레드가 동작중에 다른 스레드가 사용못하도록 막음

 => 한 스레드마다 처리 ? -> 차례차례이므로 병렬화가 아님 -> 성능이 떨어진다.

- 동기화를 시키기 위해 사용

 

 

 

 

 

 

 

동기화

- 스레드 작업 순서에 제한 두기 가능

- 공유 데이터 접근 제어

- 가능한 안쓰는것이 좋음

- 고수준 동기화 : critical, atomic, barrier

- 저수준 동기화 : flush, locks

 

critical과 atomic의 차이

- critical : 한번에 한 스레드만 이름으로 구분하는 critical 영역 진입

- atomic : 메모리의 한 위치에만 적용됨. mini-critical section. 크리티칼 영역보다 작음

 

 

 

베리어

- 모든 스레드들이 베리어에 도달 할 떄까지 대기함

- 작업 분할 구문(#pragma omp for)에서는 사용 불가

 

 

베리어가 없는 경우

- 스레드들이 베리어가 없으므로 기다리지 않고 그냥 처리

 => 결과 값이 달라짐

 

300x250
728x90

기본적인 내적 순차 연산

- 길이가 20인 벡터 a와 b의 내적(점곱)연산 결과

 

 

병렬 내적(=BLAS 내적) 연산

- BLAS Basic Linear Algebra Subsystem 선형대수 라이브러리 -> BLAS의 내적 연산 구현

- 스래드 4개 생성

- 20개의 작업을 4개의 스레드로 나눠서 수행 <- #pragma omp for(작업분할지시어)

- 결과는 순차 내적 연산 코드와 동일함. 시간 측정을 하면 병렬 코드가 더빠를듯

 

 

병렬화의 중요점

- 기본 로직과 병렬화 로직 중 병렬화를 함으로서 성능 이득이 커야함

- 기본 로직 상에서 병렬화를 수행할 부분을 잘 찾아야함

 

300x250
728x90

병렬 루프 만들기

- 코드에서 실행 시간이 오래걸리는 부분에서 병렬화를 수행해서 시간을 줄여야함

 => 그런부분들이 루프문임 => 루프문을 병렬화 해야함

- openmp의 단점. 사용 가능한 노드 수가 제한됨(1개)

- 여러 노드를 사용해야할때 mpi를 사용해야함

 

 

단순 순차 루프문

 

 

병렬 루프문

- N은 20, 스레드는 4개

- i, tid, istart, iend를 private으로 사용

tid    istart    iend       output i

 0      0        5       -> 0 ~ 4

 1      5       10      -> 5 ~ 9

 2      10      15     -> 10 ~ 14

 3      15      20     -> 15 ~ 19

- 아래에 컴파일러 지시자로 작업을 분할해주는것과 결과는 동일하나 구현은 복잡함

 

 

 

 

 

간단해진 병렬 루프문

- #pragma omp for <- 작업 분할 지시어(핵심)

 => 4개의 스레드가 20개의 문자열 출력 작업을 분할해서 수행

 

 

 

300x250
728x90

배열에 스레드 번호 저장하기

- 스래드 4개 생성

- 배열은 shared

- i는 계속 처음에 10으로 초기화

- 각 스래드마다 인덱스와 값으로 0, 4, 8을 추가하여 할당

- 정리

tid(idx)  value

0        0  4 8

1       1   5 9

2       2  6 10

3       3  7  11

 

300x250
728x90

스레드

- 프로세스 내 여러 실행 단위

- 메모리 공유. 스택에 변수 저장

 

프로세스

- 프로그램의 실행 단위

- 개별적인 메모리를 가짐

 

 

메모리 공간

- 코드 영역 : 실행할 명령어들이 저장된 공간

- 데이터 영역 : 전역 변수 저장

- 힙 영역 : 동적 할당 메모리 공간

- 스택 영역 : 함수 호출 정보와 스레드 변수, 지역 변수들을 저장

 

https://snupi.tistory.com/9

 

 

 

 

300x250
728x90

전역 변수로 초기화

-  전역변수 i = 10이 존재

- private i들을 10으로 초기화 -> firstprivate

 => print 출력 후 i는 20(지역변수)

- 병렬 영역 밖에서 i는 10

 

 

 

 

 

공유 변수

- shared(a)로 배열 변수 a를 공유 설정

 

- 병렬 영역 안에서 공유 변수 a에 값을 저장하였으나 병렬 영역밖에서도 접근 가능

 

 

private 배열 변수

- 아까 share 시킨 배열 변수 a를 private으로 지정후 병렬 영역 안에서 초기화 시키면

 => 병렬 영역 안에서만 값이 존재. 병렬 영역 밖에선 배열은 0으로 초기화 되지 않은채 남아있음.

 

300x250
728x90

OpenMP과 메모리 공유

- 스레드 중심이다보니 공유 메모리 병렬 프로그래밍 방식

-> 변수들이 공유됨

 

 

변수 공유 예시

- 아래의 코드 상에서 변수 tid들은 모든 스레드 상에서 공유됨

- 병렬 영역 전에 tid가 선언되고, 병렬 영역 안에서는 공유된 변수 공간에 초기화 수행

* 포트란에서는 모든 스레드가 덮어씌워져서 같은 tid를 가지나 c언어는 컴파일러가 수정해줘서 제대로 결과가 나옴

- 포트란에서는 tid가 공유되어 있어 다 덮어씌워지는 모습을 볼수있음.

 

 

변수 공유 해결

- tid를 private로 컴파일러 지시자를 지정해주면 됨.

 

- 혹은 tid를 지역변수로 만들어주면 됨

 

- 변수 tid에 각각의 스레드 번호가 할당되어 출력된 결과를 볼수 있음. 

 

 

 

300x250
728x90

병렬 영역 지정

#pragma omp parallel

{

 

}

 

스래드 개수 설정

- 환경 변수 : export OMP_NUM_THREADS=수

- 지시어 : #pragma omp parallel num_threads(수)

- 실행시간 라이브러리 : omp_set_num_threads(수)

 

스레드 관련 런타임 라이브러리(함수)

- omp_set_num_threads(수) : 스래드 개수설정

- omp_get_num_threads(): 현재 스래드 개수 반환

- omp_get_thread_num() : 현재 쓰래드 아이디 반환

 

 

프로그래밍 모델

- 스레드 기반

- 포크-조인 모델

 

포크-조인 모델

- 마스터 스레드는 병렬영역 끝에서 합쳐지는 스레드 모임 생성

- 동일 모임에 속한 스레드들이 공동 작업 수행

 

 

스레드 생성 예제

- 스레드 개수 출력 omp_get_num_threads()

- 스레드 3개 생성 #pragma omp parallel num_threads(3)

 -> 스래드 번호 omp_get_thread_num()와 스레드 개수 출력 omp_get_num_threads()

- 환경 변수에 지정한 만큼 스레드 생성

 -> 실행전 export OMP_NUM_THREADS=5

- 병렬 영역 밖에는 스래드 갯수가 1로 출력

 

 

 

300x250

'컴퓨터과학 > 기타' 카테고리의 다른 글

openmp - 9. firstprivate, shared, private  (0) 2020.07.29
openmp - 8. OpenMP과 메모리 공유  (0) 2020.07.29
openmp - 6. openmp 예제  (0) 2020.07.29
openmp - 5. OpenMP 시작하기  (0) 2020.07.29
openmp - 4. 잡 스캐줄러  (0) 2020.07.29
728x90

컴파일러 지시자와 함수로 스레드 갯수 설정하기

- 컴파일러 지시자 : #pragma omp parallel num_threads(2) -> 스레드 2개 설정

- 함수 : omp_set_num_threads(4) -> 스레드 4개 설정

 

 

 

컴파일러 지시자와 함수로 스레드 갯수 설정하기 - 결과

- 기본 스레드 만큼 출력 -> 4개 출력 -> 2개 출력

300x250

'컴퓨터과학 > 기타' 카테고리의 다른 글

openmp - 8. OpenMP과 메모리 공유  (0) 2020.07.29
openmp - 7. 스레드 관련  (0) 2020.07.29
openmp - 5. OpenMP 시작하기  (0) 2020.07.29
openmp - 4. 잡 스캐줄러  (0) 2020.07.29
openmp - 3. openmp와 opencv  (0) 2020.07.29

+ Recent posts