2012-05-14 8 views
5

Tôi cố gắng viết ứng dụng đơn giản bằng cách sử dụng OpenMP. Thật không may, tôi có vấn đề với tăng tốc. Trong ứng dụng này, tôi có một vòng lặp while. Nội dung của vòng lặp này bao gồm một số hướng dẫn cần được thực hiện tuần tự và một cho vòng lặp. Tôi sử dụng #pragma omp parallel for để làm điều này cho vòng lặp song song. Vòng lặp này không có nhiều công việc, nhưng được gọi rất thường xuyên.OpenMP - tạo chủ đề chỉ một lần

Tôi chuẩn bị hai phiên bản cho vòng lặp và chạy ứng dụng trên 1, 2 và 4 lõi.
phiên bản 1 (4 lần lặp trong vòng lặp): 22 giây, 23 giây, 26 giây.
phiên bản 2 (100000 lần lặp trong vòng lặp): 20 giây, 10 giây, 6 giây.

Như bạn thấy, khi vòng lặp không có nhiều công việc, thời gian trên 2 và 4 lõi cao hơn trên 1 lõi. Tôi đoán lý do là #pragma omp parallel for tạo chủ đề mới trong mỗi lần lặp của vòng lặp while. Vì vậy, tôi muốn hỏi bạn - là có khả năng để tạo ra các chủ đề một lần (trước khi trong khi vòng lặp), và đảm bảo rằng một số công việc trong vòng lặp while sẽ được thực hiện tuần tự?

#include <omp.h> 
#include <iostream> 
#include <math.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
int main(int argc, char* argv[]) 
{ 
    double sum = 0; 
    while (true) 
    { 
     // ... 
     // some work which should be done sequentially 
     // ... 

     #pragma omp parallel for num_threads(atoi(argv[1])) reduction(+:sum) 
     for(int j=0; j<4; ++j) // version 2: for(int j=0; j<100000; ++j) 
     { 
      double x = pow(j, 3.0); 
      x = sqrt(x); 
      x = sin(x); 
      x = cos(x); 
      x = tan(x); 
      sum += x; 

      double y = pow(j, 3.0); 
      y = sqrt(y); 
      y = sin(y); 
      y = cos(y); 
      y = tan(y); 
      sum += y; 

      double z = pow(j, 3.0); 
      z = sqrt(z); 
      z = sin(z); 
      z = cos(z); 
      z = tan(z); 
      sum += z; 
     } 

     if (sum > 100000000) 
     { 
      break; 
     } 
    } 
    return 0; 
} 

Trả lời

5

Bạn có thể di chuyển các khu vực song song bên ngoài của while (true) vòng lặp và sử dụng các chỉ thị single để làm cho phần nối tiếp của mã để thực hiện chỉ trong một thread. Điều này sẽ loại bỏ chi phí của mô hình ngã ba/tham gia. Ngoài ra OpenMP không thực sự hữu ích trên các vòng đấu với số lần lặp lại rất nhỏ (như phiên bản 1 của bạn). Về cơ bản bạn đo chi phí OpenMP vì công việc bên trong vòng lặp được thực hiện rất nhanh - thậm chí 100000 lần lặp với chức năng siêu việt mất ít hơn giây trên CPU thế hệ hiện tại (ở 2 GHz và khoảng 100 chu kỳ trên mỗi lệnh FP khác ngoài bổ sung, nó sẽ mất ~ 100 ms).

Đó là lý do OpenMP cung cấp if(condition) khoản có thể được sử dụng để chọn lọc tắt parallelisation cho vòng nhỏ:

#omp parallel for ... if(loopcnt > 10000) 
for (i = 0; i < loopcnt; i++) 
    ... 

Đây cũng là khuyến khích sử dụng schedule(static) cho vòng thường xuyên (có nghĩa là vòng lặp for trong đó mỗi lặp lại mất khoảng thời gian để tính toán).

8

Hầu hết các triển khai OpenMP tạo một số luồng trên khởi động chương trình và giữ chúng trong suốt thời gian của chương trình. Đó là, hầu hết các triển khai không tự động tạo và hủy các luồng trong khi thực thi; để làm như vậy sẽ đạt hiệu suất với chi phí quản lý chủ đề nghiêm trọng. Cách tiếp cận này để quản lý luồng phù hợp và phù hợp với các trường hợp sử dụng thông thường cho OpenMP.

Có nhiều khả năng là sự chậm lại mà bạn thấy khi bạn tăng số lượng các luồng OpenMP xuống để áp đặt một chi phí song song trên một vòng lặp với một số lượng nhỏ các lần lặp. Câu trả lời của Hristo nói về điều này.