是的,您可以针对特定任务执行此操作。但你不应该。
考虑如何实现这一点;开始部分将分发数据,结束部分将带回答案:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mpi.h>
typedef struct state_t {
int globaln;
int localn;
int *locals;
int *offsets;
double *localin;
double *localout;
double (*map)(double);
} state;
state *begin_parallel_mapandsum(double *in, int n, double (*map)(double)) {
state *s = malloc(sizeof(state));
s->globaln = n;
s->map = map;
/* figure out decomposition */
int size, rank;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
s->locals = malloc(size * sizeof(int));
s->offsets = malloc(size * sizeof(int));
s->offsets[0] = 0;
for (int i=0; i<size; i++) {
s->locals[i] = (n+i)/size;
if (i < size-1) s->offsets[i+1] = s->offsets[i] + s->locals[i];
}
/* allocate local arrays */
s->localn = s->locals[rank];
s->localin = malloc(s->localn*sizeof(double));
s->localout = malloc(s->localn*sizeof(double));
/* distribute */
MPI_Scatterv( in, s->locals, s->offsets, MPI_DOUBLE,
s->localin, s->locals[rank], MPI_DOUBLE,
0, MPI_COMM_WORLD);
return s;
}
double end_parallel_mapandsum(state **s) {
double localanswer=0., answer;
/* sum up local answers */
for (int i=0; i<((*s)->localn); i++) {
localanswer += ((*s)->localout)[i];
}
/* and get global result. Everyone gets answer */
MPI_Allreduce(&localanswer, &answer, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
free( (*s)->localin );
free( (*s)->localout );
free( (*s)->locals );
free( (*s)->offsets );
free( (*s) );
return answer;
}
int main(int argc, char **argv) {
int rank;
double *inputs;
double result;
int n=100;
const double pi=4.*atan(1.);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
inputs = malloc(n * sizeof(double));
for (int i=0; i<n; i++) {
inputs[i] = 2.*pi/n*i;
}
}
state *s=begin_parallel_mapandsum(inputs, n, sin);
for (int i=0; i<s->localn; i++) {
s->localout[i] = (s->map)(s->localin[i]);
}
result = end_parallel_mapandsum(&s);
if (rank == 0) {
printf("Calculated result: %lf\n", result);
double trueresult = 0.;
for (int i=0; i<n; i++) trueresult += sin(inputs[i]);
printf("True result: %lf\n", trueresult);
}
MPI_Finalize();
}
这种持续的分发/收集是一个可怕的通信负担,总结几个数字,与整个分布式内存计算模型背道而驰。
第一个近似值,共享内存方法——OpenMP、pthreads、IPP,你有什么——是关于更快地扩展计算;关于在同一块内存中投入更多处理器。另一方面,分布式内存计算是将计算规模扩大到更大;关于使用比单台计算机更多的资源,尤其是内存。使用 MPI 的最大优势是当您处理无法容纳任何节点内存的问题集时。因此,在进行分布式内存计算时,您可以避免将所有数据放在任何一个地方。
即使您只是在节点上使用 MPI 来使用所有处理器,牢记这种基本方法也很重要。上述分散/收集方法只会降低性能。更惯用的分布式内存计算方法是程序的逻辑已经分布了数据——也就是说,你begin_parallel_region
和end_parallel_region
上面的代码在一开始就已经内置到循环上面的代码中。然后,每个循环只是
for( int i=0 ; i<localn ; i++ )
{
s = s + sin(x[i]);
}
当您需要在任务之间交换数据(或减少结果,或者您拥有什么)时,您可以调用 MPI 函数来执行这些特定任务。