- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试解决 Fatal Error in MPI_Irecv: Aborting Job并收到对该查询的混合(有用但不完整)响应。
错误信息如下:
aborting job:
> Fatal error in MPI_Irecv: Other MPI
> error, error stack: MPI_Irecv(143):
> MPI_Irecv(buf=0x8294a60, count=48,
> MPI_DOUBLE, src=2, tag=-1,
> MPI_COMM_WORLD, request=0xffffd6ac)
> failed MPID_Irecv(64): Out of
> memory
我正在寻求某人的帮助来回答这些问题(我需要指导来帮助调试和解决这个僵局)
在“MPI Non Blocking Send and Receive”结束时,内存是在发送/接收完成后自行释放还是必须强制释放?
如果我使用“多核”而不是单核,“内存不足”的问题会得到解决吗?我们目前有 4 个处理器到 1 个内核,我使用以下命令提交我的作业:mpirun -np 4 <file>
.我尝试使用 mpirun n -4 <file>
但它仍然在同一核心上运行 4 个线程。
如何确定我的程序需要多少“共享内存”?
MPI_ISend
/MPI_IRecv
在我的代码中的递归循环中,因此如果错误源在那里就不是很清楚(如果我只使用发送/接收命令一次或两次,系统计算就很好,没有“内存不足问题”)。如果是这样,如何检查和解除这些信息?
#include <mpi.h>
#define Rows 48
double *A = new double[Rows];
double *AA = new double[Rows];
....
....
int main (int argc, char *argv[])
{
MPI_Status status[8];
MPI_Request request[8];
MPI_Init (&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
while (time < final_time){
...
...
for (i=0; i<Columns; i++)
{
for (y=0; y<Rows; y++)
{
if ((my_rank) == 0)
{
MPI_Isend(A, Rows, MPI_DOUBLE, my_rank+1, 0, MPI_COMM_WORLD, &request[1]);
MPI_Irecv(AA, Rows, MPI_DOUBLE, my_rank+1, MPI_ANY_TAG, MPI_COMM_WORLD, &request[3]);
MPI_Wait(&request[3], &status[3]);
MPI_Isend(B, Rows, MPI_DOUBLE, my_rank+2, 0, MPI_COMM_WORLD, &request[5]);
MPI_Irecv(BB, Rows, MPI_DOUBLE, my_rank+2, MPI_ANY_TAG, MPI_COMM_WORLD, &request[7]);
MPI_Wait(&request[7], &status[7]);
}
if ((my_rank) == 1)
{
MPI_Irecv(CC, Rows, MPI_DOUBLE, my_rank-1, MPI_ANY_TAG, MPI_COMM_WORLD, &request[1]);
MPI_Wait(&request[1], &status[1]);
MPI_Isend(Cmpi, Rows, MPI_DOUBLE, my_rank-1, 0, MPI_COMM_WORLD, &request[3]);
MPI_Isend(D, Rows, MPI_DOUBLE, my_rank+2, 0, MPI_COMM_WORLD, &request[6]);
MPI_Irecv(DD, Rows, MPI_DOUBLE, my_rank+2, MPI_ANY_TAG, MPI_COMM_WORLD, &request[8]);
MPI_Wait(&request[8], &status[8]);
}
if ((my_rank) == 2)
{
MPI_Isend(E, Rows, MPI_DOUBLE, my_rank+1, 0, MPI_COMM_WORLD, &request[2]);
MPI_Irecv(EE, Rows, MPI_DOUBLE, my_rank+1, MPI_ANY_TAG, MPI_COMM_WORLD, &request[4]);
MPI_Wait(&request[4], &status[4]);
MPI_Irecv(FF, Rows, MPI_DOUBLE, my_rank-2, MPI_ANY_TAG, MPI_COMM_WORLD, &request[5]);
MPI_Wait(&request[5], &status[5]);
MPI_Isend(Fmpi, Rows, MPI_DOUBLE, my_rank-2, 0, MPI_COMM_WORLD, &request[7]);
}
if ((my_rank) == 3)
{
MPI_Irecv(GG, Rows, MPI_DOUBLE, my_rank-1, MPI_ANY_TAG, MPI_COMM_WORLD, &request[2]);
MPI_Wait(&request[2], &status[2]);
MPI_Isend(G, Rows, MPI_DOUBLE, my_rank-1, 0, MPI_COMM_WORLD, &request[4]);
MPI_Irecv(HH, Rows, MPI_DOUBLE, my_rank-2, MPI_ANY_TAG, MPI_COMM_WORLD, &request[6]);
MPI_Wait(&request[6], &status[6]);
MPI_Isend(H, Rows, MPI_DOUBLE, my_rank-2, 0, MPI_COMM_WORLD, &request[8]);
}
}
}
}
谢谢!
最佳答案
你的程序有内存泄漏;这个:
MPI_Isend(A, Rows, MPI_DOUBLE, my_rank+1, 0, MPI_COMM_WORLD, &request[1]);
MPI_Irecv(AA, Rows, MPI_DOUBLE, my_rank+1, MPI_ANY_TAG, MPI_COMM_WORLD, &request[3]);
MPI_Wait(&request[3], &status[3])
泄漏与 MPI_Isend
请求相关的资源。您每次迭代调用此 Rows*Columns
次,大概是多次迭代;但您只是在等待其中一个请求。您可能需要为这两个请求执行 MPI_Waitall()
。
但除此之外,您的程序非常困惑。任何合理的 MPI 程序都不应该有这样一系列的 if (rank == ...)
语句。由于您在非阻塞发送/接收和等待之间没有做任何实际工作,我不明白为什么您不只是使用 MPI_Sendrecv
或其他东西。您的计划想要完成什么?
更新
好的,看来您正在做标准的光环填充操作。一些事情:
每个任务不需要它自己的数组 - A/AA 用于等级 0,B/BB 用于等级 1,等等。内存是分布式的,而不是共享的;没有等级可以看到其他数组,因此无需担心覆盖它们。 (如果有,您就不需要发送消息)。此外,想一想这会使在不同数量的进程上运行变得多么困难 - 每次更改使用的处理器数量时,您都必须向代码添加新数组。
您可以直接读取/写入 V 数组而不是使用拷贝,尽管拷贝最初可能最容易理解。
我在这里使用您的变量名(Tmyo
、Nmyo
、V
、indicies 编写了一个小版本的光环填充代码i
和 y
等)。每个任务只有它的一 block 更宽的 V 数组,并且只与它的邻居交换它的边缘数据。它使用字符,因此您可以看到发生了什么。它用它的排名#填充它在 V 数组中的部分,然后与它的邻居交换它的边数据。
我强烈鼓励您坐下来阅读 MPI 书籍并研究其中的示例。我喜欢Using MPI , 但还有很多其他的。还有很多不错的 MPI 教程。我认为可以毫不夸张地说,95% 的 MPI 书籍和教程(例如,我们的 here - 请参阅第 5 部分和第 6 部分)将把这个过程作为他们第一个重要的工作示例之一。他们会称其为光晕填充或保护单元填充或边界交换等,但这一切都归结为传递边缘数据。
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
char **alloc_2d_char(const int rows, const int cols) {
char *data = (char *)malloc(rows*cols*sizeof(char));
char **array= (char **)malloc(rows*sizeof(char*));
for (int i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
void edgeDataFill(char **locV, const int locNmyo, const int locTmyo,
const int ncols, const int myrow, const int mycol,
const int size, const int rank) {
MPI_Datatype leftright, updown;
int left, right, up, down;
int lefttag = 1, righttag = 2;
int uptag = 3, downtag = 4;
MPI_Status status;
/* figure out our neighbours */
left = rank-1;
if (mycol == 0) left = MPI_PROC_NULL;
right = rank+1;
if (mycol == ncols-1) right = MPI_PROC_NULL;
up = rank - ncols;
if (myrow == 0) up = MPI_PROC_NULL;
down = rank + ncols;
if (down >= size) down = MPI_PROC_NULL;
/* create data type for sending/receiving data left/right */
MPI_Type_vector(locNmyo, 1, locTmyo+2, MPI_CHAR, &leftright);
MPI_Type_commit(&leftright);
/* create data type for sending/receiving data up/down */
MPI_Type_contiguous(locTmyo, MPI_CHAR, &updown);
MPI_Type_commit(&updown);
/* Send edge data to our right neighbour, receive from left.
We are sending the edge (locV[1][locTmyo]..locV[locNmyo][locTmyo]),
and receiving into edge (locV[0][1]..locV[locNmyo][locTmyo]) */
MPI_Sendrecv(&(locV[1][locTmyo]), 1, leftright, right, righttag,
&(locV[1][0]), 1, leftright, left, righttag,
MPI_COMM_WORLD, &status);
/* Send edge data to our left neighbour, receive from right.
We are sending the edge (locV[1][1]..locV[locNmyo][1]),
and receiving into edge (locV[1][locTmyo+1]..locV[locNmyo][locTmyo+1]) */
MPI_Sendrecv(&(locV[1][1]), 1, leftright, left, lefttag,
&(locV[1][locTmyo+1]), 1, leftright, right, lefttag,
MPI_COMM_WORLD, &status);
/* Send edge data to our up neighbour, receive from down.
We are sending the edge (locV[1][1]..locV[1][locTmyo]),
and receiving into edge (locV[locNmyo+1][1]..locV[locNmyo+1][locTmyo]) */
MPI_Sendrecv(&(locV[1][1]), 1, updown, up, uptag,
&(locV[locNmyo+1][1]), 1, updown, down, uptag,
MPI_COMM_WORLD, &status);
/* Send edge data to our down neighbour, receive from up.
We are sending the edge (locV[locNmyo][1]..locV[locNmyo][locTmyo]),
and receiving into edge (locV[0][1]..locV[0][locTmyo]) */
MPI_Sendrecv(&(locV[locNmyo][1]),1, updown, down, downtag,
&(locV[0][1]), 1, updown, up, downtag,
MPI_COMM_WORLD, &status);
/* Release the resources associated with the Type_create() calls. */
MPI_Type_free(&updown);
MPI_Type_free(&leftright);
}
void printArrays(char **locV, const int locNmyo, const int locTmyo,
const int size, const int rank) {
/* all these barriers are a terrible idea, but it's just
for controlling output to the screen as a demo. You'd
really do something smarter here... */
for (int task=0; task<size; task++) {
if (rank == task) {
printf("\nTask %d's local array:\n", rank);
for (int i=0; i<locNmyo+2; i++) {
putc('[', stdout);
for (int y=0; y<locTmyo+2; y++) {
putc(locV[i][y], stdout);
}
printf("]\n");
}
}
fflush(stdout);
MPI_Barrier(MPI_COMM_WORLD);
}
}
int main(int argc, char **argv) {
int ierr, size, rank;
char **locV;
const int Nmyo=12; /* horizontal */
const int Tmyo=12; /* vertical */
const int ncols=2; /* n procs in horizontal direction */
int nrows;
int myrow, mycol;
int locNmyo, locTmyo;
ierr = MPI_Init(&argc, &argv);
ierr|= MPI_Comm_size(MPI_COMM_WORLD, &size);
ierr|= MPI_Comm_rank(MPI_COMM_WORLD, &rank);
nrows = size/ncols;
if (nrows*ncols != size) {
fprintf(stderr,"Size %d does not divide number of columns %d!\n",
size, ncols);
MPI_Abort(MPI_COMM_WORLD,-1);
}
/* where are we? */
mycol = rank % ncols;
myrow = rank / ncols;
/* figure out how many Tmyo we have */
locTmyo = (Tmyo / ncols);
/* in case it doesn't divide evenly... */
if (mycol == ncols-1) locTmyo = Tmyo - (ncols-1)*locTmyo;
/* figure out how many Tmyo we have */
locNmyo = (Nmyo / nrows);
/* in case it doesn't divide evenly... */
if (myrow == nrows-1) locNmyo = Nmyo - (ncols-1)*locNmyo;
/* allocate our local array, with space for edge data */
locV = alloc_2d_char(locNmyo+2, locTmyo+2);
/* fill in our local data - first spaces everywhere */
for (int i=0; i<locNmyo+2; i++)
for (int y=0; y<locTmyo+2; y++)
locV[i][y] = ' ';
/* then the inner regions have our rank # */
for (int i=1; i<locNmyo+1; i++)
for (int y=1; y<locTmyo+1; y++)
locV[i][y] = '0' + rank;
/* The "before" picture: */
if (rank==0) printf("###BEFORE###\n");
printArrays(locV, locNmyo, locTmyo, size, rank);
/* Now do edge filling. Ignore corners for now;
the right way to do that depends on your algorithm */
edgeDataFill(locV, locNmyo, locTmyo, ncols, myrow, mycol, size, rank);
/* The "after" picture: */
if (rank==0) printf("###AFTER###\n");
printArrays(locV, locNmyo, locTmyo, size, rank);
MPI_Finalize();
}
上述程序可以进一步简化,使用 MPI_Cart_create
创建您的多维域并自动为您计算您的邻居,但我想向您展示逻辑,以便您了解发生了什么。
此外,如果您可以从长期从事此工作的人那里得到一些建议:
任何时候你有一行又一行的重复代码:比如 60 (!!) 行:
Vmax =V[i][y]-Vold; updateMaxStateChange(Vmax / dt);
mmax=m[i][y]-mold; updateMaxStateChange(mmax / dt);
hmax=h[i][y]-hold; updateMaxStateChange(hmax / dt);
jmax=j[i][y]-jold; updateMaxStateChange(jmax / dt);
mLmax=mL[i][y]-mLold; updateMaxStateChange(mLmax / dt);
hLmax=hL[i][y]-hLold; updateMaxStateChange(hLmax / dt);
hLBmax=hLB[i][y]-hLBold; updateMaxStateChange(hLBmax / dt);
hLSmax=hLS[i][y]-hLSold; updateMaxStateChange(hLSmax / dt);
amax=a[i][y]-aold; updateMaxStateChange(amax / dt);
i1fmax=i1f[i][y]-i1fold; updateMaxStateChange(i1fmax / dt);
i1smax=i1s[i][y]-i1sold; updateMaxStateChange(i1smax / dt);
Xrmax=Xr[i][y]-Xrold; updateMaxStateChange(Xrmax / dt);
i2max=i2[i][y]-i2old; updateMaxStateChange(i2max / dt);
这表明您没有使用正确的数据结构。在这里,您几乎肯定想要一个状态变量的 3d 数组,(可能)第三个索引是物种或局部状态变量或您想要调用 i2、i1f、i1s 等的任何内容。然后可以替换所有这些行使用循环,并添加一个新的局部状态变量变得简单得多。
同样,将基本上所有状态都定义为全局变量将使您在更新和维护代码时的生活变得更加艰难。同样,这可能部分与拥有无数独立状态变量的事物有关,而不是拥有将所有相关数据组合在一起的结构或高维数组。
关于c++ - MPI 错误 : Out of Memory - What are some solution options,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6257876/
我的构建菜单包含两个构建选项: 构建解决方案 构建MyProjectName 如果我选择Build Solution(然后是Debug,Start Debugging (F5)),运行的可执行文件不包
我有一个带有一些输入字段的表单。这些输入字段具有指定的背景渐变,如下所示: input { background: #00b7ea; background: url(data:imag
现在这个遗留代码是多个项目,每个项目都有自己的解决方案。每个项目通过它编译的 dll 引用另一个项目。要让主项目运行,您必须以正确的顺序进行 10 多个单独的构建。 我试图解释如何将所有项目移动到一个
我在 Visual Studio 2013 中处理我的项目,我错误地点击了 Rebuild Solution。我收到以下异常,我不知道如何解决它。请建议。 Server Error in '/' Ap
class solution { void table(final int n) { for (int i = 1; i <= 10; i++) { S
我非常需要了解如何使用 Visual Studio 2010 在 c# 中管理一些非常基本的体系结构问题,而且我在教科书和网站上寻找解决方案时遇到了一些困难。假设我有一个 MyWinForm.sln
我有 Java 背景,正在尝试从 C# 开始。 我想用 C# 创建一个将在其他解决方案中使用的库。在 Eclipse 中,只需创建一个 jar 并将其添加到类路径中即可。我知道VS2013中的每个项目
在我目前的工作中,我需要打开 3 个不同的解决方案,构建并运行它们。是否有任何脚本可以像我单击 Web 服务的“构建解决方案”或“启动”或“Google Chrome”一样执行工作人员? 谢谢。 最佳
有什么方法可以告诉Visual Studio 2005的解决方案资源管理器在svn-checkout后第一次打开解决方案时不要扩展所有项目? 编辑: 感谢您指出 PowerCommands。当我使用带
我的 Visual Studio 解决方案的 Subversion 存储库中有以下目录: 项目名称 标签 分支机构 后备箱 我的解决方案.sln MyProject1(目录) MyProject2(目
我刚刚使用 Update 2 更新了 Visual Studio 2015。 现在,经过几个小时的正常工作,我收到:“检测到内存不足。对此解决方案禁用了完整的解决方案分析。”出现在我的 VS2015
在 Visual Studio Code 中,单击我的测试项目中的“调试测试”代码镜头链接: 导致错误信息: MSBUILD : error MSB1011: Specify which projec
我是Docker的新手,正在尝试为ASP.NET Core应用程序创建Dockerfile。有人可以建议我需要哪些更改吗? 这是我的Dockerfile: FROM microsoft/dotnet:
我的入门类(class)的这个实验要求我们以 pig 拉丁语返回任何用户输入。当我运行它并在控制台中输入任何字符串时,我似乎不断收到的错误是: java.lang.StringIndexOutO
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 11 个月前关闭。 Improv
我的 C++ Concert Cplex 有问题。我正在尝试重新创建最短路径问题。输出到文本文件是: Minimize obj: 2 x_12 + x_13 + 2 x_21 + x_24 + x_
有时,当我浏览我的头文件时,我想在 (doxygen) 文档中添加一些小东西。这可能是关于使用某些函数参数的快速说明,或者只是修复了一个小错字。 但后来我想:哦不,这会在下一个 make 调用时触发重
我正在使用缺少 findall 的高阶 Prolog 变体. 还有一个关于实现我们自己的问题 findall这里:Getting list of solutions in Prolog . 低效的实现
如果您的应用程序必须对大尺寸对象(> 85000 字节)进行大量分配/取消分配,则最终会导致内存碎片,并且您的应用程序将抛出内存不足异常。 这个问题有什么解决方案,还是CLR内存管理的限制? 最佳答案
我是一名优秀的程序员,十分优秀!