2013-05-08 23 views
5

Xin lỗi nếu tiêu đề không rõ ràng. Tôi hoàn toàn không biết phải nói thế nào.Lặp lại OpenMP cho vòng lặp trong vùng song song

Tôi đang tự hỏi nếu có bất kỳ cách nào tôi có thể làm như sau:

#pragma omp parallel 
{ 
    for (int i = 0; i < iterations; i++) { 
     #pragma omp for 
     for (int j = 0; j < N; j++) 
      // Do something 
    } 
} 

Bỏ qua những thứ như bỏ qua specifiers tin trong vòng lặp for, có cách nào mà tôi có thể ngã ba đề bên ngoài bên ngoài của tôi vòng lặp để tôi chỉ có thể song song vòng lặp bên trong? Từ sự hiểu biết của tôi (xin vui lòng làm cho tôi đúng nếu tôi sai), tất cả các chủ đề sẽ thực hiện vòng lặp bên ngoài. Tôi không chắc chắn về hành vi của vòng lặp bên trong, nhưng tôi nghĩ rằng for sẽ phân phối các khối cho mỗi chủ đề gặp phải nó.

Điều tôi muốn làm là không phải ngã ba/tham gia iterations lần mà chỉ thực hiện một lần trong vòng ngoài. Đây có phải là chiến lược đúng đắn để làm như vậy không?

Điều gì xảy ra nếu có một vòng lặp ngoài khác không được song song? Đó là ...

#pragma omp parallel 
{ 

    for (int i = 0; i < iterations; i++) { 
     for(int k = 0; k < innerIterations; k++) { 
      #pragma omp for 
      for (int j = 0; j < N; j++) 
       // Do something 

      // Do something else 
     } 
    } 
} 

Thật tuyệt nếu có ai đó chỉ cho tôi một ví dụ về ứng dụng lớn song song bằng OpenMP để tôi có thể hiểu rõ hơn về các chiến lược sử dụng khi sử dụng OpenMP. Tôi không thể tìm thấy bất kỳ thứ gì.

Làm rõ: Tôi đang tìm các giải pháp không thay đổi thứ tự vòng lặp hoặc liên quan đến việc chặn, lưu vào bộ nhớ cache và các cân nhắc hiệu suất chung. Tôi muốn hiểu làm thế nào điều này có thể được thực hiện trong OpenMP trên cấu trúc vòng lặp như quy định. Các // Do something có thể hoặc không có phụ thuộc, giả sử rằng họ làm và bạn không thể di chuyển mọi thứ xung quanh.

+0

Có thể bạn có thể đưa ra một ví dụ về những gì bạn muốn làm. Tôi có nghĩa là điền vào mã // làm điều gì đó –

+0

@raxman, Điều đó sẽ không giúp ích gì. Điều này có nghĩa là yêu cầu giải pháp chung cho vấn đề như vậy, không phải là giải pháp cho một ứng dụng cụ thể. – Pochi

+0

Bạn có thể tiếp tục và upvote/chấp nhận một số câu trả lời. Có vẻ như mọi người bỏ một số nỗ lực và nhận được số tiền rất nhỏ cho tất cả những điều đó. –

Trả lời

1

Tôi không chắc chắn tôi có thể trả lời câu hỏi của bạn. Tôi đã chỉ sử dụng OpenMP trong một vài tháng nay nhưng khi tôi cố gắng trả lời các câu hỏi như thế này, tôi thực hiện một số bài kiểm tra printf thế giới như tôi thấy bên dưới. Tôi nghĩ điều đó có thể giúp trả lời các câu hỏi của bạn. Ngoài ra hãy thử #pragma omp for nowait và xem điều gì sẽ xảy ra.

Chỉ cần đảm bảo khi bạn "// Làm điều gì đó và // Thực hiện điều gì đó khác" mà bạn không ghi vào cùng một địa chỉ bộ nhớ và tạo điều kiện cho cuộc đua. Ngoài ra, nếu bạn đang làm rất nhiều việc đọc và viết, bạn cần suy nghĩ về cách sử dụng bộ nhớ cache hiệu quả.

#include "stdio.h" 
#include <omp.h> 
void loop(const int iterations, const int N) { 
    #pragma omp parallel 
    { 
     int start_thread = omp_get_thread_num(); 
     printf("start thread %d\n", start_thread); 
     for (int i = 0; i < iterations; i++) { 
      printf("\titeration %d, thread num %d\n", i, omp_get_thread_num()); 
      #pragma omp for 
      for (int j = 0; j < N; j++) { 
       printf("\t\t inner loop %d, thread num %d\n", j, omp_get_thread_num()); 
      } 
     } 
    } 
} 

int main() { 
    loop(2,30); 
} 

Xét về hiệu suất, bạn có thể cân nhắc hợp nhất vòng lặp của bạn như thế này.

#pragma omp for 
for(int n=0; n<iterations*N; n++) { 
    int i = n/N; 
    int j = n%N;  
    //do something as function of index i and j 
} 
0

Rất khó để trả lời vì nó thực sự phụ thuộc vào các phụ thuộc bên trong mã của bạn. Tuy nhiên, một cách tổng quát để giải quyết này là để đảo ngược làm tổ của các vòng, như thế này:

#pragma omp parallel 
{ 
    #pragma omp for 
    for (int j = 0; j < N; j++) { 
     for (int i = 0; i < iterations; i++) { 
      // Do something 
     } 
    } 
} 

Tắt nhiên, điều này có thể hoặc có thể không thực hiện được, phụ thuộc vào mã của bạn bên trong vòng lặp là gì.

3

Cách bạn xử lý hai vòng cho phù hợp với tôi, theo nghĩa là nó đạt được hành vi bạn muốn: vòng lặp ngoài không song song, trong khi vòng lặp bên trong là.

Để làm rõ hơn về những gì xảy ra, tôi sẽ cố gắng thêm một số lưu ý để mã của bạn:

#pragma omp parallel 
{ 
    // Here you have a certain number of threads, let's say M 
    for (int i = 0; i < iterations; i++) { 
     // Each thread enters this region and executes all the iterations 
     // from i = 0 to i < iterations. Note that i is a private variable. 
     #pragma omp for 
     for (int j = 0; j < N; j++) { 
      // What happens here is shared among threads so, 
      // according to the scheduling you choose, each thread 
      // will execute a particular portion of your N iterations 
     } // IMPLICIT BARRIER    
    } 
} 

Các ngầm rào cản là một điểm đồng bộ hóa nơi đề chờ đợi nhau. Như một quy tắc chung của ngón tay cái, do đó, thích hợp hơn để so sánh các vòng ngoài thay vì vòng trong, vì điều này sẽ tạo một điểm đồng bộ hóa cho các lần lặp iterations*N (thay vì các điểm iterations bạn đang tạo ở trên).

+0

Vòng lặp ngoài được cho là chỉ định nhiều đường đi của một số thuật toán, do đó nó không thể song song. Xin lỗi nếu tôi không rõ về điều đó. – Pochi

+0

Vòng lặp ngoài không được song song, vì không có chỉ thị trang tính trên nó – Massimiliano

+0

Nếu bạn chạy các kiểm tra "hello world printf" với mã tôi đề xuất, nó sẽ hiển thị tất cả điều này. Bạn có thể thấy rằng nếu bạn thêm nhãn nowait thì rào cản sẽ bị xóa. Nói cách khác mà không phải chờ đợi vòng lặp bên ngoài không song song và với nó nó được. –