I have a strange issue where the values I am packing into a buffer for an MPI Bcast are different from those that have been unpacked.
I am not sure what this may have resulted from. The first value packed (MTD) is always correct but those afterward are very off.
I require one of these values (dimensions) for dynamic memory allocation, the result of which then causes my program to crash.
If anyone familiar with MPI can cast there eyes over I would be eternally grateful!.
void recv_sharedData(int me, SharedData *d) {
fprintf(stderr, "%d: RECEIVING SHARED DATA\n", me);
int buff_size = sizeof(int) * 4 + sizeof(float);
char * buffer = malloc(buff_size);
int position = 0;
if (MPI_Bcast(
buffer, 5, MPI_PACKED, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
fprintf(stderr, "ID %d: Could not receive SharedData", me);
MPI_Abort(MPI_COMM_WORLD, -1);
}
MPI_Unpack(buffer, buff_size, &position, &d->max_tree_depth, 1,
MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(buffer, buff_size, &position, &d->bit_depth, 1,
MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(buffer, buff_size, &position, &d->dimensions, 1,
MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(buffer, buff_size, &position, &d->origin, 1,
MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(buffer, buff_size, &position, &d->colour_max, 1,
MPI_FLOAT, MPI_COMM_WORLD);
fprintf(stderr, "%d: MTD: %d\n", me, d->max_tree_depth);
fprintf(stderr, "%d: BitDepth: %d\n", me, d->bit_depth);
fprintf(stderr, "%d: DIM: %d\n", me, d->dimensions);
fprintf(stderr, "%d: ORIGIN: %d\n", me, d->origin);
....
void bcast_sharedData(SharedData *d) {
fprintf(stderr, "Broadcasting Shared Data\n");
int position = 0;
int buff_size = sizeof(int) * 4 + sizeof(float);
char * buffer = malloc(buff_size);
int result = MPI_SUCCESS;
while(result == MPI_SUCCESS) {
result = MPI_Pack(&d->max_tree_depth, 1, MPI_INT, buffer,
buff_size, &position, MPI_COMM_WORLD);
result = MPI_Pack(&d->bit_depth, 1, MPI_INT, buffer, buff_size,
&position, MPI_COMM_WORLD);
result = MPI_Pack(&d->dimensions, 1, MPI_INT, buffer, buff_size,
&position, MPI_COMM_WORLD);
result = MPI_Pack(&d->origin, 1, MPI_INT, buffer, buff_size,
&position, MPI_COMM_WORLD);
result = MPI_Pack(&d->colour_max, 1, MPI_FLOAT, buffer,
buff_size, &position, MPI_COMM_WORLD);
break;
}
if (result != MPI_SUCCESS) {
fprintf(stderr,
"ID 0: Could not Pack Shared Data for Broadcasting");
MPI_Abort(MPI_COMM_WORLD, -1);
}
fprintf(stderr, "%d: MTD: %d\n", 0, d->max_tree_depth);
fprintf(stderr, "%d: BitDepth: %d\n", 0, d->bit_depth);
fprintf(stderr, "%d: DIM: %d\n", 0, d->dimensions);
fprintf(stderr, "%d: ORIGIN: %d\n", 0, d->origin);
The related values to the above are output below. The root values (0:) are what are being packed:
Broadcasting Shared Data
0: MTD: 2
0: BitDepth: 24
0: DIM: 19
0: ORIGIN: 9
3: MTD: 2
3: BitDepth: 32536
3: DIM: 11816240
3: ORIGIN: 0
3: Done Recieving SharedData
1: MTD: 2
1: BitDepth: 32536
1: DIM: 30698800
1: ORIGIN: 0
1: Done Recieving SharedData
1: ALLOCATING KERNEL
2: MTD: 2
2: BitDepth: 32536
2: DIM: 27622704
2: ORIGIN: 0
2: Done Recieving SharedData
Related
i'm trying send packed structure by MPI_Bsend(). Something i'm doing wrong and i cannot find solution.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mpi.h"
#define SIZE 10
struct car {
int id;
int vmax;
char marka[SIZE];
char model[SIZE];
};
int main(int argc, char **argv) {
int i;
int rank, size;
double t1, t2;
struct car BMW, BMW2;
BMW.id = 1;
strcpy(BMW.marka, "BMW");
strcpy(BMW.model, "szybki");
BMW.vmax = 199;
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
int rozmiar, packet_size, msg_size, position = 0,tag;
void *bufor;
MPI_Pack_size(2, MPI_INT, MPI_COMM_WORLD, &rozmiar);
packet_size = rozmiar;
MPI_Pack_size(2 * SIZE, MPI_CHAR, MPI_COMM_WORLD, &rozmiar);
packet_size += rozmiar;
msg_size = 2 * packet_size + MPI_BSEND_OVERHEAD;
bufor = (void *)malloc(msg_size);
MPI_Buffer_attach(bufor, msg_size);
t1 = MPI_Wtime();
if (rank == 0) {
tag = 0;
for(i=1;i<size;i++){
MPI_Pack(&BMW.id,1, MPI_INT, bufor, msg_size, &position, MPI_COMM_WORLD);
MPI_Pack(&BMW.vmax,1, MPI_INT, bufor, msg_size, &position, MPI_COMM_WORLD);
MPI_Pack(&BMW.model,SIZE, MPI_CHAR, bufor, msg_size, &position, MPI_COMM_WORLD);
MPI_Pack(&BMW.marka,SIZE, MPI_CHAR, bufor, msg_size, &position, MPI_COMM_WORLD);
MPI_Bsend(bufor,position,MPI_PACKED,i,tag,MPI_COMM_WORLD);
}
} else {
MPI_Recv(bufor,msg_size,MPI_PACKED,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
position = 0;
MPI_Unpack(bufor, msg_size, &position, &BMW2.id, 1, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(bufor, msg_size, &position, &BMW2.vmax, 1, MPI_INT, MPI_COMM_WORLD);
MPI_Unpack(bufor, msg_size, &position, &BMW2.model, SIZE, MPI_CHAR, MPI_COMM_WORLD);
MPI_Unpack(bufor, msg_size, &position, &BMW2.marka, SIZE, MPI_CHAR, MPI_COMM_WORLD);
printf("rank = %d | BMW id: %d, marka: %s, model: %s, vmax: %d \n",rank, BMW2.id, BMW2.marka, BMW2.model, BMW2.vmax);
}
t2 = MPI_Wtime();
MPI_Buffer_detach(&bufor, &msg_size);
MPI_Finalize();
if (i == size)
printf("Elapsed time is %.15f\n", t2 - t1 );
return(0);
}
Error:
====================================================================
BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
PID 25637 RUNNING AT debian
EXIT CODE: 11
================================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault
(signal 11)
You are using the buffered mode of MPI incorrectly. The buffer you give to MPI via MPI_Buffer_attach is supposed to be used by MPI internally. Do not use the buffered MPI interface, it is very rarely useful and very difficult to get right.
Just remove the MPI_Buffer_ and use MPI_Send instead of MPI_Bsend and you are on the right track. MPI_Pack can be a bit clumsy, you may want to look insto custom datatypes (MPI_Type_create_struct) instead. If you have a homogeneous system, you can also send the raw bytes of the struct car.
#include "mpi.h"
#include <stdio.h>
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, dest, source, rc, count, tag=1;
MPI_Status Stat;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank%2 == 1) {
dest = (rank+1)%numtasks;
source = (rank-1+numtasks)%numtasks;
rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag,MPICOMM_WORLD, &Stat);
}
else {
dest = (rank-1+numtasks)%numtasks;
source = (rank+1)%numtasks;
rc = MPI_Recv( &inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat );
rc = MPI_Send( &outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD );
}
rc = MPI_Get_count(&Stat, MPI_CHAR, &count);
printf("Task %d: Received %d char(s) from task %d with tag %d\n",
rank, count, Stat.MPI_SOURCE, Stat.MPI_TAG);
MPI_Finalize();
}
Results:
Task 2: Received 1 char(s) from task 3 with a tag 1
Task 0: Received 1 char(s) from task 1 with a tag 1
Why the task can't identify more than 2 processors?
I want run it on more than 2 processors.
I've updated the mpi program with the ring pattern, i think maybe wrong at the line if(rank%2==1)
May try to better investigate the MPI mechanics:
Do not hesitate to experiment with the code, as it will help you grasp the concept of numtasks, rank-ID and associated run-time operations. Compilation errors will report shortcuts in the above posted code. For more MPI-related practices and insights, one ought also assign and evaluate rc return codes, from the respective MPI_<fun>()-calls
Q: Why the task can't identify more than 2 processors?
A: It can, but the if(){..}else if(){..} code-blocks did not allow others to produce any visible output.
Q: I want to change that 4197005 result into 2, 3 - how?
A: One cannot change an MPI-reported number, but you can change the behaviour of your code ( see below ) and make some more outputs, where feasible about who is doing what, when, how and where it is actually going on. This way we learn to understand the MPI-concepts and validate the actual MPI-code execution.
Feel free to ask more.
#include "mpi.h"
#include <stdio.h>
int main( int argc,
char *argv[]
) {
int numtasks, rank, dest, source, rc, count, tag = 1;
MPI_Status Stat;
printf( "(INF) will MPI_Init()...\n" );
MPI_Init( &argc, &argv );
printf( "(INF) MPI_Init() done.\n" );
MPI_Comm_size( MPI_COMM_WORLD, &numtasks );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
printf( "(INF) I am MPI[%d of %d]\n",
rank,
numtasks
);
if ( rank == 0 ) {
dest = 1;
source = 1;
rc = MPI_Send( &outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD );
rc = MPI_Recv( &inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat );
printf( "(INF) I am MPI[%d of %d] having just completed an MPI_Send( ->MPI[%d] ) + MPI_Recv( <-MPI[%d] ). Last RetCODE == %d.\n",
rank,
numtasks,
dest,
source,
rc
);
}
else
if ( rank == 1 ) {
dest = 0;
source = 0;
rc = MPI_Recv( &inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat );
rc = MPI_Send( &outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD );
printf( "(INF) I am MPI[%d of %d] having just completed an MPI_Recv( <-MPI[%d] ) + MPI_Send( ->MPI[%d] ). Last RetCODE == %d\n",
rank,
numtasks,
source,
dest,
rc
);
}
else
if ( rank == 2 ) {
dest = 3;
source = 3;
rc = MPI_Recv( &inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat );
rc = MPI_Send( &outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD );
printf( "(INF) I am MPI[%d of %d] having just completed an MPI_Recv( <-MPI[%d] ) + MPI_Send( ->MPI[%d] ). Last RetCODE == %d\n",
rank,
numtasks,
source,
dest,
rc
);
}
else
if ( rank == 3 ) {
dest = 2;
source = 2;
rc = MPI_Send( &outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD );
rc = MPI_Recv( &inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat );
printf( "(INF) I am MPI[%d of %d] having just completed an MPI_Send( ->MPI[%d] ) + MPI_Recv( <-MPI[%d] ). Last RetCODE == %d\n",
rank,
numtasks,
dest,
source,
rc
);
}
else {
printf( "(INF) I am MPI[%d of %d] will NOP...\n",
rank,
numtasks
);
}
rc = MPI_Get_count( &Stat, MPI_CHAR, &count );
/*
Task 3: Received 1 char(s) from task 4197005 with a tag 0
Task 2: Received 1 char(s) from task 4197005 with a tag 0
Task 1: Received 1 char(s) from task 0 with a tag 1
Task 0: Received 1 char(s) from task 1 with a tag 1 */
printf( "Task %d: Received %d char(s) from task %d with tag %d\n",
rank,
count,
Stat.MPI_SOURCE,
Stat.MPI_TAG
);
printf( "(INF) I am MPI[%d of %d]: will MPI_Finalize()...\n",
rank,
numtasks
);
MPI_Finalize();
printf( "(INF) I am MPI[%d of %d]: MPI_Finalize() done, will exit()...\n",
rank,
numtasks
);
}
count and Stat are only initialized on ranks 0 and 1, so you are basically printing garbage on ranks 2 and 3.
Your program is hard-coded to run on 2 tasks (it will crash on 1 task, and print garbage with 3 tasks or more).
I suggest you investigate using MPI_Sendrecv() in order to send and receive deadlock-free in one MPI call.
Not sure what you are trying to achieve, please elaborate and update your question. That being said, you might consider a ring pattern so your program can run on any number of MPI tasks (e.g. send to (rank+1)%numtasks and receive from (rank+numtasks-1)%numtasks)
Per your edited question, the communication pattern can the same for all the MPI ranks as follow
dest = (rank+1)%numtasks;
source = (rank-1+numtasks)%numtasks;
MPI_Sendrecv(&outmsg, 1, MPI_CHAR, dest, tag,
&inmsg, 1, MPI_CHAR, source, tag,
MPI_COMM_WORLD, &Stat);
#include "mpi.h"
#include <stdio.h>
int main (argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, dest, source, rc, count, tag=1;
char inmsg, outmsg='x';
MPI_Status Stat;
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank (MPI_COMM_WORLD, &rank);
if (rank%2 == 0)
{
dest=(rank+1)%numtasks;
source=(rank+1)%numtasks;
rc = MPI_Send(&outmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
}
else {
dest = (rank-1+numtasks)%numtasks;
source = (rank-1+numtasks)%numtasks;
rc = MPI_Recv (&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
rc = MPI_Send (&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
{
rc = MPI_Get_count (&Stat, MPI_CHAR, &count);
printf ("Task %d: Received %d char(s) from task %d with a tag %d \n", rank, count, Stat.MPI_SOURCE, Stat.MPI_TAG);
}
MPI_Finalize();
I have developed a given simple MPI program such that process 0 sends message to process 1 and receives message from process p-1. Following is the code :
In the skeleton given to me ,
char *message;
message= (char*)malloc(msg_size);
is confusing me. To check the correctness of program, I am trying to look value of message that been sent or received. So should it be hexadecimal value?
int main(int argc, char **argv)
{
double startwtime, endwtime;
float elapsed_time, bandwidth;
int my_id, next_id; /* process id-s */
int p; /* number of processes */
char* message; /* storage for the message */
int i, k, max_msgs, msg_size, v;
MPI_Status status; /* return status for receive */
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &my_id );
MPI_Comm_size( MPI_COMM_WORLD, &p );
if (argc < 3)
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
if ((sscanf (argv[1], "%d", &max_msgs) < 1) ||
(sscanf (argv[2], "%d", &msg_size) < 1))
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
**message = (char*)malloc (msg_size);**
if (argc > 3) v=1; else v=0; /*are we in verbose mode*/
/* don't start timer until everybody is ok */
MPI_Barrier(MPI_COMM_WORLD);
int t=0;
if( my_id == 0 ) {
startwtime = MPI_Wtime();
// do max_msgs times:
// send message of size msg_size chars to process 1
// receive message of size msg_size chars from process p-1
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, 1 , 0, MPI_COMM_WORLD);
MPI_Recv((char *) message, msg_size, MPI_CHAR, p-1, 0, MPI_COMM_WORLD, &status);
t++;
}
MPI_Barrier(MPI_COMM_WORLD);
endwtime = MPI_Wtime();
elapsed_time = endwtime-startwtime;
bandwidth = 2.0 * max_msgs * msg_size / (elapsed_time);
printf("Number, size of messages: %3d , %3d \n", max_msgs, msg_size);
fflush(stdout);
printf("Wallclock time = %f seconds\n", elapsed_time );
fflush(stdout);
printf("Bandwidth = %f bytes per second\n", bandwidth);
fflush(stdout);
} else if( my_id == p-1 ) {
// do max_msgs times:
// receive message of size msg_size from process to the left
// send message of size msg_size to process to the right (p-1 sends to 0)
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
t++;
}
} else {
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, my_id+1, 0, MPI_COMM_WORLD);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
t++;
}
}
MPI_Barrier(MPI_COMM_WORLD);
EXIT:
MPI_Finalize();
return 0;
}
I am not completely sure if this is what you mean, but I will try.
For what I understand, you want to know what is the message being sent. Well, for the code you provide, memory is assign to the message but any real "readable" message is specify. In this line.
message = (char*)malloc (msg_size);
malloc reserves the memory for the messages, so anyone can write it, however, it doesn't provide any initial value. Sometimes, the memory contains other information previously stored and freed. Then, the message being sent is that "garbage" that is before. This is probably what you call hexadecimal (I hope I understand this right).
The type of value in this case is char (defined as MPI_CHAR in the MPI_Send and MPI_Recv functions). Here you can find more data types for MPI.
I will suggest to assign a value to the message with the with my_id and next_id. So you know who is sending to whom.
I have developed one MPI program which sends and receives messages in cycle. The message passing is initiated by process 0: it sends to process 1, and receives from process p-1. The other processes receive from their left neighbor and send to their right neighbor. Notice that (p-1)-s right neighbor is 0.
Following is my code :
#include <stdio.h>
#include "mpi.h"
#include <stdlib.h>
/* cycle
In this program a message is sent around a circle of processes 0 - (p-1), ]
where p-1 sends to 0.
*/
int main(int argc, char **argv)
{
double startwtime, endwtime;
float elapsed_time, bandwidth;
int my_id, next_id; /* process id-s */
int p; /* number of processes */
char* message; /* storage for the message */
int i, k, max_msgs, msg_size, v;
MPI_Status status; /* return status for receive */
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &my_id );
MPI_Comm_size( MPI_COMM_WORLD, &p );
if (argc < 3)
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
if ((sscanf (argv[1], "%d", &max_msgs) < 1) ||
(sscanf (argv[2], "%d", &msg_size) < 1))
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
message = (char*)malloc (msg_size);
char yahoo = 'C';
message =&yahoo;
if (argc > 3) v=1; else v=0; /*are we in verbose mode*/
/* don't start timer until everybody is ok */
MPI_Barrier(MPI_COMM_WORLD);
int t=0;
if( my_id == 0 ) {
startwtime = MPI_Wtime();
// do max_msgs times:
// send message of size msg_size chars to process 1
// receive message of size msg_size chars from process p-1
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, my_id+1, 0, MPI_COMM_WORLD);
printf("Message ,source and destination ids:%c,%d,%d \n ",*message, 0 ,my_id+1);
fflush(stdout);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
printf("Message,source and destination ids:%c,%d,%d \n",*message, my_id-1,
0);
fflush(stdout);
t++;
}
MPI_Barrier(MPI_COMM_WORLD);
endwtime = MPI_Wtime();
elapsed_time = endwtime-startwtime;
bandwidth = 2.0 * max_msgs * msg_size / (elapsed_time);
printf("Number, size of messages: %3d , %3d \n", max_msgs, msg_size);
fflush(stdout);
printf("Wallclock time = %f seconds\n", elapsed_time );
fflush(stdout);
printf("Bandwidth = %f bytes per second\n", bandwidth);
fflush(stdout);
} else if( my_id == p-1 ) {
// do max_msgs times:
// receive message of size msg_size from process to the left
// send message of size msg_size to process to the right (p-1 sends to 0)
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
t++;
}
} else {
while(t<max_msgs) {
MPI_Send((char *) message, msg_size, MPI_CHAR, my_id+1, 0, MPI_COMM_WORLD);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
t++;
}
}
MPI_Barrier(MPI_COMM_WORLD);
EXIT:
MPI_Finalize();
return 0;
}
I am unable to get correct source and destination ids. And program after running for 1/2 times goes into infinite loop. What could be wrong here?
A few notes
The first issue with your code is that it has the potential to deadlock with some MPI implementations. Check out these notes for the details.
Leaving the deadlock issue aside, there are two problems with this code. The first involves the
if( my_id == 0 ) {
conditional. You have
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
which sets the the source to receive the message from PE -1 which wont work. You want to receive from p-1.
Also something is not right with the MPI_Barrier calls. I have to think about it for a little bit ... got it. You call MPI_Barrier in the my_id==0 branch but outside the other branches. This will produce the following
PE 0 calls barrier
all conditionals finish
PE 1 to p-1 calls barrier
PE 0 calls barrier again
frozen program
put a barrier inside all the conditionals or none of them.
Working Example (deadlock possible)
#include <stdio.h>
#include "mpi.h"
#include <stdlib.h>
/* cycle
In this program a message is sent around a circle of processes 0 - (p-1), ]
where p-1 sends to 0.
*/
int main(int argc, char **argv)
{
double startwtime, endwtime;
float elapsed_time, bandwidth;
int my_id, next_id; /* process id-s */
int p; /* number of processes */
char* message; /* storage for the message */
int i, k, max_msgs, msg_size, v;
MPI_Status status; /* return status for receive */
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &my_id );
MPI_Comm_size( MPI_COMM_WORLD, &p );
if (argc < 3)
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
if ((sscanf (argv[1], "%d", &max_msgs) < 1) ||
(sscanf (argv[2], "%d", &msg_size) < 1))
{
fprintf (stderr, "need msg count and msg size as params\n");
goto EXIT;
}
fprintf(stdout, "my_id: %d, max_msgs: %d\n", my_id, max_msgs);
message = (char*)malloc (msg_size);
char yahoo = 'C';
message =&yahoo;
if (argc > 3) v=1; else v=0; /*are we in verbose mode*/
/* don't start timer until everybody is ok */
MPI_Barrier(MPI_COMM_WORLD);
fprintf(stdout, "my_id: %d, barrier 1\n", my_id);
int t=0;
if( my_id == 0 ) {
startwtime = MPI_Wtime();
// do max_msgs times:
// send message of size msg_size chars to process 1
// receive message of size msg_size chars from process p-1
while(t<max_msgs) {
printf("PE %d about to send\n ", my_id);
fflush(stdout);
MPI_Send((char *) message, msg_size, MPI_CHAR, my_id+1, 0, MPI_COMM_WORLD);
printf("PE %d completed send\n ", my_id);
fflush(stdout);
printf("PE %d about to recv\n ", my_id);
fflush(stdout);
MPI_Recv((char *) message, msg_size, MPI_CHAR, p-1, 0, MPI_COMM_WORLD, &status);
printf("PE %d completed recv\n ", my_id);
fflush(stdout);
t++;
}
MPI_Barrier(MPI_COMM_WORLD);
endwtime = MPI_Wtime();
elapsed_time = endwtime-startwtime;
bandwidth = 2.0 * max_msgs * msg_size / (elapsed_time);
printf("Number, size of messages: %3d , %3d \n", max_msgs, msg_size);
fflush(stdout);
printf("Wallclock time = %f seconds\n", elapsed_time );
fflush(stdout);
printf("Bandwidth = %f bytes per second\n", bandwidth);
fflush(stdout);
} else if( my_id == p-1 ) {
// do max_msgs times:
// receive message of size msg_size from process to the left
// send message of size msg_size to process to the right (p-1 sends to 0)
while(t<max_msgs) {
printf("PE %d about to send\n ", my_id);
fflush(stdout);
MPI_Send((char *) message, msg_size, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
printf("PE %d completed send\n ", my_id);
fflush(stdout);
printf("PE %d about to recv\n ", my_id);
fflush(stdout);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
printf("PE %d completed recv\n ", my_id);
fflush(stdout);
t++;
}
MPI_Barrier(MPI_COMM_WORLD);
} else {
while(t<max_msgs) {
printf("*PE %d about to send\n ", my_id);
fflush(stdout);
MPI_Send((char *) message, msg_size, MPI_CHAR, my_id+1, 0, MPI_COMM_WORLD);
printf("*PE %d completed send\n ", my_id);
fflush(stdout);
printf("*PE %d about to recv\n ", my_id);
fflush(stdout);
MPI_Recv((char *) message, msg_size, MPI_CHAR, my_id-1, 0, MPI_COMM_WORLD, &status);
printf("*PE %d completed recv\n ", my_id);
fflush(stdout);
t++;
}
MPI_Barrier(MPI_COMM_WORLD);
}
EXIT:
MPI_Finalize();
return 0;
}
Example Output
> mpirun -n 3 ./a.out 1 1
my_id: 0, max_msgs: 1
my_id: 1, max_msgs: 1
my_id: 2, max_msgs: 1
my_id: 0, barrier 1
PE 0 about to send
PE 0 completed send
my_id: 1, barrier 1
*PE 1 about to send
my_id: 2, barrier 1
PE 2 about to send
PE 2 completed send
PE 2 about to recv
PE 0 about to recv
PE 0 completed recv
*PE 1 completed send
*PE 1 about to recv
*PE 1 completed recv
PE 2 completed recv
Number, size of messages: 1 , 1
Wallclock time = 0.000050 seconds
Bandwidth = 40136.878906 bytes per second
In the example found here, why is the count inconsistant in the second message
if (rank == src) {
/* These message sizes are chosen to expose any alignment problems */
MPI_Bsend( msg1, 7, MPI_CHAR, dest, tag, comm );
MPI_Bsend( msg2, 2, MPI_DOUBLE, dest, tag, comm );
MPI_Bsend( msg3, 17, MPI_CHAR, dest, tag, comm );
}
if (rank == dest) {
MPI_Recv( rmsg1, 7, MPI_CHAR, src, tag, comm, MPI_STATUS_IGNORE );
MPI_Recv( rmsg2, 10, MPI_DOUBLE, src, tag, comm, MPI_STATUS_IGNORE );
MPI_Recv( rmsg3, 17, MPI_CHAR, src, tag, comm, MPI_STATUS_IGNORE );
if (strcmp( rmsg1, msg1 ) != 0) {
errs++;
fprintf( stderr, "message 1 (%s) should be %s\n", rmsg1, msg1 );fflush(stderr);
}
Why is the count for the send and receive two inconsistant?
The count argument of Recv is only an upper bound on the amount of data to receive. This is convenient if we don't know the size of the payload at compile time. After the second Recv completes, rmsg2 will contain the two doubles, and then some uninitialized data.