728x90

ref : https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html

 

 

 

1. 1 x 2 열 subplot

 

 

import numpy as np
import matplotlib.pyplot as plt

# First create some toy data:
x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create two subplots and unpack the output array immediately
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
ax1.plot(x, y)
ax1.set_title('Sharing Y axis')
ax2.scatter(x, y)

plt.show()

 

 

2. 2x2 서브플롯 생성

 

 

import numpy as np
import matplotlib.pyplot as plt

# First create some toy data:
x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create four4 axes and access them through the returned array
fig, axs = plt.subplots(2, 2)
axs[0, 0].plot(x, y)
axs[1, 1].scatter(x, y)

plt.show()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

가장 단순한 plt.subplots()

 

여러개 플롯 생성 없이 사용.

 

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

# Create just a figure and only one subplot
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title('Simple plot')

plt.show()

300x250
728x90

테스크 데이터 유효범위

- 지정하지 않은것들은 기본적으로 shared

- parallel에서 bde tid가 private -> a와 c는 shared

- single에서 스레드 하나만 a=2, b=3, c=4, d=5, e=6으로 할당.

- a와 c는 shared이므로 다른 스레드도 영향받음, 나머지 bde는 그대로 0

#include <stdio.h>
#include <omp.h>

int main()
{
        int a=1, b=2, c=3, d=4, e=5, tid;

        omp_set_num_threads(4);
#pragma omp parallel private(b,d,e, tid)
{
        tid = omp_get_thread_num();
        printf("tid=%d a=%d b=%d c=%d d=%d e=%d\n", tid, a, b, c, d, e);
        #pragma omp single
        {  printf("in single: %d \n", tid);
           a=2, b=3, c=4, d=5, e=6; }
        #pragma omp task private(e)
        {
                printf("task tid=%d a=%d b=%d c=%d d=%d e=%d\n", omp_get_thread_num(), a, b, c, d, e);
        }
}
}

 

 

단순 피보나치

 

#include <stdio.h>

int fibon(int n) // f(n) = f(n-1) + f(n-2)
{
   int x, y;
   if(n<2) return n;
   x=fibon(n-1);
   y=fibon(n-2);
   return (x+y);
}

int main()
{
   int result = fibon(MAX);
   printf("Fibonacci (%d) = %d\n", MAX, result);
   return 0;
}

 

 

재귀 프로그래밍으로 구현한 피보나치 태스크

- 9.485s 소요

#include <stdio.h>

int fibon(int n) // f(n) = f(n-1) + f(n-2)
{
   int x, y;
   if(n<2) return n;
   #pragma omp task shared(x)
   { x=fibon(n-1); }
   #pragma omp task shared(y)
   { y=fibon(n-2); }
   #pragma omp taskwait

   return (x+y);
}

int main()
{

#pragma omp parallel
{
#pragma omp single nowait
{
   printf("Fibonacci (%d) = %d\n", MAX, fibon(MAX));
}
}
   return 0;
}

 

 

재귀 프로그래밍으로 구현한 피보나치 태스크

- n < 30구문 아래의 x,y 계산은 조건문 안의 함수가 다 호출된 후 순서대로 시작 => n<30인 경우 시리얼로 처리

- n >= 30은 테스크로 처리

#include <stdio.h>

long int fibon(int n) // f(n) = f(n-1) + f(n-2)
{
   long int x, y;
   if(n<2) return n;

   if(n<30){
      return fibon(n-1)+fibon(n-2);
   }
   else
   {
   #pragma omp task shared(x)
   { x=fibon(n-1); }
   #pragma omp task shared(y)
   { y=fibon(n-2); }
   #pragma omp taskwait

   return (x+y);
   }
}

int main()
{

#pragma omp parallel
{
#pragma omp single nowait
{
   printf("Fibonacci (%d) = %ld\n", MAX, fibon(MAX));
}
}
   return 0;
}

300x250

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

matplotlib - 2. 1x2, 2x2 subplots  (0) 2020.08.25
matplotlib - 1. 단순한 subplots  (0) 2020.08.25
openmp - 24. 테스크  (0) 2020.07.30
openmp - 23. 스캐줄링과 만델브로트  (0) 2020.07.30
openmp - 22. ordered, lock  (0) 2020.07.30
728x90

테스크

- 암시적 묶음(스레드당 하나)

- 스레드 팀 발생

- 팀내 각 스레드에 테스크 하나씩 할당( 스레드 하나에 테스크가 묶임)

