谐波级数和 c++ MPI 和 OpenMP
Posted
技术标签:
【中文标题】谐波级数和 c++ MPI 和 OpenMP【英文标题】:Harmonic progression sum c++ MPI and OpenMP 【发布时间】:2012-11-12 17:49:57 【问题描述】:我正在尝试同时使用 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
【问题讨论】:
【参考方案1】:你这里有一个错误:
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 中正常运行后,您可以继续使用更复杂的方法。
【讨论】:
以上是关于谐波级数和 c++ MPI 和 OpenMP的主要内容,如果未能解决你的问题,请参考以下文章