openmp
불규칙한 OpenMP 병렬 처리
수색…
비고
일반적인 함정은 병렬 영역의 모든 스레드가 작업을 인스턴스화 (생성)해야한다고 생각하는 것입니다. 그러나 스레드 수와 처리 할 요소 수를 곱한만큼의 작업을 생성하지 않는 한 일반적으로 그렇지 않습니다. 따라서 OpenMP 태스크 코드에서
#pragma omp parallel
#pragma omp single
...
#pragma omp task
{ code for a given task; }
...
OpenMP 작업을 사용하는 C ++ 목록 컨테이너의 병렬 처리
#include <omp.h>
#include <unistd.h>
#include <iostream>
#include <list>
static void processElement (unsigned n)
{
// Tell who am I. The #pragma omp critical ensures that
// only one thread sends data to std::cout
#pragma omp critical
std::cout <<
"Thread " << omp_get_thread_num() << " processing element " << n
<< std::endl;
// Simulate some work
usleep (n*1000);
}
int main (void)
{
std::list<unsigned> lst;
// Fill the list
for (unsigned u = 0; u < 16; ++u)
lst.push_back (1+u);
// Now process each element of the list in parallel
#pragma omp parallel // Create a parallel region
#pragma omp single // Only one thread will instantiate tasks
{
for (auto element : lst)
{
#pragma omp task firstprivate (element)
processElement (element);
}
// Wait for all tasks to be finished
#pragma omp taskwait
}
return 0;
}
이 예제는 #pragma omp task
지시문을 사용하여 OpenMP 태스크 구문을 통해 병렬로 STL 목록 (코드에서 lst
의 처리를 시뮬레이트합니다. 예는 /은 각 요소에 대해 하나의 OpenMP 작업의 인스턴스를 생성 lst
하고 실행 준비로의 OpenMP 스레드가 즉시 작업을 실행합니다.
$ OMP_NUM_THREADS=4 ./a.out
Thread 0 processing element 16
Thread 3 processing element 3
Thread 2 processing element 1
Thread 1 processing element 2
Thread 2 processing element 4
Thread 1 processing element 5
Thread 3 processing element 6
Thread 2 processing element 7
Thread 1 processing element 8
Thread 3 processing element 9
Thread 2 processing element 10
Thread 1 processing element 11
Thread 0 processing element 15
Thread 3 processing element 12
Thread 2 processing element 13
Thread 1 processing element 14
OpenMP 작업을 사용하는 pi에 대한 재귀 계산
아래 코드는 재귀 적 접근 방식을 사용하여 PI 값을 계산합니다. MAX_PARALLEL_RECURSIVE_LEVEL
값을 수정하여 재귀 깊이에 따라 작업 생성을 중지하십시오. 재귀 적 응용 프로그램에서 병렬 처리를 작성하는이 접근법을 사용하면 작성하는 작업이 많을수록 생성되는 병렬 작업이 많아지고 작업 당 작업이 줄어 듭니다. 따라서 응용 프로그램을 시험하여 성능 향상 측면에서 추가 작업을 생성하는 수준을 이해하는 것이 편리합니다.
#include <stdio.h>
#include <omp.h>
double pi_r (double h, unsigned depth, unsigned maxdepth, unsigned long long begin, unsigned long long niters)
{
if (depth < maxdepth)
{
double area1, area2;
// Process first half
#pragma omp task shared(area1)
area1 = pi_r (h, depth+1, maxdepth, begin, niters/2-1);
// Process second half
#pragma omp task shared(area2)
area2 = pi_r (h, depth+1, maxdepth, begin+niters/2, niters/2);
#pragma omp taskwait
return area1+area2;
}
else
{
unsigned long long i;
double area = 0.0;
for (i = begin; i <= begin+niters; i++)
{
double x = h * (i - 0.5);
area += (4.0 / (1.0 + x*x));
}
return area;
}
}
double pi (unsigned long long niters)
{
double res;
double h = 1.0 / (double) niters;
#pragma omp parallel shared(res)
{
#define MAX_PARALLEL_RECURSIVE_LEVEL 4
#pragma omp single
res = pi_r (h, 0, MAX_PARALLEL_RECURSIVE_LEVEL, 1, niters);
}
return res * h;
}
int main (int argc, char *argv[])
{
#define NITERS (100*1000*1000ULL)
printf ("PI (w/%d iters) is %lf\n", NITERS, pi(NITERS));
return 0;
}
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow