For my Parallel Computing class, I am working on a project that parallelizes the Game of Life using MPI. I am specifically implementing exercise 6.13 in "Parallel Programming in C with MPI and OpenMP" by Michael J. Quinn.
I am using the author's pre-written library function, "read_row_striped_matrix". The following is the code for the function:
/*
* 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);
}
In the beginning of my code, I call "read_row_striped_matrix" like this:
#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);
....
The problem is, my implementation was getting stuck in an infinite loop. So I started debugging by testing to see if the data was being read from the text file correctly. My text file named "file_input.txt" contains the following input, where the first number (5) represents the number of rows, and the second number (also 5) represents the number of cols, and the rest of the data are the values in the matrix:
5 5 0 0 1 0 1 0 0 1 ...
I inserted the following printf statements in the section of library code where the length and height was being read from the text file:
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);
}
}
For executing "project_3 5 5 file_input.txt", The output of the program is:
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
...
From what I observe, the name of the file was read in correctly, and the value of m (0) is correct before calling fread. fread is reading in the correct # of elements for both m and n, but the values are "540549176" and "540090416" instead of 5 and 5. When I try changing the numbers in the beginning of the text file to say, "3 and 4" for example, the value of m and n does not change.
Does anybody have any idea why the first two integers are not being read in from the text file correctly? Thanks in advance.
You have two options here:
this program is expecting binary input. so you need to produce binary input somehow. "5" is an ascii character with the hex value 0x35 (decimal 53). When you fread sizeof(int), you are actually going to pull in 2 characters.
you can edit the program to parse ascii text but this is kind of annoying. First you read in a line of the file, then you tokenize it, then you convert each token into integers. Are you coming from a perl/python background? This text conversion stuff is nearly automatic in scripting languages. nothing is automatic in C
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments