3

在一个MPI应用程序中,我有一个分布式浮点数组和两个“并行”整数数组:对于每个浮点值,都有两个关联的整数来描述相应的值。为了缓存效率,我想将它们视为三个不同的数组,即作为数组结构,而不是结构数组。

现在,我必须将所有这些值收集到第一个节点中。我可以在一个通信指令中做到这一点,通过定义一个MPI类型,对应于一个结构,一个浮点数和两个整数。但这将迫使我使用结构数组模式而不是数组结构一。

所以,我可以选择:

  • 执行三种不同的通信,每个阵列一个,并保持阵列排列的有效结构
  • 定义MPI类型,执行单个通信,并通过调整我的算法或重新排列数据来处理生成的结构数组

您是否知道第三种选择可以让我做到两全其美,即进行单一通信并保持缓存高效配置?

4

2 回答 2

0

例如,通过使用MPI_Type_create_struct的 *array_of_blocklength* 参数

// @file mpi_compound.cpp
#include <iterator>
#include <cstdlib> // for rng
#include <ctime>   // for rng inits
#include <iostream>
#include <algorithm>

#include <mpi.h>

const std::size_t N = 10; 

struct Asset {
    float f[N];
    int m[N], n[N];

    void randomize() {
        srand(time(NULL));
        srand48(time(NULL));
        std::generate(&f[0], &f[0] + N, drand48);
        std::generate(&n[0], &n[0] + N, rand);
        std::generate(&m[0], &m[0] + N, rand);
    }
};


int main(int argc, char* argv[]) {

    MPI_Init(&argc,&argv);
    int rank,comm_size;
    MPI_Status stat;

    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&comm_size);

    Asset a;

    MPI_Datatype types[3] = { MPI_FLOAT, MPI_INT, MPI_INT };
    int bls[3] = { N, N, N }; 
    MPI_Aint disps[3];
    disps[0] = 0;
    disps[1] = int(&(a.m[0]) - (int*)&a)*sizeof(int);
    disps[2] = int(&(a.n[0]) - (int*)&a)*sizeof(int);

    MPI_Datatype MPI_USER_ASSET;

    MPI_Type_create_struct(3, bls, disps, types, &MPI_USER_ASSET);
    MPI_Type_commit(&MPI_USER_ASSET);

    if(rank==0)  {
        a.randomize();
        std::copy(&a.f[0], &a.f[0] + N, std::ostream_iterator<float>(std::cout, " "));
        std::cout << std::endl;
        std::copy(&a.m[0], &a.m[0] + N, std::ostream_iterator<int>(std::cout, " "));
        std::cout << std::endl;
        std::copy(&a.n[0], &a.n[0] + N, std::ostream_iterator<int>(std::cout, " "));
        std::cout << std::endl;
        MPI_Send(&a.f[0],1,MPI_USER_ASSET,1,0,MPI_COMM_WORLD);
    } else {
        MPI_Recv(&a.f[0],1,MPI_USER_ASSET,0,0,MPI_COMM_WORLD, &stat);
        std::cout << "\t=> ";
        std::copy(&a.f[0], &a.f[0] + N, std::ostream_iterator<float>(std::cout, " "));
        std::cout << std::endl << "\t=> ";
        std::copy(&a.m[0], &a.m[0] + N, std::ostream_iterator<int>(std::cout, " "));
        std::cout << std::endl << "\t=> ";
        std::copy(&a.n[0], &a.n[0] + N, std::ostream_iterator<int>(std::cout, " "));
        std::cout << std::endl;
    }

    MPI_Type_free(&MPI_USER_ASSET);

    MPI_Finalize();
    return 0;
}

曾与

mpirun -n 2 ./mpi_compound

在 x86_86 linux 和 g++ 4.4.5-8 上使用 mpich2 v1.5 (HYDRA) - 基于 mpic++

于 2013-05-20T08:36:34.090 回答
0

你看一下打包和拆包。

http://www.mpi-forum.org/docs/mpi-11-html/node62.html

但是,我认为如果您想经常传递相同的“结构”,您应该定义自己的 MPI 派生类型。

于 2013-05-20T08:19:12.957 回答