- 모든 태스크가 멈출때까지 마스터 스래드 대기

 

태스크의 개념

- 태스크 스캐줄링 = 은행 번호표 시스템

- 태스크 = 은행 업무

- 스레드 = 은행원

 

태스크 라이프사이클

1. 태스크 생성

2. 태스크 실행

3. 경우에 따라 일시 정지 후 재실행 등

4. 실행 완료

 

 

테스크 예제 1

- 32개의 스레드가 모두 ABCD 다 출력

#include <stdio.h>
#include <omp.h>

int main()
{
#pragma omp parallel num_threads(32)
{
        printf("A ");
        printf("B ");
        printf("C ");
        printf("D ");
        printf("\n");
} // pragma omp parallel
}

 

테스크 예제2

- ABCD다 19번스레드가 수행

#include <stdio.h>
#include <omp.h>

int main()
{
#pragma omp parallel num_threads(32)
{
        #pragma omp single
        {
                printf("A tid=%d\n", omp_get_thread_num() );
                printf("B tid=%d\n", omp_get_thread_num() );
                printf("C tid=%d\n", omp_get_thread_num() );
                printf("D tid=%d\n", omp_get_thread_num() );
        }
}
}

 

 

테스크 예제3

- 스래드 32개 준비됨

- A는 10번 스레드가 수행

- B와 C 테스크에 20, 10번 스레드가 수행

- 마무리 후 D는 1번 스레드가 수행

#include <stdio.h>
#include <omp.h>

int main()
{
#pragma omp parallel num_threads(32)
{
        #pragma omp single
        {
                printf("A tid=%d\n", omp_get_thread_num() );
                #pragma omp task
                {
                        printf("B tid=%d\n", omp_get_thread_num() );
                }
                #pragma omp task
                {
                        printf("C tid=%d\n", omp_get_thread_num() );
                }
                printf("D tid=%d\n", omp_get_thread_num() );
        }
}
}

 

 

테스크 예제 4

- taskwait : 태스크가 끝날떄까지 대기 = wait

- A를 23이 수행, 태스크 B와 C를 18, 25가 수행, 태스크가 끝나면 D를 23번이 수행

=> taskwait한 탓에 테스크 예제3번보다 0.003s 더 오래 걸림

#include <stdio.h>
#include <omp.h>

int main()
{
#pragma omp parallel num_threads(32)
{
        #pragma omp single
        {
                printf("A tid=%d\n", omp_get_thread_num() );
                #pragma omp task
                {
                        printf("B tid=%d\n", omp_get_thread_num() );
                }
                #pragma omp task
                {
                        printf("C tid=%d\n", omp_get_thread_num() );
                }
                #pragma omp taskwait
                printf("D tid=%d\n", omp_get_thread_num() );
        }
}
}

300x250
728x90

스캐줄링 정책 scheduling clauses

- 루프 실행에서 분배 방식을 지정

- 기본적인 스캐줄링 정책은 : 실행 횟수를 균등 분배

- 작업 균등 분배를 하기 위해서 스캐쥴링 정책을 사용

 

스캐줄링 정책 종류

- 정적 정책 static [, chunk_size] : 반복 실행 횟수를 스레드 마다 균일하게 할당(기본 스캐줄링 정책)

- 동적 정책 dynamic [, chunk_size] : 반복 실행 회수를 chunk_size로 나누어 chunk 생성.

                                              먼저  작업 끝난 스레드에 다음 chunk 할당

- 안내 정책 guided [, chunk_size] : 동적 스캐줄링으로, 반복 중에 chunk의 크기가 변함

- 실행 시간 정책 runtime : 프로그램 실행중에 환경변수 OMP_SCHEDULE 값을 참조하,

                                재컴파일 없이 여러 스캐줄링 방식 사용

                          => ex. export OMP_SCHEDULE="dynamic"

 

 

만델브로트

- 순차 프로그램 

- 13.261s 소요

#include <stdio.h>

#define         X_RESN  4000       /* x resolution */
#define         Y_RESN  4000       /* y resolution */
#define         X_MIN   -2.0
#define         X_MAX    2.0
#define         Y_MIN   -2.0
#define         Y_MAX    2.0


