параллельная обработка — сумма гармонической прогрессии c ++ MPI и OpenMP

Я пытаюсь создать параллельную версию проблемы «Harmonic Progression Sum», используя MPI и opemMP вместе. Но на выходе разные процессы друг друга.

Может ли кто-нибудь помочь мне решить эту проблему?

Параллельная программа: (MPI и 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;
}

Примеры:

Входные данные:

#define d 10
#define n 1000

Выход:

7,4854708606

Входные данные:

#define d 12
#define n 7

Выход:

2,592857142857

6

Решение

Вы ошиблись здесь:

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

...
}

Вы должны сначала вычислить, а затем выполнить уменьшение, а не наоборот. Изменить на:

void HPS(char* output) {
...

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

Поскольку вы хотите использовать MPI + OpenMP, вы также можете оставить это:

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

быть разделенным между процессами. И внутренний цикл делят между потоками:

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

таким образом имея что-то вроде этого:

    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;
}
}

Вы также можете, если вы предпочитаете (это похоже на то, что вы сделали), разделить количество работы внешнего цикла на все параллельные задачи (потоки / процесс), например так:

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)

...
}

Обратите внимание, что я не говорю, что это даст вам лучшую производительность, но это только начало. После того, как ваш алгоритм правильно работает в MPI + OpenMP, вы можете перейти к более сложным подходам.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]