MPI Problem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "stdafx.h"
#include <mpi.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <cstdlib>
#include <ctime>
using namespace std;

int randomize() {
	srand(time(0));
	int i = 1 + rand() % 3;
	return i;
}
int main(int argc, char** argv) {
	MPI_Init(&argc, &argv);
	int rank, size, tag = 0;
	ofstream outfile;
	ifstream infile;
	bool read = false;
	const int max = 10;
	char message[max]; char msgS[max]; char msgR[max];

	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);

	outfile.open("in.txt");
	cout << "Write messages: " << rank << endl;
	do {
		cin.getline(message, max);
		if (strcmp(message, "stop") == 0)
			break;
		outfile << message << endl;
	} while (strcmp(message, "stop") != 0);
	cout << "Messages written to file [in.txt]!" << endl;
	outfile.close();

	infile.open("in.txt");
	outfile.open("out.txt");
	if (rank == 0) {
		if (infile >> msgS) {
			MPI_Send(msgS, max, MPI_CHAR, 1, 1, MPI_COMM_WORLD);
			cout << "Rank " << rank << " sent a message" << endl;
			read = true;
		}
		else
			cout << "Messages written to file [out.txt]!" << endl;
	}
	else if (rank == 1) {
		if (read) {
			MPI_Recv(msgR, max, MPI_CHAR, 0, 1, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
			outfile << msgR << endl;
			read = false;
		}
		else
			cout << "Rank " << rank << " on standby" << endl;
	}
	else if (rank == 2) {
		cout << "Rank " << rank << " on standby" << endl;
	}
	else if (rank == 3) {
		cout << "Rank " << rank << " on standby" << endl;
	}
	MPI_Finalize();
	system("PAUSE");
	return 0;
}


I make it to this point of the program, I've been working on this for awhile now can't seem to get what's wrong:

Write messages: 3
Write messages: 0
Write messages: 1
Write messages: 2
red
blue
green
stop
Messages written to file [in.txt]!
Rank 0 sent a message

Processor 0 is the only one that knows that read = true (line 46).

Processor 1 still thinks that read = false, so won't be expecting to recv that message.
Do you suggest any tweaks I should make? I either want something where I can strictly use the send and receive routines for two processors only. I just think 2 and 3 are causing the program to idle.
@lastchance Is there a method for making the processors actually run in order. The ranks as you see by the Write messages output varies in rank execution.
The ranks as you see by the Write messages output varies in rank execution.

Yep, that is one of the features that make parallel-processing an absolute nightmare to debug - you can't guarantee which processor will finish first and the finish order will be different every time you run the program. Actually, you will defeat the entire purpose of parallel processing if you make them run in rank order - if one has to wait until the others have finished then you might as well have run in serial to start with.

A couple of points:
(1) With MPI, each processor has its own memory and its own copy of variables. So processor 1 has its own value of 'read' and it will know absolutely nothing about processor 0's version unless processor 0 chooses to send it.

(2) Only one processor - traditionally 0 - should be reading and writing disk files and it should be responsible for relaying that information to or from the others by send and recv (or sendrecv) operations. You can't have all four processors trying simultaneously to get at the same file (as you have at present in your code).


I would reorganise your code so that:
- only processor 0 does the writing and reading files
- it sends a message indicating successful read to the other processors (which they must be primed to receive, irrespective of any value possessed by 0's variables)
- processor 0 then does a global send of information to all processors.


I'm writing this somewhat blind, as the only MPI implementation I have is actually in Fortran, not C++, so I would have to translate your code into Fortran first to check what is going on.
Last edited on
Sorry, haven't quite fathomed out broadcasting booleans in C++; it was easier in Fortran. However, try this. It did at least get me to sort out running MPI in C++ as well as Fortran.

Note that you can't do very much about the order that processors write to console at the end!

One note of encouragement though. Parallelising my main code at work gave a truly staggering performance boost. A big speed-up on my desktop (8 processors max) and an enormous boost when I got access to 64 elsewhere. Requires a new way of organising code to limit the inter-processor transfers, but once that is overcome it is incredibly powerful. Most supercomputers don't have particularly fast individual processors ... they just have an awful lot of them.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "mpi.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;

int randomize() {
        srand(time(0));
        int i = 1 + rand() % 3;
        return i;
}
int main(int argc, char** argv) {
        int rank, size, tag = 0;
        ofstream outfile;
        ifstream infile;
        bool read = false;
        const int max = 10;
        char message[max]; char msgS[max]; char msgR[max];

        MPI_Status stat;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);

        // Check all Processors are alive
        cout << "Initialised processor: " << rank << endl;

        MPI_Barrier(MPI_COMM_WORLD);                       // naughty, but just for debugging

        if (rank == 0) {
           outfile.open("in.txt");
           cout << "Processor " << rank << " is asking for messages (stop to finish)\n";
           do {
                cin.getline(message, max);
                if (strcmp(message, "stop") == 0) break;
                outfile << message << endl;
           } while (strcmp(message, "stop") != 0);
           cout << "Messages written to file [in.txt]!" << endl;
           outfile.close();
        }

        MPI_Barrier(MPI_COMM_WORLD);                       // naughty, but just for debugging

        if (rank == 0) {
           infile.open("in.txt");
           infile >> msgS;
           MPI_Send(msgS, max, MPI_CHAR, 1, 1, MPI_COMM_WORLD);
           cout << "Rank " << rank << " sent message " << msgS << endl;
        }
        else if (rank == 1) {
           MPI_Recv(msgR, max, MPI_CHAR, 0, 1, MPI_COMM_WORLD, &stat);
           cout << "Rank " << rank << " received message " << msgR << endl;
        }
        else {
           cout << "Rank " << rank << " on standby" << endl;
        }

        MPI_Finalize();
        return 0;
}