typedef struct complextype
{
        float real, imag;
} Compl;


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

        /* Mandlebrot variables */
        int i, j, k;
        Compl   z, c;
        float   lengthsq, temp;
        int maxIterations;
        int res[X_RESN][Y_RESN];

        maxIterations = 1000;
        for(i=0; i < Y_RESN; i++) {
                for(j=0; j < X_RESN; j++) {
                        z.real = z.imag = 0.0;
                        c.real = X_MIN + j * (X_MAX - X_MIN)/X_RESN;
                        c.imag = Y_MAX - i * (Y_MAX - Y_MIN)/Y_RESN;
                        k = 0;

                        do  {
                                temp = z.real*z.real - z.imag*z.imag + c.real;
                                z.imag = 2.0*z.real*z.imag + c.imag;
                                z.real = temp;
                                lengthsq = z.real*z.real+z.imag*z.imag;
                                k++;

                        } while (lengthsq < 4.0 && k < maxIterations);

                        if (k >= maxIterations) res[i][j] = 0;
                        else res[i][j] = 1;

                }
        }
}

 

 

- 정적 병렬 프로그램

 -> 1.305s 소요

#include <stdio.h>

#define         X_RESN  4000       /* x resolution */
#define         Y_RESN  4000       /* y resolution */
#define         X_MIN   -2.0
#define         X_MAX    2.0
#define         Y_MIN   -2.0
#define         Y_MAX    2.0


typedef struct complextype
{
        float real, imag;
} Compl;


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

        /* Mandlebrot variables */
        int i, j, k;
        Compl   z, c;
        float   lengthsq, temp;
        int maxIterations;
        int res[X_RESN][Y_RESN];

        maxIterations = 1000;
#pragma omp parallel for shared(res,maxIterations) private(i,j,z,c,k,temp,lengthsq) schedule(static)
        for(i=0; i < Y_RESN; i++)
                for(j=0; j < X_RESN; j++) {
                        z.real = z.imag = 0.0;
                        c.real = X_MIN + j * (X_MAX - X_MIN)/X_RESN;
                        c.imag = Y_MAX - i * (Y_MAX - Y_MIN)/Y_RESN;
                        k = 0;

                        do  {

                                temp = z.real*z.real - z.imag*z.imag + c.real;
                                z.imag = 2.0*z.real*z.imag + c.imag;
                                z.real = temp;
                                lengthsq = z.real*z.real+z.imag*z.imag;
                                k++;

                        } while (lengthsq < 4.0 && k < maxIterations);

                        if (k >= maxIterations) res[i][j] = 0;
                        else res[i][j] = 1;

                }
}

- 병렬 프로그래밍 동적

 -> 0.507s 소요

#include <stdio.h>

#define         X_RESN  4000       /* x resolution */
#define         Y_RESN  8000       /* y resolution */
#define         X_MIN   -2.0
#define         X_MAX    2.0
#define         Y_MIN   -2.0
#define         Y_MAX    2.0


typedef struct complextype
{
        float real, imag;
} Compl;


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

        /* Mandlebrot variables */
        int i, j, k;
        Compl   z, c;
        float   lengthsq, temp;
        int maxIterations;
        int res[X_RESN][Y_RESN];

        maxIterations = 1000;
#pragma omp parallel for shared(res,maxIterations) private(i,j,z,c,k,temp,lengthsq) schedule(dynamic,5)
        for(i=0; i < X_RESN; i++)
                for(j=0; j < Y_RESN; j++) {
                        z.real = z.imag = 0.0;
                        c.real = X_MIN + j * (X_MAX - X_MIN)/X_RESN;
                        c.imag = Y_MAX - i * (Y_MAX - Y_MIN)/Y_RESN;
                        k = 0;

                        do  {

                                temp = z.real*z.real - z.imag*z.imag + c.real;
                                z.imag = 2.0*z.real*z.imag + c.imag;
                                z.real = temp;
                                lengthsq = z.real*z.real+z.imag*z.imag;
                                k++;

                        } while (lengthsq < 4.0 && k < maxIterations);

                        if (k >= maxIterations) res[i][j] = 0;
                        else res[i][j] = 1;

                }
}

 

 

 

 

300x250

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

openmp - 25. 테스크 데이터 유효범위와 피보나치  (0) 2020.07.30
openmp - 24. 테스크  (0) 2020.07.30
openmp - 22. ordered, lock  (0) 2020.07.30
openmp - 21. nowait  (0) 2020.07.30
openmp - 20. 작업 분할 지시어들  (0) 2020.07.30
728x90

ordered

- ciritical + 순서대로 수행

