C++:奇怪的指针损坏错误

Chr*_*ris 6 c++ debugging pointers mpi

我有以下情况:我已经编写了一些简短的MPI测试代码,以便找出哪些发送和接收操作组合在我的代码中最有效.

代码在我自己的计算机上运行得很好(用8个进程测试),但是只要我运行它一个我正在处理的集群,我得到一个损坏或双重释放指针的巨大错误输出,这是输出:http://pastebin.com/pXTRSf89

我在我的代码中做的是:我将通信功能调用100K次并测量时间.此功能如下所示.我发现的是,错误总是发生在同一次迭代中(大约6K左右).但报告的processorID确实发生了变化.即使我使用64个proc而不是8个,迭代也是一样的.问题是:我完全不知道,什么可能是错的,特别是因为没有指针被释放或分配.

void communicateGrid(int level, real* grid, const Subdomain& subdomain, std::vector<TimeMap>& tm_) {
    tm_[level]["CommGrid"].start();

    MPI_Status status[2];
    MPI_Request request[2];

    // x 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1) + innerGridpoints_[level][0] - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 0, MPI_COMM_WORLD, &request[0]);
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1)], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 1, MPI_COMM_WORLD, &request[1]);

    MPI_Recv(&grid[getIndexInner(level, 1,1,1) + innerGridpoints_[level][0]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 1, MPI_COMM_WORLD, &status[0]);
    MPI_Recv(&grid[getIndexInner(level, 1,1,1) - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 0, MPI_COMM_WORLD, &status[1]);

    //y 
    MPI_Isend(&grid[getIndex(level, 0, innerGridpoints_[level][1], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 2, MPI_COMM_WORLD, &request[0]);
    MPI_Isend(&grid[getIndex(level, 0, numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 3, MPI_COMM_WORLD, &request[1]);

    MPI_Recv(&grid[getIndex(level, 0, innerGridpoints_[level][1] + numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 3, MPI_COMM_WORLD, &status[0]);
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 2, MPI_COMM_WORLD, &status[1]);

    // z
    MPI_Isend(&grid[getIndex(level, 0, 0, innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 4, MPI_COMM_WORLD, &request[0]);
    MPI_Isend(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level])], 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 5, MPI_COMM_WORLD, &request[1]);

    MPI_Recv(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level] + innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 5, MPI_COMM_WORLD, &status[0]);
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 4, MPI_COMM_WORLD, &status[1]);

    tm_[level]["CommGrid"].stop();
}
Run Code Online (Sandbox Code Playgroud)

mpiTypes_是MPI_Datatype*类型的全局变量,innerGridpoints_和numOuterGridpoints_也是全局的(我知道这不是一个好的编码风格,但我只把它用于计时).我很确定我的数据类型是正确的,因为它们在另一个通信功能设置中工作(例如Irecv后跟Send).

最后注意:我只是尝试用一个进程来运行它.然后发生以下错误:

秩0 [周一年04月22 2点11分23秒2013] [c0-0c1s3n0]在PMPI_Isend致命错误:内部MPI错误!错误堆栈:PMPI_Isend(148):MPI_Isend(BUF = 0x2aaaab7b531c,计数= 1,D型细胞= USER, dest = 0,tag = 1,MPI_COMM_WORLD,request = 0x7fffffffb4d4)失败(未知)():内部MPI错误!_pmiu_daemon(SIGCHLD):[NID 00070] [c0-0c1s3n0] [Mon Apr 22 02:11:23 2013] PE RANK 0退出信号中止

同样,这只发生在群集上,但在我的机器上工作.

我很高兴我可以检查任何事情或错误可能在哪里!谢谢

Jon*_*rsi 2

您必须等待或测试由 所创建的 MPI 请求或其他内容MPI_Isend(),否则您将泄漏内部资源,并最终崩溃,这就是正在发生的情况。

Jeff Squyres 在他的Cisco 博客文章中阐述得非常好。

知道那些 Isend 正在完成,但 MPI 库无法知道这一点并清理这些MPI_Requests 分配和指向的资源。需要多少资源和什么样的资源取决于很多因素,包括底层网络连接(例如,可能占用稀缺的 infiniband 资源),因此它在您自己的机器上运行但在集群上不起作用并不一定令人惊讶。

您可以通过添加来修复此问题

MPI_Waitall(2, request,  status);
Run Code Online (Sandbox Code Playgroud)

MPI_Isend在/ s的每个阶段之后MPI_Recv()

这不仅是清理资源所必需的,实际上也是具有非阻塞请求的程序的正确性所必需的。