阅读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不包含任何内容。
如果需要更多详细信息,请与我们联系。
答案 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 */
);