- 스레드가 순서대로 수행되는걸 볼수있음

#include <stdio.h>
#include <omp.h>

int main()
{
        int i, a[10];
        omp_set_num_threads(4);
#pragma omp parallel private(i)
{
        #pragma omp for //ordered
        for(i=0; i<10; i++) {
                a[i] = i * 2;
//              #pragma omp ordered
                printf("a[%d] = %d\n", i, a[i]);
        }
}
}

 

 

 

lock

- critical과 동일하나 더 유용하며, 쓰임새가 다양함

- 동기화 영역을 지정 -> set_lock, unset_lock

#include <stdio.h>
#include <omp.h>

int main()
{
        int x = 1;
        omp_lock_t lock;

        omp_init_lock(&lock);

        omp_set_num_threads(4);
#pragma omp parallel
{
        omp_set_lock(&lock);
        x++;
        printf("x = %d\n", x);
        omp_unset_lock(&lock);
} // pragma omp parallel
}

 

 

 

 

300x250

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

openmp - 24. 테스크  (0) 2020.07.30
openmp - 23. 스캐줄링과 만델브로트  (0) 2020.07.30
openmp - 21. nowait  (0) 2020.07.30
openmp - 20. 작업 분할 지시어들  (0) 2020.07.30
openmp - 19. 중첩 스레드  (0) 2020.07.30
728x90

동기화

- nowait

- ordered, lock, flush

 

nowait

- 베리어 기능이 있는 명령어 사용시 작업이 끝날떄까지 기다림 => 시간 낭비 발생

- nowait 구문이 있을시 대기하지 않게함.

 

nowait 사용 예제 1

- 사용 안한경우

 -> 2번이 먼저 들어오나 이후 들어오는 작업들을 대기후, 같이 수행하여 늦게 종료됨

#include <stdio.h>
#include <omp.h>
#define N 20

int main()
{
        int i, a[N];

        omp_set_num_threads(4);
#pragma omp parallel private(i)
{
        if( omp_get_thread_num() != 2 )
                sleep(5);
        #pragma omp for
        for(i=0; i<N; i++) {
                a[i] = i;
                printf("a[%d]=%d tid=%d\n", i, a[i], omp_get_thread_num());
        }
        printf("end %d thread\n", omp_get_thread_num());
} // pragma omp parallel private(i)
}

- 사용한 경우

 2번이 먼저 들어오므로 먼저 마무리하고 나머지 스래드들의 연산 분할

 => 사용안한 경우보다 조금빨리종료

#include <stdio.h>
#include <omp.h>
#define N 20

int main()
{
        int i, a[N];

        omp_set_num_threads(4);
#pragma omp parallel private(i)
{
        if( omp_get_thread_num() != 2 )
                sleep(2);
        #pragma omp for nowait
        for(i=0; i<N; i++) {
                a[i] = i;
                printf("a[%d]=%d tid=%d\n", i, a[i], omp_get_thread_num());
        }
        printf("end %d thread\n", omp_get_thread_num());
} // pragma omp parallel private(i)
}

 

nowait 사용 예제 2 section

- 사용 안한경우

#include <stdio.h>
#include <omp.h>
#define N 4

int main()
{
        int i, tid;
        omp_set_num_threads(4);
#pragma omp parallel private(i, tid)
{
        tid = omp_get_thread_num();
        #pragma omp sections
        {
                #pragma omp section
                {
                        for(i=0; i<N; i++)
                                printf("L1 tid=%d\n", tid);
                }
                #pragma omp section
                {
                        for(i=0; i<N; i++)
                                printf("L2 tid=%d\n", tid);
                        sleep(2);
                }
        }
        printf("end tid=%d\n", tid);
} // pragma omp parallel
}

- 사용한 경우

#include <stdio.h>
#include <omp.h>
#define N 4

int main()
{
        int i, tid;
        omp_set_num_threads(4);
#pragma omp parallel private(i, tid)
{
        tid = omp_get_thread_num();
        #pragma omp sections nowait
        {
                #pragma omp section
                {
                        for(i=0; i<N; i++)
                                printf("L1 tid=%d\n", tid);
                }
                #pragma omp section
                {
                        for(i=0; i<N; i++)
                                printf("L2 tid=%d\n", tid);
                        sleep(2);
                }
        }
        printf("end tid=%d\n", tid);
} // pragma omp parallel
}

300x250
728x90

작업 분할지시어

