Reputation: 1691
Hey I have a problem with setting displacement array in MPI_IScatterv() function.
I need to scatter parts of picture to different processes. I have made my own MPI_Datatype:
private: MPI_Datatype createMPI_PixelType(){
MPI_Datatype new_type;
int count = 3;
int blocklens[] = { 1,1,1 };
MPI_Aint indices[3];
indices[0] = (MPI_Aint)offsetof(struct Pixel, Red);
indices[1] = (MPI_Aint)offsetof(struct Pixel, Green);
indices[2] = (MPI_Aint)offsetof(struct Pixel, Blue);
MPI_Datatype old_types[] = { MPI_INT, MPI_INT, MPI_INT };
MPI_Type_create_struct(count, blocklens, indices, old_types, &new_type);
MPI_Type_commit(&new_type);
return new_type;}
of structure Pixel
struct Pixel {
int Red;
int Green;
int Blue; }
As function arguments I need to pass displacement array. My understunding of it is that each process starts reading sendBuffer from different place specified as disp[proc_id]. For example process 0 disp = 0, process 1 disp = sizeof 0 element, process 2 disp = sizeof 1 + 0 element etc. Here is code
...
//specify arrays for scathering
sendCountArray = calcSendCounts(workTable);
displacementArray = calcDisplacementArray(workTable);
Pixel *fullPicture = pictureToPixelsArray();
cout << endl;
for (int i = 0; i < pixelsOnPicture; i++) {
cout <<
" r:" << fullPicture[i].Red <<
" g:" << fullPicture[i].Green <<
" b:" << fullPicture[i].Blue << endl;
}
cout << endl << "sendArray:" << endl;
for (int i = 0; i < worldSize; i++) {
cout << "i:" << i << " " << sendCountArray[i] << endl;
}
cout << endl << "displacementArray:" << endl;
for (int i = 0; i < worldSize; i++) {
cout << "i:" << i << " " << displacementArray[i] << endl;
}
}
cout << endl;
//
MPI_Scatter(sendCountArray, 1, MPI_INT, &pixelsSizeBuffer, 1, MPI_INT, 0, MPI_COMM_WORLD);
//sending part of picture
MPI_Request request;
MPI_Datatype mMPI_PIXEL = createMPI_PixelType();
partPicture = new Pixel[pixelsSizeBuffer];
MPI_Iscatterv(pictureToPixelsArray(), sendCountArray, displacementArray, mMPI_PIXEL, partPicture, pixelsSizeBuffer, mMPI_PIXEL, 0, MPI_COMM_WORLD, &request);
for (int i = 0; i < pixelsSizeBuffer; i++) {
cout << "proc:" << procID <<
" r:" << partPicture[i].Red <<
" g:" << partPicture[i].Green <<
" b:" << partPicture[i].Blue << endl;
}
and here is testing output (6 processes)
pixelsOnPicture:9
workTableSize: 6
r:255 g:242 b:0
r:63 g:72 b:204
r:237 g:28 b:36
r:0 g:162 b:232
r:163 g:73 b:164
r:63 g:11 b:15
r:34 g:177 b:76
r:255 g:242 b:0
r:63 g:10 b:16
sendArray:
i:0 2
i:1 2
i:2 2
i:3 1
i:4 1
i:5 1
displacementArray:
i:0 0
i:1 2
i:2 4
i:3 6
i:4 7
i:5 8
proc:4 r:-842150451 g:-842150451 b:-842150451
proc:0 r:255 g:242 b:0
proc:2 r:-842150451 g:-842150451 b:-842150451
proc:5 r:-842150451 g:-842150451 b:-842150451
proc:0 r:63 g:72 b:204
proc:2 r:-842150451 g:-842150451 b:-842150451
proc:1 r:-842150451 g:-842150451 b:-842150451
proc:3 r:-842150451 g:-842150451 b:-842150451
proc:1 r:-842150451 g:-842150451 b:-842150451
first 2 elements are sent correctly..
Upvotes: 2
Views: 165
Reputation: 1764
You haven't yet waited on the request so there is no guarantee that the Iscatterv is complete at the point you check the output. Calling plain old Scatterv will ensure it is complete after the call so you will then be able to check if you have set up all your parameters and datatypes correctly. Or add an MPI_Wait(&request) after the call to Iscatterv, but be aware that all you have done here is to re-implement the blocking call.
Upvotes: 2