반응형
1.async
- 사용 예시
// async : 즉시 실행
auto a1 = std::async(std::launch::async, foo); // 이 때 스레드 실행
std::cout<<a1.get();
//deferred : 리턴값을 받아올 때 실행
auto a1 = std::async(std::launch::deferred, foo);
std::cout<<a1.get(); // 이 때 스레드 실행
정책
- async : 새로운 스레드를 즉시 실행
- deferred : 리턴값을 받아올 때 실행
thread와의 차이점
- 직접 스레드를 관리(생성, 삭제) 하지 않음
- 함수에서 던진 예외에 대해 예외처리 가능
- oversubscription
- 스레드는 너무 많은 스레드 만들면 중단
- 내부적으로 task관리해주기 때문에 중단 없음
- 스레드를 직접 만들지 않고 스레드 풀 이용
- 반환값을 받을 수 있다.
future<int> a1 = async(launch::async, foo);
const int ret = a1.get();
2.OpenMP
- 병렬 프로그래밍을 쉽게 할 수 있게 제공하는 API
- 사용 방법
- 헤더 추가 : omp.h
- 사용 : 부하가 많은 곳 위에 명령 입력
#pragma omp parallel for - fork and join 모델로 컴파일 됨
- 코어 개수 만큼 스레드 생성
#include <omp.h>
void main(){
int a[1000];
int b[1000];
int c[1000];
#pragma omp parallel for
for(int i=0; i< 1000 ; i++){
c[i] = a[i] + b[i];
}
}
- 옵션
- 위의 구문 뒤에 옵션 추가 가능
1)schedule(dynamic,1) 옵션
- 1 = chuncksize, defualt = 1
- chuncksize 개수만큼 배열을 태크스로 나누고, 코어 개수 만큼 스레드 런칭
- dynamic하게 태스크를 수행하여, 먼저 끝난 스레드는 다음 태스크를 수행
- static 옵션은 스레드가 수행할 태크스를 미리 정하고 끝나면 기다리므로 비효율적
참고
3.CUDA
- 개발 순서
- 커널(함수) 선언
- 변수를 할당(cudaMalloc)
- 변수를 복사(cudaMemcpy)
- 동작 수행
- 결과 변수를 복사(cudaMemcpy)
- 변수 메모리 해제(cudaFree)
__global__
void add(int n, float *x, float *y, float *z){
int i = blcokIdx.x * blockDim.x + threadIdx.x;
if( i < n){
z[i] = x[i] + y[i];
}
}
void main(){
int N = 100000;
std::vector<float> x(N);
std::vector<float> y(N);
std::vector<float> z(N);
float * d_x, *d_y, *d_z;
cudaMalloc(&d_x, N*sizeof(float));
cudaMalloc(&d_y, N*sizeof(float));
cudaMalloc(&d_z, N*sizeof(float));
cudaMemcpy(d_x, x.data(), N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y.data(), N*sizeof(float), cudaMemcpyHostToDevice);
add<<<(N+255)/256, 256>>>(N, d_x, d_y, d_z);
cudaMemCpy(z.data(), d_z, N*sizeof*float), cudaMemcpyDeviceToHost);
cudaFree(d_x);
cudaFree(d_y);
cudaFree(d_z);
}
4. thread에서 메모리 맵
- 로컬 변수(스택 공간)는 각 스레드에 종속적
- 힙과 static 공간은 공유함
- race condition 발생 가능
5.false sharing
- 병렬 프로그래밍이 더 느릴 수 있다.
- 원인
- 멀티 코어 환경에서 각 코어에서 접근하고 있는 데이터가 같은 캐시라인에 있을 때 발생
- 실제 공유 데이터가 아님에도 하드웨어에서는 공유하는 것으로 착각
- 동기화가 발생하여 속도가 저하됨
- 해결 방법
6. condition variable
- 한 스레드에서 다른 쓰레드로 신호를 보냄
- 신호를 받은 쓰레드는 컨디션 밸류를 체크하고 동작 수행
- 컨디션 밸류는 두 쓰레드에서 쓰기 때문에 뮤텍스 필수!
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
int condition = 0;
void foo(){
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, []{return condition==1;})
//lock is acquired, mutual exc job
lock.unlock();
// do rest jobs;
}
int main(){
std::thread waitngT(foo);
{
std::scoped_lock lock(m);
condition = 1;
}
cv.notify_one();
waitngT.join();
}
참고
반응형
'C++ > C++' 카테고리의 다른 글
[C++] 함수형 프로그래밍 (0) | 2021.03.11 |
---|---|
[C++]스마트 포인터 (0) | 2021.03.09 |
[C++]LR value 및 최적화 (0) | 2021.03.09 |
[C++]빌드 프로세스 (0) | 2021.03.09 |
[C++]메모리 구조 (0) | 2021.03.09 |