2012-08-17 24 views
16

Tôi gặp vấn đề về biên dịch openmp.Cách biên dịch openmp bằng g ++

Giống như đoạn mã sau:

#include <iostream> 
#include <pthread.h> 
#include <omp.h> 
#include <semaphore.h> 
#include <stack> 
using namespace std; 
sem_t empty,full; 
stack<int> stk; 
void produce(int i) 
{ 
    { 
    sem_wait(&empty); 
      cout<<"produce "<<i*i<<endl; 
      stk.push(i*i); 
    sem_post(&full); 
    } 
} 
void consume1(int &x) 
{ 
    sem_wait(&full); 
      int data=stk.top(); 
      stk.pop(); 
      x=data; 
    sem_post(&empty); 
} 
void consume2() 
{ 
    sem_wait(&full); 
      int data=stk.top(); 
      stk.pop(); 
      cout<<"consume2 "<<data<<endl; 
    sem_post(&empty); 
} 
int main() 
{ 
    sem_init(&empty,0,1); 
    sem_init(&full,0,0); 
    pthread_t t1,t2,t3; 
    omp_set_num_threads(3); 
    int TID=0; 
    #pragma omp parallel private(TID) 
    { 
      TID=omp_get_thread_num(); 
      if(TID==0) 
      { 
      cout<<"There are "<<omp_get_num_threads()<<" threads"<<endl; 
      for(int i=0;i<5;i++) 
        produce(i); 
      } 
      else if(TID==1) 
      { 
        int x; 
        while(true) 
        { 
          consume1(x); 
          cout<<"consume1 "<<x<<endl; 
        } 
      } 
      else if(TID==2) 
      { 
        int x; 
        while(true) 
        { 
          consume1(x); 
          cout<<"consume2 "<<x<<endl; 
        } 
      } 
    } 
    return 0; 
} 

Đầu tiên, tôi biên dịch nó bằng cách sử:

g++ test.cpp -fopenmp -lpthread 

Và, tôi có câu trả lời đúng, có 3 chủ đề hoàn toàn.

Nhưng, khi tôi làm biên dịch như thế này:

g++ -c test.cpp -o test.o 
g++ test.o -o test -fopenmp -lpthread 

có chỉ duy nhất một thread.

Bất cứ ai cũng có thể cho tôi biết cách biên dịch mã này một cách chính xác. Thankyou trước.

+3

Tôi nghĩ rằng các pragmas OpenMP bị bỏ qua trừ khi bạn có '-fopenmp'. Vì vậy, bạn sẽ cần '-fopenmp' trên tất cả các mô-đun có pragmas OpenMP. – Mysticial

+0

@Mysticial Bạn nghĩ tôi nên thêm -fopenmp khi biên dịch tệp .cpp thành .o? –

+1

Vâng. Hãy thử 'g ++ -c test.cpp -o test.o -fopenmp'. Tôi sẽ làm cho nó một câu trả lời nếu nó hoạt động. – Mysticial

Trả lời

15

Các pragmas OpenMP chỉ được bật khi được biên dịch với -fopenmp. Nếu không, họ hoàn toàn bị bỏ qua bởi trình biên dịch. (Do đó, chỉ có 1 chuỗi ...)

Do đó, bạn sẽ cần phải thêm -fopenmp vào việc biên soạn mọi mô-đun đơn lẻ sử dụng OpenMP. (Trái ngược với chỉ là bước liên kết chính thức.)

g++ -c test.cpp -o test.o -fopenmp 
g++ test.o -o test -fopenmp -lpthread 
22

OpenMP là một tập hợp đang chuyển pragmas, tức là họ chỉ được áp dụng tại thời gian biên dịch. Bạn không thể áp dụng chuyển đổi mã cho một mã đối tượng đã được biên dịch (ok, bạn có thể, nhưng nó liên quan nhiều đến quá trình và ngoài phạm vi của những gì mà hầu hết các trình biên dịch làm những ngày này). Bạn cần -fopenmp trong giai đoạn liên kết chỉ để trình biên dịch tự động liên kết thư viện thời gian chạy OpenMP libgomp - nó không có gì khác đối với mã đối tượng.

Một lưu ý phụ, mặc dù về mặt kỹ thuật chính xác, mã của bạn thực hiện OpenMP theo cách không phải OpenMP. Trước tiên, bạn đã triển khai lại cấu trúc OpenMP sections. Vùng song song trong chức năng main của bạn có thể được viết lại trong một OpenMP cách hơn:

#pragma omp parallel sections 
{ 
    #pragma omp section 
    { 
     cout<<"There are "<<omp_get_num_threads()<<" threads"<<endl; 
     for(int i=0;i<5;i++) 
      produce(i); 
    } 
    #pragma omp section 
    { 
     int x; 
     while(true) 
     { 
      consume1(x); 
      cout<<"consume1 "<<x<<endl; 
     } 
    } 
    #pragma omp section 
    { 
     int x; 
     while(true) 
     { 
      consume1(x); 
      cout<<"consume2 "<<x<<endl; 
     } 
    } 
} 

(nếu bạn nhận được SIGILL khi chạy đoạn mã này với hơn ba chủ đề OpenMP, bạn đã gặp phải một lỗi trong GCC, đó sẽ là cố định trong bản phát hành sắp tới)

Thứ hai, bạn có thể muốn xem xét cấu trúc OpenMP task. Với nó, bạn có thể xếp hàng các đoạn mã được thực hiện đồng thời như các tác vụ của bất kỳ chuỗi nhàn rỗi nào. Thật không may nó đòi hỏi một trình biên dịch hỗ trợ OpenMP 3.0, mà quy tắc ra MSVC++ từ phương trình, nhưng chỉ khi bạn quan tâm đến tính di động cho Windows (và bạn rõ ràng là không, bởi vì bạn đang sử dụng chủ đề POSIX).

+3

+1 để vượt ra ngoài cuộc gọi nhiệm vụ để thực sự xem xét mã của OP chặt chẽ hơn. – Mysticial

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