c++ - 谐波级数和 c++ MPI

标签 c++ c parallel-processing mpi openmpi

我正在尝试使用 MPI 制作并行版本的“Harmonic Progression Sum”问题。 但我是 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

最佳答案

我假设您想并行化这部分:

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

每个进程都会有一个数组digits的拷贝;在并行 for 之后,主进程使用 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 将从 1 到 n/4 执行方法 escravo 内的 out for 循环,但随后进程 2 将从 1 执行到 2n/4...因此,您有不同的进程执行相同的迭代,而您真正想要的是在流程之间划分这些迭代。

关于c++ - 谐波级数和 c++ MPI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13504098/

相关文章:

c++ - 类 Python C++ 装饰器

检查文件是否存在和读取权限

c - #ifndef 指令的使用

haskell - 为什么 MVar 不适用于 `par` ?

c# - 并行循环性能下降

r - R中的doRedis/foreach GBM并行处理错误

c++ - Spirit.X3 中的递归规则

c++ - 在 QT 中创建一个简单的时钟

c++ - 在 Google 测试框架的测试用例中访问 argc 和 argv 的方法是什么?

c - C语言中的for循环语法执行