2012-11-24 32 views
6

Tôi đang cố gắng tạo ra một phiên bản song song của vấn đề "Hòa âm lũy tiến" bằng cách sử dụng MPI và opemMP cùng nhau. Nhưng đầu ra là differents mỗi quá trình khác.Sự tiến triển hài hòa tổng cộng c + + MPI và OpenMP

Ai đó có thể giúp tôi hoàn thành vấn đề này?

Chương trình song song: (Bộ KH & ĐT và OpenMP)

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <sstream> 
#include <time.h> 
#include <omp.h> 
#include <mpi.h> 

#define d 10 //Numbers of Digits (Example: 5 => 0,xxxxx) 
#define n 1000 //Value of N (Example: 5 => 1/1 + 1/2 + 1/3 + 1/4 + 1/5) 

using namespace std; 

double t_ini, t_fim, t_tot; 

int getProcessId(){ 
    int rank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    return rank; 
} 

int numberProcess(){ 
    int numProc; 
    MPI_Comm_size(MPI_COMM_WORLD, &numProc); 
    return numProc; 
} 

void reduce(long unsigned int digits1 []) 
{ 
    long unsigned int digits2[d + 11]; 
    int i = 0; 
    for(i = 0; i < d + 11; i++) digits2[i] = 0; 

    MPI_Allreduce(digits1, digits2,(d+11),MPI_INT,MPI_SUM,MPI_COMM_WORLD); 

    for(i = 0; i < d + 11; i++) digits1[i] = digits2[i]; 

} 

void slave(long unsigned int *digits) 
{ 
    int idP = getProcessId(), numP = numberProcess(); 

    int i; 
    long unsigned int digit; 
    long unsigned int remainder; 

    #pragma omp parallel for private(i, remainder, digit) 
    for (i = idP+1; i <= n; i+=numP){ 
     remainder = 1; 
     for (digit = 0; digit < d + 11 && remainder; ++digit) { 
      long unsigned int div = remainder/i; 
      long unsigned int mod = remainder % i; 
      #pragma omp atomic 
      digits[digit] += div; 
      remainder = mod * 10; 
     } 
    } 
} 

void HPS(char* output) { 
    long unsigned int digits[d + 11]; 

    for (int digit = 0; digit < d + 11; ++digit) 
     digits[digit] = 0; 

    reduce(digits); 
    slave(digits); 

    for (int i = d + 11 - 1; i > 0; --i) { 
     digits[i - 1] += digits[i]/10; 
     digits[i] %= 10; 
    } 

    if (digits[d + 1] >= 5) ++digits[d]; 


    for (int i = d; i > 0; --i) { 
     digits[i - 1] += digits[i]/10; 
     digits[i] %= 10; 
    } 
    stringstream stringstreamA; 
    stringstreamA << digits[0] << ","; 


    for (int i = 1; i <= d; ++i) stringstreamA << digits[i]; 

    string stringA = stringstreamA.str(); 
    stringA.copy(output, stringA.size()); 
} 

int main(int argc, char **argv) { 
    MPI_Init(&argc,&argv); 

    t_ini = clock(); 

    //Parallel MPI com OpenMP Method 
    cout << "Parallel MPI com OpenMP Method: " << endl; 
    char output[d + 10]; 
    HPS(output); 

    t_fim = clock(); 
    t_tot = t_fim-t_ini; 

    cout << "Parallel MPI with OpenMP Method: " << (t_tot/1000) << endl; 
    cout << output << endl; 

    MPI_Finalize(); 

    system("PAUSE"); 
    return 0; 
} 

Ví dụ:

Input:

#define d 10 
#define n 1000 

Output:

7,4854708606 

Input:

#define d 12 
#define n 7 

Output:

2,592857142857 

Trả lời

4

Bạn có một sai lầm ông re:

void HPS(char* output) { 
    ... 
    reduce(digits); 
    slave(digits); 

    ... 
} 

Trước tiên bạn phải tính toán và thực hiện giảm không theo cách khác. Thay đổi thành:

void HPS(char* output) { 
    ... 

    slave(digits); 
    reduce(digits); 
    ... 
} 

Vì bạn muốn sử dụng MPI + OpenMP, bạn cũng có thể rời khỏi đây:

for (i = idP+1; i <= n; i+=numP) 

được phân chia giữa các quá trình. Và vòng lặp phân chia bên trong một trong những chủ đề:

#pragma omp parallel for private(remainder) 
for (digit = 0; digit < d + 11 && remainder; ++digit) 

do đó có một cái gì đó như thế này:

for (i = idP+1; i <= n; i+=numP){ 
     remainder = 1; 
     #pragma omp parallel for private(i, remainder, digit) 
     for (digit = 0; digit < d + 11 && remainder; ++digit) { 
      long unsigned int div = remainder/i; 
      long unsigned int mod = remainder % i; 
      #pragma omp atomic 
      digits[digit] += div; 
      remainder = mod * 10; 
     } 
    } 

Bạn cũng có thể, nếu bạn thích (nó cũng tương tự như những gì bạn đã làm), chia số công việc của vòng ngoài thông qua tất cả các nhiệm vụ song song (chủ đề/quá trình), như thế này:

int idT = omp_get_thread_num();  // Get the thread id 
int numT = omp_get_num_threads(); // Get the number of threads. 
int numParallelTask = numT * numP; // Number of parallel task 
int start = (idP+1) + (idT*numParallelTask); // The first position here each thread will work 

#pragma omp parallel 
{ 

for (i = start; i <= n; i+=numParallelTask) 

... 
} 

Lưu ý rằng tôi không nói điều này sẽ cho bạn hiệu suất tốt nhất, nhưng nó là một sự khởi đầu. Sau khi bạn nhận được thuật toán của bạn đúng cách làm việc trong MPI + OpenMP bạn có thể tiến hành tiếp cận tinh vi hơn nữa.