2016-12-23 8 views
0

OpenMP 코드를 TBB로 변환하는 데 어려움이 있습니다. 누군가 나를 도울 수 있습니까?OpenMP를 TBB로 변환

나는 결과가

# pragma omp parallel \ 
shared (b, count, count_max, g, r, x_max, x_min, y_max, y_min) \ 
private (i, j, k, x, x1, x2, y, y1, y2) 
{ 
# pragma omp for 

for (i = 0; i < m; i++) 
{ 
for (j = 0; j < n; j++) 
{ 
//cout << omp_get_thread_num() << " thread\n"; 
    x = ((double) ( j - 1) * x_max 
     + (double) (m - j ) * x_min) 
    /(double) (m  - 1); 

    y = ((double) ( i - 1) * y_max 
     + (double) (n - i ) * y_min) 
    /(double) (n  - 1); 

    count[i][j] = 0; 

    x1 = x; 
    y1 = y; 

    for (k = 1; k <= count_max; k++) 
    { 
    x2 = x1 * x1 - y1 * y1 + x; 
    y2 = 2 * x1 * y1 + y; 

    if (x2 < -2.0 || 2.0 < x2 || y2 < -2.0 || 2.0 < y2) 
    { 
     count[i][j] = k; 
     break; 
    } 
    x1 = x2; 
    y1 = y2; 
    } 

    if ((count[i][j] % 2) == 1) 
    { 
    r[i][j] = 255; 
    g[i][j] = 255; 
    b[i][j] = 255; 
    } 
    else 
    { 
    c = (int) (255.0 * sqrt (sqrt (sqrt ( 
     ((double) (count[i][j])/(double) (count_max)))))); 
    r[i][j] = 3 * c/5; 
    g[i][j] = 3 * c/5; 
    b[i][j] = c; 
    } 
} 
} 
} 

꽤 좋은 그리고 TBB 버전은 OpenMP를

TBB의 코드 후 10 배 느린 OpenMP를, 다음 코드는

입니다했다 :

tbb::parallel_for (int(0), m, [&](int i) 
{ 
for (j = 0; j < n; j++) 
{ 
    x = ((double) ( j - 1) * x_max 
     + (double) (m - j ) * x_min) 
    /(double) (m  - 1); 

    y = ((double) ( i - 1) * y_max 
     + (double) (n - i ) * y_min) 
    /(double) (n  - 1); 

    count[i][j] = 0; 

    x1 = x; 
    y1 = y; 

    for (k = 1; k <= count_max; k++) 
    { 
    x2 = x1 * x1 - y1 * y1 + x; 
    y2 = 2 * x1 * y1 + y; 

    if (x2 < -2.0 || 2.0 < x2 || y2 < -2.0 || 2.0 < y2) 
    { 
     count[i][j] = k; 
     break; 
    } 
    x1 = x2; 
    y1 = y2; 
    } 

    if ((count[i][j] % 2) == 1) 
    { 
    r[i][j] = 255; 
    g[i][j] = 255; 
    b[i][j] = 255; 
    } 
    else 
    { 
    c = (int) (255.0 * sqrt (sqrt (sqrt ( 
     ((double) (count[i][j])/(double) (count_max)))))); 
    r[i][j] = 3 * c/5; 
    g[i][j] = 3 * c/5; 
    b[i][j] = c; 
    } 
} 
}); 
+0

은 TBB의 기본 파티션 프로그램은 큰 부담이 발생할 수 있습니다 스레드 당 하나의 루프 반복의 수준까지 재귀 작업 구획을 수행하는'auto_partitioner'이다. 많은 컴파일러를 가진'for' worksharing 구조의 기본 스케쥴링은'static'이므로,'parallel_for' 알고리즘을'static_partitioner'의 싱글 톤 인스턴스와 함께 제공하여 OpenMP에서와 같은 TBB에서 작업 배포를해야합니다. –

+0

난 : –

+0

TBB :: parallel_for (TBB로 parallel_for 변경 blocked_range2d 한 \t는 - [(TBB는 :: S, static_partitioner()) { \t 대를 blocked_range2d (0, m, 0, N) (int j = s.cols(). begin(); j

답변

2

OpenMP 버전 코드의 private (i, j, k, x, x1, x2, y, y1, y2) 절에주의하십시오. 이 변수 목록은 병렬 루프 본문 내부의 개인/로컬 변수를 지정합니다. 그러나 TBB 버전의 코드에서는 이러한 변수 중 상당수가 람다에 의해 참조 ([&])로 캡처되므로 코드가 올바르지 않습니다. 그것은 경주가 있고, 내 의견으로는, 여러 스레드 (캐시 일관성 오버 헤드 및 루프 인덱스 엉망)에서 이러한 변수에 액세스하여 속도가 느려집니다. 코드를 수정하려면 이러한 변수를 로컬 변수로 만듭니다.

tbb::parallel_for (int(0), m, [&](int i) 
{ 
double x, y, x1, x2, y1, y2; // !!!! 
int j, k;     // !!!! 
for (j = 0; j < n; j++) 
{ 
    x = ((double) ( j - 1) * x_max 
     + (double) (m - j ) * x_min) 
    /(double) (m  - 1); 
...