尝试启动另一个进程并通过MPI加入,但是访问违规

时间:2017-05-08 22:42:57

标签: c++ windows mpi

我试图启动另一个调用第一个进程并通过MPI加入它的进程,但是我得到了一个我无法理解的访问冲突。我认为代码应该是非常自我解释的,访问冲突在MPI_COMM_ACCEPT行上命中。我认为一切看起来都或多或少,它应该有效,但它不会。

如果我发现这一切都错了,而且方法更简单,请告诉我。我没有使用mpiexec,因为我试图在构建整个混乱的测试框架中尝试这样做,但如果这样做更有意义,那么告诉我我做了一个拙劣的事情它的。

#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();
    // }
}

编辑: 作品!这很糟糕但是它的工作原理!

#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();
    // }
}

1 个答案:

答案 0 :(得分:1)

您没有正确使用<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.20.1</version> <extensions>true</extensions> <configuration> <images> <image> <alias>database</alias> <name>mysql:5.7</name> <run> <wait> <log>mysqld: ready for connections</log> <time>20000</time> </wait> <env> <MYSQL_ROOT_PASSWORD>abc123</MYSQL_ROOT_PASSWORD> <MYSQL_DATABASE>testdb</MYSQL_DATABASE> <MYSQL_USER>mysql</MYSQL_USER> <MYSQL_PASSWORD>mysql</MYSQL_PASSWORD> </env> <ports> <port>3306:3306</port> </ports> </run> </image> <image> <name>mvndemo</name> <build> <from>java:8-jre</from> <assembly> <descriptorRef>artifact</descriptorRef> </assembly> </build> </image> </images> </configuration> <executions> <execution> <id>docker:start</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> </execution> <execution> <id>docker:stop</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-failsafe-plugin</artifactId> <version>2.17</version> <executions> <execution> <id>integration-test</id> <goals> <goal>integration-test</goal> </goals> </execution> <execution> <id>verify</id> <goals> <goal>verify</goal> </goals> </execution> </executions> <configuration> <systemPropertyVariables> <mysql.jdbc.url>jdbc:mysql://${docker.host.address}/testdb</mysql.jdbc.url> </systemPropertyVariables> </configuration> </plugin> </plugins> </build> </project> 。您的案例中的第二个参数是字符串文字MPI_Open_port,而函数期望它是至少"A"个元素的字符数组。这是一个输出参数,其中写入了实际的端口名称。传递常量字符串会导致访问冲突,因为字符串常量通常存储在现代操作系统的只读段中。

此外,MPI_MAX_PORT_NAMEMPI_Comm_accept的第一个参数应该是MPI_Comm_connect返回的端口名称。由于端口名称可能每次都不同,因此MPI允许使用MPI_Open_port在众所周知的服务名称下注册。然后可以将该已知名称传递给MPI_Publish_name以获取端口。使用一些MPI实现使名称注册正常工作有点棘手,因此对于在同一节点上运行的进程,可以简单地将端口地址写入文件。显然,在调用MPI_Lookup_name之前,您应该这样做。