尝试启动另一个进程并通过MPI加入该进程,但出现访问冲突 [英] Trying to start another process and join it via MPI but getting access violation
问题描述
我正在尝试启动另一个进程,该进程将调用第一个进程并通过MPI将其加入,但是我遇到无法确定的访问冲突.我认为代码应该很容易说明,访问冲突在MPI_COMM_ACCEPT行上.我认为一切看起来或多或少都符合要求,应该可以,但不会.
I'm trying to start up another process that calls the first and joins it via MPI, but I'm getting an access violation I can't figure out. I think the code should be pretty self explanatory, the access violation hits on the MPI_COMM_ACCEPT line. I think everything looks more or less in line, it should work, but it won't.
如果我要解决所有这些错误,并且有一种更简单的方法,请告诉我.我没有使用mpiexec,因为我正在尝试使用一个构建整个混乱的测试框架来执行此操作,但是如果这样做更有意义,那么请告诉我我已经犯了一个错误.
If I'm going about this all wrong and there's a simpler way, let me know. I'm not using mpiexec as I'm trying to do this w/in a test framework that constructs the whole mess, but if that makes way more sense, then just tell me I've made a botch of it.
#include <windows.h>
#include <AtlBase.h>
#include <atlconv.h>
#include <iostream>
#include "mpi.h"
#include <string>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
MPI_Comm intercomm;
if (argc == 1)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
std::string x = std::string(argv[0]);
x += " ";
x += std::to_string(1);
int res = CreateProcess(NULL, CA2T(x.c_str()), NULL, NULL, false, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
std::cout << res <<std::endl;
MPI_Open_port(MPI_INFO_NULL, "A");
MPI_Comm_accept("A", MPI_INFO_NULL, 0, MPI_COMM_SELF,&intercomm);
std::cout << MPI_Comm_size(intercomm, &res);
std::cout << res;
}
else
{
MPI_Comm_connect("A", MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm);
}
MPI_Finalize();
// }
}
作品!这很麻烦,但行得通!
WORKS! THIS WAS VERY FRUSTRATING BUT IT WORKS!
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <mpi.h>
#include <windows.h>
#include <AtlBase.h>
#include <atlconv.h>
#include <iostream>
#include "mpi.h"
#include <string>
int main(int argc, char** argv)
{
char myPort[MPI_MAX_PORT_NAME];
MPI_Init(&argc, &argv);
MPI_Comm intercomm;
if (argc == 1)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
MPI_Open_port(MPI_INFO_NULL, myPort);
std::string x = std::string(argv[0])+" \""+myPort+"\"";
std::cout <<"OLDPROCESS:" << x << std::endl;
int res = CreateProcess(NULL, CA2T(x.c_str()), NULL, NULL, false, NORMAL_PRIORITY_CLASS , NULL, NULL, &si, &pi);
MPI_Comm_accept(myPort, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm);
std::cout << MPI_Comm_size(intercomm, &res);
}
else
{
std::cout << "NEWPROCESS:"<<argv[1] << std::endl;
strcpy_s(myPort,argv[1]);
MPI_Comm_connect(myPort, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm);
}
MPI_Finalize();
// }
}
推荐答案
您没有正确使用MPI_Open_port
.您的情况下的第二个参数是字符串文字"A"
,而函数希望它是至少包含MPI_MAX_PORT_NAME
个元素的字符数组.这是一个输出参数,实际的端口名将写入该参数.传递常量字符串会导致访问冲突,因为字符串常量通常存储在现代OS的只读段中.
You are not using MPI_Open_port
properly. The second argument in your case is the string literal "A"
while the function expects it to be a character array of at least MPI_MAX_PORT_NAME
elements. This is an output argument where the actual port name gets written to. Passing a constant string results in an access violation as string constants are usually stored in read-only segments on modern OSes.
此外,MPI_Comm_accept
和MPI_Comm_connect
的第一个参数应该是MPI_Open_port
返回的端口名.由于端口名称可能每次都不同,因此MPI允许使用MPI_Publish_name
将其注册为众所周知的服务名称.然后可以将该知名名称传递给MPI_Lookup_name
以获取端口.对于某些MPI实现,要使名称注册正常工作是有些棘手的,因此对于在同一节点上运行的进程,只需将端口地址写入文件即可.显然,您应该在调用CreateProcess
之前执行此操作.
Also, the first argument to both MPI_Comm_accept
and MPI_Comm_connect
should be the port name as returned by MPI_Open_port
. As the port name might differ every time, MPI allows it to be registered under a well-known service name using MPI_Publish_name
. That well-known name can then be passed to MPI_Lookup_name
to obtain the port. Getting the name registration to work properly is a bit tricky with some MPI implementations, therefore for processes that run on the same node one could simply write the port address to a file. You should obviously do this before calling CreateProcess
.
这篇关于尝试启动另一个进程并通过MPI加入该进程,但出现访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!