SlideShare a Scribd company logo
1 of 89
최윤종
   Advanced! 리눅스 네트워크 시스템 프로그래밍
   김선영 저, 2판
   가메출판사

   책의 8장 스레드 프로그래밍
   무임승차했던 성능 문제
   멀티스레딩과 성능 향상
   병렬 처리 패턴
   스레드 안전
   pthread
   OpenMP 프로그래밍
   성능을 고려한 프로그래밍
   인텔 CPU의 발전
                 80년대 초반    90년대 초반
반도체 미세 공정 능력      0.18㎛          65㎚
트랜지스터 집적 능력      약 9.5M개     약 291M
      클록(㎐)       500㎒           3.2㎓


   무어의 법칙
    ◦ 반도체의 회로 집적도는 2년마다 2배씩 증가

   성능이 떨어지는 코드  하드웨어 교체로 개선
   AMD 4㎓ CPU
    ◦ 매우 많은 전력 소모와 무자비한 발열
   전산업계의 거품 현상
    ◦ 비용 소모(전력 등)는 투자 및 자금 유치로 해결
    ◦ 거품이 빠지면서 공황상태
   Green IT, 모바일 시장의 발전
    ◦ 전력 절감만이 살길
   I7입니다. 내용과 무관합니다
   공정 기술의 향상으로 CPU에 복수 개의 코어 이식
    ◦ CMP(Chip Multi Processor), 내장 그래픽 등




                             I7입니다. 내용과 무관합니다
   성능이 비슷하거나 낮은 여러 개의 코어
    ◦ 병렬 처리, 비동기 처리 기법에 대한 연구 진행
    ◦ 단일 스레드 프로그램에서는 성능 저하 유발




                       I7입니다. 내용과 무관합니다
   책에서는 Thread Building Block 소개가 없습니다
   pthread(POSIX thread)
    ◦ 최신 UNIX 커널은 대부분 지원
    ◦ 윈도우 native 스레드에 비해 성능이 떨어집니다
   OpenMP
    ◦   스레드 기법 몇가지를 단순화
    ◦   C/C++ portran 등 다양한 언어 지원
    ◦   #pragma omp로 직접 함수를 코딩하지 않아도 됩니다
    ◦   전처리기 수준에서 처리하므로 높은 이식성 확보
    ◦   GCC/MSC 지원
   단일 CPU 에서의 처리 방법
         Task #1   Task #2


   멀티코어 CPU에서의 병렬 처리 방법
         Task #1

      Task #2


   단일 CPU에서의 동시 처리 방법
                             Task #1


                             Task #2
   Latency
    ◦ 요청 후 실제 응답이 오기까지 걸리는 대기 시간
    ◦ CPU가 다른 장치에 비해 매우 빠르므로 생기는 시간


   Latency 중 CPU에서 다른 스레드의 작업을 처리
    ◦ I/O를 비동기로 처리하므로 Latency Hiding 가능

                            I/O Response
                            & processing
               wait              wait


              I/O Request
   프로그램의 성능 향상을 위한 I/O 및 저장장치 접
    근 최소화를 위한 두가지 방법

   Multi Thread
    ◦ 프로세스 내부 처리 구조를 Multi Process처럼 분업화
    ◦ 스레드 간 통신에 따른 비용 소모가 거의 없음
    ◦ 스레드 간 동기화 처리 비용 소모
   Multi Process
    ◦ 동기적 프로그래밍 모델
    ◦ 보호되는 자원(메모리, 장치 등)
    ◦ 프로세스간 통신에 따른 비용 소모(IPC 등)
   Multi Process
                       Process          Process

                     copy                   copy
                                  IPC




   Multi Thread    process

                       Thread           Thread



                                 Data
   멀티 스레딩은 최후의 보루입니다
    ◦ 개발, 테스트, 디버깅이 복잡해집니다
    ◦ 설계나 개발 단계에서 예측하지 못한 상황에 빠질 가능성
      이 있습니다
    ◦ “프로그래머가 관찰을 위해 개입하는 순간, 비결정적인
      결과를 나타내어 버그가 사라지는 현상”
   고려 사항
    ◦ I/O 측면에서 병목(bottleneck)이 제거된 상태인가?
    ◦ 멀티 스레드 도입 전의 코드는 다른 최적화 방법을 적용
      해 보았는가?
    ◦ 멀티 스레드 도입 전의 시스템에 가용할 수 있는 CPU나
      관련 유휴 자원은 충분한가?
    ◦ 효율을 극대화하려면 스레드의 숫자를 어떻게 결정해야
      하는가?
   대분류에 속하는 패턴입니다

   태스크 분해(Task Decomposition)
    ◦ 작업의 단위나 순서의 흐름이 중요한 경우

   데이터 분해(Data Decomposition)
    ◦ 작업할 데이터의 형태나 크기가 중요한 경우
   처리해야 하는 데이터나 행위가 매번 달라지거나,
    연속적인 흐름을 띄는 경우에 적합
   콜백, 트리/파면 분기, 파이프라인 등
    ◦ 웹 브라우저에 적용


   병렬 처리를 위해 분해된 태스크들을 스레드가 실
    행하는 형태
    ◦ 규모에 따라 태스크 하나에 하위 스레드 여러 개 할당
    ◦ 선후관계/의존성에 따른 동기화 처리 요구(배리어 등)
   트리 구조의 태스크
                            Task

           Task             Task               Task

                                               Task
                            Task
                                               Task


   파이프라인 구조의 태스크
    Data      Data Data            Data Data          Data Data   Data

                  Task #1            Task #2            Task #3
   동일하거나 비슷한 작업을 하는 복수의 태스크 생성
   데이터 인코딩/디코딩, 대규모 계산 등에 사용
    ◦ 압축, 이미지 프로세싱, 행렬 계산 등
   적절한 부하 분산(Load Balancing) 요구
    ◦ 데이터를 적절한 단위(chunk)로 분할하여 작업 할당

                                             load      thread   thread
                                           balancing
                           chunk   chunk               chunk    chunk
           decomposition   chunk   chunk               chunk    chunk
    Data                   chunk   chunk
                           chunk   chunk
                                                       thread   thread
                                                       chunk    chunk
                                                       chunk    chunk
   병렬 처리에 루프를 주로 사용하는 경우 데이터 분
    해 방식 적합
   분기 혹은 데이터 부분 가공인 경우 태스크 분해
    방식 적합
   필요에 따라 복합적으로 사용합니다
                                       로컬 임시파일/결과 복사
                         partitioner      file 1-1
                               map
                                1         file 1-2
               block 1                                    reduce 1
                                          file 2-1
    대용량 데이터    block 2
                               map
                                2         file 2-2
    분석 프레임워크   block 3
                               map        file 3-1                   output 1
                                                       병합/정렬
    맵리듀스 구조
                                3         file 3-2
               block 4                    file 4-1
                               map                        reduce 2
                                4         file 4-2
               block 5
                               map        file 5-1
                                5                                    output 2
                                          file 5-2
   스레드에서 사용해도 안전한 코드의 총칭
    ◦ 스레드에서 사용해도 안전하게 수행되는 코드
    ◦ 주로 함수에 대해 안전한지 판단합니다


   UNIX 계열에서는 스레드 안전에 대해 상세 분류
    ◦ 재진입, 병렬 처리, 시그널 처리에 대한 안전 여부 등
    ◦ 스레드 안전 개념의 혼란 초래


   유닉스 표준(SUSv4)에서 용어 가지치기 단행
    ◦ 용어와 개념, 그리고 잔재들을 소개하는 절입니다
   static char buf_sum[16]; 이 함정




                        지역 변수로 만들어 해결하면 되지만 예제이므로
                        상황을 복잡하게 만듭니다
thread 1
           sum_strnum()




thread 2
                      sum_strnum()
   뮤텍스를 통한 스레드 안전 시도  실패
    WHY?
T0        T1   T2      T3    T4       T5      T6    T7       T8      T9
                                   unlock
    thread 1   lock
                                     &
                      sum_strnum()
                                switching
                                                                  sum_strnum()


                                                                   unlock
    thread 2                           lock
                                                                      &
                                  wait…       sum_strnum()
                                                                  switching
   병렬 실행을 보장하도록 작성된 형태를 취햐여 스
    레드 안전을 획득한 경우
   같은 프로세스 내에서 재귀 호출되어도 문제 없음
   재진입성이 없는 표준 함수들
    ◦ strtok, ctime, gethostbyname, rand, srand, …
    ◦ _r로 끝나는 함수는 안전합니다(UNIX)
   최신 유닉스 표준(SUSv4)에서 재진입성은 스레드
    안전에 포함되는 개념으로 편입시켜 정의
   재진입은 정적 객체를 사용하는 경우나 극히 제한
    적인 코드에만 적용 가능
   전역 변수의 경우 뮤텍스를 통해 스레드 안전 확보

   공유 자원에 락을 걸면 안됩니다
    ◦ 네트워크, 파일 입출력 등
    ◦ 부분 입출력 후 스위칭되는 경우 기아 유발
    ◦ Isolated I/O 사용(IOCP 등)
