【发布时间】:2014-09-17 00:10:51
【问题描述】:
我在使用 MPI 发送和(或)接收动态数组时遇到了一个大问题。下面只是我的代码的一部分,但应该足以看出我做错了什么。请帮助我,我经过一夜的搜索解决方案。 我是这样的: * 检测到 glibc ./mv2.out: munmap_chunk(): 无效指针:0x0000000000da2a70 检测到 glibc ./mv2.out: malloc(): 内存损坏(快速):0x0000000000da2a50 *
当我用静态替换动态数组时,一切正常。
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0
#define FROM_MASTER 1
#define FROM_WORKER 2
double **alloc_2d_array(int rows, int cols) {
int i;
double *data = (double *)malloc(rows*cols*sizeof(double));
double **array= (double **)malloc(rows*sizeof(double*));
for (i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
int main (int argc, char *argv[])
{
int degree,
numtasks,
taskid,
numworkers,
source,
dest,
mtype,
rows,
offset,
averow,
extra,
i, j, k, rc;
MPI_Status status;
double **a, *b, *c;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
if (numtasks < 2 )
{
printf("Aby rozpoczac obliczenia rownolegle potrzeba co najmniej 2 procesow.\n");
MPI_Abort(MPI_COMM_WORLD, rc);
exit(1);
}
numworkers = numtasks-1;
if (taskid == MASTER)
{
printf("Podaj stopien macierzy: \n");
scanf ("%d", °ree);
printf("Obecnie dostepnych jest %d procesow do dyspozycji mastera.\n", numtasks);
FILE *file;
file = fopen("matrix.txt", "r");
if(file == NULL)
{
printf("Nie mozna otworzyc pliku!\n");
MPI_Finalize();
exit(0);
}
a = alloc_2d_array(degree, degree);
b = (double*) malloc(sizeof(double) * degree);
c = (double*) malloc(sizeof(double) * degree);
printf("Tworzenie macierzy z pliku\n");
for(i = 0; i < degree; i++)
for(j = 0; j < degree; j++)
fscanf(file, "%lf", &a[i][j]);
for(i = 0; i < degree; i++)
{
for(j = 0; j < degree; j++)
{
printf("%f", a[i][j]);
}
printf("\n");
}
printf("Tworzenie wektora z pliku\n");
for(i = 0; i < degree; i++)
fscanf(file, "%lf", &b[i]);
for(i = 0; i < degree; i++)
{
printf("%f\n", b[i]);
}
fclose(file);
averow = degree / numworkers;
extra = degree % numworkers;
offset = 0;
mtype = FROM_MASTER;
for (dest = 1; dest <= numworkers; dest++)
{
rows = (dest <= extra) ? (averow + 1) : averow;
printf("Wysylanie %d wierszy do procesu nr %d, z offset'em = %d\n", rows, dest, offset);
MPI_Send(°ree, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&offset, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&a[offset][0], rows * degree, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&b, degree, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
offset = offset + rows;
}
mtype = FROM_WORKER;
for (i=1; i<=numworkers; i++)
{
source = i;
MPI_Recv(&offset, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&c[offset], rows, MPI_DOUBLE, source, mtype, MPI_COMM_WORLD, &status);
printf("Otrzymalem wyniki od procesu nr %d\n", source);
}
printf("***\n");
printf("Wektor wynikowy:\n");
for (i = 0; i < degree; i++)
{
printf("\n%6.2f", c[i]);
}
printf("\n***\n");
printf ("KONIEC\n");
}
if (taskid > MASTER)
{
b = (double*) malloc(sizeof(double) * degree);
c = (double*) malloc(sizeof(double) * degree);
mtype = FROM_MASTER;
MPI_Recv(°ree, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&a, rows * degree, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status); //HERE IS THE PROBLEM
MPI_Recv(&b, degree, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
for (i = 0; i < rows; i++)
{
c[i] = 0.0;
for (j = 0; j < degree; j++)
c[i] += a[i][j] * b[j];
}
mtype = FROM_WORKER;
MPI_Send(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&c, rows, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD);
}
MPI_Finalize();
}
重现错误的最短版本:
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0
#define FROM_MASTER 1
#define FROM_WORKER 2
double **alloc_2d_array(int rows, int cols) {
int i;
double *data = (double *)malloc(rows*cols*sizeof(double));
double **array= (double **)malloc(rows*sizeof(double*));
for (i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
int main (int argc, char *argv[])
{
int degree,
taskid,
source,
dest,
mtype,
rows,
offset,
i, j;
MPI_Status status;
double **a, *b, *c;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
if (taskid == MASTER)
{
FILE *file;
file = fopen("matrix.txt", "r");
a = alloc_2d_array(degree, degree);
b = (double*) malloc(sizeof(double) * degree);
c = (double*) malloc(sizeof(double) * degree);
for(i = 0; i < degree; i++)
for(j = 0; j < degree; j++)
fscanf(file, "%lf", &a[i][j]);
for(i = 0; i < degree; i++)
fscanf(file, "%lf", &b[i]);
fclose(file);
offset = 0;
mtype = FROM_MASTER;
MPI_Send(°ree, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&offset, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&a[offset][0], rows * degree, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&b, degree, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
}
}
if (taskid > MASTER)
{
a = alloc_2d_array(degree, degree);
b = (double*) malloc(sizeof(double) * degree);
c = (double*) malloc(sizeof(double) * degree);
mtype = FROM_MASTER;
MPI_Recv(°ree, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
// v HERE IS THE PROBLEM v
MPI_Recv(&a, rows * degree, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&b, degree, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
编辑:没有从工作人员发送到主机的版本可以正常工作,但是当我添加响应应用程序时会挂起。 在下面的链接中,您可以找到静态数组的示例。当我用动态替换它们时,应用程序无法正常工作。 https://computing.llnl.gov/tutorials/mpi/samples/C/mpi_mm.c
【问题讨论】:
-
有什么问题?你能把你的代码减少到最低限度来重新创建它吗?
-
我添加了完整的源代码。当我用静态替换动态数组时,一切都很完美。
-
如果您可以编写一个最小的示例来重现您的问题,这将是一个更清晰的问题。例如,只需分配一个数组并发送/接收它。
-
为什么你认为这是问题所在?你得到什么输出,你期望什么输出?
-
然后使用
-g编译您的代码并进行一些调试。目前,任何人都可以帮助您的唯一方法是目视检查您的源代码,这几乎是最糟糕的调试方式。它似乎依赖一个名为matrix.txt的文件才能运行,而我们没有。就像我之前说的,如果您将代码减少到可以重现问题的最少行数,对您和我们都会有所帮助。
标签: c arrays mpi dynamic-arrays