【发布时间】:2015-05-07 13:44:19
【问题描述】:
对于我的并行计算课程,我正在研究一个使用 MPI 并行化生命游戏的项目。我正在执行 Michael J. Quinn 的“使用 MPI 和 OpenMP 进行 C 并行编程”中的练习 6.13。
我正在使用作者预先编写的库函数“read_row_striped_matrix”。下面是函数的代码:
/*
* Process p-1 opens a file and inputs a two-dimensional
* matrix, reading and distributing blocks of rows to the
* other processes.
*/
void read_row_striped_matrix (
char *s, /* IN - File name */
void ***subs, /* OUT - 2D submatrix indices */
void **storage, /* OUT - Submatrix stored here */
MPI_Datatype dtype, /* IN - Matrix element type */
int *m, /* OUT - Matrix rows */
int *n, /* OUT - Matrix cols */
MPI_Comm comm) /* IN - Communicator */
{
int datum_size; /* Size of matrix element */
int i;
int id; /* Process rank */
FILE *infileptr; /* Input file pointer */
int local_rows; /* Rows on this proc */
void **lptr; /* Pointer into 'subs' */
int p; /* Number of processes */
void *rptr; /* Pointer into 'storage' */
MPI_Status status; /* Result of receive */
int x; /* Result of read */
MPI_Comm_size (comm, &p);
MPI_Comm_rank (comm, &id);
datum_size = get_size (dtype);
/* Process p-1 opens file, reads size of matrix,
and broadcasts matrix dimensions to other procs */
if (id == (p-1)) {
infileptr = fopen (s, "r");
if (infileptr == NULL) *m = 0;
else {
fread (m, sizeof(int), 1, infileptr);
fread (n, sizeof(int), 1, infileptr);
}
}
MPI_Bcast (m, 1, MPI_INT, p-1, comm);
if (!(*m)) MPI_Abort (MPI_COMM_WORLD, OPEN_FILE_ERROR);
MPI_Bcast (n, 1, MPI_INT, p-1, comm);
local_rows = BLOCK_SIZE(id,p,*m);
/* Dynamically allocate matrix. Allow double subscripting
through 'a'. */
*storage = (void *) my_malloc (id,
local_rows * *n * datum_size);
*subs = (void **) my_malloc (id, local_rows * PTR_SIZE);
lptr = (void *) &(*subs[0]);
rptr = (void *) *storage;
for (i = 0; i < local_rows; i++) {
*(lptr++)= (void *) rptr;
rptr += *n * datum_size;
}
/* Process p-1 reads blocks of rows from file and
sends each block to the correct destination process.
The last block it keeps. */
if (id == (p-1)) {
for (i = 0; i < p-1; i++) {
x = fread (*storage, datum_size,
BLOCK_SIZE(i,p,*m) * *n, infileptr);
MPI_Send (*storage, BLOCK_SIZE(i,p,*m) * *n, dtype,
i, DATA_MSG, comm);
}
x = fread (*storage, datum_size, local_rows * *n,
infileptr);
fclose (infileptr);
} else
MPI_Recv (*storage, local_rows * *n, dtype, p-1,
DATA_MSG, comm, &status);
}
在我的代码开头,我这样称呼“read_row_striped_matrix”:
#include <stdio.h>
#include <mpi.h>
#include "MyMPI.h"
typedef int dtype;
#define MPI_TYPE MPI_INT
int main(int argc, char *argv[]) {
dtype** matrix; /* Doubly-subscripted array */
dtype* storage; /* Local portion of array elements */
int proc_id; /* Process Rank */
int row_count; /* Number of rows in matrix */
int col_count; /* Number of columns in matrix */
int proc_count; /* Number of processes */
int i; /* Used with for loop */
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &proc_id);
MPI_Comm_size (MPI_COMM_WORLD, &proc_count);
read_row_striped_matrix (argv[3], (void *) &matrix, (void *) &storage, MPI_TYPE,
&row_count, &col_count, MPI_COMM_WORLD);
....
问题是,我的实现陷入了无限循环。所以我通过测试开始调试,看看数据是否从文本文件中正确读取。我的名为“file_input.txt”的文本文件包含以下输入,其中第一个数字(5)表示行数,第二个数字(也是 5)表示列数,其余数据是值在矩阵中:
5 5 0 0 1 0 1 0 0 1 ...
我在从文本文件中读取长度和高度的库代码部分插入了以下 printf 语句:
if (id == (p-1))
printf("The name of the file is %s\n", s);
infileptr = fopen (s, "r");
if (infileptr == NULL) *m = 0;
else {
printf("The value of m is %d\n", *m);
size_t ret_val = fread (m, sizeof(int), 1, infileptr);
size_t next_ret_val = fread (n, sizeof(int), 1, infileptr);
printf("The total # of elements successfully read is: %d\n", ret_val);
printf("The total # of elements successfully read is: %d\n", next_ret_val);
printf("The value of m is %d\n", *m);
printf("The value of n is %d\n", *n);
}
}
对于执行“project_3 5 5 file_input.txt”,程序的输出为:
The name of the file is: file_input.txt
The value of m is 0
The total number of elements successfully read is: 1
The total number of elements successfully read is: 1
The value of m is: 540549176
The value of n is: 540090416
...
据我观察,文件名被正确读入,m(0)的值在调用fread之前是正确的。 fread 正在读取 m 和 n 的正确元素数,但值是“540549176”和“540090416”而不是 5 和 5。当我尝试将文本文件开头的数字更改为“3和 4" 为例,m 和 n 的值不变。
有人知道为什么前两个整数没有从文本文件中正确读取吗?提前致谢。
【问题讨论】:
-
看看这些大数的十六进制表示:“(空格)1(空格)0”和“(空格)8(空格)8”。您正在尝试将 ASCII 文件作为二进制整数读取。
-
但是在 fopen 调用中,它传递的是“r”,而不是“rb”,所以我认为这确实意味着将文本文件解释为 ASCII,对吧?
-
@SamParsons 否。该标志在 Linux 上被忽略;在 Windows 上,它会转换换行符。您仍然必须从十六进制转换为二进制,反之亦然。
-
我很抱歉,但我想我在这里误解了一些东西。我会将“540549176”转换为什么?无论我将其转换为什么,它都不等于“5”,即我想从文本文件中读取的值。您是否建议我添加一行代码来解决此问题?