worker
thread       뮤텍스로 보호되는 구간
worker
thread                          output
                   큐                     network
worker   send 등록       send     thread
thread                 작업 꺼내기

worker
thread
   함수 실행 중 시그널에 의한 인터럽트 발생 
    EINTER 오류 반환(Error Interrupt)
    ◦ 멀티스레드 환경에서 lock 함수 호출 도중 시그널 발생 등
    ◦ 세마포어 lock 시도  시그널 안전하지 않음
    ◦ 세마포어 unlock 시도  시그널 안전
   스레드 취소 함수(pthread_cancel)시 수행중인 함
    수가 정상 종료하는 경우 비동기 취소 안전
   저수준 입출력(read, write)는 버퍼(PIPE_BUF)보다
    입출력이 작은 경우 실행 보장
   sig_atomic_t 정수형 변수의 접근 보장
   대부분의 함수는 원자적 실행을 보장하지 않습니다
   입출력 구간을 나누어 스레드마다 구간 입출력
   write()  pwrite() 사용
   POSIX Realtime Extension의 AIO 사용
   pthread는 전통적인 API 스펙이므로 한번 익혀두
    면 오랫동안 별 탈 없이 사용할 수 있습니다
   기능별 세분화가 잘 되어있음
    ◦ 복잡합니다
   오류 처리 방법
    ◦ 성공시 0 반환, 실패시 오류 코드 반환
    ◦ errono 전역변수 공유 회피
   시그널 처리에 의해 인터럽트되지 않습니다
    ◦ 비동기 시그널 함수는 인터럽트 됩니다
   Windows Native thread와 비슷합니다
    pthread_create         스레드 생성
    pthread_exit           스레드 종료
    pthread_join           스레드를 프로세스에 병합
    pthread_detach         스레드를 프로세스에서 분리
    pthread_cancel         스레드 취소
   pthread_create(pthread_t *restrict_thread,
    const pthread_attr_t *restrict_attr, void
    *(*start_routine)(void *), void *restrict_arg);
   pthread_join/pthread_detach
    ◦ join은 스레드 대기, detach는 스레드 제어 포기
   pthread_exit의 반환 주소는 스레드 스택에 두면
    안됩니다
    ◦ 스레드 스택이 파괴되면 반환 주소가 날아가면서
      pthread_join으로 대기할 수 없습니다
   pthread_cancel은 강제 종료가 아닙니다
    ◦ 스레드 중지 요청(deferred cancel, 지연된 취소)
    ◦ 스레드는 특정 지점마다 중지 요청이 있는지 확인 후 중지
    ◦ 공유 메모리, 자원 등 누수 가능성 존재
   pthread_mutex_timedlock
    ◦ lock + 타임아웃
    ◦ 타임아웃 시간 이후 오류를 반환합니다
   Win32의 그것과 매우 흡사합니다
    ◦ waitfor- 함수 대신 lock & unlock 함수 사용
    ◦ try, timeout 함수 제공
    ◦ 객체의 생성, 뮤텍스 획득, 해제, 파괴 함수 제공
   뮤텍스 속성
    ◦ pthread_mutexattr_settype(*attr, type)
                          normal     errcheck   recursive
                                                재귀 잠금 허
    중복 잠금                 교착 상태      오류 반환
                                                용(횟수 적용)
                                     오류 반환      오류 반환
    소유권이 없는 잠금 해제 시도 undefined
                                     (EPERM)    (EPERM)
                                     오류 반환      오류 반환
    풀린 뮤텍스에 잠금 해제 시도 undefined
                                     (EPERM)    (EPERM)
    성능                    빠름         약간 느림      약간 느림
   스레드가 특정 조건을 만족할 때까지 대기
                                                         thread B
                                         lock mutex
            item 준비
thread A                       뮤텍스
                               영역          큐 확인
            lock mutex
                                          yes            no
                                         조건 변수 블록
            item 큐잉                조건   (unlock mutex)
                                   변수
                                   영역   조건 변수에서 깨어남
           unlock mutex                   (lock mutex)

            thread B에     signal         item 디큐잉
            시그널 전송         전송

                                        unlock mutex
   조건 변수에 의해 대기하는 경우 뮤텍스 해제
    ◦ 기아 방지
   조건 변수에서 깨어나는 경우 즉시 조건 검사를 해
    야 합니다
    ◦ 복수의 스레드가 깨어나는 경우 경쟁 상태 유발
   조건 변수 관련 함수 & 매크로
    pthread_cond_init          조건 변수 초기화
    pthread_cond_wait          조건 변수 대기
    pthread_cond_timedwait     대기후 타임아웃 지정
                               (지정 시간 후 오류 반환)
    pthread_cond_signal        스레드 하나를 깨움
    pthread_cond_broadcast     스레드 집합을 깨움
    pthread_cond_destroy       조건 변수 파괴
    PTHREAD_COND_INITIALIZER   선언 및 초기화에 사용하는 매크로
   뮤텍스와 조건 변수는 공유 메모리에 둡니다
   프로세스 공유 속성 함수
pthread_mutexattr_setpshared   뮤텍스 속성에 프로세스 공유 기능 설정
pthread_mutexattr_getpshared   뮤텍스 속성의 프로세스 공유 기능 반환
pthread_condattr_setpshared    조건 변수 속성에 프로세스 공유 기능 설정
pthread_condattr_getpshared    조건 변수 속성의 프로세스 공유 기능 반환

   매개변수
    ◦ pthread_mutexattr_t : 뮤텍스 속성
    ◦ pthread_condattr_t : 조건 변수 속성
    ◦ int pshared : PTHREAD_PROCESS_SHARED,
                    PTHREAD_PROCESS_PRIVATE
   스레드들이 특정 코드 지점에 모일 때까지 대기
   POSIX.1003.2-2001에 추가됨
    ◦ _XOPEN_SOURCE 매크로가 600 이상이면 됩니다
   배리어 함수들
                              배리어 객체 초기화
pthread_barrier_init(count)
                              (count만큼 wait 호출 전까지 스레드 대기)
pthread_barrier_destroy       배리어 객체 파괴
pthread_barrier_wait          다른 스레드 도착 대기
pthread_barrierattr_init      배리어 속성 객체 초기화
pthread_barrierattr_destroy   배리어 속성 객체 파괴
pthread_barrierattr_getpshared 배리어 공유 속성 확인
pthread_barrierattr_setpsahred 배리어 공유 속성 설정
   문맥 교환(context switching) 최소화
   바쁜 대기(busy wait)를 수행합니다
    ◦ 대기시간이 길어질수록 효율이 떨어집니다
   스핀락 함수들
pthread_spin_init      스핀락 객체 초기화
pthread_spin_destroy   스핀락 객체 파괴
pthread_spin_lock      스핀락 획득
pthread_spin_trylock   스핀락 획득 시도, 실패시 오류 반환(EBUSY)
pthread_spin_unlock    스핀락 해제
   공유 자원에 여러 스레드가 효율적으로 접근
   reader-lock이 걸린 경우 writer-lock은 잠깁니다
   위의 함수 원형들과 형태가 비슷합니다
    ◦ pthread_rwlock_init / destroy
    ◦ rwlock_rdlock / wrlock
    ◦ try__lock, timed__lock
   프로세스 공유 속성은 지원하지 않습니다
   Win32의 그것과 비슷합니다
   GCC에서는 __thread 예약어 제공
   스레드 안전한 함수를 작성할 때 유용합니다
   int pthread_key_create(pthread_key_t *key, void
    (*destructor)(void *));
    ◦ 파괴자 함수를 직접 지정할 수 있습니다
   기타
    ◦ pthread_key_delete(key)
    ◦ pthread_setspecific(key, value)
    ◦ value pthread_getspecific(key)
   Win32 뮤텍스의 WAIT_ABANDONED_0
    ◦ 뮤텍스가 잠긴 채 스레드가 죽었습니다
    ◦ pthread에서는 EOWNERDEAD 오류 반환
   잠긴 뮤텍스를 자동으로 다른 스레드가 받음
    ◦ pthread_mutexattr_(set/get)robust(attr, int robust)
    ◦ robust 값
      PTHREAD_MUTEX_STALLED : 교착 상태
      PTHREAD_MUTEX_ROBUST : 다른 스레드가 뮤텍스를 받음
    ◦ 뮤텍스를 받은 스레드는 뮤텍스 인계 함수 호출
      pthread_mutex_consistent
      처리하지 않는 경우 lock 함수 실패, ENOTRECOVERABLE
       반환
   WndProc이 아닙니다
   스레드 종료 / fork() 호출 등 예외 이벤트 처리용
    ◦ fork() 이전에 비동기 작업을 정지하거나 제거
   스레드 클린업 핸들러
    ◦ 스레드가 종료될 때 실행하는 함수 등록
    ◦ atexit() 함수의 스레드 버전
    ◦ 핸들러에 등록된 이벤트는 스택처럼 쌓입니다
      pthread_cleanup_push(routine, arg)
      pthread_cleanup_pop(n) : 0 or ~0
      ~0이면 클린업 핸들러 실행 후 제거, 0이면 바로 제거
   스레드 fork 핸들러
    ◦ pthread_atfork(prepair, parent, child)
      prepair는 fork() 이전에 실행할 함수
      parent는 fork() 호출 이후 부모 프로세스가 실행할 함수
      child는 fork() 호출 이후 자식 프로세스가 실행할 함수
    ◦ fork()를 호출하는 스레드만 복제됩니다
      다른 스레드는 복제되지 않습니다
      복잡해지므로 fork()를 사용하지 않는 것을 권장합니다
   간단한 지시어를 사용하여 멀티스레딩을 적용할 수
    있는 기법
   이식성이 높고 학습 용이
   코드 수정을 최소화하고 멀티스레딩 적용 시간 단축
   짧은 역사(1996~)
   다양한 언어(C/C++, Fortran 등) 지원
   #define _OPENMP 매크로 정의됨
   OpenMP 3.0 코드는 실행이 불가능합니다
    ◦ visual studio 2012에서 OpenMP 3.0을 지원하지 않습
      니다
    ◦ Intel Parallel Studio 설치시 지원 가능합니다($1,599)
    ◦ 해봤더니 안됩니다 ㅠㅠ
   전처리기 지시어 이하 문장(혹은 블록)을 여러
    스레드로 처리합니다
   기본 OMP 스레드 수 == CPU 수
   #pragma omp … num_threads(n)
    ◦ 한번 적용
   omp_set_num_threads(n)
    ◦ 함수입니다
    ◦ 호출 이후 OpenMP 스레드를 자동으로 n만큼 만듭니다
