【问题标题】:MPI Error: (Segmentation fault: 11)MPI 错误:(分段错误:11)
【发布时间】:2017-06-25 08:34:11
【问题描述】:

我在这里看到了许多类似的线程,但我的问题是,我的程序实际上是针对不同的设置运行的。

例如:当我的矩阵是1024x1024

对于 2 个内核:错误 11

对于 4、8、16 等都可以正常工作。

矩阵2048x2048:

对于任何核心设置:错误 11。

我不明白为什么会这样,每个进程都需要一个 2048/(总进程)X 2028 矩阵来计算。它应该可以正常工作。

这就是我声明我的矩阵的方式:

int temp[wp][hp];

接收:

rc = MPI_Recv(&temp[0][0], wp*hp, MPI_INT, i, tag, MPI_COMM_WORLD, &status);

对于发送:

 rc = MPI_Send(&temp[0][0], wp*hp, MPI_INT, 0, tag, MPI_COMM_WORLD);

我不明白,它应该可以工作。您是否认为这可能是内存问题而不是指针相关?

【问题讨论】:

  • C 和 C++ 是两种不同的语言。如果wp 和/或hp 是变量,则:int temp[wp][hp]; 不是合法的C++。
  • 另外,2048 * 2048 * sizeof(int) -- 考虑这相当于什么,以及您的数组是在本地还是全局声明的。如果是本地的。你可能会炸毁堆栈。
  • @PaulMcKenzie 是 C,你是对的。我不太清楚你所说的全球或本地是什么意思。 temp它在 main() 中声明,每个进程都可以访问它;如果我们有 8 个进程,这个矩阵应该是 256x2048。最终的矩阵称为im,它是 2048x2048,每个进程都可以访问,但实际上只有主进程最终会使用它。
  • tempIt 在 main() 中声明——嗯,这可能是问题所在。您在本地声明数组,因此使用堆栈空间。我怀疑你有 16 兆字节的堆栈空间。而是使用动态分配(例如malloc)。
  • @PaulMcKenzie 好的,我是 C 新手(我什至认为 C++ 也一样)我更喜欢 java、python 和 matlab,所以我很难掌握这一点。我应该在 main() 之外分配一些空间还是分配一些空间(如何)?

标签: c pointers parallel-processing mpi


【解决方案1】:

我会用 malloc 创建数组

int *temp =(int*)malloc(wp * hp * sizeof(int));

然后我会将其他行更改为

rc = MPI_Recv(temp, wp*hp, MPI_INT, i, tag, MPI_COMM_WORLD, &status);

rc = MPI_Send(temp, wp*hp, MPI_INT, 0, tag, MPI_COMM_WORLD);

当我处理完数组后,我释放它。

free(temp)

就像一位评论者已经说过的那样,以您的方式分配数组是不合法的 c++。

编辑:

如果你想访问二维数组,这里是模式:

temp[rowToAccess * numberOfColumns + columnToAcess]

【讨论】:

  • 感谢您的意见!我现在得到这个:error: subscripted value is not an array, pointer, or vectorim[k][l]=temp[cnt][l];
  • @MpkRoes 问题是您使用二维数组语法来访问基本上是一维“数组”(它实际上不是一个数组,但我们为了参数起见称它为)。因此,如果您想保留 [ ][ ] 语法,则必须动态创建 2D 数组,这就是一本好的 C 书籍比在编程板上快速回答更好的地方。
  • @MpkRoes - 给出的答案基本上是正确的。唯一的问题是您需要以某种方式使用malloc 创建二维数组,以便使用二维数组语法[][]。如果您有兴趣,我发布了答案。
【解决方案2】:

给出的答案基本上是问题的概要——您很可能会用完堆栈空间来存储数组,从而耗尽为堆栈保留的内存。

因此解决方案是动态创建数组。

下面是一个动态创建二维数组的例子:

#include <stdlib.h>
//...
int** create2DArray(unsigned nrows, unsigned ncols)
{
   unsigned i;
   int** ptr = malloc(nrows * sizeof(int*));  // allocate pointers to rows
   if ( ptr != NULL )
   { 
       int* pool = malloc(nrows * ncols * sizeof(int)); // allocate pool of memory
       if ( pool != NULL )
       {
           for (i = 0; i < nrows; ++i, pool += ncols )
               ptr[i] = pool;  // point the row pointers into the pool
       }
       else
       { 
          free(ptr);  
          ptr = NULL;
       }
   }
   return ptr;
}

void delete2DArray(int** arr)
{
   free(arr[0]);  // remove the pool
   free(arr);     // remove the pointers
}

int main()
{ 
   int **temp = create2DArray(2048, 2048); 
   if ( temp != NULL )
   {
       temp[0][0] = 10;  // for example you can use it like a 2D array
       delete2DArray(temp);  // free the memory
   }
}

这实际上将创建一个连续的二维数组,类似于您尝试使用int temp[2048][2048] 创建的数组,但这次,内存是从堆而不是堆栈中获取的。

请注意,您可以使用[][] 语法,就像二维数组一样。

我不会详细介绍它是如何工作的,但是它很简单,可以遵循逻辑。

【讨论】:

  • 嗯,像这样分配我所有的数组是不是很好的 C 策略?
  • 如果您的数组不大并且在编译时已知维度,那么我不建议您这样做,因为您有确保free() 内存的问题,否则您得到内存泄漏。只有当您需要动态创建数组时才应该这样做。原因是 -- 1) 数组的大小在运行时之前是未知的,或者 2) 数组对于堆栈来说太大了。
  • 我所有的矩阵都是这样的。它编译。我在原始帖子中使用sendrecv,否则我会遇到各种错误。虽然计算不正确。不知道发生了什么。
【解决方案3】:

所以这些是问题:

1) 正如@PaulMcKenzie 和@Alex 所指出的,我必须动态分配内存。现在的问题是,如果我使用了

rc = MPI_Send(temp, wp*hp, MPI_INT, 0, tag, MPI_COMM_WORLD);

rc = MPI_Recv(temp, wp*hp, MPI_INT, i, tag, MPI_COMM_WORLD, &status);

正如@Alex 建议的那样,我的程序会由于某种原因而崩溃。所以我最初的&amp;temp[0][0] 是正确的。

2) 第二个问题是,我使用 fwrite 保存了这个数组,但是当你有动态数组时,你需要这样做:

for (int i = 0; i < w; i++){
for (int j = 0; j < h; j++){
    fwrite(&im[i][j], sizeof(int), 1, yourfilename);
}
} 

祝大家好运

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 2015-01-26
    • 1970-01-01
    • 2016-05-08
    • 2014-05-07
    • 1970-01-01
    • 2019-06-26
    • 2017-01-07
    • 1970-01-01
    相关资源
    最近更新 更多