2011-11-07 26 views
5

Tôi có một vấn đề rất lạ sử dụng OpenMP trong C++ của tôi mã:OpenMP - Easy Loop, nhưng vẫn vô hạn?

void update(double *source, double *target, int n) 
{ 
    target[0] = source[0]; 
    target[n-1] = source[n-1]; 
    #pragma omp parallel for 
    for(int i = 1; i < n-1; ++i) 
     target[i] = (1.0/3.0) * (source[i-1] + source[i] + source[i+1]); 
} 

Cả hai nguồn và mục tiêu là mảng đôi với các yếu tố n. Mã hoạt động tốt khi sử dụng nó mà không có OpenMP. Nhưng ngay sau khi tôi sử dụng pragma, mã dường như bị kẹt trong vòng lặp này. Vấn đề là: tôi hoàn toàn KHÔNG có IDEA tại sao. Hy vọng mọi người có thể giúp tôi

+0

biên dịch và chạy tốt với GCC 4.6.1. Bạn sử dụng trình biên dịch nào? –

+0

Bạn có thể thêm một số chi tiết về trình biên dịch và hệ điều hành không? – talonmies

+0

gcc 4.2.1 trên MacOS Snow Leopard, chính xác: 686-apple-darwin10-g ++ - 4.2.1 (GCC) 4.2.1 (Apple Inc. xây dựng 5666) (dấu chấm 3) – Chris

Trả lời

2

Mức độ lớn bằng n?

Lập lịch mặc định cho chỉ thị OpenMP parallel for là triển khai cụ thể. Dường như trong GOMP (triển khai OpenMP được sử dụng bởi gcc), mặc định là (dynamic,1) theo số documentation here. Điều này có nghĩa là mỗi luồng đang truy cập (tại các địa chỉ bộ nhớ i-1i+1) được tải bởi các chuỗi lân cận, điều này có thể dẫn đến việc sử dụng bộ nhớ cache kém. Trên các kiến ​​trúc CPU hiện đại, các hoạt động stencil như thế này thường xuyên bị ràng buộc về bộ nhớ và nhạy cảm với bộ nhớ đệm. Bạn có thể thử chỉ định lịch biểu với các khối lớn hơn, ví dụ:

#pragma omp parallel for schedule(dynamic,1024) 

Tôi chỉ sử dụng 1024 ở đây làm ví dụ. Trong thực tế, bạn nên thử nghiệm để tìm ra yếu tố chunking tối ưu (hoặc tìm kiếm một cách hệ thống với một quét tham số, một quá trình thường được gọi là "tự động điều chỉnh"). Hoặc bạn có thể chọn một giá trị dựa trên lý thuyết hơn, ví dụ bằng cách lấy nó từ kích thước bộ nhớ cache L1 hoặc L2 của CPU của bạn. Hoặc thay vào đó bạn có thể thử lập lịch tĩnh, vì số lượng tính toán bên trong vòng lặp for là thống nhất giữa các luồng và chi phí của trình lên lịch động có thể gây ra tắc nghẽn. Nếu bạn chỉ định

#pragma omp parallel for schedule(static) 

không có kích thước chunk, thì mỗi chuỗi sẽ được chỉ định một đoạn duy nhất có cùng kích thước.

Cuối cùng, bạn cũng có thể muốn ghim các chuỗi OpenMP vào lõi CPU của chính chúng. Bạn có thể thực hiện việc này bằng biến môi trường GOMP_CPU_AFFINITY.

Edit:

Tôi chỉ chơi đùa với các chương trình thử nghiệm sau đây được biên soạn với gcc 4.2.1, và tôi nghĩ rằng các tài liệu tôi liên kết với trên là không chính xác. Dường như GOMP mặc định là schedule(static).

#include <stdio.h> 
#include <omp.h> 

int main(int argc, char** argv) 
{ 
    int i; 
    #pragma omp parallel for 
    for (i=0; i<15; i++) { 
     int id = omp_get_thread_num(); 
     printf("%d assigned to thread %d\n", i, id); 
    } 
} 

Và đầu ra với hai chủ đề là:

$ ./test_sched | sort -n 
0 assigned to thread 0 
1 assigned to thread 0 
2 assigned to thread 0 
3 assigned to thread 0 
4 assigned to thread 0 
5 assigned to thread 0 
6 assigned to thread 0 
7 assigned to thread 0 
8 assigned to thread 1 
9 assigned to thread 1 
10 assigned to thread 1 
11 assigned to thread 1 
12 assigned to thread 1 
13 assigned to thread 1 
14 assigned to thread 1 
+0

Mặc định khi không có lịch biểu được xác định thực sự là phụ thuộc, nhưng AFAIK thường là 'tĩnh'. Liên kết GOMP đề xuất '(động, 1)' là mặc định thực sự đề cập đến trường hợp trong đó 'lịch biểu (thời gian chạy)' được sử dụng. – eran

Các vấn đề liên quan