loop 모델       루프 작업을 분할하여 병렬 처리
                           직렬 코드 블록들을 몇 개의 구간으로 분할
            sections 모델
워크 쉐어링 구조                  하여 병렬 처리
                           병렬 처리되는 구간회서 1회성 실행 구간
             single 모델
                           설정
 태스크 구조     task 모델(3.0)   태스크 단위 작업을 처리하는 스레드 생성
   OpenMP 병렬 구간에서 변수의 공유 설정
                 private(list)   list에 지정된 변수를 TLS에 생성

    사설(private) firstprivate(list) list를 main 스레드의 초기화값으로 초
      속성                           기화
                                   마지막 스레드의 해당 변수 값을 main
                lastprivate(list)
                                   스레드에 반영
                                 명시적으로 모든 스레드가 공유하는 변
     공유 속성       shared(list)
                                 수로 선언
                                 value : shared, none
     기본 설정      default(value)   변수의 공유 설정 기본값, parallel 병
                                 렬 구간이 시작할 때 설정
   reduction(operand:var)
    ◦ var 값에 operand 연산자 수행
    ◦ 내부에서 묵시적으로 private 지시어 수행
      default가 none일 경우 명시적으로 shared로 선언
   reduction 연산
    연산자        초기값           연산자      초기값
     +          0             &        ~0
     *          1             |        0
     -          0            &&        1
     ^          0             ||       0
    max    표현 가능한 최소값        min   표현 가능한 최대값
   루프는 반복 횟수가 정해져 있어야 함
   #pragma omp parallel 이후 문장부터 스레드 생
    성
   for문 반복 횟수 == 분할 개수 * 스레드 수
   모든 스레드가 완료할 때까지 대기(묵시적 배리어)
   #pragma 두 줄
    ◦ 합쳐서 기술 가능
    ◦ #… parallel for
   omp_get_thread_num()
    ◦ 스레드 번호 반환
main()

#pragma omp parallel

    #pragma omp for


i   =   0            i   =   4
i   =   1            i   =   5
i   =   2            i   =   6
i   =   3            i   =   7


/* implicit barrier */
   남는 스레드가 밀린 작업을 하도록 작업 할당

schedule(static [, n])    라운드 로빈 방식으로 순서대로 n개씩 할당. n
                          생략시 1
schedule(dynamic [, n])   한가한 스레드에게 n개씩 할당. n 생략시 1
schedule(guided [, n])    dynamic과 동일하게 한가한 슬데ㅡ에게 할당
                          하지만 chunk의 크기가 다름. 할당되는 chunk
                          크기는 큰 수에서 n까지 줄여나감. n 생략시 1
schedule(auto)            임플리먼테이션이 자동으로 판단
schedule(runtime)         실행시 ICV 환경 변수에 의해 결정
   dynamic 스케줄링은 개별 작업의 수행 시간이 균
    일하지 못할 때 좀 더 빨리 작업을 끝낸 스레드에
    게 새로운 chunk 할당
   static, dynamic 스케줄링은 chunk 크기가 작은
    경우 오버헤드 유발
   guided는 chunk 크기를 점점 줄여 나가며 할당
    ◦ 전체적으로 스케줄링 횟수가 줄어듦
   runtime에 쓰이는 OpenMP 내부 제어 변수
    (OpenMP ICV)은 환경 설정 변수나 함수 호출로
    설정 가능
   스레드 작업 순서를 정렬하여 결과를 순서대로 작
    성
   직렬화/동기화 기법을 직접 구현하는 것보다 성능
    향상
   코드의 특정 구간을 다수의 섹션으로 분할하여 병
    렬 처리하는 태스크 방식
               main()

     #pragma omp parallel

     #pragma omp sections



     section            section
       #1                 #2



      /* implicit barrier */
   임의의 섹션을 임의의 스레드가 수행
    ◦ 수행 순서는 보장되지 않음
   변수 공유 및 환원 가능
   single 블록은 한번만 수행
   스레드 중 가장 먼저 진입하는 스레드가 수행
    ◦ 나머지 스레드들은 single 작업이 끝날 때 까지 대기
   주로 초기화 작업 등에 사용
                 main()

       #pragma omp parallel

      single

       /* implicit barrier */
      parallel            parallel
        #1                  #1

       /* implicit barrier */
   특정 작업 단위로 분할된구간을 스레드에게 할당
   임의의 구간을 임의의 스레드가 수행
   루프의 개수, 중첩 여부, 재귀 여부에 관계없이 활
    용 가능

                           task   thread
                           code     #1


      task   task   task   task   thread
      code   code   code   code     #2


                           task   thread
                           code     #n
   현재 스레드(주로 메인 스레드)가 작업 코드에 해
    당하는 구간을 스레드에게 분배
   if
    ◦ 스레드가 작업을 분배할 조건을 설정
    ◦ 특정 시점부터 분배를 시작하게 할 수 있습니다
    ◦ #pragma omp ~ if(exp)
   untied
    ◦ 스레드가 정지 후 재시작(suspeded  resume)될 때 다
      른 스레드가 작업을 이어 받도록 설정
    ◦ tied인 경우 재시작 이후에도 같은 스레드가 작업(기본값)
   배리어, 크리티컬 섹션, 원자적 실행, OpenMP
    lock 제공
   크리티컬 섹션은 Win32의 그것과 다를 수 있음
   OpenMP lock은 뮤텍스와 유사
   parallel, for, sections, single의 끝에는 묵시적
    배리어가 존재
   명시적 배리어
    ◦ #pragma omp barrier
    ◦ #pragma omp taskwait
      자식 task 대기                  조건문과 결합하는 경우
   묵시적 배리어 제거
    ◦ #pragma omp ~ nowait
    ◦ loop, sections, single에 사용
   #pragma omp critical [name]
    ◦ name을 생략하면 이름이 없는 것으로 간주
   #pragma omp atomic [read | write | update |
    capture]
    ◦ 생략시 update로 간주
   atomic 형식 분류(x : 대상)
    read      v = x;                             v는 TLS 변수
    write     x = exp;                           exp는 보호되지 않음
              x++;
                                                 대상이 변하면서 읽어야 하는 경우
              x--;
                                                 사용
    update    ++x;
              --x;
                                                 축약 대입 연산 가능
              x binary_operator = exp;
              v   =   x++;
              v   =   x--;                       update + read
    capture   v   =   ++x;                       공유 데이터를 변경하고 값을 읽어야
              v   =   --x;                       하는 다수의 작업에 적합
              v   =   x binary_operator = exp;
   커널 객체(≒뮤텍스) 처럼 사용합니다
   omp_lock_t
    ◦ 범용 lock
   omp_nest_lock_t
    ◦ 중첩 가능한 lock
   lock 관련 함수들
