-
MPI Scatter
I'm having difficulties passing the right amount of characters to other processes using scatter. I'm trying to open a file which contains 6 file names and splitting it up and sending a file name to each process. I would look to send two file names to each process and have three processes going at once, but right now I'm just trying to do one. Below is my code, any suggestions you could give I'd greatly appreciate, I've been fiddling with these characters and scattering them for awhile now and am getting pretty frustrated.
Here is what is actually in the txt document I'm reading in right away:
data/file0.txt
data/file1.txt
data/file2.txt
data/file3.txt
data/file4.txt
data/file5.txt
Somewhere it isn't getting that last 't'
Here is the output:
data/file2.tx
data/file3.tx
data/file4.tx
data/file5.tx
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mpi.h>
int main(int argc, char **argv){
int p;
int id;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
if(id==0) { // Process 0
FILE *infile;
infile = fopen("data/data/filelist.txt", "r");
if (infile == NULL) {
printf("I couldn't open file.\n");
}
int ch = 0;
char fileList[84];
int sizeCount = 0;
while(ch != EOF){
//while(ch != '\n'){
fileList[sizeCount] = ch;
ch = getc(infile);
//printf("%c",ch);
sizeCount++;
//}
}
fclose(infile);
sizeCount -= 6;
int lineSize = sizeCount/6;
printf("sizeCount: %d\n",sizeCount);
printf("lineSize: %d\n",lineSize);
char files[5][(sizeCount/6)];
int counter = 0;
for(int i = 0; i < 6; i++){
for(int j = 0; j <= lineSize; j++){
files[i][j] = fileList[counter];
//printf("%c", files[i][j]);
counter++;
}
}
printf("counter:%d", counter);
printf("\n");
char receiveArray[lineSize*2];
MPI_Scatter(files,lineSize*2,MPI_CHAR,receiveArray,lineSize*2,MPI_CHAR,0,MPI_COMM_WORLD);
//do stuff as process 0
}else { // All other processes
int id;
MPI_Comm_rank(MPI_COMM_WORLD, &id);
char receiveArray[28];
MPI_Scatter(NULL,28,MPI_CHAR,receiveArray,28,MPI_CHAR,0,MPI_COMM_WORLD);
//
//if(id==1) sleep(1);
//else if(id==2) sleep(2);
//else if(id==3) sleep(3);
for(int i = 0; i <= sizeof(receiveArray); i++){
printf("%c",receiveArray[i]);
}
printf("\n");
//
//char fileName[23] = "data/data/filelist0.txt";
// for(int i = 0; i < sizeof(fileName); i++){
// printf("%c", receiveArray[i]);
// }
printf("\n");
/*
FILE *infile;
infile = fopen(fileName, "r");
if (infile == NULL) {
printf("\nI couldn't open file.\n");
}
int ch = 0;
while(ch != EOF){
ch = getc(infile);
printf("%c",ch);
}
*/
}
MPI_Finalize();
}
-
Perhaps you should begin with learning how to read a file and use arrays without overflow, before trying any MPI stuff.
Code:
int ch = 0;
char fileList[84];
int sizeCount = 0;
while(ch != EOF){
//while(ch != '\n'){
fileList[sizeCount] = ch;
ch = getc(infile);
//printf("%c",ch);
sizeCount++;
//}
}
Now I counted your input data as 90 chars and 6 lines, so you're already off by a large chunk on the fileList array.
> fileList[sizeCount] = ch;
Then you make the first char of your array zero (you haven't read the file yet).
Code:
sizeCount -= 6;
int lineSize = sizeCount/6;
printf("sizeCount: %d\n",sizeCount);
printf("lineSize: %d\n",lineSize);
char files[5][(sizeCount/6)];
Why do you subtract 6 from sizeCount?
Why only [5], when you have 6 files?
Code:
for(int i = 0; i < 6; i++){
for(int j = 0; j <= lineSize; j++){
files[i][j] = fileList[counter];
//printf("%c", files[i][j]);
counter++;
}
}
Both these loops overrun the bounds of their respective array limits.
If you just wanted an array of 6 lines, then why don't you start with
Code:
char files[6][100];
for ( i = 0 ; i < 6 && fgets(files[i], sizeof(files[i]), infile) != NULL ; i++ ) {
// if you want to remove the \n from the end of the line, then
// read the FAQ to find out how to do it.
}
-
Code:
int p;
int id;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
if(id==0) { // Process 0
FILE *infile;
infile = fopen("data/data/filelist.txt", "r");
if (infile == NULL) {
printf("I couldn't open file.\n");
}
int sizeCount = 0;
char ch;
char files[6][100];
for(int i=0; i<6 &&fgets(files[i],sizeof(files[i]),infile)!=NULL;i++){
for(int j=0; j<14; j++){
ch = getc(infile);
files[i][j] = ch;
sizeCount++;
}
}
fclose(infile);
char receiveArray[28/*lineSize*2*/];
MPI_Scatter(files,28,MPI_CHAR,receiveArray,28,MPI_CHAR,0,MPI_COMM_WORLD);
}else { // All other processes
int id;
MPI_Comm_rank(MPI_COMM_WORLD, &id);
char receiveArray[28];
MPI_Scatter(NULL,28,MPI_CHAR,receiveArray,28,MPI_CHAR,0,MPI_COMM_WORLD);
if(id==1) sleep(1);
else if(id==2) sleep(2);
for(int i = 0; i < sizeof(receiveArray); i++){
printf("%c",receiveArray[i]);
}
I do this, but now I'm not even getting any characters printed...just garbage from memory
-
Here is my second version going off what you said about my previous code:
Code:
int p;
int id;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
if(id==0) { // Process 0
FILE *infile;
infile = fopen("data/data/filelist.txt", "r");
if (infile == NULL) {
printf("I couldn't open file.\n");
}
char fileList[100];
int sizeCount = 0;
char ch = fileList[sizeCount];
while(ch != EOF){
//while(ch != '\n'){
fileList[sizeCount] = ch;
ch = getc(infile);
//printf("%c",ch);
sizeCount++;
//}
}
fclose(infile);
printf("sizeCount: %d\n",sizeCount);
char files[6][14];
int counter = 0;
for(int i = 0; i < 6; i++){
for(int j = 0; j < 14; j++){
files[i][j] = fileList[counter];
// printf("%c", files[i][j]);
counter++;
//if(counter==84) files[i][j] = fileList[counter];
}
}
I'm sorry about some of the formatting, I'm copying several chunks into here and some of it gets out of place...thank you very much for the help
-
This part shouldn't work
Code:
char ch = fileList[sizeCount]; // this initializes ch with a random value
while(ch != EOF){ // EOF is an int (usually -1 ) that doesn't fit into a char
//while(ch != '\n'){
fileList[sizeCount] = ch;
ch = getc(infile);
//printf("%c",ch);
sizeCount++;
//}
}
at least define ch to be an int
Kurt
EDIT: salem has already given you a solution for that part that would work
-
Code:
char files[6][100];
for(int i=0; i<6 &&fgets(files[i],sizeof(files[i]),infile)!=NULL;i++){
for(int j=0; j<14; j++){
ch = getc(infile);
files[i][j] = ch;
sizeCount++;
}
}
I suggest you read my post again, and figure out where exactly I said you should call getc() 14 times inside the loop reading each line.
Learn to read the file before posting any more MPI calls.
-
Ok, that's working now, thank you! I've been doing a little looking around and I think there is an easier route to do simple file IO. What if I went a different route, say fscanf.... dealing with lines rather than single characters seems to be a bit easier. When I do this though, it gives me the first line of text, which is the first file, and then a bunch of garbage because I'm assuming it does not increment to the next line. Is there a way of incrementing it to read the next line?
Code:
FILE *infile;
infile = fopen("data/data/filelist.txt", "r");
if (infile == NULL) {
printf("I couldn't open file.\n");
}
char fileList[100];
for(int i = 0; i < 6; i++){
fscanf(infile, "%s", fileList);
}
for(int i = 0; i < sizeof(fileList); i++){
printf("%c", fileList[i]);
}
-
It prints garbage because you're doing two things.
1. Reading 6 words before you do anything (maybe that's what you want).
2. Using sizeof() rather than strlen() when processing the data.
You read a 5-letter word into a 100 byte buffer.
How many times round the loop printing data do you need?
-
I was making an attempt to read the first line, then the next 5 lines of the file...each line is one word, the file path...and store each file path all into the same buffer, i changed it to strlen() and now it's just outputting the last file, "data/file5.txt" this is probably because i have the fscanf in a loop and the last thing that is read is the last line of the file and just replacing the previous read in...but I want it to read the next line and store all of them in one buffer