Thread: MPI Scatter

  1. #1
    Registered User
    Join Date
    Feb 2013
    Posts
    100

    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();
    }
    Last edited by johngoodman; 05-01-2013 at 05:12 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    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.
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2013
    Posts
    100
    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
    Last edited by johngoodman; 05-02-2013 at 12:38 PM.

  4. #4
    Registered User
    Join Date
    Feb 2013
    Posts
    100
    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

  5. #5
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    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
    Last edited by ZuK; 05-02-2013 at 01:20 PM.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    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.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Feb 2013
    Posts
    100
    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]);
            }

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    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?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Feb 2013
    Posts
    100
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. draw a scatter plot?
    By nano_nasa in forum C++ Programming
    Replies: 1
    Last Post: 11-07-2002, 09:00 AM