-do/for : 전체 스래드들에게 일을 분담하여 맡김. 노는 스래드 x

-sections : 스레드 하나씩에게 일 할당. 나머지 스레드는 대기

-single : 하나의 스레드에게만 일시킴. 나머지는 대기

-workshare : fortran 명령어

 

 

 

 

 

section

- 스레드 하나에게 작업을 할당해주는 구문

- 모든 section이 종료될때까지 대기함

- 문제점 : 스레드가 10개가 존재하는데, section이 2개뿐이라면 -> 8개는 쉬고 있음

 

section 예제

#include <stdio.h>
#include <omp.h>

int main()
{
        int i, a[10], b[20];

        omp_set_num_threads(2);
#pragma omp parallel private(i)
{
        #pragma omp sections
        {
                #pragma omp section
                for(i=0; i<10; i++)
                        a[i] = i*10+5;
                #pragma omp section
                for(i=0; i<20; i++)
                        b[i] = i*5+10;
        }
} // pragma omp parallel private(i)

        for(i=0; i<10; i++)
                printf("%d ", a[i]);
        printf("\n");
        for(i=0; i<20; i++)
                printf("%d ", b[i]);
        printf("\n");
}

 

 

 

 

 

 

 

single

- 하나의 스레드만 들어와서 작업

- 먼저 도착하는 스레드가 일함

- 다른 스레드는 싱글에 도착한 스레드가 작업 끝날때까지 대기(베리어)

 

 

single 예제

#include <stdio.h>
#include <omp.h>

int main()
{
        omp_set_num_threads(4);
#pragma omp parallel
{
        #pragma omp single
        {
                printf("hello world\n");
        }
} // pragma omp parallel
}

 

 

 

 

 

 

 

master

- single이랑 동일함

- 마스터 스래드에서만 실행함

- 다른 스레드들은 싱글과 달리 베리어가 없어 넘어감

 

 

master 예제

#include <stdio.h>
#include <omp.h>

int main()
{
        omp_set_num_threads(4);
#pragma omp parallel
{
        #pragma omp master
        {
                sleep(1);
                printf("hello world\n");
        }
        printf("tid = %d\n", omp_get_thread_num());
} // pragma omp parallel
}

 

300x250
728x90

중첩 스레드

- 루프 안에 루프가 나오는경우를 -> 중첩 루프문이라 함

- 스레드 안에 스레드가 생성되는 경우

 => 병렬 구문 안에 다시 병렬 구문 쓰기

 

중첩 스레드문 작성

- omp_set_nested(1); 중첩 스레드 기능 on 

 * 런타임 라이브러리 말고, 환경변수로도 지정가능 OMP_NESTED=TRUE(or 1)

- 중첩 스레드 기능 확인하기 : get_nested() -> 0은 꺼짐, 1은 켜짐

#include <stdio.h>
#include <omp.h>

int main()
{
        int tid;

        omp_set_nested(1);
        omp_set_num_threads(2);
#pragma omp parallel private(tid)
{
        tid = omp_get_thread_num();
        printf("thread id = %d\n", tid );
        if( tid == 1) {
                #pragma omp parallel private(tid)
                {
                        tid = omp_get_thread_num();
                        printf("\t thread id = %d\n", tid );
                }
        }
} // end #pragma omp parallel
}

 

중첩 스레드문 실행 결과

- 스레드 갯수 2개 설정하여 처음 2개 생성

- tid == 1인 경우 스레드 다시 생성 -> 1번 스레드 내부에서 2개 또 생성

- tid == 1 조건이 없는 경우 -> 1번 스레드, 2번 스래드 둘다 내부에서 2개 생성

 

더 많은 중첩 스레드

- 스레드 4개 생성, tid와 level private 처리

- tid가 2번인 경우 중첩 스레드 생성

- 중첩 스래드 내부 tid다시 private

- 이 중첩 스래드들의 조상은 2번 스레드(tid == 2 조건에 의해)

#include <stdio.h>
#include <omp.h>

int main()
{
        int tid, level;

        omp_set_nested(1);
        omp_set_num_threads(4);
#pragma omp parallel private(tid, level)
{
        tid = omp_get_thread_num();
        level = omp_get_level();
        printf("tid = %d level = %d\n", tid, level);
        if( tid == 2) {
                #pragma omp parallel private(tid) num_threads(tid+2)
                {
                        tid = omp_get_thread_num();
                        printf("\ttid = %d ancestor_thread_num(%d)=%d\n", tid, level, omp_get_ancestor_thread_num(level) );
                }
        }
} // end #pragma omp parallel
}

 

 

