I'm trying to read in multiple files using MPI-IO in C. I'm following this example : http://users.abo.fi/Mats.Aspnas/PP2010/examples/MPI/readfile1.c
However I'm reading in a matrix a doubles instead of a string of chars. Here is that implementation:
/*
Simple MPI-IO program that demonstrate parallel reading from a file.
Compile the program with 'mpicc -O2 readfile1.c -o readfile1'
*/
#include <stdlib.h>
#include <stdio.h>
#include "mpi.h"
#define FILENAME "filename.dat"
double** ArrayAllocation() {
int i;
double** array2D;
array2D= (double**) malloc(num_procs*sizeof(double*));
for(i = 0; i < num_procs; i++) {
twoDarray[i] = (double*) malloc(column_size*sizeof(double));
}
return array2D;
}
int main(int argc, char* argv[]) {
int i, np, myid;
int bufsize, nrchar;
double *buf; /* Buffer for reading */
double **matrix = ArrayAllocation();
MPI_Offset filesize;
MPI_File myfile; /* Shared file */
MPI_Status status; /* Status returned from read */
/* Initialize MPI */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD, &np);
/* Open the files */
MPI_File_open (MPI_COMM_WORLD, FILENAME, MPI_MODE_RDONLY,
MPI_INFO_NULL, &myfile);
/* Get the size of the file */
MPI_File_get_size(myfile, &filesize);
/* Calculate how many elements that is */
filesize = filesize/sizeof(double);
/* Calculate how many elements each processor gets */
bufsize = filesize/np;
/* Allocate the buffer to read to, one extra for terminating null char */
buf = (double *) malloc((bufsize)*sizeof(double));
/* Set the file view */
MPI_File_set_view(myfile, myid*bufsize*sizeof(double), MPI_DOUBLE,
MPI_DOUBLE,"native", MPI_INFO_NULL);
/* Read from the file */
MPI_File_read(myfile, buf, bufsize, MPI_DOUBLE, &status);
/* Find out how many elemyidnts were read */
MPI_Get_count(&status, MPI_DOUBLE, &nrchar);
/* Set terminating null char in the string */
//buf[nrchar] = (double)0;
printf("Process %2d read %d characters: ", myid, nrchar);
int j;
for (j = 0; j <bufsize;j++){
matrix[myid][j] = buf[j];
}
/* Close the file */
MPI_File_close(&myfile);
if (myid==0) {
printf("Done\n");
}
MPI_Finalize();
exit(0);
}
However when I try to call MPI_File_open after I close the first file, I get an error. Do I need multiple communicators to perform this? Any tips will be appreciated.
The code in ArrayAllocation above does not quite match the logic of the main program. The matrix is allocated as an array of pointers to vectors of doubles before MPI is initialized, therefore it is impossible to set the number of rows to the number of MPI processes.
The column_size is also not known until the file size is determined.
It is a general convention in the C language to store matrices by rows. Violating this convention might confuse you or the reader of your code.
All in all in order to get this program working you need to declare
int num_procs, column_size;
as global variables before the definition of ArrayAllocation and move the call to this function down below the line where bufsize is calculated:
...
/* Calculate how many elements each processor gets */
bufsize = filesize/np;
num_procs = np;
column_size = bufsize;
double **matrix = ArrayAllocation();
...
With the above modifications this example should work on any MPI implementation that supports MPI-IO. I have tested it with OpenMPI 1.2.8.
In order to generate a test file you could use for instance the following code:
FILE* f = fopen(FILENAME,"w");
double x = 0;
for(i=0;i<100;i++){
fwrite(&x, 1,sizeof(double), f);
x +=0.1;
}
fclose(f);
Related
I am trying to write MPI C code that repeatedly performs a calculation and saves its outcome into a single array for outputting less frequently. Example code below (the size of var, 200, is sufficient for the number of CPUs in use):
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv){
float *phie, *phitemp, var[200];
int time=0, gatherphi=10, gatherfile = 200, j, iter=0, lephie, x;
int nelecrank = 2, size, rank, Tmax = 2000;
FILE *out;
MPI_Init(&argc, &argv) ;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
lephie = gatherfile/gatherphi; // number of runs of calculation before output
// allocate memory
//printf("%d Before malloc.\n", rank);
if (rank==1) phie=(float *) malloc(nelecrank*size*gatherfile/gatherphi*sizeof(float));
phitemp=(float *) malloc(nelecrank*sizeof(float));
//printf("%d After malloc.\n", rank);
for(j=0;j<200;j++) var[j]=rank;
for(time=0;time<Tmax;time++){
if (!time%gatherphi) {// do calculation
for (j=0;j<nelecrank;j++) { // each processor does the calculation nelecrank times
phitemp[j]=0;
for (x = 0; x<=4; x++) {
phitemp[j]=phitemp[j]+var[rank+j*size];
}
}
} // end of j for loop
printf("iter: %d, %d Before MPI_Gather.\n", iter, rank);
MPI_Gather(phitemp, nelecrank, MPI_FLOAT, phie+iter*nelecrank*size*sizeof(float), nelecrank, MPI_FLOAT, 1, MPI_COMM_WORLD);
iter++;
} // end of gatherphi condition
if (time % gatherfile) { //output result of calculation
iter=0;
if (rank==1) {
out = fopen ("output.txt", "wt+");
if (out == NULL) {
printf("Could not open output file.\n");
exit(1);
}
else printf("Have opened output file.\n");
for (j=0;j<nelecrank*size*lephie;j++) {
fprintf(out,"%f ",*(phie+j*sizeof(float)));
}
fclose(out);
}
} // end of file output
if (rank==1) {
if (phie) free (phie);
}
if (phitemp) free (phitemp);
MPI_Finalize();
return 0;
}
It gives me repeated memory allocation problems until it finally exits. I am not experienced using memory allocation in MPI - can you help?
Many thanks,
Marta
Basically, phie is not big enough.
You malloced nelecrank*size*gatherfile/gatherphi*sizeof(float)=80*sizeof(float) memory for phie.
But, your MPI_Gather usage requires iter*nelecrank*size*sizeof(float)+nelecrank*size*sizeof(float) memory. iter takes a maximum value of nelecrank*Tmax-1, so phie needs to be (nelecrank*Tmax-1)*nelecrank*size*sizeof(float)+nelecrank*size*sizeof(float), which is around 8000*size*sizeof(float) large.
Maybe you want to reset iter=0 in your loop somewhere?
I'm new to using MPI, and I'm having an issue understanding why my code isn't working correctly.
#include "mpi.h"
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
int list_size = 1000
int threads;
int th_nums;
int slice;
char* the_array[list_size];
char* temp_array[list_size];
char str_to_search[10];
FILE *in = fopen("inputfile", "r");
char parse[10];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &threads);
MPI_Comm_size(MPI_COMM_WORLD, &th_nums);
if (threads == 0) { // if master task
fgets(parse, 10, in);
slice = atoi(parse); // How many slices to cut the array into
fgets(parse, 10, in);
sscanf(parse, "%s", search); // gives us the string we want to search
int i;
for (i = 0; i < list_size; i++) {
char temp[10];
fgets(parse, 10, in);
sscanf(parse, "%s", temp);
the_array[i] = strdup(temp);
}
int index = list_size/slice; //
MPI_Bcast(&str_to_search, 10, MPI_CHAR, 0, MPI_COMM_WORLD);
}
MPI_Bcast(&str_to_search, 10, MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Scatter(the_array, index, MPI_CHAR, temp_array, index, 0, MPI_COMM_WORLD);
// Search for string occurs here
MPI_Finalize();
return 0;
}
However, I'm finding that when I try to search, only the master task receives some of the slice, the rest is null. All other tasks don't receive anything. I've tried placing MPI_Scatter outside of the if(master task) statement, but I have no luck with this. Also, when the list_size increases, I find the program basically gets stuck at the MPI_Scatter line. What am I doing wrong, and what can I do to correct this?
You should go look up some tutorials on MPI collectives. They require all processes to participate collectively. So if any process calls MPI_Scatter, then all processes must call MPI_Scatter. I'd recommend looking at some sample code and playing with it until you understand what's going on. Then try coming back to your own code and seeing if you can figure out what's going on.
My favorite reference for anything pre-MPI-3 is DeinoMPI. I've never used the implementation, but the documentation is great since it has a complete example for each function in the MPI-2 Spec.
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
Look you need to rip the library function off and rewrite it to read and interpret text files. At present it reads binary data, when it reads into m and n it reads sizeof(int) (probably 4 bytes) of hexadecimal data ie 00,00,00,05 is what's expected to be in your file but the first 4 bytes are something like 76,32,76,32
Rather than rewrite the library function it probably makes sense to write a file compiler that reads a text file as input and writes it as it's binary data
I have a buffer of int16_t with some audio PCM data in it. I need to play the buffer repetitively from a point a to a point b, so that you hear an infinite audio loop.
I found that the easiest way to play sound is by using libao, but I agree with any other method.
This is my code:
int play(int a, int b, char *buf);
int main()
{
int16_t *buf; /*my buffer*/
int a, b;
/* a and b are the indexes of the buffer;
* because libao wants a buffer of char,
* and buf points to of int16_t, I'll pass
* the value a and b multiplied with 2.
*/
[ยทยทยท]
play(2*a, 2*b, (char *) buf);
return 0;
}
int play(int a, int b, char *buf)
{
ao_device *device;
ao_sample_format format;
int default_driver;
/* -- Initialize -- */
fprintf(stderr, "libao example program\n");
ao_initialize();
/* -- Setup for default driver -- */
default_driver = ao_default_driver_id();
memset(&format, 0, sizeof(format));
format.bits = 16;
format.channels = 1;
format.rate = 44100;
format.byte_format = AO_FMT_LITTLE;
/* -- Open driver -- */
device = ao_open_live(default_driver, &format, NULL /* no options */);
if (device == NULL) {
fprintf(stderr, "Error opening device.\n");
exit(1);
}
/* -- Play the infinite loop -- */
for (;;){
ao_play(device, buf+a, b-a+1);
/*buf+a is the start of the loop, b-a+1 the number of byte to play--edited*/
}
/* -- Close and shutdown -- */
ao_close(device);
ao_shutdown();
return 0;
}
The problem is that I hear a period of silence between the end and the start of the loop. Because I'm using this code to testing other code, I absolutely need to know if it could be caused by an incorrect use of libao.
Yes, it absolutely could be caused by incorrect use of libao. Please remove the +1 from the ao_play() call, like so:
ao_play(device, buf+a, b-a);
I am currently making a small test program for simple file checking. The program writes two small matrices(A and B) to files, closes and reopens them, reads in the matrices from the files, multiplies them and writes the resulting matrix(C) to a new file. It then closes and reopens this file containing the answer and prints it out for me to check if the IO operation proceeded correctly.
My problem is that the result matrix reads differently than expected.
I consider myself a beginner in C and of file input/output operations and this is the code that is causing me trouble. I am using WinXP, Codeblocks and Mingw.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define bufferA(i,k) (bufferA[i*cols+k])
#define bufferB(k,j) (bufferB[k*cols+j])
#define bufferC(i,j) (bufferC[i*cols+j])
void printMatrix(int *nMatrixToPrint, int nNumberOfElements, int nDimension) {
// This function prints out the element of an Array. This array represents a matrix in memory.
int nIndex;
printf("\n");
for (nIndex = 0; nIndex < nNumberOfElements; nIndex++) {
if (nIndex % nDimension == 0)
printf("\n");
printf("%d,",nMatrixToPrint[nIndex]);
}
return;
}
int main(int argc, char *argv[]) {
int nElements = 16, nDim = 4;
int A[4][4] = {{1,2,3,1},{2,2,1,2},{4,2,3,1},{5,1,1,3}};
int B[4][4] = {{3,2,1,4},{2,2,3,3},{4,1,3,2},{2,2,5,1}};
// Create files of A and B, delete old ones if present
FILE *fpA = fopen("A.dat", "w+");
FILE *fpB = fopen("B.dat", "w+");
// Write data to them
fwrite((int*)A, sizeof(*A), nElements, fpA);
fwrite((int*)B, sizeof(*B), nElements, fpB);
// and close them
fclose(fpA);
fclose(fpB);
// Reopen files
fpA = fopen("A.dat", "r");
fpB = fopen("B.dat", "r");
// Allocate memory
int *bufferA = (int*)malloc(nElements * sizeof(*bufferA));
int *bufferB = (int*)malloc(nElements * sizeof(*bufferB));
int *bufferC = (int*)calloc(nElements, sizeof(*bufferC));
// Read files
fread(bufferA, sizeof(int), nElements, fpA);
fread(bufferB, sizeof(int), nElements, fpB);
printf("\nA");
printMatrix(bufferA, nElements, nDim);
printf("\n\nB");
printMatrix(bufferB, nElements, nDim);
// Matrix multiplication
// Calculate and write to C
int i,j,k = 0; // Loop indices
int n = nDim,l = nDim, m = nDim, cols = nDim;
// multiply
for (i = 0; i < n; i++) { // Columns
for (j = 0; j < m; j++) { // Rows
//C(i,j) = 0;
for (k = 0; k < l; k++) {
bufferC(i,j) += bufferA(i,k) * bufferB(k,j);
}
}
}
printf("\n\nC_buffer");
printMatrix(bufferC, nElements, nDim);
// Create C and write to it
FILE* Cfile = fopen("C.dat", "w");
fwrite(bufferC, sizeof(*bufferC), nElements, Cfile);
// Close files
fclose(fpA);
fclose(fpB);
fclose(Cfile);
// reopen C for reading
Cfile = fopen("C.dat", "r");
// Obtain file size
fseek(Cfile , 0 , SEEK_END);
long lSize = ftell(Cfile);
rewind(Cfile);
printf("\nC file length is: %ld", lSize);
// read data into bufferA
fread(bufferA, sizeof(int), lSize, Cfile);
fclose(Cfile);
printf("\n\nC_file");
printMatrix(bufferA, nElements, nDim);
// Free allocated memory and remove dangling pointers
free(bufferA); bufferA = NULL;
free(bufferB); bufferB = NULL;
free(bufferC); bufferC = NULL;
exit(0);
}
Which gives me the following output:
A
1,2,3,1,
2,2,1,2,
4,2,3,1,
5,1,1,3,
B
3,2,1,4,
2,2,3,3,
4,1,3,2,
2,2,5,1,
C_buffer
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,26,28,
C file length is: 64
C_file
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,1,3,
As you can see, the last two elements in C_file are wrong, instead the output shows the last two elements in A as I was writing the file contents into bufferA. A switch to bufferB would swap the last two characters with the last elements in B which is still erroneous. A filecopy into another project would yield the last two integers as whatever was in ram at that malloc address.
My question is as follows: Why does not fwrite write the proper data into the file. Why does it manage the first 14 elements but not the last two? And how does this differ from my previous correct uses of fwrite and fread when I wrote and retrieved the elements of A and B?
You are writing binary data, and therefore you have to open the file in binary mode, the default is text mode. This makes a difference on windows, but not on *nix, which explains why it works for the other people here.
for all your fopen calls, include the letter 'b' in the mode argument, e.g. replace "w+" with "w+b" , replace "r" with "rb" and so on.
Your program runs just fine on my Mac.
The results would look better if printMatrix() output a final newline. Perhaps the unterminated line is causing some sort of confusion on your system?