omp_init_lock         초기화
omp_destroy_lock      객체 파괴
omp_set_lcok          lock 획득
omp_unset_lcok        lock 해제
omp_test_lcok         lock 획득 시도(0 == 실패)
   master 스레드에서 동작하는 코드 지정
   묵시적 배리어, private 변수가 없습니다
                 main()

      #pragma omp parallel

      #pragma omp sections

      master


      parallel            parallel
        #1                  #2

       /* implicit barrier */
   행렬 곱(2x2)을 어떻게 구하시나요?
    ◦ a₁₁ * a₁₁ + a₁₂ * a₂₁   a₁₁ * a₁₂ + a₁₂ * a₂₂
    ◦ a₂₁ * a₁₂ + a₂₂ * a₂₁   a₂₁ * a₁₂ + a₂₂ * a₂₂


   중첩된 루프의 경우 가장 바깥 루프를 기준으로 병
    렬화
    ◦ 코어수 보다 분할횟수가 적은 경우 나머지 스레드는 돌지
      않습니다
    ◦ for(i=0; i < 3; ++i)  쿼드코어에서 4번째 스레드 X
   omp_set_nedsted(0 or ~0)
    ◦ TRUE / FALSE로 중첩 기능을 설정합니다
    ◦ OMP_NESTED 환경 변수로도 설정 가능합니다
   collapse(n)
    ◦ 중첩된 n단계 루프를 풀어버립니다
    ◦ OpenMP 3.0 이상에서 지원
   #pragma omp threadprivate(list)
    ◦ 리스트에 있는 변수를 TLS 변수로 선언
    ◦ 원본 변수는 정적 변수
    ◦ 예제는 길어서 생략합니다
   TLS 변수의 복사
    ◦ 원본은 마스터 스레드
    ◦ TLS 변수 중 일부만 복사 가능
    ◦ #pragma omp parallel copyin(list)
      병렬 구간이 시작될 때 TLS 변수 복사
    ◦ #pragma omp single copyprivate(list)
      single 코드 블록이 끝나면서 TLS 변수 복사
   Internal Control Variable의 약자입니다
   스레드 개수 관련 ICV
                                    생성할 스레드의 개수 설정
환경 변수      OMP_NUM_THREADS=n[, …]
                                    중첩 단계별로 „,‟로 구분
           omp_set_num_threads(n)   생성할 스레드의 개수 설정
           omp_get_num_threads()    현재 스레드 개수 제한
함수
           omp_get_max_threads()    현재 최대 스레드 개수 제한
           omp_get_team_size()      중첩 단계
   중첩 관련 ICV
환경 변수    OMP_NESTED               value : true or false
         omp_set_nested(value)    value : 0 or ~0
함수       omp_get_nested()         0 or ~0 반환
         omp_get_level            현재 병렬화 중첩 단계 반환


   스케줄링 관련 ICV (스케줄링 방법이 runtime인
    경우)
         OMP_SCHEDULE=type [,     type : static, dynamic,
환경 변수
         chunk]                   guided, auto
         omp_set_schedule(omp_sch kind : 스케줄 방법
함수       ed_t kind, int modifier) modifier : chunk 개수
         int omp_get_schedule()   현재 스케줄링 방법
schedule(static [, n])    라운드 로빈 방식으로 순서대로 n개씩 할당. n
                          생략시 1
schedule(dynamic [, n])   한가한 스레드에게 n개씩 할당. n 생략시 1
schedule(guided [, n])    dynamic과 동일하게 한가한 슬데ㅡ에게 할당
                          하지만 chunk의 크기가 다름. 할당되는 chunk
                          크기는 큰 수에서 n까지 줄여나감. n 생략시 1
schedule(auto)            임플리먼테이션이 자동으로 판단
schedule(runtime)         실행시 ICV 환경 변수에 의해 결정
   동적 조정 관련 ICV (실행 중 스레드 개수 조정)
환경 변수    OMP_DYNAMIC=value        value : true or false

         omp_set_dynamic(value)   value : 0 or ~0
함수
         omp_get_dynamic()        동적 조정 여부 반환


   기타
                                  과거 특정 시점부터 흐른 시
         double omp_get_wtime()
함수                                간(time처럼 쓰입니다)
         double omp_get_wtick()   ↑의 정밀도(단위) 반환


   omp_get_wtime()은 부팅 이후도 반환할 수 있음
parallel   for   sections   single   task
  private         ●       ●        ●         ●       ●
firstprivate      ●       ●        ●         ●       ●
 lastprivate              ●        ●
  shared          ●                                  ●
  default         ●                                  ●
 reduction        ●       ●        ●                 ●
   copyin         ●
copyprivate                                  ●
 schedule                 ●
  ordered                 ●
  nowait                  ●        ●         ●
   untied                                            ●
     if           ●
  collapse                ●
num_threads       ●
   64byte를 캐시에서 읽어들이면서 생기는 공유 문제
     ◦ 수정할 때마다 상대방 CPU 캐시 무효화 요청

   CPU 0                          CPU 1
 (thread 1)                     (thread 2)

              int cnt_sheep[]
[0] [1] [2] [3]              [0] [1] [2] [3]

     cache                        cache
     access                       access

                  invalid
       64 byte                      64 byte
                   invalid
   가짜 공유에 의한 성능 저하
   컴파일러 단계에서 BSS 최적화 수행
   패딩 비트를 설계합니다
    ◦ 컴파일러에게 맡겨버리는 방법(GCC)
   전역 변수, 힙, 공유 메모리를 지양합니다
    ◦ 전역 변수를 TLS에 복사하거나 합니다
    ◦ 병렬 구간에서 chunk 크기를 조절합니다
   pipeline 모델에서는 chunk 크기를 동적으로 조절
    하게 합니다

More Related Content

What's hot

