1 /*
2 * Copyright (c) 2009-2012 Mellanox Technologies. All rights reserved.
3 * Copyright (c) 2009-2012 Oak Ridge National Laboratory. All rights reserved.
4 * Copyright (c) 2012 Los Alamos National Security, LLC.
5 * All rights reserved.
6 * Copyright (c) 2014 Research Organization for Information Science
7 * and Technology (RIST). All rights reserved.
8 * Copyright (c) 2017 IBM Corporation. All rights reserved.
9 * $COPYRIGHT$
10 *
11 * Additional copyrights may follow
12 *
13 * $HEADER$
14 */
15 /** @file */
16
17 #include "ompi_config.h"
18
19 #include "ompi/constants.h"
20 #include "ompi/op/op.h"
21 #include "ompi/datatype/ompi_datatype.h"
22 #include "ompi/communicator/communicator.h"
23 #include "opal/include/opal/sys/atomic.h"
24 #include "ompi/mca/pml/pml.h"
25 #include "ompi/patterns/net/netpatterns.h"
26 #include "coll_ops.h"
27
28 /**
29 * Bcast - subgroup in communicator
30 * This is a very simple algorithm - binary tree, transmitting the full
31 * message at each step.
32 */
ompi_comm_bcast_pml(void * buffer,int root,int count,ompi_datatype_t * dtype,int my_rank_in_group,int n_peers,int * ranks_in_comm,ompi_communicator_t * comm)33 OMPI_DECLSPEC int ompi_comm_bcast_pml(void *buffer, int root, int count,
34 ompi_datatype_t *dtype, int my_rank_in_group,
35 int n_peers, int *ranks_in_comm,ompi_communicator_t *comm)
36 {
37 /* local variables */
38 int rc=OMPI_SUCCESS,msg_cnt,i;
39 ompi_request_t *requests[2];
40 int node_rank, peer_rank;
41 netpatterns_tree_node_t node_data;
42
43 /*
44 * shift rank to root==0 tree
45 */
46 node_rank=(my_rank_in_group-root+n_peers)%n_peers;
47
48 /*
49 * compute my communication pattern - binary tree
50 */
51 rc=ompi_netpatterns_setup_narray_tree(2, node_rank, n_peers,
52 &node_data);
53 if( OMPI_SUCCESS != rc ) {
54 goto Error;
55 }
56
57 /* 1 process special case */
58 if(1 == n_peers) {
59 return OMPI_SUCCESS;
60 }
61
62 /* if I have parents - wait on the data to arrive */
63 if(node_data.n_parents) {
64 /* I will have only 1 parent */
65 peer_rank=node_data.parent_rank;
66 peer_rank=(peer_rank+root)%n_peers;
67 /* translate back to actual rank */
68 rc=MCA_PML_CALL(recv(buffer, count,dtype,peer_rank,
69 -OMPI_COMMON_TAG_BCAST, comm, MPI_STATUSES_IGNORE));
70 if( 0 > rc ) {
71 goto Error;
72 }
73 }
74
75 /* send the data to my children */
76 msg_cnt=0;
77 for(i=0 ; i < node_data.n_children ; i++ ) {
78 peer_rank=node_data.children_ranks[i];
79 peer_rank=(peer_rank+root)%n_peers;
80 rc=MCA_PML_CALL(isend(buffer,
81 count,dtype,peer_rank,
82 -OMPI_COMMON_TAG_BCAST,MCA_PML_BASE_SEND_STANDARD,
83 comm,&(requests[msg_cnt])));
84 if( 0 > rc ) {
85 goto Error;
86 }
87 msg_cnt++;
88 }
89 /* wait for send completion */
90 if(msg_cnt) {
91 /* wait on send and receive completion */
92 ompi_request_wait_all(msg_cnt,requests,MPI_STATUSES_IGNORE);
93 }
94
95 if (node_data.children_ranks) {
96 free(node_data.children_ranks);
97 }
98
99 /* return */
100 return OMPI_SUCCESS;
101
102 Error:
103 return rc;
104 }
105