중첩 스레드문 데이터 범위

1. 스래드 갯수

- 바깥 스레드에서 y, tid만 private, 스래드 갯수는 4개

- 내부 스레드에서 x, tid가 private, 내부 스레드 갯수는 2개

 

2. 중첩 스래드 영역 x, y, z(shared)

- 중첩 스레드 영역 x = 10

- 중첩 스레드 tid = 0일때, 상위에서 y = 12 -> y++ -> y = 13이됨.

- 중첩 스레드 tid = 1일때, y = 13 -> y++ -> y= 14가 됨

- 중첩 스레드 상위에서 z = 22 -> 4개의 스레드가 중첩 스래드 2개씩 생성 총 8개

 => 22 ~ 30까지 z가 상승

 

3. 중첩 스레드 밖, 스래드 안

- z는 shared이므로 30으로 고정

- x = 1 -> x++을 스래드 4개 반복 -> x = 5가 출력

- y = 12 -> 중첩 스레드에서 2번 y++ -> y = 14로 출력

- tid = 0 ~3 까지 x = 5, y = 14, z = 30

 

4. 스래드 밖

- z는 shared로 30

- x는 4번 ++했으므로 5

- y는 스레드 구문에서 private이므로, 초기화 10 그대로

=> x = 5, y = 10, z = 30

 

#include <stdio.h>
#include <omp.h>

int main()
{
        int x=1, y=10, z=20, tid;

        omp_set_nested(1);
        omp_set_num_threads(4);
#pragma omp parallel private(y, tid)
{
        tid = omp_get_thread_num();
        x++;
        y = 12;
        z = 22;
        #pragma omp parallel num_threads(2) private(x,tid)
        {
                tid = omp_get_thread_num();
                x = 10;
                y++;
                z++;
                printf("\t tid=%d x=%d y=%d z=%d\n", tid, x, y, z);
        }
        printf("tid=%d x=%d y=%d z=%d\n", tid, x, y, z);
} // end #pragma omp parallel

        printf("x=%d y=%d z=%d\n", x, y, z);
}

300x250
728x90

병렬 블록 문제

1. 병렬 영역안에 점프문을 쓰면 안됨

2. if(omp_get_thread_num() == 1)로 1번 스레드만 들어올수 있는데 안에 barrier 구문이 존재

 => 나머지 스레드가 들어오지 못함 => 영원히 종료 x

#include <stdio.h>
#include <omp.h>


int main()
{
	omp_set_num_threads(4);
    goto L1;
    
#pragma omp parallel
{
L1:
	if (omp_get_thread_num() == 1)
    	goto L2;
}
L2:
#pragma omp parallel
{
	if(omp_get_thread_num() == 1){
    	#pragma omp barrier
    }
}
}

 

 

 

포크 조인 모델 문제

- 배열 a는 private 처리 됨

- a[0]는 그대로 0으로 남아있음

#include <stdio.h>
#include <omp.h>


int main()
{
    int a[4] = {0}, tid;
    omp_set_num_threads(4);
#pragma omp parallel private(a, tid)
{
    tid = omp_get_thread_num();
    a[tid] = tid;
    printf("a[%d] = %d in %d - th thread\n", tid, a[tid], tid);
    a[0] = 100;
}

    printf("a[0] = %d\n", a[0]);

}

 

동기화 문제

- 서로 다른 크리티컬 구간에서 동일한 변수에 접근하려함

#include <stdio.h>
#include <omp.h>

int main()
{
        int x=1;

        omp_set_num_threads(4);
#pragma omp parallel
{
        #pragma omp critical(n1)
        { x++; }
        #pragma omp critical(n2)
        { x++; }
        #pragma omp atomic
        x++;

        printf("x = %d\n", x);
}
}

 

 

- 서로 다른 임계구간에서 동일 변수 접근을 막도록 임계 구간을 동일한 이름으로 변경

#include <stdio.h>
#include <omp.h>

int main()
{
        int x=1;

        omp_set_num_threads(4);
#pragma omp parallel
{
        #pragma omp critical(n1)
        { x++; }
        #pragma omp critical(n1)
        { x++; }
        #pragma omp atomic
        x++;

        printf("x = %d\n", x);
}
}

300x250

+ Recent posts