Programing/C- programing

병렬 프로그래밍을 이용한 For loop 속도향상

sosal 2015. 5. 13. 17:42
반응형

/*

 http://sosal.tistory.com/
 * made by so_Sal
 */


1. CPU core 개수 확인하기

2. OMP_NUM_THREADS 환경변수 추가하기

3. Visual studio / OpenMP 설정하기

4. For loop 속도 test


더블코어 이상의 CPU에서 for loop를 돌릴 때는

일반적으로 하나의 cpu 코어만 사용하기 때문에 컴퓨터의 성능을 최대 활용하지 못합니다.


듀오 혹은 그 이상의 다중코어 CPU를 사용하는 프로그래머들은

병렬 프로그래밍을 사용한다면 훨씬더 빠르게 실행할 수 있습니다.



1. CPU core 개수 확인하기


컴퓨터의 코어 개수를 확인하기 위해서는 내컴퓨터의 속성을 들어가시면 아래와 같이 확인 가능합니다.




제 싸구려 노트북은 듀오네요. 즉 2개의 코어로 프로그램을 병렬처리 할 수 있습니다.





2. OMP_NUM_THREADS 환경변수 추가하기


병렬 프로그래밍을 하기위해서는 환경변수에 코어의 개수를 명시해주어야 합니다.

아래 환경변수 세팅에서 OMP_NUM_THREADS 라는 변수를 추가해주고

해당 값을 코어의 개수로 입력해줍니다.



환경변수 세팅에서 아래와같이 추가해줍니다.



변수값은 위에서 말했듯이 코어의 개수를 넣어주시면 됩니다.

듀오이기 때문에 2를 입력해주었습니다.





3. Visual studio / OpenMP 설정하기


이젠 비쥬얼 스튜디오에서 OpenMP를 지원하도록 설정해줍니다.


프로젝트 설정 -> 구성속성 -> C/C++ -> 언어



위에 보이시는것처럼 OpenMP 지원 -> 예(/openmp)로 설정해줍니다.




4. For loop 속도 test


#include<stdio.h>

#include<iostream>

#include<time.h>


using namespace std;

#define len 100000000


int loop(int i,int j){

return i + j;

}


int main(){

clock_t begin, end;

int j;


begin = clock();

for (int j = 0; j < len; j++){

loop(j, j + 1);

}end = clock();


cout << (double)(end - begin) / CLOCKS_PER_SEC << endl;



begin = clock();

#pragma omp parallel for private(j) 

for (j = 0; j < len; j++){

loop(j, j + 1);

}end = clock();


cout << (double)(end - begin) / CLOCKS_PER_SEC << endl;

return 0;

}




결과:



시간은 약 2배가량 단축되었고



첫번째 루프 돌때의 CPU 사용량:


두번째 루프 돌때의 CPU 사용량:


실제 코어가 활용되는정도를 작업관리자에서 확인할 수 있습니다.




* 주의: Task에 dependency가 존재한다면 OpenMP를 simple하게 사용해선 안된다.


#include<stdio.h>

#include<iostream>

#include<time.h>


using namespace std;

#define len 10000


int main(){

clock_t begin, end;

int j,sum = 0;


begin = clock();

for (int j = 0; j < len; j++){

sum+=j;

}end = clock();


cout << (double)(end - begin) / CLOCKS_PER_SEC << endl;

cout<<sum<<endl;

sum=0;

begin = clock();

#pragma omp parallel for private(j) 

for (j = 0; j < len; j++){

sum += j;

}end = clock();


cout << (double)(end - begin) / CLOCKS_PER_SEC << endl;

cout<<sum<<endl;

return 0;

}





- Task dependency 가 존재할 경우 큰 문제가 생김


#pragma omp task shared(x) 

#pragma omp taskwait

등의 방법으로 문제를 해결할 수 있습니다.



참고 사이트: http://himskim.egloos.com/3261640

openMP에 대해서 자세히 설명되어있는 포스트입니다.


참고 사이트: http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html#f432

SVM + Parallel