[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현NAVER D2
 
Concurrency in action - chapter 7
Concurrency in action - chapter 7Concurrency in action - chapter 7
Concurrency in action - chapter 7JinWoo Lee
 
242 naver-2
242 naver-2242 naver-2
242 naver-2NAVER D2
 
안드로이드 멀티스레딩 입문 송형주
안드로이드 멀티스레딩 입문 송형주안드로이드 멀티스레딩 입문 송형주
안드로이드 멀티스레딩 입문 송형주iamhjoo (송형주)
 
Concurrency in action - chapter 5
Concurrency in action - chapter 5Concurrency in action - chapter 5
Concurrency in action - chapter 5JinWoo Lee
 
LockFree Algorithm
LockFree AlgorithmLockFree Algorithm
LockFree AlgorithmMerry Merry
 
(2013 DEVIEW) 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
(2013 DEVIEW) 멀티쓰레드 프로그래밍이  왜이리 힘드나요? (2013 DEVIEW) 멀티쓰레드 프로그래밍이  왜이리 힘드나요?
(2013 DEVIEW) 멀티쓰레드 프로그래밍이 왜이리 힘드나요? 내훈 정
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화sung ki choi
 
Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10hyun soomyung
 
11_웹서비스활용
11_웹서비스활용11_웹서비스활용
11_웹서비스활용noerror
 
android_thread
android_threadandroid_thread
android_threadhandfoot
 
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기Daehee Kim
 
Free rtos seminar
Free rtos seminarFree rtos seminar
Free rtos seminarCho Daniel
 
07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도ssuser3fb17c
 
[160402_데브루키_박민근] UniRx 소개
[160402_데브루키_박민근] UniRx 소개[160402_데브루키_박민근] UniRx 소개
[160402_데브루키_박민근] UniRx 소개MinGeun Park
 
windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. JobHyosung Jeon
 
Multithread design pattern
Multithread design patternMultithread design pattern
Multithread design pattern종빈 오
 
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http RequestNAVER D2
 
Go lang(goroutine, channel, 동기화 객체)
Go lang(goroutine, channel, 동기화 객체)Go lang(goroutine, channel, 동기화 객체)
Go lang(goroutine, channel, 동기화 객체)seungkyu park
 

What's hot (20)

[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
[2D7]레기온즈로 살펴보는 확장 가능한 게임서버의 구현
 
Concurrency in action - chapter 7
Concurrency in action - chapter 7Concurrency in action - chapter 7
Concurrency in action - chapter 7
 
242 naver-2
242 naver-2242 naver-2
242 naver-2
 
Ndc12 2
Ndc12 2Ndc12 2
Ndc12 2
 
안드로이드 멀티스레딩 입문 송형주
안드로이드 멀티스레딩 입문 송형주안드로이드 멀티스레딩 입문 송형주
안드로이드 멀티스레딩 입문 송형주
 
Concurrency in action - chapter 5
Concurrency in action - chapter 5Concurrency in action - chapter 5
Concurrency in action - chapter 5
 
LockFree Algorithm
LockFree AlgorithmLockFree Algorithm
LockFree Algorithm
 
(2013 DEVIEW) 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
(2013 DEVIEW) 멀티쓰레드 프로그래밍이  왜이리 힘드나요? (2013 DEVIEW) 멀티쓰레드 프로그래밍이  왜이리 힘드나요?
(2013 DEVIEW) 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
 
Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10
 
11_웹서비스활용
11_웹서비스활용11_웹서비스활용
11_웹서비스활용
 
android_thread
android_threadandroid_thread
android_thread
 
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
 
Free rtos seminar
Free rtos seminarFree rtos seminar
Free rtos seminar
 
07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도
 
[160402_데브루키_박민근] UniRx 소개
[160402_데브루키_박민근] UniRx 소개[160402_데브루키_박민근] UniRx 소개
[160402_데브루키_박민근] UniRx 소개
 
windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. Job
 
Multithread design pattern
Multithread design patternMultithread design pattern
Multithread design pattern
 
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request
[D2 CAMPUS] 안드로이드 오픈소스 스터디자료 - Http Request
 
Go lang(goroutine, channel, 동기화 객체)
Go lang(goroutine, channel, 동기화 객체)Go lang(goroutine, channel, 동기화 객체)
Go lang(goroutine, channel, 동기화 객체)
 

Similar to Thread programming

파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍Yong Joon Moon
 
서버 아키텍처 이해를 위한 프로세스와 쓰레드
서버 아키텍처 이해를 위한 프로세스와 쓰레드서버 아키텍처 이해를 위한 프로세스와 쓰레드
서버 아키텍처 이해를 위한 프로세스와 쓰레드KwangSeob Jeong
 
쓰레드.pdf
쓰레드.pdf쓰레드.pdf
쓰레드.pdfSeokju Hong
 
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arcNAVER D2
 
Introduction to Parallel Programming
Introduction to Parallel ProgrammingIntroduction to Parallel Programming
Introduction to Parallel ProgrammingUNIST
 
Linux programming study
Linux programming studyLinux programming study
Linux programming studyYunseok Lee
 
스톰 접근 중
스톰 접근 중스톰 접근 중
스톰 접근 중June Yi
 
Concurrent programming
Concurrent programmingConcurrent programming
Concurrent programmingByeongsu Kang
 
Multithread pattern 소개
Multithread pattern 소개Multithread pattern 소개
Multithread pattern 소개Sunghyouk Bae
 
스레드
스레드스레드
스레드xxbdxx
 
Cloud datacenter network architecture (2014)
Cloud datacenter network architecture (2014)Cloud datacenter network architecture (2014)
Cloud datacenter network architecture (2014)Gasida Seo
 
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스NAVER D2
 
Implementing remote procedure calls rev2
Implementing remote procedure calls rev2Implementing remote procedure calls rev2
Implementing remote procedure calls rev2Sung-jae Park
 
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013devCAT Studio, NEXON
 
R2서버정진욱
R2서버정진욱R2서버정진욱
R2서버정진욱jungjinwouk
 
리눅스 커널 기초 태스크관리
리눅스 커널 기초 태스크관리리눅스 커널 기초 태스크관리
리눅스 커널 기초 태스크관리Seungyong Lee
 
UNIX 시스템 2014-2018년 기말시험 기출문제
UNIX 시스템 2014-2018년 기말시험 기출문제UNIX 시스템 2014-2018년 기말시험 기출문제
UNIX 시스템 2014-2018년 기말시험 기출문제Lee Sang-Ho
 
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)내훈 정
 
Linux Performan tuning Part I
Linux Performan tuning Part ILinux Performan tuning Part I
Linux Performan tuning Part Isprdd
 

Similar to Thread programming (20)

파이썬 병렬프로그래밍
파이썬 병렬프로그래밍파이썬 병렬프로그래밍
파이썬 병렬프로그래밍
 
서버 아키텍처 이해를 위한 프로세스와 쓰레드
서버 아키텍처 이해를 위한 프로세스와 쓰레드서버 아키텍처 이해를 위한 프로세스와 쓰레드
서버 아키텍처 이해를 위한 프로세스와 쓰레드
 
쓰레드.pdf
쓰레드.pdf쓰레드.pdf
쓰레드.pdf
 
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc
3.[d2 오픈세미나]분산시스템 개발 및 교훈 n base arc
 
Introduction to Parallel Programming
Introduction to Parallel ProgrammingIntroduction to Parallel Programming
Introduction to Parallel Programming
 
Linux programming study
Linux programming studyLinux programming study
Linux programming study
 
스톰 접근 중
스톰 접근 중스톰 접근 중
스톰 접근 중
 
Concurrent programming
Concurrent programmingConcurrent programming
Concurrent programming
 
Multithread pattern 소개
Multithread pattern 소개Multithread pattern 소개
Multithread pattern 소개
 
스레드
스레드스레드
스레드
 
Cloud datacenter network architecture (2014)
Cloud datacenter network architecture (2014)Cloud datacenter network architecture (2014)
Cloud datacenter network architecture (2014)
 
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스[232] 수퍼컴퓨팅과 데이터 어낼리틱스
[232] 수퍼컴퓨팅과 데이터 어낼리틱스
 
Implementing remote procedure calls rev2
Implementing remote procedure calls rev2Implementing remote procedure calls rev2
Implementing remote procedure calls rev2
 
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
전형규, M2 클라이언트 스레딩 아키텍쳐, NDC2013
 
R2서버정진욱
R2서버정진욱R2서버정진욱
R2서버정진욱
 
리눅스 커널 기초 태스크관리
리눅스 커널 기초 태스크관리리눅스 커널 기초 태스크관리
리눅스 커널 기초 태스크관리
 
서울 R&D 캠퍼스 자연어 수업자료
서울 R&D 캠퍼스 자연어 수업자료서울 R&D 캠퍼스 자연어 수업자료
서울 R&D 캠퍼스 자연어 수업자료
 
UNIX 시스템 2014-2018년 기말시험 기출문제
UNIX 시스템 2014-2018년 기말시험 기출문제UNIX 시스템 2014-2018년 기말시험 기출문제
UNIX 시스템 2014-2018년 기말시험 기출문제
 
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이  왜 이리 힘드나요?  (Lock-free에서 Transactional Memory까지)
Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)
 
Linux Performan tuning Part I
Linux Performan tuning Part ILinux Performan tuning Part I
Linux Performan tuning Part I
 

