3

MPIを使用して「調和数列和」問題の並列バージョンを作成しようとしています。しかし、私はMPIを初めて使用し、このメソッドをMPIで実行する方法がわかりません。これは、機能しないためです。

並列プログラム:

//#include "stdafx.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#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;

int numProcess, rank, msg, source, dest, tag, qtd_elemento;

int escravo(long unsigned int *digits, int ValueEnd)
{
    MPI_Status status;

    MPI_Recv(digits, (d + 11), MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

    for (int i = 1; i <= ValueEnd; ++i) {
        long unsigned int remainder = 1;
        for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit) {
            long unsigned int div = remainder / i;
            long unsigned int mod = remainder % i;
            digits[digit] += div;
            remainder = mod * 10;
        }
    }

    MPI_Send(&digits, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
}

void HPSSeguencial(char* output) {
    long unsigned int digits[d + 11];
    int DivN = n / 4; //Limiting slave.

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

    if (rank != 0){
        escravo(digits, (DivN * 1 ) );
        escravo(digits, (DivN * 2 ) );
        escravo(digits, (DivN * 3 ) );
        escravo(digits, (DivN * 4 ) );
    }

    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() {
    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &numProcess);

    char output[d + 10];
    HPSSeguencial(output);
    cout << output << endl;

    MPI_Finalize();

    system("PAUSE");
    return 0;
}

元のコード

#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <time.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;

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

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

    for (int i = 1; i <= n; ++i) {
        long unsigned int remainder = 1;
        for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit) {
            long unsigned int div = remainder / i;
            long unsigned int mod = remainder % i;
            digits[digit] += div;
            remainder = mod * 10;
        }
    }


    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() {

    char output[d + 10];
    HPS(output);
    cout << output<< endl;

    system("PAUSE");
    return 0;
}

例:

入力:

#define d 10
#define n 1000

出力:

7,4854708606╠╠╠╠╠╠╠╠╠╠╠╠

入力:

#define d 12
#define n 7

出力:

2,592857142857╠╠╠╠╠╠╠╠╠╠╠╠╠╠ÀÂ♂ü─¨@

よろしく

元のコード

http://regulus.pcs.usp.br/marathon/current/warmup.pdf

4

1 に答える 1

4

この部分を並列化することを想定しています。

for (int i = 1; i <= ValueEnd; ++i) 
{
        long unsigned int remainder = 1;
        for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit)
        {
            long unsigned int div = remainder / i;
            long unsigned int mod = remainder % i;
            digits[digit] += div;
            remainder = mod * 10;
        }
}

反復のためにそれぞれを各MPIプロセスで分割できます。

int idP = getProcessId(), numP = numberProcess();
for (int i = idP; i <= ValueEnd; i+=numP)
{
  ...
}

getProcessId()はプロセスIDを示し、プロセスのnumberProcess()数を示します。

int getProcessId(){
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    return rank;
}
// Get number of process
int numberProcess(){
    int numProc;
    MPI_Comm_size(MPI_COMM_WORLD, &numProc);
    return numProc;
}

各プロセスには、配列の数字のコピーがあります。の並列処理の後、マスタープロセスはMPI_reduceを使用してすべてのスレーブプロセスから結果を収集します。または、すべてのプロセスからの値を組み合わせて、結果をすべてのプロセスに配布する場合は、MPI_Allreduceを使用できます。

 long unsigned int digits[d + 11];
    int DivN = n / 4; //Limiting slave.

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

    if (rank != 0){
        escravo(digits, (DivN * 1 ) );
        escravo(digits, (DivN * 2 ) );
        escravo(digits, (DivN * 3 ) );
        escravo(digits, (DivN * 4 ) );
    }

上記のコードによると、プロセス0はメソッドを実行しませんescravo。さらに、プロセス間で作業を正しく分散していません。プロセス1はメソッド内のoutforループescravoを1からn/4まで実行しますが、プロセス2は1から2n / 4まで実行します...したがって、実際に必要なのは、同じ反復を実行するさまざまなプロセスがあります。これらの反復をプロセス間で分割します。

于 2012-11-22T00:37:29.073 に答える