【发布时间】:2019-08-29 08:37:23
【问题描述】:
我已经在单个节点上成功编写了矩阵-矩阵乘法,现在我的目标是链接该程序以在集群节点上并行执行。
主要工作是通过我的程序 (mydgemm) 通过部分计算矩阵-矩阵乘法 (在本例中为 dgemm_) 更改原始代码 (ScaLAPACK) 来修改 Scalapack Netlib 源代码的代码。
在这里,原始代码是C程序,但该程序中的所有例程都调用Fortran例程(如dgemm_是Fortran语言),而我的程序(mydgemm)是C程序。
修改后,我可以用任何大小的矩阵的单个节点执行成功,但是当我用4个节点(矩阵大小大于200)运行时 -> 节点之间的通信数据有错误(MPI)。
这是一个错误:
*BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
PID 69754 RUNNING AT localhost.localdomain
EXIT CODE: 11
CLEANING UP REMAINING PROCESSES
YOU CAN IGNORE THE BELOW CLEANUP MESSAGES*
我只是在主函数中使用 MPI 在每个节点处创建随机矩阵(附后) - 例程称为new_pdgemm (...)。 (我修改了new-pdgemm里面的代码)。
在mydgemm.c内部,我使用OMP进行并行处理,这段代码在内核上执行。
能给我一个指导或想法来解决我的问题吗?
您是否认为问题是因为 Fortran 主要是列,而 C 是主要行?
或者我需要将
mydgemm.c更改为mydgemm.f(这真的很难,也许我做不到)?
我的代码:
int main(int argc, char **argv) {
int i, j, k;
/************ MPI ***************************/
int myrank_mpi, nprocs_mpi;
MPI_Init( &argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank_mpi);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs_mpi);
/************ BLACS ***************************/
int ictxt, nprow, npcol, myrow, mycol,nb;
int info,itemp;
int _ZERO=0,_ONE=1;
int M=20000;
int K=20000;
int N=20000;
nprow = 2; npcol = 2;
nb=1200;
Cblacs_pinfo( &myrank_mpi, &nprocs_mpi ) ;
Cblacs_get( -1, 0, &ictxt );
Cblacs_gridinit( &ictxt, "Row", nprow, npcol );
Cblacs_gridinfo( ictxt, &nprow, &npcol, &myrow, &mycol );
//printf("myrank = %d\n",myrank_mpi);
int rA = numroc_( &M, &nb, &myrow, &_ZERO, &nprow );
int cA = numroc_( &K, &nb, &mycol, &_ZERO, &npcol );
int rB = numroc_( &K, &nb, &myrow, &_ZERO, &nprow );
int cB = numroc_( &N, &nb, &mycol, &_ZERO, &npcol );
int rC = numroc_( &M, &nb, &myrow, &_ZERO, &nprow );
int cC = numroc_( &N, &nb, &mycol, &_ZERO, &npcol );
double *A = (double*) malloc(rA*cA*sizeof(double));
double *B = (double*) malloc(rB*cB*sizeof(double));
double *C = (double*) malloc(rC*cC*sizeof(double));
int descA[9],descB[9],descC[9];
descinit_(descA, &M, &K, &nb, &nb, &_ZERO, &_ZERO, &ictxt, &rA, &info);
descinit_(descB, &K, &N, &nb, &nb, &_ZERO, &_ZERO, &ictxt, &rB, &info);
descinit_(descC, &M, &N, &nb, &nb, &_ZERO, &_ZERO, &ictxt, &rC, &info);
double alpha = 1.0; double beta = 1.0;
double start, end, flops;
srand(time(NULL)*myrow+mycol);
#pragma simd
for (j=0; j<rA*cA; j++)
{
A[j]=((double)rand()-(double)(RAND_MAX)*0.5)/(double)(RAND_MAX);
// printf("A in myrank: %d\n",myrank_mpi);
}
// printf("A: %d\n",myrank_mpi);
#pragma simd
for (j=0; j<rB*cB; j++)
{
B[j]=((double)rand()-(double)(RAND_MAX)*0.5)/(double)(RAND_MAX);
}
#pragma simd
for (j=0; j<rC*cC; j++)
{
C[j]=((double)rand()-(double)(RAND_MAX)*0.5)/(double)(RAND_MAX);
}
MPI_Barrier(MPI_COMM_WORLD);
start=MPI_Wtime();
new_pdgemm ("N", "N", &M , &N , &K , &alpha, A , &_ONE, &_ONE , descA , B , &_ONE, &_ONE , descB , &beta , C , &_ONE, &_ONE , descC );
MPI_Barrier(MPI_COMM_WORLD);
end=MPI_Wtime();
if (myrow==0 && mycol==0)
{
flops = 2 * (double) M * (double) N * (double) K / (end-start) / 1e9;
/* printf("This is value: %d\t%d\t%d\t%d\t%d\t%d\t\n",rA,cA,rB,cB,rC,cC);
printf("%f\t%f\t%f\n", A[4], B[6], C[3]);*/
printf("%f Gflops\n", flops);
}
Cblacs_gridexit( 0 );
MPI_Finalize();
free(A);
free(B);
free(C);
return 0;
}
【问题讨论】:
-
欢迎。以小步骤工作。在您的基本 MPI 完美运行之前,请勿使用 OpenMP。添加新的小功能后,请尝试尽可能多地测试您的代码。使用调试器或打印语句或地址清理来找出崩溃发生在哪一行代码。
-
如果您在调试代码时需要帮助,您应该发帖minimal reproducible example
-
谢谢@Gilles Gouaillardet。
-
感谢@Vladimir F,我使用了 degugger 或 print 语句,但它也向我显示相同的错误。我不知道如何处理你所说的“地址清理以找出崩溃发生在哪一行代码上。”
-
忘记消毒。使用调试器或打印语句找出它崩溃的地方。您也可以使用代码二分法,但可能需要更多经验en.wikipedia.org/wiki/Bisection_(software_engineering)
标签: c fortran mpi cluster-computing intel