2010-02-07 6 views
6

Tôi khá mới đối với OpenMP và tôi đang cố bắt đầu một chuỗi riêng lẻ để xử lý từng mục trong một mảng 2D.Bắt đầu một chuỗi cho mỗi vòng lặp bên trong trong OpenMP

Vì vậy, về cơ bản, điều này:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) 
    for (i = 0; i < dimension; i++) { 
     for (int j = 0; j < dimension; j++) { 
      a[i][j] = b[i][j] + c[i][j]; 

Điều này trên thực tế bắt đầu một chủ đề cho từng hạng mục 2D hay không:

for (i = 0; i < dimension; i++) { 
    for (int j = 0; j < dimension; j++) { 
     a[i][j] = b[i][j] + c[i][j]; 

Những gì tôi đang làm điều này là gì? Làm thế nào tôi sẽ kiểm tra điều đó? Nếu nó là sai, cách chính xác để làm điều đó là gì? Cảm ơn!

Lưu ý: Mã đã được đơn giản hóa rất nhiều

+0

thể muốn gắn thẻ nó với ngôn ngữ bạn đang sử dụng, mặc dù bạn phải xóa một trong các thẻ hiện tại. –

+0

Điểm tốt mmyers - để tham khảo có vẻ như ông đang sử dụng c/c + + (openMP là c/C++ và fortran chỉ) –

Trả lời

7

Chỉ vòng lặp ngoài song song trong mẫu mã của bạn. Bạn có thể kiểm tra bằng cách in omp_get_thread_num() trong vòng lặp bên trong và bạn sẽ thấy rằng, đối với một số i, số thứ tự là giống nhau (tất nhiên, thử nghiệm này là minh chứng hơn là dứt khoát vì các lần chạy khác nhau sẽ cho kết quả khác nhau). Ví dụ, với:

#include <stdio.h> 
#include <omp.h> 
#define dimension 4 

int main() { 
    #pragma omp parallel for 
    for (int i = 0; i < dimension; i++) 
     for (int j = 0; j < dimension; j++) 
      printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); 
    } 

tôi nhận được:

i=1, j=0, thread = 1 
i=3, j=0, thread = 3 
i=2, j=0, thread = 2 
i=0, j=0, thread = 0 
i=1, j=1, thread = 1 
i=3, j=1, thread = 3 
i=2, j=1, thread = 2 
i=0, j=1, thread = 0 
i=1, j=2, thread = 1 
i=3, j=2, thread = 3 
i=2, j=2, thread = 2 
i=0, j=2, thread = 0 
i=1, j=3, thread = 1 
i=3, j=3, thread = 3 
i=2, j=3, thread = 2 
i=0, j=3, thread = 0 

Đối với phần còn lại của mã của bạn, bạn có thể muốn đưa thêm chi tiết trong một câu hỏi mới (rất khó để nói từ mẫu nhỏ), nhưng ví dụ, bạn không thể đặt private(j) khi j chỉ được khai báo sau. Nó được tự động riêng tư trong ví dụ của tôi ở trên. Tôi đoán diff là một biến mà chúng ta không thể thấy trong mẫu. Ngoài ra, biến vòng lặp i là tự động tư nhân (từ version 2.5 spec - cùng trong spec 3,0)

Các vòng lặp biến trong cho vòng một cho hay song song cho xây dựng là tư nhân trong đó xây dựng .

Chỉnh sửa: Tất cả các điều trên đều đúng cho mã mà bạn và tôi đã hiển thị, nhưng bạn có thể quan tâm đến những điều sau. Đối với OpenMP Phiên bản 3.0 (có sẵn trong ví dụ: gcc version 4.4, nhưng không phải phiên bản 4.3), có điều khoản collapse nơi bạn có thể viết mã như bạn có, nhưng với #pragma omp parallel for collapse (2) để song song cho cả hai vòng (xem the spec).

Sửa: OK, tôi đã tải về gcc 4.5.0 và chạy đoạn mã trên, nhưng sử dụng collapse (2) để có được kết quả như sau, cho thấy các vòng trong tại song song:

i=0, j=0, thread = 0 
i=0, j=2, thread = 1 
i=1, j=0, thread = 2 
i=2, j=0, thread = 4 
i=0, j=1, thread = 0 
i=1, j=2, thread = 3 
i=3, j=0, thread = 6 
i=2, j=2, thread = 5 
i=3, j=2, thread = 7 
i=0, j=3, thread = 1 
i=1, j=1, thread = 2 
i=2, j=1, thread = 4 
i=1, j=3, thread = 3 
i=3, j=1, thread = 6 
i=2, j=3, thread = 5 
i=3, j=3, thread = 7 

Comments here (tìm kiếm "Cách giải quyết") cũng phù hợp với công việc xung quanh trong phiên bản 2.5 nếu bạn muốn song song cả hai vòng, nhưng thông số phiên bản 2.5 được trích dẫn ở trên khá rõ ràng (xem các ví dụ không phù hợp trong phần A.35).

+0

Cảm ơn, sụp đổ là thủ thuật tôi đang tìm kiếm! – achinda99

0

Bạn có thể thử sử dụng các giá trị song song omp lồng nhau (sau khi gọi omp_set_nested(1)), nhưng chúng không được hỗ trợ trên tất cả các triển khai openmp.

Vì vậy, tôi đoán để làm cho một số lưới 2D và bắt đầu tất cả các chủ đề trên lưới điện từ duy nhất cho (ví dụ cho 4x4 cố định lưới thread):

#pragma omp parallel for 
for(k = 0; k < 16; k++) 
{ 
    int i,j,i_min,j_min,i_max,j_max; 
    i_min=(k/4) * (dimension/4); 
    i_max=(k/4 + 1) * (dimension/4); 
    j_min=(k%4) * (dimension/4); 
    j_max=(k%4 + 1) * (dimension/4); 

    for(i=i_min;i<i_max;i++) 
     for(j=j_min;j<j_max;j++) 
     f(i,j); 

}