I want to generate an string with each process and then gather everything. But the strings created in each process are created by appending ints and chars.
I'm still not able to gather everything correctly. I can print all the partial strings one by one, but If I try to print the rcv_string, I only get one partial string or maybe a Segmentation Fault.
I've tried putting zeros at the end of strings with memset, reserving memory for the strings dynamically and statically, ... But I don't find the way.
It would be great if someone knew how to inizialize the strings and do the gather properly for achieving the objective.
int main(int argc, char *argv[]) {
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
char *string; // ????????????
char *rcv_string; // ????????????
if (rank == 0) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 1) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 2) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 3) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 4) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 5) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
MPI_Gather(string,???,MPI_CHAR,rcv_string,???,MPI_CHAR,0,MPI_COMM_WORLD);
if (rank == 0) {
printf("%s",rcv_string);
}
MPI_Finalize();
return 0;
}
I managed to reproduce the incorrect behavior where only one partial string is printed.
It is related to your usage of
sprintf
.How does C handle
char
arrays?When working with arrays in C, you must first allocate memory for it. Dynamic or static, it doesn't matter. Suppose you allocate enough memory for 10
char
s.Without initializing it, it contains nonsense characters.
Let's pretend
my_string
contains"qwertyuiop"
.Suppose you want to fill
my_string
with the stringfoo
. You usesprintf
.How does C fill 10 slots with 3 characters?
It fills the first 3 slots with the 3 characters. Then, it fills the 4th slot with an "end of string" character. This is denoted by
'\0'
, which is converted to an "end of string" character when it goes through the compiler.So, after your command,
my_string
contains"foo\0tyuiop"
. If you print outmy_string
, C knows not to print out the nonsense characters after the\0
.How does this relate to
MPI_Gather
?MPI_Gather
collects arrays from different processes, and puts them all into one array on one process.If you had
"foo\0tyuiop"
on process 0 and"bar\0ghjkl;"
on process 1, they get combined into"foo\0tyuiopbar\0ghjkl;"
.As you can see, the array from process 1 appears after the "end of line" character from process 0. C will treat all of the characters from process 1 as nonsense.
A patchy solution
Rather than attempting to print all of
rcv_string
at once, acknowledge that there are "end of string" characters scattered throughout. Then, print out strings with different "start of string" positions, according to the process it came from.Try the following:
Running this code with
mpirun -n 5 ./a.out
produces the following:Make sure to define
MAX_STR_LEN
so that is big enough for your requirements. If the value grows to big you may want to consider heap allocation (i.e.malloc
).