c - How to get all ranks in MPI to do a send a value to rank 0 which then does a blocking receive on all of them? -
say have n processes:
they calculation, , send result rank 0. want happen:
rank 0 wait till has result of ranks , add them up.
how do this? also, want avoid following:
for eg. 4 processes p0, p1, p2, p3,
p1 -> p0 p2 -> p0 p3 -> p0
in meanwhile p1 has finished calculation , p1->p0 happens again.
i want p0 make addition 3 processes in 1 cycle before doing next one.
can suggest mpi function this? know mpi_gather i'm not sure if blocking
i've thought of this:
#include <mpi.h> #include <stdio.h> int main() { int pross, rank,p_count = 0; int count = 10; mpi_init(&argc,&argv); mpi_comm_size(mpi_comm_world,&pross); mpi_comm_rank(mpi_comm_world,&rank); int * num = malloc((pross-1)*sizeof(int)); if(rank !=0) { mpi_send(&count,1,mpi_int,0,1,mpi_comm_world); } else { mpi_gather(&count, 1,mpi_int,num, 1, mpi_int, 0,mpi_comm_world); for(ii = 0; ii < pross-1;ii++ ){printf("\n num %d \n",num[ii]); p_count += num[ii]; } } mpi_finalize(); }
i'm getting error:
*** process received signal *** signal: segmentation fault (11) signal code: address not mapped (1) failing @ address: (nil) [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11630)[0x7fb3e3bc3630] [ 1] /lib/x86_64-linux-gnu/libc.so.6(+0x90925)[0x7fb3e387b925] [ 2] /usr/lib/libopen-pal.so.13(+0x30177)[0x7fb3e3302177] [ 3] /usr/lib/libmpi.so.12(ompi_datatype_sndrcv+0x54c)[0x7fb3e3e1e3ec] [ 4] /usr/lib/openmpi/lib/openmpi/mca_coll_tuned.so(ompi_coll_tuned_gather_intra_basic_linear+0x143)[0x7fb3d53d9063] [ 5] /usr/lib/libmpi.so.12(pmpi_gather+0x1ba)[0x7fb3e3e29a3a] [ 6] sosuks(+0xe83)[0x55ee72119e83] [ 7] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7fb3e380b3f1] [ 8] sosuks(+0xb5a)[0x55ee72119b5a] *** end of error message ***
also, tried:
#include <mpi.h> #include <stdio.h> int main() { int pross, rank,p_count = 0; int count = 10; mpi_init(&argc,&argv); mpi_comm_size(mpi_comm_world,&pross); mpi_comm_rank(mpi_comm_world,&rank); int * num = malloc((pross-1)*sizeof(int)); if(rank !=0) { mpi_send(&count,1,mpi_int,0,1,mpi_comm_world); } else { mpi_gather(&count, 1,mpi_int,num, 1, mpi_int, 0,mpi_comm_world); for(ii = 0; ii < pross-1;ii++ ){printf("\n num %d \n",num[ii]); p_count += num[ii]; } } mpi_finalize(); }
i'm getting error here:
*** process received signal *** signal: segmentation fault (11) signal code: address not mapped (1) failing @ address: 0x560600000002 [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11630)[0x7fefc8c11630] [ 1] mdscisuks(+0xeac)[0x5606c1263eac] [ 2] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7fefc88593f1] [ 3] mdscisuks(+0xb4a)[0x5606c1263b4a] *** end of error message ***
for second attempt, thing note here send , recv successful root receive 2 messages ranks reason. segmentation fault seen due there being 2 elements in num, dont see why num receives twice.
i'm calling code as
mpiexec -n 6 ./sosuks
can tell me better / correct way implement idea ?
update:
apart answer below found mistake in implementation above wanted share:
#include <mpi.h> #include <stdio.h> int main() { int pross, rank,p_count = 0; int count = 10; mpi_init(&argc,&argv); mpi_comm_size(mpi_comm_world,&pross); mpi_comm_rank(mpi_comm_world,&rank); mpi_status status; int * num = malloc((pross-1)*sizeof(int)); if(rank !=0) { mpi_send(&count,1,mpi_int,0,1,mpi_comm_world); } else { int var,lick = 0; for(lick = 1; lick < pross; u++) { int fetihs; mpi_recv(&fetihs,1,mpi_int,lick,1,mpi_comm_world,&status); var += fetihs; } // things var } mpi_finalize(); }
in case, sneftel pointed out, need mpi_reduce
. also, don't need explicit synchronization before cycle completes.
#include <mpi.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { int pross, rank, p_count, count = 10; mpi_init(&argc,&argv); mpi_comm_size(mpi_comm_world, &pross); mpi_comm_rank(mpi_comm_world, &rank); int* num = malloc((pross-1)*sizeof(int)); // master not send data itself. // workers send data master. (int i=0; i<3; ++i) { // prove no further sync needed. // same answer in each cycle. p_count = 0; if (rank == 0) { // has not effect since master uses p_count both // send , receive buffers due mpi_in_place. count = 500; mpi_reduce(mpi_in_place, &p_count, 1, mpi_int, mpi_sum, 0, mpi_comm_world); } else { // slave p_count irrelevant. mpi_reduce(&count, null, 1, mpi_int, mpi_sum, 0, mpi_comm_world); } if (rank == 0) { printf("p_count = %i\n", p_count); } // slaves send data master before cycle completes. // no need explicit sync such mpi_barrier. // mpi_barrier(mpi_comm_world); // no need. } mpi_finalize(); }
in code above count
in slaves reduced p_count
in master. note mpi_in_place
, 2 mpi_reduce
calls. can same functionality setting count = 0
, calling mpi_reduce
ranks without mpi_in_place
.
for (int i=0; i<3; ++i) { p_count = 0; if (rank == 0) count = 0; mpi_reduce(&count, &p_count, 1, mpi_int, mpi_sum, 0, mpi_comm_world); }
Comments
Post a Comment