Thread programming

  • 2. Advanced! 리눅스 네트워크 시스템 프로그래밍  김선영 저, 2판  가메출판사  책의 8장 스레드 프로그래밍
  • 3. 무임승차했던 성능 문제  멀티스레딩과 성능 향상  병렬 처리 패턴  스레드 안전  pthread  OpenMP 프로그래밍  성능을 고려한 프로그래밍
  • 4.
  • 5. 인텔 CPU의 발전 80년대 초반 90년대 초반 반도체 미세 공정 능력 0.18㎛ 65㎚ 트랜지스터 집적 능력 약 9.5M개 약 291M 클록(㎐) 500㎒ 3.2㎓  무어의 법칙 ◦ 반도체의 회로 집적도는 2년마다 2배씩 증가  성능이 떨어지는 코드  하드웨어 교체로 개선
  • 6. AMD 4㎓ CPU ◦ 매우 많은 전력 소모와 무자비한 발열  전산업계의 거품 현상 ◦ 비용 소모(전력 등)는 투자 및 자금 유치로 해결 ◦ 거품이 빠지면서 공황상태  Green IT, 모바일 시장의 발전 ◦ 전력 절감만이 살길
  • 7. I7입니다. 내용과 무관합니다
  • 8. 공정 기술의 향상으로 CPU에 복수 개의 코어 이식 ◦ CMP(Chip Multi Processor), 내장 그래픽 등 I7입니다. 내용과 무관합니다
  • 9. 성능이 비슷하거나 낮은 여러 개의 코어 ◦ 병렬 처리, 비동기 처리 기법에 대한 연구 진행 ◦ 단일 스레드 프로그램에서는 성능 저하 유발 I7입니다. 내용과 무관합니다
  • 10. 책에서는 Thread Building Block 소개가 없습니다  pthread(POSIX thread) ◦ 최신 UNIX 커널은 대부분 지원 ◦ 윈도우 native 스레드에 비해 성능이 떨어집니다  OpenMP ◦ 스레드 기법 몇가지를 단순화 ◦ C/C++ portran 등 다양한 언어 지원 ◦ #pragma omp로 직접 함수를 코딩하지 않아도 됩니다 ◦ 전처리기 수준에서 처리하므로 높은 이식성 확보 ◦ GCC/MSC 지원
  • 11.
  • 12. 단일 CPU 에서의 처리 방법 Task #1 Task #2  멀티코어 CPU에서의 병렬 처리 방법 Task #1 Task #2  단일 CPU에서의 동시 처리 방법 Task #1 Task #2
  • 13. Latency ◦ 요청 후 실제 응답이 오기까지 걸리는 대기 시간 ◦ CPU가 다른 장치에 비해 매우 빠르므로 생기는 시간  Latency 중 CPU에서 다른 스레드의 작업을 처리 ◦ I/O를 비동기로 처리하므로 Latency Hiding 가능 I/O Response & processing wait wait I/O Request
  • 14. 프로그램의 성능 향상을 위한 I/O 및 저장장치 접 근 최소화를 위한 두가지 방법  Multi Thread ◦ 프로세스 내부 처리 구조를 Multi Process처럼 분업화 ◦ 스레드 간 통신에 따른 비용 소모가 거의 없음 ◦ 스레드 간 동기화 처리 비용 소모  Multi Process ◦ 동기적 프로그래밍 모델 ◦ 보호되는 자원(메모리, 장치 등) ◦ 프로세스간 통신에 따른 비용 소모(IPC 등)
  • 15. Multi Process Process Process copy copy IPC  Multi Thread process Thread Thread Data
  • 16. 멀티 스레딩은 최후의 보루입니다 ◦ 개발, 테스트, 디버깅이 복잡해집니다 ◦ 설계나 개발 단계에서 예측하지 못한 상황에 빠질 가능성 이 있습니다 ◦ “프로그래머가 관찰을 위해 개입하는 순간, 비결정적인 결과를 나타내어 버그가 사라지는 현상”
  • 17. 고려 사항 ◦ I/O 측면에서 병목(bottleneck)이 제거된 상태인가? ◦ 멀티 스레드 도입 전의 코드는 다른 최적화 방법을 적용 해 보았는가? ◦ 멀티 스레드 도입 전의 시스템에 가용할 수 있는 CPU나 관련 유휴 자원은 충분한가? ◦ 효율을 극대화하려면 스레드의 숫자를 어떻게 결정해야 하는가?
  • 18.
  • 19. 대분류에 속하는 패턴입니다  태스크 분해(Task Decomposition) ◦ 작업의 단위나 순서의 흐름이 중요한 경우  데이터 분해(Data Decomposition) ◦ 작업할 데이터의 형태나 크기가 중요한 경우
  • 20. 처리해야 하는 데이터나 행위가 매번 달라지거나, 연속적인 흐름을 띄는 경우에 적합  콜백, 트리/파면 분기, 파이프라인 등 ◦ 웹 브라우저에 적용  병렬 처리를 위해 분해된 태스크들을 스레드가 실 행하는 형태 ◦ 규모에 따라 태스크 하나에 하위 스레드 여러 개 할당 ◦ 선후관계/의존성에 따른 동기화 처리 요구(배리어 등)
  • 21. 트리 구조의 태스크 Task Task Task Task Task Task Task  파이프라인 구조의 태스크 Data Data Data Data Data Data Data Data Task #1 Task #2 Task #3
  • 22. 동일하거나 비슷한 작업을 하는 복수의 태스크 생성  데이터 인코딩/디코딩, 대규모 계산 등에 사용 ◦ 압축, 이미지 프로세싱, 행렬 계산 등  적절한 부하 분산(Load Balancing) 요구 ◦ 데이터를 적절한 단위(chunk)로 분할하여 작업 할당 load thread thread balancing chunk chunk chunk chunk decomposition chunk chunk chunk chunk Data chunk chunk chunk chunk thread thread chunk chunk chunk chunk
  • 23. 병렬 처리에 루프를 주로 사용하는 경우 데이터 분 해 방식 적합  분기 혹은 데이터 부분 가공인 경우 태스크 분해 방식 적합  필요에 따라 복합적으로 사용합니다 로컬 임시파일/결과 복사 partitioner file 1-1 map 1 file 1-2 block 1 reduce 1 file 2-1 대용량 데이터 block 2 map 2 file 2-2 분석 프레임워크 block 3 map file 3-1 output 1 병합/정렬 맵리듀스 구조 3 file 3-2 block 4 file 4-1 map reduce 2 4 file 4-2 block 5 map file 5-1 5 output 2 file 5-2
  • 24.
  • 25. 스레드에서 사용해도 안전한 코드의 총칭 ◦ 스레드에서 사용해도 안전하게 수행되는 코드 ◦ 주로 함수에 대해 안전한지 판단합니다  UNIX 계열에서는 스레드 안전에 대해 상세 분류 ◦ 재진입, 병렬 처리, 시그널 처리에 대한 안전 여부 등 ◦ 스레드 안전 개념의 혼란 초래  유닉스 표준(SUSv4)에서 용어 가지치기 단행 ◦ 용어와 개념, 그리고 잔재들을 소개하는 절입니다
  • 26. static char buf_sum[16]; 이 함정 지역 변수로 만들어 해결하면 되지만 예제이므로 상황을 복잡하게 만듭니다
  • 27. thread 1 sum_strnum() thread 2 sum_strnum()
  • 28. 뮤텍스를 통한 스레드 안전 시도  실패
  • 29. WHY? T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 unlock thread 1 lock & sum_strnum() switching sum_strnum() unlock thread 2 lock & wait… sum_strnum() switching
  • 30. 병렬 실행을 보장하도록 작성된 형태를 취햐여 스 레드 안전을 획득한 경우  같은 프로세스 내에서 재귀 호출되어도 문제 없음  재진입성이 없는 표준 함수들 ◦ strtok, ctime, gethostbyname, rand, srand, … ◦ _r로 끝나는 함수는 안전합니다(UNIX)  최신 유닉스 표준(SUSv4)에서 재진입성은 스레드 안전에 포함되는 개념으로 편입시켜 정의
  • 31. 재진입은 정적 객체를 사용하는 경우나 극히 제한 적인 코드에만 적용 가능  전역 변수의 경우 뮤텍스를 통해 스레드 안전 확보  공유 자원에 락을 걸면 안됩니다 ◦ 네트워크, 파일 입출력 등 ◦ 부분 입출력 후 스위칭되는 경우 기아 유발 ◦ Isolated I/O 사용(IOCP 등)
  • 32. worker thread 뮤텍스로 보호되는 구간 worker thread output 큐 network worker send 등록 send thread thread 작업 꺼내기 worker thread
  • 33. 함수 실행 중 시그널에 의한 인터럽트 발생  EINTER 오류 반환(Error Interrupt) ◦ 멀티스레드 환경에서 lock 함수 호출 도중 시그널 발생 등 ◦ 세마포어 lock 시도  시그널 안전하지 않음 ◦ 세마포어 unlock 시도  시그널 안전  스레드 취소 함수(pthread_cancel)시 수행중인 함 수가 정상 종료하는 경우 비동기 취소 안전
  • 34. 저수준 입출력(read, write)는 버퍼(PIPE_BUF)보다 입출력이 작은 경우 실행 보장  sig_atomic_t 정수형 변수의 접근 보장  대부분의 함수는 원자적 실행을 보장하지 않습니다
  • 35. 입출력 구간을 나누어 스레드마다 구간 입출력  write()  pwrite() 사용  POSIX Realtime Extension의 AIO 사용
  • 36.
  • 37. pthread는 전통적인 API 스펙이므로 한번 익혀두 면 오랫동안 별 탈 없이 사용할 수 있습니다  기능별 세분화가 잘 되어있음 ◦ 복잡합니다  오류 처리 방법 ◦ 성공시 0 반환, 실패시 오류 코드 반환 ◦ errono 전역변수 공유 회피  시그널 처리에 의해 인터럽트되지 않습니다 ◦ 비동기 시그널 함수는 인터럽트 됩니다
  • 38. Windows Native thread와 비슷합니다 pthread_create 스레드 생성 pthread_exit 스레드 종료 pthread_join 스레드를 프로세스에 병합 pthread_detach 스레드를 프로세스에서 분리 pthread_cancel 스레드 취소  pthread_create(pthread_t *restrict_thread, const pthread_attr_t *restrict_attr, void *(*start_routine)(void *), void *restrict_arg);  pthread_join/pthread_detach ◦ join은 스레드 대기, detach는 스레드 제어 포기
  • 39. pthread_exit의 반환 주소는 스레드 스택에 두면 안됩니다 ◦ 스레드 스택이 파괴되면 반환 주소가 날아가면서 pthread_join으로 대기할 수 없습니다  pthread_cancel은 강제 종료가 아닙니다 ◦ 스레드 중지 요청(deferred cancel, 지연된 취소) ◦ 스레드는 특정 지점마다 중지 요청이 있는지 확인 후 중지 ◦ 공유 메모리, 자원 등 누수 가능성 존재  pthread_mutex_timedlock ◦ lock + 타임아웃 ◦ 타임아웃 시간 이후 오류를 반환합니다
  • 40. Win32의 그것과 매우 흡사합니다 ◦ waitfor- 함수 대신 lock & unlock 함수 사용 ◦ try, timeout 함수 제공 ◦ 객체의 생성, 뮤텍스 획득, 해제, 파괴 함수 제공  뮤텍스 속성 ◦ pthread_mutexattr_settype(*attr, type) normal errcheck recursive 재귀 잠금 허 중복 잠금 교착 상태 오류 반환 용(횟수 적용) 오류 반환 오류 반환 소유권이 없는 잠금 해제 시도 undefined (EPERM) (EPERM) 오류 반환 오류 반환 풀린 뮤텍스에 잠금 해제 시도 undefined (EPERM) (EPERM) 성능 빠름 약간 느림 약간 느림
  • 41. 스레드가 특정 조건을 만족할 때까지 대기 thread B lock mutex item 준비 thread A 뮤텍스 영역 큐 확인 lock mutex yes no 조건 변수 블록 item 큐잉 조건 (unlock mutex) 변수 영역 조건 변수에서 깨어남 unlock mutex (lock mutex) thread B에 signal item 디큐잉 시그널 전송 전송 unlock mutex
  • 42. 조건 변수에 의해 대기하는 경우 뮤텍스 해제 ◦ 기아 방지  조건 변수에서 깨어나는 경우 즉시 조건 검사를 해 야 합니다 ◦ 복수의 스레드가 깨어나는 경우 경쟁 상태 유발  조건 변수 관련 함수 & 매크로 pthread_cond_init 조건 변수 초기화 pthread_cond_wait 조건 변수 대기 pthread_cond_timedwait 대기후 타임아웃 지정 (지정 시간 후 오류 반환) pthread_cond_signal 스레드 하나를 깨움 pthread_cond_broadcast 스레드 집합을 깨움 pthread_cond_destroy 조건 변수 파괴 PTHREAD_COND_INITIALIZER 선언 및 초기화에 사용하는 매크로
  • 43. 뮤텍스와 조건 변수는 공유 메모리에 둡니다  프로세스 공유 속성 함수 pthread_mutexattr_setpshared 뮤텍스 속성에 프로세스 공유 기능 설정 pthread_mutexattr_getpshared 뮤텍스 속성의 프로세스 공유 기능 반환 pthread_condattr_setpshared 조건 변수 속성에 프로세스 공유 기능 설정 pthread_condattr_getpshared 조건 변수 속성의 프로세스 공유 기능 반환  매개변수 ◦ pthread_mutexattr_t : 뮤텍스 속성 ◦ pthread_condattr_t : 조건 변수 속성 ◦ int pshared : PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE
  • 44. 스레드들이 특정 코드 지점에 모일 때까지 대기  POSIX.1003.2-2001에 추가됨 ◦ _XOPEN_SOURCE 매크로가 600 이상이면 됩니다  배리어 함수들 배리어 객체 초기화 pthread_barrier_init(count) (count만큼 wait 호출 전까지 스레드 대기) pthread_barrier_destroy 배리어 객체 파괴 pthread_barrier_wait 다른 스레드 도착 대기 pthread_barrierattr_init 배리어 속성 객체 초기화 pthread_barrierattr_destroy 배리어 속성 객체 파괴 pthread_barrierattr_getpshared 배리어 공유 속성 확인 pthread_barrierattr_setpsahred 배리어 공유 속성 설정
  • 45. 문맥 교환(context switching) 최소화  바쁜 대기(busy wait)를 수행합니다 ◦ 대기시간이 길어질수록 효율이 떨어집니다  스핀락 함수들 pthread_spin_init 스핀락 객체 초기화 pthread_spin_destroy 스핀락 객체 파괴 pthread_spin_lock 스핀락 획득 pthread_spin_trylock 스핀락 획득 시도, 실패시 오류 반환(EBUSY) pthread_spin_unlock 스핀락 해제
  • 46. 공유 자원에 여러 스레드가 효율적으로 접근  reader-lock이 걸린 경우 writer-lock은 잠깁니다  위의 함수 원형들과 형태가 비슷합니다 ◦ pthread_rwlock_init / destroy ◦ rwlock_rdlock / wrlock ◦ try__lock, timed__lock  프로세스 공유 속성은 지원하지 않습니다
  • 47. Win32의 그것과 비슷합니다  GCC에서는 __thread 예약어 제공  스레드 안전한 함수를 작성할 때 유용합니다  int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); ◦ 파괴자 함수를 직접 지정할 수 있습니다  기타 ◦ pthread_key_delete(key) ◦ pthread_setspecific(key, value) ◦ value pthread_getspecific(key)
  • 48. Win32 뮤텍스의 WAIT_ABANDONED_0 ◦ 뮤텍스가 잠긴 채 스레드가 죽었습니다 ◦ pthread에서는 EOWNERDEAD 오류 반환  잠긴 뮤텍스를 자동으로 다른 스레드가 받음 ◦ pthread_mutexattr_(set/get)robust(attr, int robust) ◦ robust 값  PTHREAD_MUTEX_STALLED : 교착 상태  PTHREAD_MUTEX_ROBUST : 다른 스레드가 뮤텍스를 받음 ◦ 뮤텍스를 받은 스레드는 뮤텍스 인계 함수 호출  pthread_mutex_consistent  처리하지 않는 경우 lock 함수 실패, ENOTRECOVERABLE 반환
  • 49. WndProc이 아닙니다  스레드 종료 / fork() 호출 등 예외 이벤트 처리용 ◦ fork() 이전에 비동기 작업을 정지하거나 제거  스레드 클린업 핸들러 ◦ 스레드가 종료될 때 실행하는 함수 등록 ◦ atexit() 함수의 스레드 버전 ◦ 핸들러에 등록된 이벤트는 스택처럼 쌓입니다  pthread_cleanup_push(routine, arg)  pthread_cleanup_pop(n) : 0 or ~0  ~0이면 클린업 핸들러 실행 후 제거, 0이면 바로 제거
  • 50. 스레드 fork 핸들러 ◦ pthread_atfork(prepair, parent, child)  prepair는 fork() 이전에 실행할 함수  parent는 fork() 호출 이후 부모 프로세스가 실행할 함수  child는 fork() 호출 이후 자식 프로세스가 실행할 함수 ◦ fork()를 호출하는 스레드만 복제됩니다  다른 스레드는 복제되지 않습니다  복잡해지므로 fork()를 사용하지 않는 것을 권장합니다
  • 51.
  • 52. 간단한 지시어를 사용하여 멀티스레딩을 적용할 수 있는 기법  이식성이 높고 학습 용이  코드 수정을 최소화하고 멀티스레딩 적용 시간 단축  짧은 역사(1996~)  다양한 언어(C/C++, Fortran 등) 지원  #define _OPENMP 매크로 정의됨
  • 53. OpenMP 3.0 코드는 실행이 불가능합니다 ◦ visual studio 2012에서 OpenMP 3.0을 지원하지 않습 니다 ◦ Intel Parallel Studio 설치시 지원 가능합니다($1,599) ◦ 해봤더니 안됩니다 ㅠㅠ
  • 54. 전처리기 지시어 이하 문장(혹은 블록)을 여러 스레드로 처리합니다
  • 55. 기본 OMP 스레드 수 == CPU 수  #pragma omp … num_threads(n) ◦ 한번 적용  omp_set_num_threads(n) ◦ 함수입니다 ◦ 호출 이후 OpenMP 스레드를 자동으로 n만큼 만듭니다
  • 56. loop 모델 루프 작업을 분할하여 병렬 처리 직렬 코드 블록들을 몇 개의 구간으로 분할 sections 모델 워크 쉐어링 구조 하여 병렬 처리 병렬 처리되는 구간회서 1회성 실행 구간 single 모델 설정 태스크 구조 task 모델(3.0) 태스크 단위 작업을 처리하는 스레드 생성
  • 57. OpenMP 병렬 구간에서 변수의 공유 설정 private(list) list에 지정된 변수를 TLS에 생성 사설(private) firstprivate(list) list를 main 스레드의 초기화값으로 초 속성 기화 마지막 스레드의 해당 변수 값을 main lastprivate(list) 스레드에 반영 명시적으로 모든 스레드가 공유하는 변 공유 속성 shared(list) 수로 선언 value : shared, none 기본 설정 default(value) 변수의 공유 설정 기본값, parallel 병 렬 구간이 시작할 때 설정
  • 58. reduction(operand:var) ◦ var 값에 operand 연산자 수행 ◦ 내부에서 묵시적으로 private 지시어 수행  default가 none일 경우 명시적으로 shared로 선언  reduction 연산 연산자 초기값 연산자 초기값 + 0 & ~0 * 1 | 0 - 0 && 1 ^ 0 || 0 max 표현 가능한 최소값 min 표현 가능한 최대값
  • 59.
  • 60. 루프는 반복 횟수가 정해져 있어야 함  #pragma omp parallel 이후 문장부터 스레드 생 성  for문 반복 횟수 == 분할 개수 * 스레드 수  모든 스레드가 완료할 때까지 대기(묵시적 배리어)  #pragma 두 줄 ◦ 합쳐서 기술 가능 ◦ #… parallel for  omp_get_thread_num() ◦ 스레드 번호 반환
  • 61. main() #pragma omp parallel #pragma omp for i = 0 i = 4 i = 1 i = 5 i = 2 i = 6 i = 3 i = 7 /* implicit barrier */
  • 62. 남는 스레드가 밀린 작업을 하도록 작업 할당 schedule(static [, n]) 라운드 로빈 방식으로 순서대로 n개씩 할당. n 생략시 1 schedule(dynamic [, n]) 한가한 스레드에게 n개씩 할당. n 생략시 1 schedule(guided [, n]) dynamic과 동일하게 한가한 슬데ㅡ에게 할당 하지만 chunk의 크기가 다름. 할당되는 chunk 크기는 큰 수에서 n까지 줄여나감. n 생략시 1 schedule(auto) 임플리먼테이션이 자동으로 판단 schedule(runtime) 실행시 ICV 환경 변수에 의해 결정
  • 63. dynamic 스케줄링은 개별 작업의 수행 시간이 균 일하지 못할 때 좀 더 빨리 작업을 끝낸 스레드에 게 새로운 chunk 할당  static, dynamic 스케줄링은 chunk 크기가 작은 경우 오버헤드 유발  guided는 chunk 크기를 점점 줄여 나가며 할당 ◦ 전체적으로 스케줄링 횟수가 줄어듦  runtime에 쓰이는 OpenMP 내부 제어 변수 (OpenMP ICV)은 환경 설정 변수나 함수 호출로 설정 가능
  • 64. 스레드 작업 순서를 정렬하여 결과를 순서대로 작 성  직렬화/동기화 기법을 직접 구현하는 것보다 성능 향상
  • 65. 코드의 특정 구간을 다수의 섹션으로 분할하여 병 렬 처리하는 태스크 방식 main() #pragma omp parallel #pragma omp sections section section #1 #2 /* implicit barrier */
  • 66. 임의의 섹션을 임의의 스레드가 수행 ◦ 수행 순서는 보장되지 않음  변수 공유 및 환원 가능
  • 67. single 블록은 한번만 수행  스레드 중 가장 먼저 진입하는 스레드가 수행 ◦ 나머지 스레드들은 single 작업이 끝날 때 까지 대기  주로 초기화 작업 등에 사용 main() #pragma omp parallel single /* implicit barrier */ parallel parallel #1 #1 /* implicit barrier */
  • 68. 특정 작업 단위로 분할된구간을 스레드에게 할당  임의의 구간을 임의의 스레드가 수행  루프의 개수, 중첩 여부, 재귀 여부에 관계없이 활 용 가능 task thread code #1 task task task task thread code code code code #2 task thread code #n
  • 69. 현재 스레드(주로 메인 스레드)가 작업 코드에 해 당하는 구간을 스레드에게 분배  if ◦ 스레드가 작업을 분배할 조건을 설정 ◦ 특정 시점부터 분배를 시작하게 할 수 있습니다 ◦ #pragma omp ~ if(exp)
  • 70. untied ◦ 스레드가 정지 후 재시작(suspeded  resume)될 때 다 른 스레드가 작업을 이어 받도록 설정 ◦ tied인 경우 재시작 이후에도 같은 스레드가 작업(기본값)
  • 71. 배리어, 크리티컬 섹션, 원자적 실행, OpenMP lock 제공  크리티컬 섹션은 Win32의 그것과 다를 수 있음  OpenMP lock은 뮤텍스와 유사
  • 72. parallel, for, sections, single의 끝에는 묵시적 배리어가 존재  명시적 배리어 ◦ #pragma omp barrier ◦ #pragma omp taskwait  자식 task 대기 조건문과 결합하는 경우  묵시적 배리어 제거 ◦ #pragma omp ~ nowait ◦ loop, sections, single에 사용  #pragma omp critical [name] ◦ name을 생략하면 이름이 없는 것으로 간주
  • 73. #pragma omp atomic [read | write | update | capture] ◦ 생략시 update로 간주  atomic 형식 분류(x : 대상) read v = x; v는 TLS 변수 write x = exp; exp는 보호되지 않음 x++; 대상이 변하면서 읽어야 하는 경우 x--; 사용 update ++x; --x; 축약 대입 연산 가능 x binary_operator = exp; v = x++; v = x--; update + read capture v = ++x; 공유 데이터를 변경하고 값을 읽어야 v = --x; 하는 다수의 작업에 적합 v = x binary_operator = exp;
  • 74. 커널 객체(≒뮤텍스) 처럼 사용합니다  omp_lock_t ◦ 범용 lock  omp_nest_lock_t ◦ 중첩 가능한 lock  lock 관련 함수들 omp_init_lock 초기화 omp_destroy_lock 객체 파괴 omp_set_lcok lock 획득 omp_unset_lcok lock 해제 omp_test_lcok lock 획득 시도(0 == 실패)
  • 75. master 스레드에서 동작하는 코드 지정  묵시적 배리어, private 변수가 없습니다 main() #pragma omp parallel #pragma omp sections master parallel parallel #1 #2 /* implicit barrier */
  • 76. 행렬 곱(2x2)을 어떻게 구하시나요? ◦ a₁₁ * a₁₁ + a₁₂ * a₂₁ a₁₁ * a₁₂ + a₁₂ * a₂₂ ◦ a₂₁ * a₁₂ + a₂₂ * a₂₁ a₂₁ * a₁₂ + a₂₂ * a₂₂  중첩된 루프의 경우 가장 바깥 루프를 기준으로 병 렬화 ◦ 코어수 보다 분할횟수가 적은 경우 나머지 스레드는 돌지 않습니다 ◦ for(i=0; i < 3; ++i)  쿼드코어에서 4번째 스레드 X
  • 77. omp_set_nedsted(0 or ~0) ◦ TRUE / FALSE로 중첩 기능을 설정합니다 ◦ OMP_NESTED 환경 변수로도 설정 가능합니다
  • 78. collapse(n) ◦ 중첩된 n단계 루프를 풀어버립니다 ◦ OpenMP 3.0 이상에서 지원
  • 79. #pragma omp threadprivate(list) ◦ 리스트에 있는 변수를 TLS 변수로 선언 ◦ 원본 변수는 정적 변수 ◦ 예제는 길어서 생략합니다  TLS 변수의 복사 ◦ 원본은 마스터 스레드 ◦ TLS 변수 중 일부만 복사 가능 ◦ #pragma omp parallel copyin(list)  병렬 구간이 시작될 때 TLS 변수 복사 ◦ #pragma omp single copyprivate(list)  single 코드 블록이 끝나면서 TLS 변수 복사
  • 80. Internal Control Variable의 약자입니다  스레드 개수 관련 ICV 생성할 스레드의 개수 설정 환경 변수 OMP_NUM_THREADS=n[, …] 중첩 단계별로 „,‟로 구분 omp_set_num_threads(n) 생성할 스레드의 개수 설정 omp_get_num_threads() 현재 스레드 개수 제한 함수 omp_get_max_threads() 현재 최대 스레드 개수 제한 omp_get_team_size() 중첩 단계
  • 81. 중첩 관련 ICV 환경 변수 OMP_NESTED value : true or false omp_set_nested(value) value : 0 or ~0 함수 omp_get_nested() 0 or ~0 반환 omp_get_level 현재 병렬화 중첩 단계 반환  스케줄링 관련 ICV (스케줄링 방법이 runtime인 경우) OMP_SCHEDULE=type [, type : static, dynamic, 환경 변수 chunk] guided, auto omp_set_schedule(omp_sch kind : 스케줄 방법 함수 ed_t kind, int modifier) modifier : chunk 개수 int omp_get_schedule() 현재 스케줄링 방법
  • 82. schedule(static [, n]) 라운드 로빈 방식으로 순서대로 n개씩 할당. n 생략시 1 schedule(dynamic [, n]) 한가한 스레드에게 n개씩 할당. n 생략시 1 schedule(guided [, n]) dynamic과 동일하게 한가한 슬데ㅡ에게 할당 하지만 chunk의 크기가 다름. 할당되는 chunk 크기는 큰 수에서 n까지 줄여나감. n 생략시 1 schedule(auto) 임플리먼테이션이 자동으로 판단 schedule(runtime) 실행시 ICV 환경 변수에 의해 결정
  • 83. 동적 조정 관련 ICV (실행 중 스레드 개수 조정) 환경 변수 OMP_DYNAMIC=value value : true or false omp_set_dynamic(value) value : 0 or ~0 함수 omp_get_dynamic() 동적 조정 여부 반환  기타 과거 특정 시점부터 흐른 시 double omp_get_wtime() 함수 간(time처럼 쓰입니다) double omp_get_wtick() ↑의 정밀도(단위) 반환  omp_get_wtime()은 부팅 이후도 반환할 수 있음
  • 84. parallel for sections single task private ● ● ● ● ● firstprivate ● ● ● ● ● lastprivate ● ● shared ● ● default ● ● reduction ● ● ● ● copyin ● copyprivate ● schedule ● ordered ● nowait ● ● ● untied ● if ● collapse ● num_threads ●
  • 85.
  • 86. 64byte를 캐시에서 읽어들이면서 생기는 공유 문제 ◦ 수정할 때마다 상대방 CPU 캐시 무효화 요청 CPU 0 CPU 1 (thread 1) (thread 2) int cnt_sheep[] [0] [1] [2] [3] [0] [1] [2] [3] cache cache access access invalid 64 byte 64 byte invalid
  • 87. 가짜 공유에 의한 성능 저하
  • 88. 컴파일러 단계에서 BSS 최적화 수행  패딩 비트를 설계합니다 ◦ 컴파일러에게 맡겨버리는 방법(GCC)
  • 89. 전역 변수, 힙, 공유 메모리를 지양합니다 ◦ 전역 변수를 TLS에 복사하거나 합니다 ◦ 병렬 구간에서 chunk 크기를 조절합니다  pipeline 모델에서는 chunk 크기를 동적으로 조절 하게 합니다