如何防止在 class 析构函数中调用 MPI_Finalize()?
How to prevent calling of MPI_Finalize() within class destructor?
我有一个 class,它在其构造函数中创建一个新的 MPI_Datatype
,然后在其析构函数中将其删除。但是,删除自定义数据类型的存在以某种方式触发了析构函数中 MPI_Finalize()
的调用。
#include <cstdio>
#include "mpi.h"
class foo
{
public:
MPI_Datatype M_INT;
foo(MPI_Comm comm)
{
MPI_Comm_rank(comm, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT); // problematic line
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
foo bar(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}
这会产生运行时错误 Attempting to use an MPI routine after finalizing MPICH
。删除析构函数中自定义 MPI_Datatype
的删除是一种临时解决方法。但是,我想要一个更好、更合适的解决方案。如果您知道为什么会发生这种情况以及如何解决,请解释一下。谢谢。
编辑:
根据评论中的建议,我尝试了以下方法。这仍然存在与我之前的示例代码完全相同的问题。
#include <cstdio>
#include "mpi.h"
class M_Comm
{
public:
MPI_Comm p;
int already_finalised;
M_Comm(const MPI_Comm& _comm) : p(_comm) {}
~M_Comm()
{
MPI_Finalized(&already_finalised);
if (!already_finalised)
MPI_Finalize();
}
};
class foo
{
public:
MPI_Datatype M_INT;
foo(const M_Comm& comm)
{
MPI_Comm_rank(comm.p, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT); // problematic line
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
M_Comm comm_std(MPI_COMM_WORLD);
foo bar(comm_std);
MPI_Finalize();
return 0;
}
@VictorEijkhout 在他的评论中提出了以下解决方案。这个想法是创建一个在其构造函数和析构函数中调用 MPI_Init
和 MPI_Finalize
的通信对象,然后将该对象传递给其他函数或 类 以进行进一步操作。
#include <cstdio>
#include "mpi.h"
class MPI_Obj
{
public:
MPI_Comm COMM = MPI_COMM_WORLD;
int already_finalised;
MPI_Obj(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
}
~MPI_Obj()
{
MPI_Finalized(&already_finalised);
if (!already_finalised)
MPI_Finalize();
}
};
class foo
{
public:
MPI_Datatype M_INT;
foo(const MPI_Obj& mpi)
{
MPI_Comm_rank(mpi.COMM, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT);
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Obj comm_std(argc, argv);
foo bar(comm_std);
return 0;
}
我有一个 class,它在其构造函数中创建一个新的 MPI_Datatype
,然后在其析构函数中将其删除。但是,删除自定义数据类型的存在以某种方式触发了析构函数中 MPI_Finalize()
的调用。
#include <cstdio>
#include "mpi.h"
class foo
{
public:
MPI_Datatype M_INT;
foo(MPI_Comm comm)
{
MPI_Comm_rank(comm, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT); // problematic line
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
foo bar(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}
这会产生运行时错误 Attempting to use an MPI routine after finalizing MPICH
。删除析构函数中自定义 MPI_Datatype
的删除是一种临时解决方法。但是,我想要一个更好、更合适的解决方案。如果您知道为什么会发生这种情况以及如何解决,请解释一下。谢谢。
编辑:
根据评论中的建议,我尝试了以下方法。这仍然存在与我之前的示例代码完全相同的问题。
#include <cstdio>
#include "mpi.h"
class M_Comm
{
public:
MPI_Comm p;
int already_finalised;
M_Comm(const MPI_Comm& _comm) : p(_comm) {}
~M_Comm()
{
MPI_Finalized(&already_finalised);
if (!already_finalised)
MPI_Finalize();
}
};
class foo
{
public:
MPI_Datatype M_INT;
foo(const M_Comm& comm)
{
MPI_Comm_rank(comm.p, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT); // problematic line
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
M_Comm comm_std(MPI_COMM_WORLD);
foo bar(comm_std);
MPI_Finalize();
return 0;
}
@VictorEijkhout 在他的评论中提出了以下解决方案。这个想法是创建一个在其构造函数和析构函数中调用 MPI_Init
和 MPI_Finalize
的通信对象,然后将该对象传递给其他函数或 类 以进行进一步操作。
#include <cstdio>
#include "mpi.h"
class MPI_Obj
{
public:
MPI_Comm COMM = MPI_COMM_WORLD;
int already_finalised;
MPI_Obj(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
}
~MPI_Obj()
{
MPI_Finalized(&already_finalised);
if (!already_finalised)
MPI_Finalize();
}
};
class foo
{
public:
MPI_Datatype M_INT;
foo(const MPI_Obj& mpi)
{
MPI_Comm_rank(mpi.COMM, &id);
printf("%2d: Constructing foo.\n", id);
MPI_Type_dup(MPI_INT, &M_INT);
}
~foo()
{
printf("%2d: Destructing foo.\n", id);
MPI_Type_free(&M_INT);
}
private:
int id;
};
int main(int argc, char* argv[])
{
MPI_Obj comm_std(argc, argv);
foo bar(comm_std);
return 0;
}