2012-08-16 23:11:35 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2009-2012 Mellanox Technologies. All rights reserved.
|
|
|
|
* Copyright (c) 2009-2012 Oak Ridge National Laboratory. All rights reserved.
|
2013-01-28 03:25:10 +04:00
|
|
|
* Copyright (c) 2012 Los Alamos National Security, LLC.
|
|
|
|
* All rights reserved.
|
2012-08-16 23:11:35 +04:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef COMM_PATTERNS_KNOMIAL_TREE_H
|
|
|
|
#define COMM_PATTERNS_KNOMIAL_TREE_H
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
|
|
|
|
BEGIN_C_DECLS
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pair-wise data exchange
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* enum for node type */
|
|
|
|
enum {
|
|
|
|
EXCHANGE_NODE,
|
|
|
|
EXTRA_NODE
|
|
|
|
};
|
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
struct netpatterns_pair_exchange_node_t {
|
2012-08-16 23:11:35 +04:00
|
|
|
|
|
|
|
/* Order of a node in the tree - usually 2 */
|
|
|
|
int tree_order;
|
|
|
|
|
|
|
|
/* number of nodes this node will exchange data with */
|
|
|
|
int n_exchanges;
|
|
|
|
|
|
|
|
/* ranks of nodes involved in data exchnge */
|
|
|
|
int *rank_exchanges;
|
|
|
|
|
|
|
|
/* number of extra sources of data - outside largest power of 2 in
|
|
|
|
* this group */
|
|
|
|
int n_extra_sources;
|
|
|
|
|
|
|
|
/* rank of the extra source */
|
|
|
|
/* deprecated */ int rank_extra_source;
|
|
|
|
int *rank_extra_sources_array;
|
|
|
|
|
|
|
|
/* number of tags needed per stripe */
|
|
|
|
int n_tags;
|
|
|
|
|
|
|
|
/* log 2 of largest full power of 2 for this node set */
|
|
|
|
/* deprecated */ int log_2;
|
|
|
|
int log_tree_order;
|
|
|
|
|
|
|
|
/* largest power of 2 that fits in this group */
|
|
|
|
/* deprecated */ int n_largest_pow_2;
|
|
|
|
int n_largest_pow_tree_order;
|
|
|
|
|
|
|
|
/* node type */
|
|
|
|
int node_type;
|
|
|
|
|
|
|
|
};
|
2013-02-06 01:52:55 +04:00
|
|
|
typedef struct netpatterns_pair_exchange_node_t netpatterns_pair_exchange_node_t;
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
struct netpatterns_payload_t {
|
2012-08-16 23:11:35 +04:00
|
|
|
int s_len;
|
|
|
|
int r_len;
|
|
|
|
int s_offset;
|
|
|
|
int r_offset;
|
|
|
|
};
|
2013-02-06 01:52:55 +04:00
|
|
|
typedef struct netpatterns_payload_t netpatterns_payload_t;
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
struct netpatterns_k_exchange_node_t {
|
2012-08-16 23:11:35 +04:00
|
|
|
/* Order of a node in the tree - usually 2 */
|
|
|
|
int tree_order;
|
|
|
|
/* number of nodes this node will exchange data with */
|
|
|
|
int n_exchanges;
|
|
|
|
/* total number of exchanges that I actually participate in */
|
|
|
|
int n_actual_exchanges;
|
|
|
|
/* ranks of nodes involved in data exchnge */
|
|
|
|
int **rank_exchanges;
|
|
|
|
/* number of extra sources of data - outside largest power of 2 in
|
|
|
|
* this group */
|
|
|
|
int n_extra_sources;
|
|
|
|
/* rank/s of the extra source */
|
|
|
|
int *rank_extra_sources_array;
|
|
|
|
/* number of tags needed per stripe */
|
|
|
|
int n_tags;
|
|
|
|
/* log k of largest full power of k for this node set */
|
|
|
|
int log_tree_order;
|
|
|
|
/* largest power of k that fits in this group */
|
|
|
|
int n_largest_pow_tree_order;
|
|
|
|
/* node type */
|
|
|
|
int node_type;
|
|
|
|
/* start of extra ranks k_nomial */
|
|
|
|
int k_nomial_stray;
|
|
|
|
/* reindex map */
|
|
|
|
int *reindex_map;
|
|
|
|
/* inverse of reindex map, i.e. given a reindexed id find out its actual rank */
|
|
|
|
int *inv_reindex_map;
|
|
|
|
/* reindexed node_rank */
|
|
|
|
int reindex_myid;
|
|
|
|
/* 2-d array that hold payload info for each level of recursive k-ing */
|
2013-02-06 01:52:55 +04:00
|
|
|
netpatterns_payload_t **payload_info;
|
2012-08-16 23:11:35 +04:00
|
|
|
};
|
2013-02-06 01:52:55 +04:00
|
|
|
typedef struct netpatterns_k_exchange_node_t
|
|
|
|
netpatterns_k_exchange_node_t;
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
OMPI_DECLSPEC int netpatterns_setup_recursive_doubling_n_tree_node(int num_nodes, int node_rank, int tree_order,
|
|
|
|
netpatterns_pair_exchange_node_t *exchange_node);
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
OMPI_DECLSPEC void netpatterns_free_recursive_doubling_tree_node(
|
|
|
|
netpatterns_pair_exchange_node_t *exchange_node);
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
OMPI_DECLSPEC int netpatterns_setup_recursive_doubling_tree_node(int num_nodes, int node_rank,
|
|
|
|
netpatterns_pair_exchange_node_t *exchange_node);
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
OMPI_DECLSPEC int netpatterns_setup_recursive_knomial_tree_node(
|
2012-08-16 23:11:35 +04:00
|
|
|
int num_nodes, int node_rank, int tree_order,
|
2013-02-06 01:52:55 +04:00
|
|
|
netpatterns_k_exchange_node_t *exchange_node);
|
2012-08-16 23:11:35 +04:00
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
OMPI_DECLSPEC int netpatterns_setup_recursive_knomial_allgather_tree_node(
|
2012-08-16 23:11:35 +04:00
|
|
|
int num_nodes, int node_rank, int tree_order, int *hier_ranks,
|
2013-02-06 01:52:55 +04:00
|
|
|
netpatterns_k_exchange_node_t *exchange_node);
|
2012-08-16 23:11:35 +04:00
|
|
|
|
|
|
|
|
|
|
|
/* Input: k_exchange_node structure
|
|
|
|
Output: index in rank_exchanges array that points
|
|
|
|
to the "start_point" for outgoing send.
|
|
|
|
|
|
|
|
Please see below example of usage:
|
|
|
|
for (i = start_point ; i > 0; i--)
|
|
|
|
for (k = 0; k < tree_radix; k++)
|
|
|
|
send messages to exchange_node->rank_exchanges[i][k];
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline __opal_attribute_always_inline__
|
2013-02-06 01:52:55 +04:00
|
|
|
int netpatterns_get_knomial_level(
|
2012-08-16 23:11:35 +04:00
|
|
|
int my_rank, int src_rank,
|
|
|
|
int radix, int size,
|
|
|
|
int *k_level)
|
|
|
|
{
|
|
|
|
int distance,
|
|
|
|
pow_k;
|
|
|
|
int logk_level = 0;
|
|
|
|
|
|
|
|
/* Calculate disctance from source of data */
|
|
|
|
distance = src_rank - my_rank;
|
|
|
|
|
|
|
|
/* Wrap around */
|
|
|
|
if (0 > distance) {
|
|
|
|
distance += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
pow_k = 1;
|
|
|
|
while(distance / (pow_k * radix)) {
|
|
|
|
pow_k *= radix;
|
|
|
|
++logk_level;
|
|
|
|
}
|
|
|
|
--logk_level;
|
|
|
|
|
|
|
|
*k_level = pow_k;
|
|
|
|
return logk_level;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Input: my_rank, root, radix, size
|
|
|
|
* Output: source of the data, offset in power of K
|
|
|
|
*/
|
|
|
|
static inline __opal_attribute_always_inline__
|
2013-02-06 01:52:55 +04:00
|
|
|
int netpatterns_get_knomial_data_source(
|
2012-08-16 23:11:35 +04:00
|
|
|
int my_rank, int root, int radix, int size,
|
|
|
|
int *k_level, int *logk_level)
|
|
|
|
{
|
|
|
|
int level = radix;
|
|
|
|
int step = 0;
|
|
|
|
|
|
|
|
/* Calculate source of the data */
|
|
|
|
while((0 == (root - my_rank) % level)
|
|
|
|
&& (level <= size)) {
|
|
|
|
level *= radix;
|
|
|
|
++step;
|
|
|
|
}
|
|
|
|
|
|
|
|
*k_level = level/radix;
|
|
|
|
*logk_level = step;
|
|
|
|
return my_rank - (my_rank % level - root % level);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Input: my_rank, radix,
|
2013-02-06 01:52:55 +04:00
|
|
|
* k_level - that you get from netpatterns_get_knomial_data_source
|
2012-08-16 23:11:35 +04:00
|
|
|
* k_step - some integer
|
|
|
|
* Output: peer - next children in the tree
|
|
|
|
* Usage:
|
2013-02-06 01:52:55 +04:00
|
|
|
* src = netpatterns_get_knomial_data_source(
|
2012-08-16 23:11:35 +04:00
|
|
|
* my_rank, root, radix, size,
|
|
|
|
* &k_level, &logk_level)
|
|
|
|
* recv_from(src......);
|
|
|
|
*
|
|
|
|
* MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_INIT(step_info, k_level, my_rank);
|
|
|
|
* while(MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_PEER_CHECK_LEVEL(step_info)) {
|
|
|
|
* MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_PEER(my_rank, radix, step_info, peer);
|
|
|
|
* send_to(peer....);
|
|
|
|
* }
|
|
|
|
* for more example please grep in ptpcoll bcol bcast files
|
|
|
|
*/
|
|
|
|
|
2013-02-06 01:52:55 +04:00
|
|
|
typedef struct netpatterns_knomial_step_info_t {
|
2012-08-16 23:11:35 +04:00
|
|
|
int k_step;
|
|
|
|
int k_level;
|
|
|
|
int k_tmp_peer;
|
2013-02-06 01:52:55 +04:00
|
|
|
} netpatterns_knomial_step_info_t;
|
2012-08-16 23:11:35 +04:00
|
|
|
|
|
|
|
#define MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_UPDATE_LEVEL_FOR_BCAST(step_info, radix)\
|
|
|
|
do { \
|
|
|
|
if (1 != step_info.k_step) { \
|
|
|
|
step_info.k_level /= radix; \
|
|
|
|
} \
|
|
|
|
} while (0) \
|
|
|
|
|
|
|
|
#define MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_INIT(step_info, in_k_level, in_peer)\
|
|
|
|
do { \
|
|
|
|
step_info.k_step = 1; \
|
|
|
|
step_info.k_level = in_k_level; \
|
|
|
|
step_info.k_tmp_peer = in_peer; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_PEER_CHECK_LEVEL(step_info) \
|
|
|
|
(step_info.k_level > 1)
|
|
|
|
|
|
|
|
#define MCA_COMMON_NETPATTERNS_GET_NEXT_KNOMIAL_PEER(my_rank, radix, step_info, peer) \
|
|
|
|
do { \
|
|
|
|
int rank_radix_base = my_rank/step_info.k_level; \
|
|
|
|
\
|
|
|
|
peer = step_info.k_tmp_peer + step_info.k_level/radix; \
|
|
|
|
if (rank_radix_base != peer/step_info.k_level) { \
|
|
|
|
/* Wraparound the number */ \
|
|
|
|
peer -= step_info.k_level; \
|
|
|
|
assert(peer >=0); \
|
|
|
|
} \
|
|
|
|
++step_info.k_step; \
|
|
|
|
if (radix == step_info.k_step) { \
|
|
|
|
step_info.k_level /= radix; \
|
|
|
|
step_info.k_step = 1; \
|
|
|
|
step_info.k_tmp_peer = my_rank; \
|
|
|
|
} else { \
|
|
|
|
step_info.k_tmp_peer = peer; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
END_C_DECLS
|
|
|
|
#endif
|