1 /* Copyright (c) 2013-2019. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "../colls_private.hpp"
10 //#include <star-reduction.c>
13 int Coll_reduce_binomial::reduce(const void *sendbuf, void *recvbuf, int count,
14 MPI_Datatype datatype, MPI_Op op, int root,
19 int mask, relrank, source;
21 int tag = COLL_TAG_REDUCE;
23 MPI_Aint true_lb, true_extent;
27 comm_size = comm->size();
29 extent = datatype->get_extent();
31 unsigned char* tmp_buf = smpi_get_tmp_sendbuffer(count * extent);
32 int is_commutative = (op==MPI_OP_NULL || op->is_commutative());
40 relrank = (rank - lroot + comm_size) % comm_size;
42 datatype->extent(&true_lb, &true_extent);
44 /* adjust for potential negative lower bound in datatype */
45 tmp_buf = tmp_buf - true_lb;
47 /* If I'm not the root, then my recvbuf may not be valid, therefore
48 I have to allocate a temporary one */
50 recvbuf = (void*)smpi_get_tmp_recvbuffer(count * std::max(extent, true_extent));
51 recvbuf = (void *)((char*)recvbuf - true_lb);
53 if ((rank != root) || (sendbuf != MPI_IN_PLACE)) {
54 Datatype::copy(sendbuf, count, datatype, recvbuf,count, datatype);
57 while (mask < comm_size) {
59 if ((mask & relrank) == 0) {
60 source = (relrank | mask);
61 if (source < comm_size) {
62 source = (source + lroot) % comm_size;
63 Request::recv(tmp_buf, count, datatype, source, tag, comm, &status);
66 if(op!=MPI_OP_NULL) op->apply( tmp_buf, recvbuf, &count, datatype);
68 if(op!=MPI_OP_NULL) op->apply( recvbuf, tmp_buf, &count, datatype);
69 Datatype::copy(tmp_buf, count, datatype,recvbuf, count, datatype);
73 dst = ((relrank & (~mask)) + lroot) % comm_size;
74 Request::send(recvbuf, count, datatype, dst, tag, comm);
80 if (not is_commutative && (root != 0)) {
82 Request::send(recvbuf, count, datatype, root,tag, comm);
83 }else if (rank == root){
84 Request::recv(recvbuf, count, datatype, 0, tag, comm, &status);
89 smpi_free_tmp_buffer(static_cast<unsigned char*>(recvbuf));
91 smpi_free_tmp_buffer(tmp_buf);