使用MPI派生数据类型

时间:2012-01-05 14:35:55

标签: mpi derived-types

阅读this后,我仍然想知道发送C / C ++结构数据的最佳方法。事实上,我已决定使用派生类型,但我遇到了问题。

MPI_Init(...)之后,我有一个函数写在一个单独的文件(MPI_NewTypes.cpp / h)中,基本上用于提交新的数据类型。这是一个快照:

int loop_counter;
    msgInstallP InstallPStruct;
    MPI_Datatype MPI_MSGINSTALLP;
    MPI_Datatype type[4] = {MPI_INT, MPI_INT, MPI_INT, MPI_CHAR};
    int blocklen[4] = {
                        sizeof(InstallPStruct.type),
                        sizeof(InstallPStruct.location),
                        sizeof(InstallPStruct.processID),
                        sizeof(InstallPStruct.name)
                      };

    MPI_Aint     disp[4];
    int          base;
    MPI_Address( &InstallPStruct,                disp);
    MPI_Address( &InstallPStruct.location,       disp+1);
    MPI_Address( &InstallPStruct.processID,      disp+2);
    MPI_Address( &InstallPStruct.name,           disp+3);
    base = disp[0];

    for (loop_counter=0; loop_counter < 4; loop_counter++)
      {
        disp[loop_counter] = disp[loop_counter] - base;
      }

    MPI_Type_struct(
                    4, /*count of elements */
                    blocklen, /* array_of_blocklengths */
                    disp, /* array_of_displacements */
                    type, /* array_of_types */
                    &MPI_MSGINSTALLP /* newtype */
                    );

    MPI_Type_commit( &MPI_MSGINSTALLP);

在对不同文件中实现的函数进行几次函数调用之后,我使用的是新数据类型:MPI_MSGINSTALLP。但是,我的链接器抱怨它不知道这个新的派生类型是什么。表面上看,这是一个C / C ++ scopinq问题,但我说得不对。我如何确保每当我使用新的派生数据类型时,MPI会知道它存在?每次在应用程序中使用这种新类型时,我都不想重做所有提交。

我尝试将其放在MPI_NewTypes.h头文件中: MPI_Datatype MPI_MSGINSTALLP

希望mpic ++能够看到它,如果我在使用新数据类型的文件中包含此标头。

没有运气。

任何帮助?

根据建议,这是启动MPI的顶级文件:

 #include <atomic>
#include "mpi.h"
#include <iostream>
#include "Fifo.h"
#include <thread>
#include <fstream>
#include <unistd.h>
#include <mpi.h>
#include "GlobalSettings.h"
#include "Run.h"
#include "Add_MPI_Types.h"

int main(int argc, char **argv)
{
  int myrank;
  int desired_thread_support = MPI_THREAD_MULTIPLE;
  int provided_thread_support;

  MPI_Init_thread(&argc, &argv, desired_thread_support, &provided_thread_support);

  /* check if the thread support has been provided */
  if (provided_thread_support!=desired_thread_support)
    {
      std::cout << "MPI thread support not available! Aborted. " << std::endl;
    }

  MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);

  Add_MPI_Types();

  /* get rank information */
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

  /* Rank 0 is always the master, other ranks are slaves */
  if (MASTERNODE == myrank)
    {
      /* run the wrapper for master node */
      run(MASTERAPPLICATION);
    }
  else
    {
      /* run the wrapper for the slave node */
      run(SLAVEAPPLICATION);
    }
  MPI_Finalize();
  return 0;
}

此处,Add_MPI_Types();是提交新数据类型的函数,驻留在MPI_NewTypes.cpp / h文件中(已显示)。

run(...)函数也在另一个文件中定义,该文件实际上尝试执行MPI-Send / Recv:

  msgInstallP InstallPMessage;
  InstallPMessage = *(msgInstallP*)Data;
  //Add_MPI_msgInstallP_Type();
  MPI_Ssend(
            (void*)&InstallPMessage,             /* Payload */
            sizeof(msgInstallP),                 /* size of the payload */
            MPI_MSGINSTALLP,                      /* MPI Data type */
            InstallPMessage.location,             /* location to which the message is being sent */
            InstallPMessage.type,                 /* Tag */
            MPI_COMM_WORLD                        /* Communicator */
            );

其中msgInstallP是C / C ++结构类型(在MPI中它的等价物是MPI_MSGINSTALLP)。除函数Add_MPI_Types()的接口声明外,MPI_MSGINSTALLP.h不包含任何内容。

如果需要更多详细信息,请与我们联系。

1 个答案:

答案 0 :(得分:4)

这绝对是一个范围问题。 MPI_MSGINSTALLP只是MPI_Datatype类型的普通旧变量,而不是一个特殊的文字,你可以在任何地方使用它(这基本上就是你尝试使用它的方式)。由于变量在Add_MPI_Types()范围内是临时变量,因此在调用run()时它很久就不存在了。

就个人而言,我会在MPI_MSGINSTALLP内移动run()的声明,在MPI_Datatype&的参数中添加Add_MPI_Types(),并将MPI_MSGINSTALLP传递给它,所以run()看起来像这样:

msgInstallP InstallPMessage;
InstallPMessage = *(msgInstallP*)Data;
MPI_Datatype MPI_MSGINSTALLP;
Add_MPI_Types(MPI_MSGINSTALLP);
//Add_MPI_msgInstallP_Type();
MPI_Ssend(
            (void*)&InstallPMessage,             /* Payload */
            sizeof(msgInstallP),                 /* size of the payload */
            MPI_MSGINSTALLP,                      /* MPI Data type */
            InstallPMessage.location,             /* location to which the message is being sent */
            InstallPMessage.type,                 /* Tag */
            MPI_COMM_WORLD                        /* Communicator */
            );