"C:\Program Files\MPICH2\bin\mpiexec" -n 4 test.exe 
Initialised processor: 3
Initialised processor: 0
Initialised processor: 2
Initialised processor: 1
Processor 0 is asking for messages (stop to finish)
red
green
blue
stop
Messages written to file [in.txt]!
Rank 2 on standby
Rank 3 on standby
Rank 1 received message red
Rank 0 sent message red

Last edited on
Very helpful answers. I really appreciate this assistance. Lastly, this demonstrates what I need it to do. Now how should I implement the code for the rank 0 to read all the lines and rank 1 to receive and store them?
@lastchance I was successful with my intentions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "stdafx.h"
#include "mpi.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;

int main(int argc, char** argv) {
	int rank, size, tag = 0;
	ofstream outfile;
	ifstream infile;
	bool read = false;
	const int max = 10;
	char message[max]; char msgS[max]; char msgR[max];

	MPI_Status stat;
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);

	// Check all Processors are alive
	cout << "Initialised processor: " << rank << endl;

	MPI_Barrier(MPI_COMM_WORLD);                       // naughty, but just for debugging

	if (rank == 0) {
		outfile.open("in.txt");
		cout << "Processor " << rank << " is asking for messages (stop to finish)\n";
		do {
			cin.getline(message, max);
			if (strcmp(message, "stop") == 0) break;
			outfile << message << endl;
		} while (strcmp(message, "stop") != 0);
		cout << "Messages written to file [in.txt]!" << endl;
		outfile.close();
	}

	MPI_Barrier(MPI_COMM_WORLD);                       // naughty, but just for debugging
		if (rank == 0) {
			int count = 0;
			infile.open("in.txt");
			while (infile >> msgS) {
				MPI_Send(msgS, max, MPI_CHAR, 1, 1, MPI_COMM_WORLD);
				cout << "Rank " << rank << " sent message " << msgS << endl;
				count++;
			}
			MPI_Send(&count, 1, MPI_INT, 1, 2, MPI_COMM_WORLD);
		}
		else if (rank == 1) {
			int count1;
			outfile.open("out.txt");
			MPI_Recv(&count1, 1, MPI_INT, 0, 2, MPI_COMM_WORLD, &stat);
			do {
				MPI_Recv(msgR, max, MPI_CHAR, 0, 1, MPI_COMM_WORLD, &stat);
				cout << "Rank " << rank << " received message " << msgR << endl;
				outfile << msgR << endl;
				count1--;
			} while (count1 != 0);
		}
		else {
			cout << "Rank " << rank << " on standby" << endl;
		}
	infile.close();
	outfile.close();
	MPI_Finalize();
	return 0;
}


Initialised processor: 1
Initialised processor: 3
Initialised processor: 0
Initialised processor: 2
Processor 0 is asking for messages (stop to finish)
red
green
blue
orange
yellow
pink
stop
Messages written to file [in.txt]!
Rank 0 sent message red
Rank 0 sent message green
Rank 0 sent message blue
Rank 0 sent message orange
Rank 0 sent message yellow
Rank 0 sent message pink
Rank 1 received message red
Rank 1 received message green
Rank 1 received message blue
Rank 1 received message orange
Rank 3 on standby
Rank 1 received message yellow
Rank 1 received message pink
Rank 2 on standby
Press any key to continue . . .


By carefully placing the loops within each if, Sending another routine that contained the length of the file, I was able to send line by line and store in a separate file line by line. From your informative descriptions and "Lesson on MPI" lol, I understood clearly.
Thank you very much lastchance. That is the updated code, and the files contain what they should.
Last edited on
Topic archived. No new replies allowed.