使用某些线程进行矩阵乘法的 MPI 程序的调试断言失败
Posted
技术标签:
【中文标题】使用某些线程进行矩阵乘法的 MPI 程序的调试断言失败【英文标题】:Debug Assertion Failed For MPI program for matrix multiplication with some threads 【发布时间】:2021-12-26 23:21:59 【问题描述】:美好的一天。我在运行乘以矩阵的 MPI 程序时遇到了一些问题。 这是代码(不是我的代码)我从 http://dkl.cs.arizona.edu/teaching/csc522-fall16/examples/hybrid-openmp-mm.c 获得 如果您能帮助我,我将不胜感激 我也在寻找类似的问题和解决方案,但它没有解决我的问题
#include <omp.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define TAG 13
int main(int argc, char* argv[])
double** A, ** B, ** C, * tmp;
double startTime, endTime;
int numElements, offset, stripSize, myrank, numnodes, N, i, j, k;
int numThreads, chunkSize = 10;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &numnodes);
N = atoi(argv[1]);
numThreads = atoi(argv[2]); // difference from MPI: how many threads/rank?
omp_set_num_threads(numThreads); // OpenMP call to set threads per rank
// allocate A, B, and C --- note that you want these to be
// contiguously allocated. Workers need less memory allocated.
if (myrank == 0)
tmp = (double*)malloc(sizeof(double) * N * N);
A = (double**)malloc(sizeof(double*) * N);
for (i = 0; i < N; i++)
A[i] = &tmp[i * N];
else
tmp = (double*)malloc(sizeof(double) * N * N / numnodes);
A = (double**)malloc(sizeof(double*) * N / numnodes);
for (i = 0; i < N / numnodes; i++)
A[i] = &tmp[i * N];
tmp = (double*)malloc(sizeof(double) * N * N);
B = (double**)malloc(sizeof(double*) * N);
for (i = 0; i < N; i++)
B[i] = &tmp[i * N];
if (myrank == 0)
tmp = (double*)malloc(sizeof(double) * N * N);
C = (double**)malloc(sizeof(double*) * N);
for (i = 0; i < N; i++)
C[i] = &tmp[i * N];
else
tmp = (double*)malloc(sizeof(double) * N * N / numnodes);
C = (double**)malloc(sizeof(double*) * N / numnodes);
for (i = 0; i < N / numnodes; i++)
C[i] = &tmp[i * N];
if (myrank == 0)
// initialize A and B
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
A[i][j] = 1.0;
B[i][j] = 1.0;
// start timer
if (myrank == 0)
startTime = MPI_Wtime();
stripSize = N / numnodes;
// send each node its piece of A -- note could be done via MPI_Scatter
if (myrank == 0)
offset = stripSize;
numElements = stripSize * N;
for (i = 1; i < numnodes; i++)
MPI_Send(A[offset], numElements, MPI_DOUBLE, i, TAG, MPI_COMM_WORLD);
offset += stripSize;
else // receive my part of A
MPI_Recv(A[0], stripSize * N, MPI_DOUBLE, 0, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
// everyone gets B
MPI_Bcast(B[0], N * N, MPI_DOUBLE, 0, MPI_COMM_WORLD);
// Let each process initialize C to zero
for (i = 0; i < stripSize; i++)
for (j = 0; j < N; j++)
C[i][j] = 0.0;
// do the work---this is the primary difference from the pure MPI program
#pragma omp parallel for shared(A,B,C,numThreads) private(i,j,k) schedule (static, chunkSize)
for (i = 0; i < stripSize; i++)
for (j = 0; j < N; j++)
for (k = 0; k < N; k++)
C[i][j] += A[i][k] * B[k][j];
// master receives from workers -- note could be done via MPI_Gather
if (myrank == 0)
offset = stripSize;
numElements = stripSize * N;
for (i = 1; i < numnodes; i++)
MPI_Recv(C[offset], numElements, MPI_DOUBLE, i, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
offset += stripSize;
else // send my contribution to C
MPI_Send(C[0], stripSize * N, MPI_DOUBLE, 0, TAG, MPI_COMM_WORLD);
// stop timer
if (myrank == 0)
endTime = MPI_Wtime();
printf("Time is %f\n", endTime - startTime);
// print out matrix here, if I'm the master
if (myrank == 0 && N < 10)
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
printf("%f ", C[i][j]);
printf("\n");
MPI_Finalize();
return 0;
这是我的问题
【问题讨论】:
程序需要命令行参数。你提供了吗? hmmm,真的,通过命令行运行程序并提供参数是可能且必要的,而不是像往常一样在工作室中启动项目。我现在试试 你能通过命令行演示如何操作吗?非常非常感谢 你有两行使用给程序的参数:N = atoi(argv[1])
和numThreads = atoi(argv[2]);
如果你不提供这些参数,程序将有未定义的行为。对我来说,如果我不提供它们,它就会崩溃。顺便说一句,程序泄漏。不要在 C++ 程序中使用malloc
。
@Sviatoslavch Visual Studio 调试选项有一个地方可以添加命令行选项。此外,如果程序不检查您是否指定了命令参数(检查argc
的值),我也不会很有信心。一个好的程序会检测到您没有指定参数,并会在命令行上输出“用法”或某种错误消息,说明您缺少命令行参数。程序不应该只是假设您已将这些命令参数放入其中而崩溃。
【参考方案1】:
您正在对B
执行MPI_Bcast
,就好像它是N*N
元素的连续块一样。然而,它不是:它是一个指向N
的指针数组,长度为N
的单独数组。所以要么你需要连续分配B
,要么你需要做N
广播。
【讨论】:
以上是关于使用某些线程进行矩阵乘法的 MPI 程序的调试断言失败的主要内容,如果未能解决你的问题,请参考以下文章