Reputation: 127
EDITED: Thanks for the previous assistance. I really appreciate it.
Should i remove the pointer from *list too? In order to create atributo and estrucura i'm using pointers too, will it be a problem too?
union atributo{
int valor1;
char valor2[tamChar];
float valor3;
};
struct estructura{
int tipo[tamEstruct]; //Here i will have an array with the types of the union
union atributo *list[tamEstruct];
};
union atributo *atributos;
struct estructura *estructuras;
estructuras = malloc (sizeof(struct estructura) * (cantEstruct) );
MPI_Datatype atributo_MPI;
MPI_Datatype type[1] = { MPI_BYTE };
int blocklen[1] = { tamChar }; // the largest element is the chat
MPI_Aint disp[1];
disp[0]= atributos[0]; // the begin of the union
MPI_Datatype estructura_MPI;
MPI_Datatype type[2] = { MPI_INT, atributo_MPI };
int blocklen[2] = { tamEstruct, tamEstruct};
MPI_Aint disp2[2];
disp2[0]= offsetof(atributos, tipo);
disp2[1]= offsetof(atributos, list);
Am i getting close the correct code?
Upvotes: 1
Views: 499
Reputation: 8273
There's several things wrong in that bit of code.
First, structs and unions are very different in this context. A struct contains each of its elements listed, lined up one after another in memory. A union, on the other hand, is only as large as its largest element, and all of its members share the same memory space (as if they were the sole members of a struct). This means you can't pack a union into an MPI_Struct
, since every member's offset is in fact 0.
There's two ways to tackle the problem of an array of unions:
MPI_BYTE
. This is simple, but risks data corruption if your processes don't share the same data representation (e.g. their integers differ in endianness).MPI_Pack()
to pack the values one by one. This is type safe, but more complicated, and it will result in an in-memory copy of your data.Note that in either case, the receiving process will need to know what values it received (i.e. if it received 3 unions, are those 3 integers, or 2 integers and a float, etc). You'll have to send this information as well if you use unions.
You might want to consider a trickier approach: group the enums according to which of their value is valid, and send a message in which similar enums are placed next to each other (e.g. a message that contains an array of MPI_INT
s, then an array of MPI_FLOAT
s and so on). With clever use of derived MPI datatypes, you can preserve type safety, avoid in-memory copying, and avoid sending several messages.
Second: NEVER, ever send pointers between MPI processes! It's easy to think of a char*
as an array of char
s, but it really isn't. It's just a memory address that won't make sense to the process you send it to, and even if it did, you didn't actually send the data that it was pointing to. If valor2
is a string with a reasonably short maximum length, I'd recommend declaring it as char valor2[maxLength]
so that memory for it is allocated inside the actual struct/union. If that is not feasible, you'll have to do even more memory juggling to get your strings across to the other processes, as you would with any variable sized array.
Upvotes: 1