Initial import of the HAN collective module
a hierarchical, architecture-aware collective communication module. Add Reduce and remove up_seg_size and low_seg_size in Bcast Increase HAN's priority Signed-off-by: Xi Luo <xluo12@vols.utk.edu> Signed-off-by: George Bosilca <bosilca@icl.utk.edu>
Этот коммит содержится в:
родитель
5c16e968b1
Коммит
feb5a7113c
49
ompi/mca/coll/han/Makefile.am
Обычный файл
49
ompi/mca/coll/han/Makefile.am
Обычный файл
@ -0,0 +1,49 @@
|
||||
#
|
||||
# Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
sources = \
|
||||
coll_han.h \
|
||||
coll_han_trigger.h \
|
||||
coll_han_bcast.c \
|
||||
coll_han_reduce.c \
|
||||
coll_han_scatter.c \
|
||||
coll_han_gather.c \
|
||||
coll_han_allreduce.c \
|
||||
coll_han_allgather.c \
|
||||
coll_han_component.c \
|
||||
coll_han_module.c \
|
||||
coll_han_trigger.c \
|
||||
coll_han_utils.c
|
||||
|
||||
# Make the output library in this directory, and name it either
|
||||
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
|
||||
# (for static builds).
|
||||
|
||||
component_noinst =
|
||||
component_install =
|
||||
if MCA_BUILD_ompi_coll_han_DSO
|
||||
component_install += mca_coll_han.la
|
||||
else
|
||||
component_noinst += libmca_coll_han.la
|
||||
endif
|
||||
|
||||
# See ompi/mca/btl/sm/Makefile.am for an explanation of
|
||||
# libmca_common_sm.la.
|
||||
|
||||
mcacomponentdir = $(ompilibdir)
|
||||
mcacomponent_LTLIBRARIES = $(component_install)
|
||||
mca_coll_han_la_SOURCES = $(sources)
|
||||
mca_coll_han_la_LDFLAGS = -module -avoid-version
|
||||
mca_coll_han_la_LIBADD =
|
||||
|
||||
noinst_LTLIBRARIES = $(component_noinst)
|
||||
libmca_coll_han_la_SOURCES =$(sources)
|
||||
libmca_coll_han_la_LDFLAGS = -module -avoid-version
|
410
ompi/mca/coll/han/coll_han.h
Обычный файл
410
ompi/mca/coll/han/coll_han.h
Обычный файл
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef MCA_COLL_HAN_EXPORT_H
|
||||
#define MCA_COLL_HAN_EXPORT_H
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include "mpi.h"
|
||||
#include "ompi/mca/mca.h"
|
||||
#include "ompi/mca/coll/coll.h"
|
||||
#include "ompi/communicator/communicator.h"
|
||||
#include "ompi/include/mpi.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "opal/util/info.h"
|
||||
#include "ompi/op/op.h"
|
||||
#include "opal/runtime/opal_progress.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
BEGIN_C_DECLS typedef struct {
|
||||
uint32_t umod;
|
||||
uint32_t lmod;
|
||||
uint32_t fs;
|
||||
uint32_t ualg;
|
||||
uint32_t us;
|
||||
} selection;
|
||||
|
||||
struct mca_bcast_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *buff;
|
||||
int seg_count;
|
||||
struct ompi_datatype_t *dtype;
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int num_segments;
|
||||
int cur_seg;
|
||||
int w_rank;
|
||||
int last_seg_count;
|
||||
bool noop;
|
||||
};
|
||||
typedef struct mca_bcast_argu_s mca_bcast_argu_t;
|
||||
|
||||
struct mca_reduce_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *sbuf;
|
||||
void *rbuf;
|
||||
int seg_count;
|
||||
struct ompi_datatype_t *dtype;
|
||||
struct ompi_op_t *op;
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int num_segments;
|
||||
int cur_seg;
|
||||
int w_rank;
|
||||
int last_seg_count;
|
||||
bool noop;
|
||||
};
|
||||
typedef struct mca_reduce_argu_s mca_reduce_argu_t;
|
||||
|
||||
struct mca_allreduce_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *sbuf;
|
||||
void *rbuf;
|
||||
int seg_count;
|
||||
struct ompi_datatype_t *dtype;
|
||||
struct ompi_op_t *op;
|
||||
int root_up_rank;
|
||||
int root_low_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int num_segments;
|
||||
int cur_seg;
|
||||
int w_rank;
|
||||
int last_seg_count;
|
||||
bool noop;
|
||||
ompi_request_t *req;
|
||||
int *completed;
|
||||
};
|
||||
typedef struct mca_allreduce_argu_s mca_allreduce_argu_t;
|
||||
|
||||
struct mca_scatter_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *sbuf;
|
||||
void *sbuf_inter_free;
|
||||
void *sbuf_reorder_free;
|
||||
int scount;
|
||||
struct ompi_datatype_t *sdtype;
|
||||
void *rbuf;
|
||||
int rcount;
|
||||
struct ompi_datatype_t *rdtype;
|
||||
int root;
|
||||
int root_up_rank;
|
||||
int root_low_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int w_rank;
|
||||
bool noop;
|
||||
ompi_request_t *req;
|
||||
};
|
||||
typedef struct mca_scatter_argu_s mca_scatter_argu_t;
|
||||
|
||||
struct mca_gather_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *sbuf;
|
||||
void *sbuf_inter_free;
|
||||
int scount;
|
||||
struct ompi_datatype_t *sdtype;
|
||||
void *rbuf;
|
||||
int rcount;
|
||||
struct ompi_datatype_t *rdtype;
|
||||
int root;
|
||||
int root_up_rank;
|
||||
int root_low_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int w_rank;
|
||||
bool noop;
|
||||
ompi_request_t *req;
|
||||
};
|
||||
typedef struct mca_gather_argu_s mca_gather_argu_t;
|
||||
|
||||
struct mca_allgather_argu_s {
|
||||
mca_coll_task_t *cur_task;
|
||||
void *sbuf;
|
||||
void *sbuf_inter_free;
|
||||
int scount;
|
||||
struct ompi_datatype_t *sdtype;
|
||||
void *rbuf;
|
||||
int rcount;
|
||||
struct ompi_datatype_t *rdtype;
|
||||
int root_low_rank;
|
||||
struct ompi_communicator_t *up_comm;
|
||||
struct ompi_communicator_t *low_comm;
|
||||
int w_rank;
|
||||
bool noop;
|
||||
bool is_mapbycore;
|
||||
int *topo;
|
||||
ompi_request_t *req;
|
||||
};
|
||||
typedef struct mca_allgather_argu_s mca_allgather_argu_t;
|
||||
|
||||
/**
|
||||
* Structure to hold the han coll component. First it holds the
|
||||
* base coll component, and then holds a bunch of
|
||||
* han-coll-component-specific stuff (e.g., current MCA param
|
||||
* values).
|
||||
*/
|
||||
typedef struct mca_coll_han_component_t {
|
||||
/** Base coll component */
|
||||
mca_coll_base_component_2_0_0_t super;
|
||||
|
||||
/** MCA parameter: Priority of this component */
|
||||
int han_priority;
|
||||
/* whether output the log message */
|
||||
int han_output;
|
||||
/* segment size for bcast */
|
||||
uint32_t han_bcast_segsize;
|
||||
/* up level module for bcast */
|
||||
uint32_t han_bcast_up_module;
|
||||
/* low level module for bcast */
|
||||
uint32_t han_bcast_low_module;
|
||||
/* segment size for reduce */
|
||||
uint32_t han_reduce_segsize;
|
||||
/* up level module for reduce */
|
||||
uint32_t han_reduce_up_module;
|
||||
/* low level module for reduce */
|
||||
uint32_t han_reduce_low_module;
|
||||
/* segment size for allreduce */
|
||||
uint32_t han_allreduce_segsize;
|
||||
/* up level module for allreduce */
|
||||
uint32_t han_allreduce_up_module;
|
||||
/* low level module for allreduce */
|
||||
uint32_t han_allreduce_low_module;
|
||||
/* up level module for allgather */
|
||||
uint32_t han_allgather_up_module;
|
||||
/* low level module for allgather */
|
||||
uint32_t han_allgather_low_module;
|
||||
/* up level module for gather */
|
||||
uint32_t han_gather_up_module;
|
||||
/* low level module for gather */
|
||||
uint32_t han_gather_low_module;
|
||||
/* up level module for scatter */
|
||||
uint32_t han_scatter_up_module;
|
||||
/* low level module for scatter */
|
||||
uint32_t han_scatter_low_module;
|
||||
/* whether enable auto tune */
|
||||
uint32_t han_auto_tune;
|
||||
/* create a 3D array
|
||||
* num_processes (n): 2 4 8 16 32 64 (6)
|
||||
* num_core (c): 2 4 8 12 (4)
|
||||
* message size (m): 1 - 4194304 (23)
|
||||
*/
|
||||
uint32_t han_auto_tune_n;
|
||||
uint32_t han_auto_tune_c;
|
||||
uint32_t han_auto_tune_m;
|
||||
selection *han_auto_tuned;
|
||||
} mca_coll_han_component_t;
|
||||
|
||||
/** Coll han module */
|
||||
typedef struct mca_coll_han_module_t {
|
||||
/** Base module */
|
||||
mca_coll_base_module_t super;
|
||||
|
||||
/* Whether this module has been lazily initialized or not yet */
|
||||
bool enabled;
|
||||
|
||||
struct ompi_communicator_t *cached_comm;
|
||||
struct ompi_communicator_t **cached_low_comms;
|
||||
struct ompi_communicator_t **cached_up_comms;
|
||||
int *cached_vranks;
|
||||
int *cached_topo;
|
||||
bool is_mapbycore;
|
||||
} mca_coll_han_module_t;
|
||||
OBJ_CLASS_DECLARATION(mca_coll_han_module_t);
|
||||
|
||||
/**
|
||||
* Global component instance
|
||||
*/
|
||||
OMPI_MODULE_DECLSPEC extern mca_coll_han_component_t mca_coll_han_component;
|
||||
|
||||
/*
|
||||
* coll module functions
|
||||
*/
|
||||
int mca_coll_han_init_query(bool enable_progress_threads, bool enable_mpi_threads);
|
||||
|
||||
mca_coll_base_module_t *mca_coll_han_comm_query(struct ompi_communicator_t *comm, int *priority);
|
||||
|
||||
int han_request_free(ompi_request_t ** request);
|
||||
|
||||
/* Subcommunicator creation */
|
||||
void mca_coll_han_comm_create(struct ompi_communicator_t *comm, mca_coll_han_module_t * han_module);
|
||||
|
||||
/* Gather topology information */
|
||||
int mca_coll_han_pow10_int(int pow_value);
|
||||
int mca_coll_han_hostname_to_number(char *hostname, int size);
|
||||
void mca_coll_han_topo_get(int *topo, struct ompi_communicator_t *comm, int num_topo_level);
|
||||
void mca_coll_han_topo_sort(int *topo, int start, int end, int size, int level, int num_topo_level);
|
||||
bool mca_coll_han_topo_is_mapbycore(int *topo, struct ompi_communicator_t *comm,
|
||||
int num_topo_level);
|
||||
int *mca_coll_han_topo_init(struct ompi_communicator_t *comm, mca_coll_han_module_t * han_module,
|
||||
int num_topo_level);
|
||||
void mca_coll_han_topo_print(int *topo, struct ompi_communicator_t *comm, int num_topo_level);
|
||||
|
||||
/* Utils */
|
||||
void mca_coll_han_get_ranks(int *vranks, int root, int low_size, int *root_low_rank,
|
||||
int *root_up_rank);
|
||||
uint32_t han_auto_tuned_get_n(uint32_t n);
|
||||
uint32_t han_auto_tuned_get_c(uint32_t c);
|
||||
uint32_t han_auto_tuned_get_m(uint32_t m);
|
||||
|
||||
|
||||
/* Bcast */
|
||||
void mac_coll_han_set_bcast_argu(mca_bcast_argu_t * argu, mca_coll_task_t * cur_task, void *buff,
|
||||
int seg_count, struct ompi_datatype_t *dtype,
|
||||
int root_up_rank, int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments, int cur_seg, int w_rank, int last_seg_count,
|
||||
bool noop);
|
||||
int mca_coll_han_bcast_intra(void *buff, int count, struct ompi_datatype_t *dtype, int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module);
|
||||
int mca_coll_han_bcast_t0_task(void *task_argu);
|
||||
int mca_coll_han_bcast_t1_task(void *task_argu);
|
||||
|
||||
/* Reduce */
|
||||
void mac_coll_han_set_reduce_argu(mca_reduce_argu_t * argu, mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *rbuf, int seg_count, struct ompi_datatype_t *dtype,
|
||||
struct ompi_op_t *op,
|
||||
int root_up_rank, int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments, int cur_seg, int w_rank, int last_seg_count,
|
||||
bool noop);
|
||||
|
||||
int mca_coll_han_reduce_intra(const void *sbuf,
|
||||
void *rbuf,
|
||||
int count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
ompi_op_t* op,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm,
|
||||
mca_coll_base_module_t * module);
|
||||
|
||||
int mca_coll_han_reduce_t0_task(void *task_argu);
|
||||
int mca_coll_han_reduce_t1_task(void *task_argu);
|
||||
|
||||
/* Allreduce */
|
||||
void mac_coll_han_set_allreduce_argu(mca_allreduce_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *rbuf,
|
||||
int seg_count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
struct ompi_op_t *op,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments,
|
||||
int cur_seg,
|
||||
int w_rank,
|
||||
int last_seg_count,
|
||||
bool noop, ompi_request_t * req, int *completed);
|
||||
int mca_coll_han_allreduce_intra(const void *sbuf,
|
||||
void *rbuf,
|
||||
int count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
struct ompi_op_t *op,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module);
|
||||
int mca_coll_han_allreduce_t0_task(void *task_argu);
|
||||
int mca_coll_han_allreduce_t1_task(void *task_argu);
|
||||
int mca_coll_han_allreduce_t2_task(void *task_argu);
|
||||
int mca_coll_han_allreduce_t3_task(void *task_argu);
|
||||
|
||||
/* Scatter */
|
||||
int
|
||||
mca_coll_han_scatter_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module);
|
||||
int mca_coll_han_scatter_us_task(void *task_argu);
|
||||
int mca_coll_han_scatter_ls_task(void *task_argu);
|
||||
void mac_coll_han_set_scatter_argu(mca_scatter_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
void *sbuf_reorder_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank, bool noop, ompi_request_t * req);
|
||||
|
||||
/* Gatter */
|
||||
int
|
||||
mca_coll_han_gather_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module);
|
||||
int mca_coll_han_gather_lg_task(void *task_argu);
|
||||
int mca_coll_han_gather_ug_task(void *task_argu);
|
||||
void mac_coll_han_set_gather_argu(mca_gather_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank, bool noop, ompi_request_t * req);
|
||||
|
||||
/* Allgather */
|
||||
int
|
||||
mca_coll_han_allgather_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module);
|
||||
int mca_coll_han_allgather_lg_task(void *task_argu);
|
||||
int mca_coll_han_allgather_uag_task(void *task_argu);
|
||||
int mca_coll_han_allgather_lb_task(void *task_argu);
|
||||
void mac_coll_han_set_allgather_argu(mca_allgather_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank,
|
||||
bool noop, bool is_mapbycore, int *topo, ompi_request_t * req);
|
||||
|
||||
END_C_DECLS
|
||||
#endif /* MCA_COLL_HAN_EXPORT_H */
|
240
ompi/mca/coll/han/coll_han_allgather.c
Обычный файл
240
ompi/mca/coll/han/coll_han_allgather.c
Обычный файл
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
void mac_coll_han_set_allgather_argu(mca_allgather_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank,
|
||||
bool noop, bool is_mapbycore, int *topo, ompi_request_t * req)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->sbuf = sbuf;
|
||||
argu->sbuf_inter_free = sbuf_inter_free;
|
||||
argu->scount = scount;
|
||||
argu->sdtype = sdtype;
|
||||
argu->rbuf = rbuf;
|
||||
argu->rcount = rcount;
|
||||
argu->rdtype = rdtype;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->w_rank = w_rank;
|
||||
argu->noop = noop;
|
||||
argu->is_mapbycore = is_mapbycore;
|
||||
argu->topo = topo;
|
||||
argu->req = req;
|
||||
}
|
||||
|
||||
int
|
||||
mca_coll_han_allgather_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module)
|
||||
{
|
||||
int w_rank;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm =
|
||||
han_module->cached_low_comms[mca_coll_han_component.han_allgather_low_module];
|
||||
ompi_communicator_t *up_comm =
|
||||
han_module->cached_up_comms[mca_coll_han_component.han_allgather_up_module];
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
|
||||
ompi_request_t *temp_request = NULL;
|
||||
/* Set up request */
|
||||
temp_request = OBJ_NEW(ompi_request_t);
|
||||
OMPI_REQUEST_INIT(temp_request, false);
|
||||
temp_request->req_state = OMPI_REQUEST_ACTIVE;
|
||||
temp_request->req_type = 0;
|
||||
temp_request->req_free = han_request_free;
|
||||
temp_request->req_status.MPI_SOURCE = 0;
|
||||
temp_request->req_status.MPI_TAG = 0;
|
||||
temp_request->req_status.MPI_ERROR = 0;
|
||||
temp_request->req_status._cancelled = 0;
|
||||
temp_request->req_status._ucount = 0;
|
||||
|
||||
/* Init topo */
|
||||
int *topo = mca_coll_han_topo_init(comm, han_module, 2);
|
||||
|
||||
int root_low_rank = 0;
|
||||
/* Create lg (lower level gather) task */
|
||||
mca_coll_task_t *lg = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup lg task arguments */
|
||||
mca_allgather_argu_t *lg_argu = malloc(sizeof(mca_allgather_argu_t));
|
||||
mac_coll_han_set_allgather_argu(lg_argu, lg, (char *) sbuf, NULL, scount, sdtype, rbuf, rcount,
|
||||
rdtype, root_low_rank, up_comm, low_comm, w_rank,
|
||||
low_rank != root_low_rank, han_module->is_mapbycore, topo,
|
||||
temp_request);
|
||||
/* Init lg task */
|
||||
init_task(lg, mca_coll_han_allgather_lg_task, (void *) (lg_argu));
|
||||
/* Issure lg task */
|
||||
issue_task(lg);
|
||||
|
||||
ompi_request_wait(&temp_request, MPI_STATUS_IGNORE);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* lg: lower level (shared memory) gather task */
|
||||
int mca_coll_han_allgather_lg_task(void *task_argu)
|
||||
{
|
||||
mca_allgather_argu_t *t = (mca_allgather_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] HAN Allgather: lg\n",
|
||||
t->w_rank));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
|
||||
/* If the process is one of the node leader */
|
||||
char *tmp_buf = NULL;
|
||||
char *tmp_rbuf = NULL;
|
||||
if (!t->noop) {
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
ptrdiff_t rsize, rgap = 0;
|
||||
rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size, &rgap);
|
||||
tmp_buf = (char *) malloc(rsize);
|
||||
tmp_rbuf = tmp_buf - rgap;
|
||||
}
|
||||
/* Shared memory gather */
|
||||
t->low_comm->c_coll->coll_gather((char *) t->sbuf, t->scount, t->sdtype, tmp_rbuf, t->rcount,
|
||||
t->rdtype, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_gather_module);
|
||||
t->sbuf = tmp_rbuf;
|
||||
t->sbuf_inter_free = tmp_buf;
|
||||
|
||||
/* Create uag (upper level all-gather) task */
|
||||
mca_coll_task_t *uag = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup uag task arguments */
|
||||
t->cur_task = uag;
|
||||
/* Init uag task */
|
||||
init_task(uag, mca_coll_han_allgather_uag_task, (void *) t);
|
||||
/* Issure uag task */
|
||||
issue_task(uag);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* uag: upper level (inter-node) all-gather task */
|
||||
int mca_coll_han_allgather_uag_task(void *task_argu)
|
||||
{
|
||||
mca_allgather_argu_t *t = (mca_allgather_argu_t *) task_argu;
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
|
||||
if (t->noop) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allgather: uag noop\n", t->w_rank));
|
||||
} else {
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
int up_size = ompi_comm_size(t->up_comm);
|
||||
char *reorder_buf = NULL;
|
||||
char *reorder_rbuf = NULL;
|
||||
if (t->is_mapbycore) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: HAN Allgather is bycore: ", t->w_rank));
|
||||
reorder_rbuf = (char *) t->rbuf;
|
||||
} else {
|
||||
ptrdiff_t rsize, rgap = 0;
|
||||
rsize =
|
||||
opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size * up_size,
|
||||
&rgap);
|
||||
reorder_buf = (char *) malloc(rsize);
|
||||
reorder_rbuf = reorder_buf - rgap;
|
||||
}
|
||||
|
||||
/* Inter node allgather */
|
||||
t->up_comm->c_coll->coll_allgather((char *) t->sbuf, t->scount * low_size, t->sdtype,
|
||||
reorder_rbuf, t->rcount * low_size, t->rdtype,
|
||||
t->up_comm, t->up_comm->c_coll->coll_allgather_module);
|
||||
|
||||
if (t->sbuf_inter_free != NULL) {
|
||||
free(t->sbuf_inter_free);
|
||||
t->sbuf_inter_free = NULL;
|
||||
}
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allgather: ug allgather finish\n", t->w_rank));
|
||||
|
||||
/* Reorder the node leader's rbuf, copy data from tmp_rbuf to rbuf */
|
||||
if (!t->is_mapbycore) {
|
||||
int i, j;
|
||||
ptrdiff_t rextent;
|
||||
ompi_datatype_type_extent(t->rdtype, &rextent);
|
||||
for (i = 0; i < up_size; i++) {
|
||||
for (j = 0; j < low_size; j++) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: HAN Allgather copy from %d %d\n", t->w_rank,
|
||||
(i * low_size + j) * 2 + 1,
|
||||
t->topo[(i * low_size + j) * 2 + 1]));
|
||||
ompi_datatype_copy_content_same_ddt(t->rdtype, (ptrdiff_t) t->rcount,
|
||||
(char *) t->rbuf +
|
||||
rextent *
|
||||
(ptrdiff_t) t->topo[(i * low_size + j) * 2 +
|
||||
1] *
|
||||
(ptrdiff_t) t->rcount,
|
||||
reorder_rbuf + rextent * (i * low_size +
|
||||
j) *
|
||||
(ptrdiff_t) t->rcount);
|
||||
}
|
||||
}
|
||||
free(reorder_buf);
|
||||
reorder_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create lb (low level broadcast) task */
|
||||
mca_coll_task_t *lb = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup lb task arguments */
|
||||
t->cur_task = lb;
|
||||
/* Init lb task */
|
||||
init_task(lb, mca_coll_han_allgather_lb_task, (void *) t);
|
||||
/* Issure lb task */
|
||||
issue_task(lb);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* lb: low level (shared-memory) broadcast task */
|
||||
int mca_coll_han_allgather_lb_task(void *task_argu)
|
||||
{
|
||||
mca_allgather_argu_t *t = (mca_allgather_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] HAN Allgather: uag noop\n",
|
||||
t->w_rank));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
int up_size = ompi_comm_size(t->up_comm);
|
||||
t->low_comm->c_coll->coll_bcast((char *) t->rbuf, t->rcount * low_size * up_size, t->rdtype,
|
||||
t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_bcast_module);
|
||||
|
||||
ompi_request_t *temp_req = t->req;
|
||||
free(t);
|
||||
ompi_request_complete(temp_req, 1);
|
||||
return OMPI_SUCCESS;
|
||||
|
||||
}
|
395
ompi/mca/coll/han/coll_han_allreduce.c
Обычный файл
395
ompi/mca/coll/han/coll_han_allreduce.c
Обычный файл
@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
/* Only work with regular situation (each node has equal number of processes) */
|
||||
|
||||
void mac_coll_han_set_allreduce_argu(mca_allreduce_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *rbuf,
|
||||
int seg_count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
struct ompi_op_t *op,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments,
|
||||
int cur_seg,
|
||||
int w_rank,
|
||||
int last_seg_count,
|
||||
bool noop, ompi_request_t * req, int *completed)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->sbuf = sbuf;
|
||||
argu->rbuf = rbuf;
|
||||
argu->seg_count = seg_count;
|
||||
argu->dtype = dtype;
|
||||
argu->op = op;
|
||||
argu->root_up_rank = root_up_rank;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->num_segments = num_segments;
|
||||
argu->cur_seg = cur_seg;
|
||||
argu->w_rank = w_rank;
|
||||
argu->last_seg_count = last_seg_count;
|
||||
argu->noop = noop;
|
||||
argu->req = req;
|
||||
argu->completed = completed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each segment of the messsage needs to go though 4 steps to perform MPI_Allreduce:
|
||||
* lr: lower level (shared-memory or intra-node) reduce,
|
||||
* ur: upper level (inter-node) reduce,
|
||||
* ub: upper level (inter-node) bcast,
|
||||
* lb: lower level (shared-memory or intra-node) bcast.
|
||||
* Hence, in each iteration, there is a combination of collective operations which is called a task.
|
||||
* | seg 0 | seg 1 | seg 2 | seg 3 |
|
||||
* iter 0 | lr | | | | task: t0, contains lr
|
||||
* iter 1 | ur | lr | | | task: t1, contains ur and lr
|
||||
* iter 2 | ub | ur | lr | | task: t2, contains ub, ur and lr
|
||||
* iter 3 | lb | ub | ur | lr | task: t3, contains lb, ub, ur and lr
|
||||
* iter 4 | | lb | ub | ur | task: t3, contains lb, ub and ur
|
||||
* iter 5 | | | lb | ub | task: t3, contains lb and ub
|
||||
* iter 6 | | | | lb | task: t3, contains lb
|
||||
*/
|
||||
|
||||
int
|
||||
mca_coll_han_allreduce_intra(const void *sbuf,
|
||||
void *rbuf,
|
||||
int count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
struct ompi_op_t *op,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module)
|
||||
{
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(dtype, &lb, &extent);
|
||||
int w_rank;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
int seg_count = count;
|
||||
size_t typelng;
|
||||
ompi_datatype_type_size(dtype, &typelng);
|
||||
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm;
|
||||
ompi_communicator_t *up_comm;
|
||||
/* Auto tune is enabled */
|
||||
if (mca_coll_han_component.han_auto_tune && mca_coll_han_component.han_auto_tuned != NULL) {
|
||||
uint32_t n = han_auto_tuned_get_n(ompi_comm_size(han_module->cached_up_comms[0]));
|
||||
uint32_t c = han_auto_tuned_get_c(ompi_comm_size(han_module->cached_low_comms[0]));
|
||||
uint32_t m = han_auto_tuned_get_m(typelng * count);
|
||||
uint32_t id =
|
||||
n * mca_coll_han_component.han_auto_tune_c * mca_coll_han_component.han_auto_tune_m +
|
||||
c * mca_coll_han_component.han_auto_tune_m + m +
|
||||
mca_coll_han_component.han_auto_tune_n * mca_coll_han_component.han_auto_tune_c *
|
||||
mca_coll_han_component.han_auto_tune_m;
|
||||
uint32_t umod = mca_coll_han_component.han_auto_tuned[id].umod;
|
||||
uint32_t lmod = mca_coll_han_component.han_auto_tuned[id].lmod;
|
||||
uint32_t fs = mca_coll_han_component.han_auto_tuned[id].fs;
|
||||
/* ualg and us are only available when using ADAPT */
|
||||
/*
|
||||
uint32_t ualg = mca_coll_han_component.han_auto_tuned[id].ualg;
|
||||
uint32_t us = mca_coll_han_component.han_auto_tuned[id].us;
|
||||
*/
|
||||
/* Set up umod */
|
||||
up_comm = han_module->cached_up_comms[umod];
|
||||
/* Set up lmod */
|
||||
low_comm = han_module->cached_low_comms[lmod];
|
||||
/* Set up fs */
|
||||
COLL_BASE_COMPUTED_SEGCOUNT((size_t) fs, typelng, seg_count);
|
||||
/* Set up ualg and us, which is only available when using ADAPT */
|
||||
/*
|
||||
if (umod == 1) {
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_algorithm = ualg;
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_algorithm = ualg;
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_segment_size = us;
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_segment_size = us;
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
low_comm = han_module->cached_low_comms[mca_coll_han_component.han_bcast_low_module];
|
||||
up_comm = han_module->cached_up_comms[mca_coll_han_component.han_bcast_up_module];
|
||||
COLL_BASE_COMPUTED_SEGCOUNT(mca_coll_han_component.han_allreduce_segsize, typelng,
|
||||
seg_count);
|
||||
}
|
||||
|
||||
/* Determine number of elements sent per task. */
|
||||
OPAL_OUTPUT_VERBOSE((10, mca_coll_han_component.han_output,
|
||||
"In HAN Allreduce seg_size %d seg_count %d count %d\n",
|
||||
mca_coll_han_component.han_allreduce_segsize, seg_count, count));
|
||||
int num_segments = (count + seg_count - 1) / seg_count;
|
||||
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
int root_up_rank = 0;
|
||||
int root_low_rank = 0;
|
||||
/* Create t0 task for the first segment */
|
||||
mca_coll_task_t *t0 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t0 task arguments */
|
||||
int *completed = (int *) malloc(sizeof(int));
|
||||
completed[0] = 0;
|
||||
mca_allreduce_argu_t *t = malloc(sizeof(mca_allreduce_argu_t));
|
||||
mac_coll_han_set_allreduce_argu(t, t0, (char *) sbuf, (char *) rbuf, seg_count, dtype, op,
|
||||
root_up_rank, root_low_rank, up_comm, low_comm, num_segments, 0,
|
||||
w_rank, count - (num_segments - 1) * seg_count,
|
||||
low_rank != root_low_rank, NULL, completed);
|
||||
/* Init t0 task */
|
||||
init_task(t0, mca_coll_han_allreduce_t0_task, (void *) (t));
|
||||
/* Issure t0 task */
|
||||
issue_task(t0);
|
||||
|
||||
/* Create t1 tasks for the current segment */
|
||||
mca_coll_task_t *t1 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t1 task arguments */
|
||||
t->cur_task = t1;
|
||||
/* Init t1 task */
|
||||
init_task(t1, mca_coll_han_allreduce_t1_task, (void *) t);
|
||||
/* Issue t1 task */
|
||||
issue_task(t1);
|
||||
|
||||
/* Create t2 tasks for the current segment */
|
||||
mca_coll_task_t *t2 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t2 task arguments */
|
||||
t->cur_task = t2;
|
||||
/* Init t2 task */
|
||||
init_task(t2, mca_coll_han_allreduce_t2_task, (void *) t);
|
||||
issue_task(t2);
|
||||
|
||||
/* Create t3 tasks for the current segment */
|
||||
mca_coll_task_t *t3 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t3 task arguments */
|
||||
t->cur_task = t3;
|
||||
/* Init t3 task */
|
||||
init_task(t3, mca_coll_han_allreduce_t3_task, (void *) t);
|
||||
issue_task(t3);
|
||||
|
||||
while (t->completed[0] != t->num_segments) {
|
||||
/* Create t3 tasks for the current segment */
|
||||
mca_coll_task_t *t3 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t3 task arguments */
|
||||
t->cur_task = t3;
|
||||
t->sbuf = (char *) t->sbuf + extent * t->seg_count;
|
||||
t->rbuf = (char *) t->rbuf + extent * t->seg_count;
|
||||
t->cur_seg = t->cur_seg + 1;
|
||||
/* Init t3 task */
|
||||
init_task(t3, mca_coll_han_allreduce_t3_task, (void *) t);
|
||||
issue_task(t3);
|
||||
}
|
||||
if (t->completed != NULL) {
|
||||
free(t->completed);
|
||||
t->completed = NULL;
|
||||
}
|
||||
free(t);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t0 task */
|
||||
int mca_coll_han_allreduce_t0_task(void *task_argu)
|
||||
{
|
||||
mca_allreduce_argu_t *t = (mca_allreduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allreduce: t0 %d r_buf %d\n", t->w_rank, t->cur_seg,
|
||||
((int *) t->rbuf)[0]));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf, (char *) t->rbuf, t->seg_count, t->dtype,
|
||||
t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t1 task */
|
||||
int mca_coll_han_allreduce_t1_task(void *task_argu)
|
||||
{
|
||||
mca_allreduce_argu_t *t = (mca_allreduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allreduce: t1 %d r_buf %d\n", t->w_rank, t->cur_seg,
|
||||
((int *) t->rbuf)[0]));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *ireduce_req;
|
||||
int tmp_count = t->seg_count;
|
||||
if (!t->noop) {
|
||||
int up_rank = ompi_comm_rank(t->up_comm);
|
||||
/* ur of cur_seg */
|
||||
if (up_rank == t->root_up_rank) {
|
||||
t->up_comm->c_coll->coll_ireduce(MPI_IN_PLACE, (char *) t->rbuf, t->seg_count, t->dtype,
|
||||
t->op, t->root_up_rank, t->up_comm, &ireduce_req,
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
} else {
|
||||
t->up_comm->c_coll->coll_ireduce((char *) t->rbuf, (char *) t->rbuf, t->seg_count,
|
||||
t->dtype, t->op, t->root_up_rank, t->up_comm,
|
||||
&ireduce_req, t->up_comm->c_coll->coll_ireduce_module);
|
||||
}
|
||||
}
|
||||
/* lr of cur_seg+1 */
|
||||
if (t->cur_seg <= t->num_segments - 2) {
|
||||
if (t->cur_seg == t->num_segments - 2 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf + extent * t->seg_count,
|
||||
(char *) t->rbuf + extent * t->seg_count, tmp_count,
|
||||
t->dtype, t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
|
||||
}
|
||||
if (!t->noop) {
|
||||
ompi_request_wait(&ireduce_req, MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t2 task */
|
||||
int mca_coll_han_allreduce_t2_task(void *task_argu)
|
||||
{
|
||||
mca_allreduce_argu_t *t = (mca_allreduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allreduce: t2 %d r_buf %d\n", t->w_rank, t->cur_seg,
|
||||
((int *) t->rbuf)[0]));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *reqs[2];
|
||||
int req_count = 0;
|
||||
int tmp_count = t->seg_count;
|
||||
if (!t->noop) {
|
||||
int up_rank = ompi_comm_rank(t->up_comm);
|
||||
/* ub of cur_seg */
|
||||
t->up_comm->c_coll->coll_ibcast((char *) t->rbuf, t->seg_count, t->dtype, t->root_up_rank,
|
||||
t->up_comm, &(reqs[0]),
|
||||
t->up_comm->c_coll->coll_ibcast_module);
|
||||
req_count++;
|
||||
/* ur of cur_seg+1 */
|
||||
if (t->cur_seg <= t->num_segments - 2) {
|
||||
if (t->cur_seg == t->num_segments - 2 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
if (up_rank == t->root_up_rank) {
|
||||
t->up_comm->c_coll->coll_ireduce(MPI_IN_PLACE,
|
||||
(char *) t->rbuf + extent * t->seg_count,
|
||||
tmp_count, t->dtype, t->op, t->root_up_rank,
|
||||
t->up_comm, &(reqs[1]),
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
} else {
|
||||
t->up_comm->c_coll->coll_ireduce((char *) t->rbuf + extent * t->seg_count,
|
||||
(char *) t->rbuf + extent * t->seg_count,
|
||||
tmp_count, t->dtype, t->op, t->root_up_rank,
|
||||
t->up_comm, &(reqs[1]),
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
}
|
||||
req_count++;
|
||||
}
|
||||
}
|
||||
/* lr of cur_seg+2 */
|
||||
if (t->cur_seg <= t->num_segments - 3) {
|
||||
if (t->cur_seg == t->num_segments - 3 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf + 2 * extent * t->seg_count,
|
||||
(char *) t->rbuf + 2 * extent * t->seg_count, tmp_count,
|
||||
t->dtype, t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
}
|
||||
if (!t->noop && req_count > 0) {
|
||||
ompi_request_wait_all(req_count, reqs, MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t3 task */
|
||||
int mca_coll_han_allreduce_t3_task(void *task_argu)
|
||||
{
|
||||
mca_allreduce_argu_t *t = (mca_allreduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allreduce: t3 %d r_buf %d\n", t->w_rank, t->cur_seg,
|
||||
((int *) t->rbuf)[0]));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *reqs[2];
|
||||
int req_count = 0;
|
||||
int tmp_count = t->seg_count;
|
||||
if (!t->noop) {
|
||||
int up_rank = ompi_comm_rank(t->up_comm);
|
||||
/* ub of cur_seg+1 */
|
||||
if (t->cur_seg <= t->num_segments - 2) {
|
||||
if (t->cur_seg == t->num_segments - 2 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->up_comm->c_coll->coll_ibcast((char *) t->rbuf + extent * t->seg_count, t->seg_count,
|
||||
t->dtype, t->root_up_rank, t->up_comm, &(reqs[0]),
|
||||
t->up_comm->c_coll->coll_ibcast_module);
|
||||
req_count++;
|
||||
}
|
||||
/* ur of cur_seg+2 */
|
||||
if (t->cur_seg <= t->num_segments - 3) {
|
||||
if (t->cur_seg == t->num_segments - 3 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
if (up_rank == t->root_up_rank) {
|
||||
t->up_comm->c_coll->coll_ireduce(MPI_IN_PLACE,
|
||||
(char *) t->rbuf + 2 * extent * t->seg_count,
|
||||
tmp_count, t->dtype, t->op, t->root_up_rank,
|
||||
t->up_comm, &(reqs[1]),
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
} else {
|
||||
t->up_comm->c_coll->coll_ireduce((char *) t->rbuf + 2 * extent * t->seg_count,
|
||||
(char *) t->rbuf + 2 * extent * t->seg_count,
|
||||
tmp_count, t->dtype, t->op, t->root_up_rank,
|
||||
t->up_comm, &(reqs[1]),
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
}
|
||||
req_count++;
|
||||
}
|
||||
}
|
||||
/* lr of cur_seg+3 */
|
||||
if (t->cur_seg <= t->num_segments - 4) {
|
||||
if (t->cur_seg == t->num_segments - 4 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf + 3 * extent * t->seg_count,
|
||||
(char *) t->rbuf + 3 * extent * t->seg_count, tmp_count,
|
||||
t->dtype, t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
}
|
||||
/* lb of cur_seg */
|
||||
t->low_comm->c_coll->coll_bcast((char *) t->rbuf, t->seg_count, t->dtype, t->root_low_rank,
|
||||
t->low_comm, t->low_comm->c_coll->coll_bcast_module);
|
||||
if (!t->noop && req_count > 0) {
|
||||
ompi_request_wait_all(req_count, reqs, MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
t->completed[0]++;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] HAN Allreduce: t3 %d total %d\n", t->w_rank, t->cur_seg,
|
||||
t->completed[0]));
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
222
ompi/mca/coll/han/coll_han_bcast.c
Обычный файл
222
ompi/mca/coll/han/coll_han_bcast.c
Обычный файл
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
void mac_coll_han_set_bcast_argu(mca_bcast_argu_t * argu, mca_coll_task_t * cur_task, void *buff,
|
||||
int seg_count, struct ompi_datatype_t *dtype,
|
||||
int root_up_rank, int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments, int cur_seg, int w_rank, int last_seg_count,
|
||||
bool noop)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->buff = buff;
|
||||
argu->seg_count = seg_count;
|
||||
argu->dtype = dtype;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->root_up_rank = root_up_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->num_segments = num_segments;
|
||||
argu->cur_seg = cur_seg;
|
||||
argu->w_rank = w_rank;
|
||||
argu->last_seg_count = last_seg_count;
|
||||
argu->noop = noop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each segment of the messsage needs to go though 2 steps to perform MPI_Bcast:
|
||||
* ub: upper level (inter-node) bcast
|
||||
* lb: low level (shared-memory or intra-node) bcast.
|
||||
* Hence, in each iteration, there is a combination of collective operations which is called a task.
|
||||
* | seg 0 | seg 1 | seg 2 | seg 3 |
|
||||
* iter 0 | ub | | | | task: t0, contains ub
|
||||
* iter 1 | lb | ub | | | task: t1, contains ub and lb
|
||||
* iter 2 | | lb | ub | | task: t1, contains ub and lb
|
||||
* iter 3 | | | lb | ub | task: t1, contains ub and lb
|
||||
* iter 4 | | | | lb | task: t1, contains lb
|
||||
*/
|
||||
int
|
||||
mca_coll_han_bcast_intra(void *buff,
|
||||
int count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module)
|
||||
{
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(dtype, &lb, &extent);
|
||||
int w_rank;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
int seg_count = count;
|
||||
size_t typelng;
|
||||
ompi_datatype_type_size(dtype, &typelng);
|
||||
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm;
|
||||
ompi_communicator_t *up_comm;
|
||||
/* Auto tune is enabled */
|
||||
if (mca_coll_han_component.han_auto_tune && mca_coll_han_component.han_auto_tuned != NULL) {
|
||||
uint32_t n = han_auto_tuned_get_n(ompi_comm_size(han_module->cached_up_comms[0]));
|
||||
uint32_t c = han_auto_tuned_get_c(ompi_comm_size(han_module->cached_low_comms[0]));
|
||||
uint32_t m = han_auto_tuned_get_m(typelng * count);
|
||||
uint32_t id =
|
||||
n * mca_coll_han_component.han_auto_tune_c * mca_coll_han_component.han_auto_tune_m +
|
||||
c * mca_coll_han_component.han_auto_tune_m + m;
|
||||
uint32_t umod = mca_coll_han_component.han_auto_tuned[id].umod;
|
||||
uint32_t lmod = mca_coll_han_component.han_auto_tuned[id].lmod;
|
||||
uint32_t fs = mca_coll_han_component.han_auto_tuned[id].fs;
|
||||
/* ualg and us are only available when using ADAPT */
|
||||
/*
|
||||
uint32_t ualg = mca_coll_han_component.han_auto_tuned[id].ualg;
|
||||
uint32_t us = mca_coll_han_component.han_auto_tuned[id].us;
|
||||
*/
|
||||
/* Set up umod */
|
||||
up_comm = han_module->cached_up_comms[umod];
|
||||
/* Set up lmod */
|
||||
low_comm = han_module->cached_low_comms[lmod];
|
||||
/* Set up fs */
|
||||
COLL_BASE_COMPUTED_SEGCOUNT((size_t) fs, typelng, seg_count);
|
||||
/* Set up ualg and us, which is only available when using ADAPT */
|
||||
/*
|
||||
if (umod == 1) {
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_algorithm = ualg;
|
||||
((mca_coll_adapt_module_t *) (up_comm->c_coll->coll_ibcast_module))->adapt_component->
|
||||
adapt_ibcast_segment_size = us;
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
/* If auto tune is disabled, use MCA parameters */
|
||||
low_comm = han_module->cached_low_comms[mca_coll_han_component.han_bcast_low_module];
|
||||
up_comm = han_module->cached_up_comms[mca_coll_han_component.han_bcast_up_module];
|
||||
COLL_BASE_COMPUTED_SEGCOUNT(mca_coll_han_component.han_bcast_segsize, typelng,
|
||||
seg_count);
|
||||
}
|
||||
|
||||
int num_segments = (count + seg_count - 1) / seg_count;
|
||||
OPAL_OUTPUT_VERBOSE((20, mca_coll_han_component.han_output,
|
||||
"In HAN seg_count %d count %d num_seg %d\n",
|
||||
seg_count, count, num_segments));
|
||||
|
||||
int *vranks = han_module->cached_vranks;
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
int low_size = ompi_comm_size(low_comm);
|
||||
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank);
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: root_low_rank %d root_up_rank %d\n", w_rank, root_low_rank,
|
||||
root_up_rank));
|
||||
|
||||
/* Create t0 tasks for the first segment */
|
||||
mca_coll_task_t *t0 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t0 task arguments */
|
||||
mca_bcast_argu_t *t = malloc(sizeof(mca_bcast_argu_t));
|
||||
mac_coll_han_set_bcast_argu(t, t0, (char *) buff, seg_count, dtype,
|
||||
root_up_rank, root_low_rank, up_comm, low_comm,
|
||||
num_segments, 0, w_rank, count - (num_segments - 1) * seg_count,
|
||||
low_rank != root_low_rank);
|
||||
/* Init the first task */
|
||||
init_task(t0, mca_coll_han_bcast_t0_task, (void *) t);
|
||||
issue_task(t0);
|
||||
|
||||
/* Create t1 task */
|
||||
mca_coll_task_t *t1 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t1 task arguments */
|
||||
t->cur_task = t1;
|
||||
/* Init the t1 task */
|
||||
init_task(t1, mca_coll_han_bcast_t1_task, (void *) t);
|
||||
issue_task(t1);
|
||||
|
||||
while (t->cur_seg <= t->num_segments - 2) {
|
||||
/* Create t1 task */
|
||||
mca_coll_task_t *t1 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t1 task arguments */
|
||||
t->cur_task = t1;
|
||||
t->buff = (char *) t->buff + extent * seg_count;
|
||||
t->cur_seg = t->cur_seg + 1;
|
||||
/* Init the t1 task */
|
||||
init_task(t1, mca_coll_han_bcast_t1_task, (void *) t);
|
||||
issue_task(t1);
|
||||
}
|
||||
|
||||
free(t);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t0 task: issue and wait for the upper level ibcast of segment 0 */
|
||||
int mca_coll_han_bcast_t0_task(void *task_argu)
|
||||
{
|
||||
mca_bcast_argu_t *t = (mca_bcast_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: in t0 %d\n", t->w_rank,
|
||||
t->cur_seg));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
if (t->noop) {
|
||||
return OMPI_SUCCESS;
|
||||
} else {
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *ibcast_req;
|
||||
t->up_comm->c_coll->coll_ibcast((char *) t->buff, t->seg_count, t->dtype, t->root_up_rank,
|
||||
t->up_comm, &ibcast_req, t->up_comm->c_coll->coll_ibcast_module);
|
||||
ompi_request_wait(&ibcast_req, MPI_STATUSES_IGNORE);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* t1 task:
|
||||
* 1. issue the upper level ibcast of segment cur_seg + 1
|
||||
* 2. issue the low level bcast of segment cur_seg
|
||||
* 3. wait for the completion of the ibcast
|
||||
*/
|
||||
int mca_coll_han_bcast_t1_task(void *task_argu)
|
||||
{
|
||||
mca_bcast_argu_t *t = (mca_bcast_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: in t1 %d\n", t->w_rank,
|
||||
t->cur_seg));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *ibcast_req = NULL;
|
||||
int tmp_count = t->seg_count;
|
||||
if (!t->noop) {
|
||||
if (t->cur_seg <= t->num_segments - 2 ) {
|
||||
if (t->cur_seg == t->num_segments - 2 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->up_comm->c_coll->coll_ibcast((char *) t->buff + extent * t->seg_count,
|
||||
tmp_count, t->dtype, t->root_up_rank,
|
||||
t->up_comm, &ibcast_req,
|
||||
t->up_comm->c_coll->coll_ibcast_module);
|
||||
}
|
||||
}
|
||||
|
||||
t->low_comm->c_coll->coll_bcast((char *) t->buff,
|
||||
t->seg_count, t->dtype, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_bcast_module);
|
||||
|
||||
if (!t->noop && ibcast_req != NULL) {
|
||||
ompi_request_wait(&ibcast_req, MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
279
ompi/mca/coll/han/coll_han_component.c
Обычный файл
279
ompi/mca/coll/han/coll_han_component.c
Обычный файл
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Most of the description of the data layout is in the
|
||||
* coll_han_module.c file.
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include "opal/util/show_help.h"
|
||||
#include "ompi/constants.h"
|
||||
#include "ompi/mca/coll/coll.h"
|
||||
#include "coll_han.h"
|
||||
|
||||
/*
|
||||
* Public string showing the coll ompi_han component version number
|
||||
*/
|
||||
const char *mca_coll_han_component_version_string =
|
||||
"Open MPI han collective MCA component version " OMPI_VERSION;
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int han_open(void);
|
||||
static int han_close(void);
|
||||
static int han_register(void);
|
||||
|
||||
/*
|
||||
* Instantiate the public struct with all of our public information
|
||||
* and pointers to our public functions in it
|
||||
*/
|
||||
|
||||
mca_coll_han_component_t mca_coll_han_component = {
|
||||
|
||||
/* First, fill in the super */
|
||||
|
||||
{
|
||||
/* First, the mca_component_t struct containing meta
|
||||
information about the component itself */
|
||||
|
||||
.collm_version = {
|
||||
MCA_COLL_BASE_VERSION_2_0_0,
|
||||
|
||||
/* Component name and version */
|
||||
.mca_component_name = "han",
|
||||
MCA_BASE_MAKE_VERSION(component, OMPI_MAJOR_VERSION, OMPI_MINOR_VERSION,
|
||||
OMPI_RELEASE_VERSION),
|
||||
|
||||
/* Component functions */
|
||||
.mca_open_component = han_open,
|
||||
.mca_close_component = han_close,
|
||||
.mca_register_component_params = han_register,
|
||||
},
|
||||
.collm_data = {
|
||||
/* The component is not checkpoint ready */
|
||||
MCA_BASE_METADATA_PARAM_NONE},
|
||||
|
||||
/* Initialization / querying functions */
|
||||
|
||||
.collm_init_query = mca_coll_han_init_query,
|
||||
.collm_comm_query = mca_coll_han_comm_query,
|
||||
},
|
||||
|
||||
/* han-component specifc information */
|
||||
|
||||
/* (default) priority */
|
||||
20,
|
||||
};
|
||||
|
||||
/*
|
||||
* Init the component
|
||||
*/
|
||||
static int han_open(void)
|
||||
{
|
||||
mca_coll_han_component_t *cs = &mca_coll_han_component;
|
||||
if (cs->han_auto_tune) {
|
||||
cs->han_auto_tuned =
|
||||
(selection *) malloc(2 * cs->han_auto_tune_n * cs->han_auto_tune_c *
|
||||
cs->han_auto_tune_m * sizeof(selection));
|
||||
char *filename = "/home/dycz0fx/results/auto/auto_tuned.bin";
|
||||
FILE *file = fopen(filename, "r");
|
||||
fread(cs->han_auto_tuned, sizeof(selection),
|
||||
2 * cs->han_auto_tune_n * cs->han_auto_tune_c * cs->han_auto_tune_m, file);
|
||||
fclose(file);
|
||||
}
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shut down the component
|
||||
*/
|
||||
static int han_close(void)
|
||||
{
|
||||
mca_coll_han_component_t *cs = &mca_coll_han_component;
|
||||
if (cs->han_auto_tune && cs->han_auto_tuned != NULL) {
|
||||
free(cs->han_auto_tuned);
|
||||
cs->han_auto_tuned = NULL;
|
||||
}
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Register MCA params
|
||||
*/
|
||||
static int han_register(void)
|
||||
{
|
||||
mca_base_component_t *c = &mca_coll_han_component.super.collm_version;
|
||||
mca_coll_han_component_t *cs = &mca_coll_han_component;
|
||||
|
||||
cs->han_priority = 50;
|
||||
(void) mca_base_component_var_register(c, "priority", "Priority of the han coll component",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_priority);
|
||||
|
||||
int coll_han_verbose = 0;
|
||||
(void) mca_base_component_var_register(c, "verbose",
|
||||
"Verbose level",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &coll_han_verbose);
|
||||
cs->han_output = opal_output_open(NULL);
|
||||
opal_output_set_verbosity(cs->han_output, coll_han_verbose);
|
||||
|
||||
cs->han_bcast_segsize = 65536;
|
||||
(void) mca_base_component_var_register(c, "bcast_segsize",
|
||||
"segment size for bcast",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_bcast_segsize);
|
||||
|
||||
cs->han_bcast_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "bcast_up_module",
|
||||
"up level module for bcast, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_bcast_up_module);
|
||||
|
||||
cs->han_bcast_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "bcast_low_module",
|
||||
"low level module for bcast, 0 sm, 1 solo",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_bcast_low_module);
|
||||
|
||||
cs->han_reduce_segsize = 524288;
|
||||
(void) mca_base_component_var_register(c, "reduce_segsize",
|
||||
"segment size for reduce",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_reduce_segsize);
|
||||
|
||||
cs->han_reduce_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "reduce_up_module",
|
||||
"up level module for allreduce, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_reduce_up_module);
|
||||
|
||||
cs->han_reduce_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "reduce_low_module",
|
||||
"low level module for allreduce, 0 sm, 1 shared",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_reduce_low_module);
|
||||
cs->han_allreduce_segsize = 524288;
|
||||
(void) mca_base_component_var_register(c, "allreduce_segsize",
|
||||
"segment size for allreduce",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_allreduce_segsize);
|
||||
|
||||
cs->han_allreduce_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "allreduce_up_module",
|
||||
"up level module for allreduce, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_allreduce_up_module);
|
||||
|
||||
cs->han_allreduce_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "allreduce_low_module",
|
||||
"low level module for allreduce, 0 sm, 1 shared",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_allreduce_low_module);
|
||||
|
||||
cs->han_allgather_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "allgather_up_module",
|
||||
"up level module for allgather, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_allgather_up_module);
|
||||
|
||||
cs->han_allgather_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "allgather_low_module",
|
||||
"low level module for allgather, 0 sm, 1 shared",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_allgather_low_module);
|
||||
|
||||
cs->han_gather_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "gather_up_module",
|
||||
"up level module for gather, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_gather_up_module);
|
||||
|
||||
cs->han_gather_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "gather_low_module",
|
||||
"low level module for gather, 0 sm, 1 shared",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_gather_low_module);
|
||||
|
||||
cs->han_scatter_up_module = 0;
|
||||
(void) mca_base_component_var_register(c, "scatter_up_module",
|
||||
"up level module for scatter, 0 libnbc, 1 adapt",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_scatter_up_module);
|
||||
|
||||
cs->han_scatter_low_module = 0;
|
||||
(void) mca_base_component_var_register(c, "scatter_low_module",
|
||||
"low level module for scatter, 0 sm, 1 shared",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY,
|
||||
&cs->han_scatter_low_module);
|
||||
|
||||
cs->han_auto_tune = 0;
|
||||
(void) mca_base_component_var_register(c, "auto_tune",
|
||||
"whether enable auto tune, 0 disable, 1 enable, default 0",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_auto_tune);
|
||||
|
||||
cs->han_auto_tune_n = 5;
|
||||
(void) mca_base_component_var_register(c, "auto_tune_n",
|
||||
"auto tune n",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_auto_tune_n);
|
||||
|
||||
cs->han_auto_tune_c = 3;
|
||||
(void) mca_base_component_var_register(c, "auto_tune_c",
|
||||
"auto tune c",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_auto_tune_c);
|
||||
|
||||
cs->han_auto_tune_m = 21;
|
||||
(void) mca_base_component_var_register(c, "auto_tune_m",
|
||||
"auto tune n",
|
||||
MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
|
||||
OPAL_INFO_LVL_9,
|
||||
MCA_BASE_VAR_SCOPE_READONLY, &cs->han_auto_tune_m);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
224
ompi/mca/coll/han/coll_han_gather.c
Обычный файл
224
ompi/mca/coll/han/coll_han_gather.c
Обычный файл
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
/* only work with regular situation (each node has equal number of processes) */
|
||||
|
||||
void mac_coll_han_set_gather_argu(mca_gather_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank, bool noop, ompi_request_t * req)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->sbuf = sbuf;
|
||||
argu->sbuf_inter_free = sbuf_inter_free;
|
||||
argu->scount = scount;
|
||||
argu->sdtype = sdtype;
|
||||
argu->rbuf = rbuf;
|
||||
argu->rcount = rcount;
|
||||
argu->rdtype = rdtype;
|
||||
argu->root = root;
|
||||
argu->root_up_rank = root_up_rank;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->w_rank = w_rank;
|
||||
argu->noop = noop;
|
||||
argu->req = req;
|
||||
}
|
||||
|
||||
int
|
||||
mca_coll_han_gather_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module)
|
||||
{
|
||||
int i, j;
|
||||
int w_rank, w_size;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
w_size = ompi_comm_size(comm);
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm =
|
||||
han_module->cached_low_comms[mca_coll_han_component.han_gather_low_module];
|
||||
ompi_communicator_t *up_comm =
|
||||
han_module->cached_up_comms[mca_coll_han_component.han_gather_up_module];
|
||||
int *vranks = han_module->cached_vranks;
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
int low_size = ompi_comm_size(low_comm);
|
||||
int up_size = ompi_comm_size(up_comm);
|
||||
|
||||
ompi_request_t *temp_request = NULL;
|
||||
/* Set up request */
|
||||
temp_request = OBJ_NEW(ompi_request_t);
|
||||
OMPI_REQUEST_INIT(temp_request, false);
|
||||
temp_request->req_state = OMPI_REQUEST_ACTIVE;
|
||||
temp_request->req_type = 0;
|
||||
temp_request->req_free = han_request_free;
|
||||
temp_request->req_status.MPI_SOURCE = 0;
|
||||
temp_request->req_status.MPI_TAG = 0;
|
||||
temp_request->req_status.MPI_ERROR = 0;
|
||||
temp_request->req_status._cancelled = 0;
|
||||
temp_request->req_status._ucount = 0;
|
||||
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank);
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Future Gather root %d root_low_rank %d root_up_rank %d\n", w_rank,
|
||||
root, root_low_rank, root_up_rank));
|
||||
|
||||
char *reorder_buf = NULL;
|
||||
char *reorder_rbuf = NULL;
|
||||
ptrdiff_t rsize, rgap = 0, rextent;
|
||||
ompi_datatype_type_extent(rdtype, &rextent);
|
||||
int *topo = mca_coll_han_topo_init(comm, han_module, 2);
|
||||
if (w_rank == root) {
|
||||
/* If the processes are mapped-by core, no need to reorder */
|
||||
if (han_module->is_mapbycore) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Future Gather is_bycore: ", w_rank));
|
||||
reorder_rbuf = (char *) rbuf;
|
||||
} else {
|
||||
rsize = opal_datatype_span(&rdtype->super, (int64_t) rcount * w_size, &rgap);
|
||||
reorder_buf = (char *) malloc(rsize); //TODO:free
|
||||
reorder_rbuf = reorder_buf - rgap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create lg task */
|
||||
mca_coll_task_t *lg = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup lg task arguments */
|
||||
mca_gather_argu_t *lg_argu = malloc(sizeof(mca_gather_argu_t));
|
||||
mac_coll_han_set_gather_argu(lg_argu, lg, (char *) sbuf, NULL, scount, sdtype, reorder_rbuf,
|
||||
rcount, rdtype, root, root_up_rank, root_low_rank, up_comm,
|
||||
low_comm, w_rank, low_rank != root_low_rank, temp_request);
|
||||
/* Init lg task */
|
||||
init_task(lg, mca_coll_han_gather_lg_task, (void *) (lg_argu));
|
||||
/* Issure lg task */
|
||||
issue_task(lg);
|
||||
|
||||
ompi_request_wait(&temp_request, MPI_STATUS_IGNORE);
|
||||
|
||||
/* Reorder rbuf based on rank.
|
||||
* Suppose, message is 0 1 2 3 4 5 6 7,
|
||||
* and the processes are mapped on 2 nodes (the processes on the node 0 is 0 2 4 6 and the processes on the node 1 is 1 3 5 7),
|
||||
* so the message needs to be reordered to 0 2 4 6 1 3 5 7
|
||||
*/
|
||||
if (w_rank == root && !han_module->is_mapbycore) {
|
||||
for (i = 0; i < up_size; i++) {
|
||||
for (j = 0; j < low_size; j++) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Future Gather copy from %d %d\n", w_rank,
|
||||
(i * low_size + j) * 2 + 1, topo[(i * low_size + j) * 2 + 1]));
|
||||
ompi_datatype_copy_content_same_ddt(rdtype, (ptrdiff_t) rcount,
|
||||
(char *) rbuf +
|
||||
rextent * (ptrdiff_t) topo[(i * low_size + j) *
|
||||
2 +
|
||||
1] *
|
||||
(ptrdiff_t) rcount,
|
||||
reorder_rbuf + rextent * (i * low_size +
|
||||
j) *
|
||||
(ptrdiff_t) rcount);
|
||||
}
|
||||
}
|
||||
free(reorder_buf);
|
||||
}
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* lg: lower level (shared memory) gather task */
|
||||
int mca_coll_han_gather_lg_task(void *task_argu)
|
||||
{
|
||||
mca_gather_argu_t *t = (mca_gather_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Future Gather: lg\n",
|
||||
t->w_rank));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
|
||||
/* If the process is one of the node leader */
|
||||
char *tmp_buf = NULL;
|
||||
char *tmp_rbuf = NULL;
|
||||
if (!t->noop) {
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
ptrdiff_t rsize, rgap = 0;
|
||||
rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size, &rgap);
|
||||
tmp_buf = (char *) malloc(rsize);
|
||||
tmp_rbuf = tmp_buf - rgap;
|
||||
}
|
||||
/* Shared memory gather */
|
||||
t->low_comm->c_coll->coll_gather((char *) t->sbuf, t->scount, t->sdtype, tmp_rbuf, t->rcount,
|
||||
t->rdtype, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_gather_module);
|
||||
t->sbuf = tmp_rbuf;
|
||||
t->sbuf_inter_free = tmp_buf;
|
||||
|
||||
/* Create ug (upper level all-gather) task */
|
||||
mca_coll_task_t *ug = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup ug task arguments */
|
||||
t->cur_task = ug;
|
||||
/* Init ug task */
|
||||
init_task(ug, mca_coll_han_gather_ug_task, (void *) t);
|
||||
/* Issure ug task */
|
||||
issue_task(ug);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* ug: upper level (intra-node) gather task */
|
||||
int mca_coll_han_gather_ug_task(void *task_argu)
|
||||
{
|
||||
mca_gather_argu_t *t = (mca_gather_argu_t *) task_argu;
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
|
||||
if (t->noop) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] Future Gather: ug noop\n", t->w_rank));
|
||||
} else {
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
/* Inter node gather */
|
||||
t->up_comm->c_coll->coll_gather((char *) t->sbuf, t->scount * low_size, t->sdtype,
|
||||
(char *) t->rbuf, t->rcount * low_size, t->rdtype,
|
||||
t->root_up_rank, t->up_comm,
|
||||
t->up_comm->c_coll->coll_gather_module);
|
||||
|
||||
if (t->sbuf_inter_free != NULL) {
|
||||
free(t->sbuf_inter_free);
|
||||
t->sbuf_inter_free = NULL;
|
||||
}
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] Future Gather: ug gather finish\n", t->w_rank));
|
||||
}
|
||||
ompi_request_t *temp_req = t->req;
|
||||
free(t);
|
||||
ompi_request_complete(temp_req, 1);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
468
ompi/mca/coll/han/coll_han_module.c
Обычный файл
468
ompi/mca/coll/han/coll_han_module.c
Обычный файл
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif /* HAVE_SYS_MMAN_H */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "opal_stdint.h"
|
||||
#include "opal/mca/hwloc/base/base.h"
|
||||
#include "opal/util/os_path.h"
|
||||
|
||||
#include "ompi/communicator/communicator.h"
|
||||
#include "ompi/group/group.h"
|
||||
#include "ompi/mca/coll/coll.h"
|
||||
#include "ompi/mca/coll/base/base.h"
|
||||
#include "ompi/proc/proc.h"
|
||||
#include "coll_han.h"
|
||||
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int han_module_enable(mca_coll_base_module_t * module, struct ompi_communicator_t *comm);
|
||||
static int mca_coll_han_module_disable(mca_coll_base_module_t * module,
|
||||
struct ompi_communicator_t *comm);
|
||||
|
||||
/*
|
||||
* Module constructor
|
||||
*/
|
||||
static void mca_coll_han_module_construct(mca_coll_han_module_t * module)
|
||||
{
|
||||
module->enabled = false;
|
||||
module->super.coll_module_disable = mca_coll_han_module_disable;
|
||||
module->cached_comm = NULL;
|
||||
module->cached_low_comms = NULL;
|
||||
module->cached_up_comms = NULL;
|
||||
module->cached_vranks = NULL;
|
||||
module->cached_topo = NULL;
|
||||
module->is_mapbycore = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module destructor
|
||||
*/
|
||||
static void mca_coll_han_module_destruct(mca_coll_han_module_t * module)
|
||||
{
|
||||
module->enabled = false;
|
||||
if (module->cached_low_comms != NULL) {
|
||||
ompi_comm_free(&(module->cached_low_comms[0]));
|
||||
ompi_comm_free(&(module->cached_low_comms[1]));
|
||||
module->cached_low_comms[0] = NULL;
|
||||
module->cached_low_comms[1] = NULL;
|
||||
free(module->cached_low_comms);
|
||||
module->cached_low_comms = NULL;
|
||||
}
|
||||
if (module->cached_up_comms != NULL) {
|
||||
ompi_comm_free(&(module->cached_up_comms[0]));
|
||||
ompi_comm_free(&(module->cached_up_comms[1]));
|
||||
module->cached_up_comms[0] = NULL;
|
||||
module->cached_up_comms[1] = NULL;
|
||||
free(module->cached_up_comms);
|
||||
module->cached_up_comms = NULL;
|
||||
}
|
||||
if (module->cached_vranks != NULL) {
|
||||
free(module->cached_vranks);
|
||||
module->cached_vranks = NULL;
|
||||
}
|
||||
if (module->cached_topo != NULL) {
|
||||
free(module->cached_topo);
|
||||
module->cached_topo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Module disable
|
||||
*/
|
||||
static int mca_coll_han_module_disable(mca_coll_base_module_t * module,
|
||||
struct ompi_communicator_t *comm)
|
||||
{
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
OBJ_CLASS_INSTANCE(mca_coll_han_module_t,
|
||||
mca_coll_base_module_t,
|
||||
mca_coll_han_module_construct, mca_coll_han_module_destruct);
|
||||
|
||||
/*
|
||||
* Initial query function that is invoked during MPI_INIT, allowing
|
||||
* this component to disqualify itself if it doesn't support the
|
||||
* required level of thread support. This function is invoked exactly
|
||||
* once.
|
||||
*/
|
||||
int mca_coll_han_init_query(bool enable_progress_threads, bool enable_mpi_threads)
|
||||
{
|
||||
opal_output_verbose(10, ompi_coll_base_framework.framework_output,
|
||||
"coll:han:init_query: pick me! pick me!");
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Invoked when there's a new communicator that has been created.
|
||||
* Look at the communicator and decide which set of functions and
|
||||
* priority we want to return.
|
||||
*/
|
||||
mca_coll_base_module_t *mca_coll_han_comm_query(struct ompi_communicator_t * comm, int *priority)
|
||||
{
|
||||
mca_coll_han_module_t *han_module;
|
||||
|
||||
/* If we're intercomm, or if there's only one process in the
|
||||
communicator */
|
||||
if (OMPI_COMM_IS_INTER(comm) || 1 == ompi_comm_size(comm)
|
||||
|| !ompi_group_have_remote_peers(comm->c_local_group)) {
|
||||
opal_output_verbose(10, ompi_coll_base_framework.framework_output,
|
||||
"coll:han:comm_query (%d/%s): intercomm, comm is too small, only on one node; disqualifying myself",
|
||||
comm->c_contextid, comm->c_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the priority level attached to this module. If priority is less
|
||||
* than or equal to 0, then the module is unavailable. */
|
||||
*priority = mca_coll_han_component.han_priority;
|
||||
if (mca_coll_han_component.han_priority <= 0) {
|
||||
opal_output_verbose(10, ompi_coll_base_framework.framework_output,
|
||||
"coll:han:comm_query (%d/%s): priority too low; disqualifying myself",
|
||||
comm->c_contextid, comm->c_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
han_module = OBJ_NEW(mca_coll_han_module_t);
|
||||
if (NULL == han_module) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* All is good -- return a module */
|
||||
han_module->super.coll_module_enable = han_module_enable;
|
||||
han_module->super.ft_event = NULL;
|
||||
han_module->super.coll_allgather = NULL; //mca_coll_han_allgather_intra;
|
||||
han_module->super.coll_allgatherv = NULL;
|
||||
han_module->super.coll_allreduce = mca_coll_han_allreduce_intra;
|
||||
han_module->super.coll_alltoall = NULL;
|
||||
han_module->super.coll_alltoallv = NULL;
|
||||
han_module->super.coll_alltoallw = NULL;
|
||||
han_module->super.coll_barrier = NULL;
|
||||
han_module->super.coll_bcast = mca_coll_han_bcast_intra;
|
||||
han_module->super.coll_exscan = NULL;
|
||||
han_module->super.coll_gather = mca_coll_han_gather_intra;
|
||||
han_module->super.coll_gatherv = NULL;
|
||||
han_module->super.coll_reduce = mca_coll_han_reduce_intra;
|
||||
han_module->super.coll_reduce_scatter = NULL;
|
||||
han_module->super.coll_scan = NULL;
|
||||
han_module->super.coll_scatter = mca_coll_han_scatter_intra;
|
||||
han_module->super.coll_scatterv = NULL;
|
||||
|
||||
opal_output_verbose(10, ompi_coll_base_framework.framework_output,
|
||||
"coll:han:comm_query (%d/%s): pick me! pick me!",
|
||||
comm->c_contextid, comm->c_name);
|
||||
return &(han_module->super);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init module on the communicator
|
||||
*/
|
||||
static int han_module_enable(mca_coll_base_module_t * module, struct ompi_communicator_t *comm)
|
||||
{
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the han request
|
||||
*/
|
||||
int han_request_free(ompi_request_t ** request)
|
||||
{
|
||||
(*request)->req_state = OMPI_REQUEST_INVALID;
|
||||
OBJ_RELEASE(*request);
|
||||
*request = MPI_REQUEST_NULL;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Create the communicators used in the HAN module */
|
||||
void mca_coll_han_comm_create(struct ompi_communicator_t *comm, mca_coll_han_module_t * han_module)
|
||||
{
|
||||
/* Use cached communicators if possible */
|
||||
if (han_module->cached_comm == comm && han_module->cached_low_comms != NULL
|
||||
&& han_module->cached_up_comms != NULL && han_module->cached_vranks != NULL) {
|
||||
return;
|
||||
}
|
||||
/* Create communicators if there is no cached communicator */
|
||||
else {
|
||||
int low_rank, low_size;
|
||||
int up_rank;
|
||||
int w_rank = ompi_comm_rank(comm);
|
||||
int w_size = ompi_comm_size(comm);
|
||||
ompi_communicator_t **low_comms =
|
||||
(struct ompi_communicator_t **) malloc(sizeof(struct ompi_communicator_t *) * 2);
|
||||
ompi_communicator_t **up_comms =
|
||||
(struct ompi_communicator_t **) malloc(sizeof(struct ompi_communicator_t *) * 2);
|
||||
/* Create low_comms which contain all the process on a node */
|
||||
const int *origin_priority = NULL;
|
||||
/* Lower the priority of HAN module */
|
||||
int han_var_id;
|
||||
int tmp_han_priority = 0;
|
||||
int tmp_han_origin = 0;
|
||||
mca_base_var_find_by_name("coll_han_priority", &han_var_id);
|
||||
mca_base_var_get_value(han_var_id, &origin_priority, NULL, NULL);
|
||||
tmp_han_origin = *origin_priority;
|
||||
mca_base_var_set_flag(han_var_id, MCA_BASE_VAR_FLAG_SETTABLE, true);
|
||||
mca_base_var_set_value(han_var_id, &tmp_han_priority, sizeof(int), MCA_BASE_VAR_SOURCE_SET,
|
||||
NULL);
|
||||
comm->c_coll->coll_allreduce = ompi_coll_base_allreduce_intra_recursivedoubling;
|
||||
comm->c_coll->coll_allgather = ompi_coll_base_allgather_intra_bruck;
|
||||
|
||||
int var_id;
|
||||
int tmp_priority = 100;
|
||||
int tmp_origin = 0;
|
||||
/* Set up low_comms[0] with sm module */
|
||||
mca_base_var_find_by_name("coll_sm_priority", &var_id);
|
||||
mca_base_var_get_value(var_id, &origin_priority, NULL, NULL);
|
||||
tmp_origin = *origin_priority;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] sm_priority origin %d %d\n", w_rank, *origin_priority,
|
||||
tmp_origin));
|
||||
mca_base_var_set_flag(var_id, MCA_BASE_VAR_FLAG_SETTABLE, true);
|
||||
mca_base_var_set_value(var_id, &tmp_priority, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, (opal_info_t *) (&ompi_mpi_info_null),
|
||||
&(low_comms[0]));
|
||||
mca_base_var_set_value(var_id, &tmp_origin, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
low_size = ompi_comm_size(low_comms[0]);
|
||||
low_rank = ompi_comm_rank(low_comms[0]);
|
||||
|
||||
/* Set up low_comms[1] with solo module */
|
||||
mca_base_var_find_by_name("coll_solo_priority", &var_id);
|
||||
mca_base_var_get_value(var_id, &origin_priority, NULL, NULL);
|
||||
tmp_origin = *origin_priority;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] solo_priority origin %d %d\n", w_rank, *origin_priority,
|
||||
tmp_origin));
|
||||
mca_base_var_set_flag(var_id, MCA_BASE_VAR_FLAG_SETTABLE, true);
|
||||
mca_base_var_set_value(var_id, &tmp_priority, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, (opal_info_t *) (&ompi_mpi_info_null),
|
||||
&(low_comms[1]));
|
||||
mca_base_var_set_value(var_id, &tmp_origin, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
|
||||
/* Create up_comms[0] with libnbc which contain one process per node (across nodes) */
|
||||
mca_base_var_find_by_name("coll_libnbc_priority", &var_id);
|
||||
mca_base_var_get_value(var_id, &origin_priority, NULL, NULL);
|
||||
tmp_origin = *origin_priority;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] libnbc_priority origin %d %d\n", w_rank, *origin_priority,
|
||||
tmp_origin));
|
||||
mca_base_var_set_flag(var_id, MCA_BASE_VAR_FLAG_SETTABLE, true);
|
||||
mca_base_var_set_value(var_id, &tmp_priority, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
ompi_comm_split(comm, low_rank, w_rank, &(up_comms[0]), false);
|
||||
mca_base_var_set_value(var_id, &tmp_origin, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
up_rank = ompi_comm_rank(up_comms[0]);
|
||||
|
||||
/* Create up_comms[1] with adapt which contain one process per node (across nodes) */
|
||||
mca_base_var_find_by_name("coll_adapt_priority", &var_id);
|
||||
mca_base_var_get_value(var_id, &origin_priority, NULL, NULL);
|
||||
tmp_origin = *origin_priority;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] adapt_priority origin %d %d\n", w_rank, *origin_priority,
|
||||
tmp_origin));
|
||||
mca_base_var_set_flag(var_id, MCA_BASE_VAR_FLAG_SETTABLE, true);
|
||||
mca_base_var_set_value(var_id, &tmp_priority, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
ompi_comm_split(comm, low_rank, w_rank, &(up_comms[1]), false);
|
||||
mca_base_var_set_value(var_id, &tmp_origin, sizeof(int), MCA_BASE_VAR_SOURCE_SET, NULL);
|
||||
|
||||
int *vranks = malloc(sizeof(int) * w_size);
|
||||
/* Do allgather to gather vrank from each process so every process knows other processes' vrank */
|
||||
int vrank = low_size * up_rank + low_rank;
|
||||
ompi_coll_base_allgather_intra_bruck(&vrank, 1, MPI_INT, vranks, 1, MPI_INT, comm,
|
||||
comm->c_coll->coll_allgather_module);
|
||||
han_module->cached_comm = comm;
|
||||
han_module->cached_low_comms = low_comms;
|
||||
han_module->cached_up_comms = up_comms;
|
||||
han_module->cached_vranks = vranks;
|
||||
|
||||
mca_base_var_set_value(han_var_id, &tmp_han_origin, sizeof(int), MCA_BASE_VAR_SOURCE_SET,
|
||||
NULL);
|
||||
comm->c_coll->coll_allreduce = mca_coll_han_allreduce_intra;
|
||||
comm->c_coll->coll_allgather = mca_coll_han_allgather_intra;
|
||||
}
|
||||
}
|
||||
|
||||
int mca_coll_han_pow10_int(int pow_value)
|
||||
{
|
||||
int i, result = 1;
|
||||
for (i = 0; i < pow_value; i++) {
|
||||
result *= 10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int mca_coll_han_hostname_to_number(char *hostname, int size)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
char *number_array = (char *) malloc(sizeof(char) * size);
|
||||
while (hostname[i] != '\0') {
|
||||
if (hostname[i] >= '0' && hostname[i] <= '9') {
|
||||
number_array[j++] = hostname[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int number = 0;
|
||||
for (i = 0; i < j; i++) {
|
||||
number += (number_array[i] - '0') * mca_coll_han_pow10_int(j - 1 - i);
|
||||
}
|
||||
free(number_array);
|
||||
return number;
|
||||
}
|
||||
|
||||
void mca_coll_han_topo_get(int *topo, struct ompi_communicator_t *comm, int num_topo_level)
|
||||
{
|
||||
int *self_topo = (int *) malloc(sizeof(int) * num_topo_level);
|
||||
/* Set daemon vpid */
|
||||
char hostname[1024];
|
||||
gethostname(hostname, 1024);
|
||||
self_topo[0] = mca_coll_han_hostname_to_number(hostname, 1024);
|
||||
/* Set core id */
|
||||
self_topo[1] = ompi_comm_rank(comm);
|
||||
|
||||
/* Allgather all the topology information */
|
||||
ompi_coll_base_allgather_intra_bruck(self_topo, num_topo_level, MPI_INT, topo, num_topo_level,
|
||||
MPI_INT, comm, comm->c_coll->coll_allgather_module);
|
||||
free(self_topo);
|
||||
return;
|
||||
}
|
||||
|
||||
void mca_coll_han_topo_sort(int *topo, int start, int end, int size, int level, int num_topo_level)
|
||||
{
|
||||
if (level > num_topo_level - 1 || start >= end) {
|
||||
return;
|
||||
}
|
||||
int i, j;
|
||||
int min = INT_MAX;
|
||||
int min_loc = -1;
|
||||
for (i = start; i <= end; i++) {
|
||||
/* Find min */
|
||||
for (j = i; j <= end; j++) {
|
||||
if (topo[j * num_topo_level + level] < min) {
|
||||
min = topo[j * num_topo_level + level];
|
||||
min_loc = j;
|
||||
|
||||
}
|
||||
}
|
||||
/* Swap i and min_loc */
|
||||
int temp;
|
||||
for (j = 0; j < num_topo_level; j++) {
|
||||
temp = topo[i * num_topo_level + j];
|
||||
topo[i * num_topo_level + j] = topo[min_loc * num_topo_level + j];
|
||||
topo[min_loc * num_topo_level + j] = temp;
|
||||
}
|
||||
min = INT_MAX;
|
||||
min_loc = -1;
|
||||
}
|
||||
int last = 0;
|
||||
int new_start = 0;
|
||||
int new_end = 0;
|
||||
for (i = start; i <= end; i++) {
|
||||
if (i == start) {
|
||||
last = topo[i * num_topo_level + level];
|
||||
new_start = start;
|
||||
} else if (i == end) {
|
||||
new_end = end;
|
||||
mca_coll_han_topo_sort(topo, new_start, new_end, size, level + 1, num_topo_level);
|
||||
} else if (last != topo[i * num_topo_level + level]) {
|
||||
new_end = i - 1;
|
||||
mca_coll_han_topo_sort(topo, new_start, new_end, size, level + 1, num_topo_level);
|
||||
new_start = i;
|
||||
last = topo[i * num_topo_level + level];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the current processes are mapped by core */
|
||||
bool mca_coll_han_topo_is_mapbycore(int *topo, struct ompi_communicator_t * comm,
|
||||
int num_topo_level)
|
||||
{
|
||||
int i;
|
||||
int size = ompi_comm_size(comm);
|
||||
for (i = 1; i < size; i++) {
|
||||
if (topo[(i - 1) * num_topo_level] > topo[i * num_topo_level]
|
||||
|| topo[(i - 1) * num_topo_level + 1] > topo[i * num_topo_level + 1]) {
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int *mca_coll_han_topo_init(struct ompi_communicator_t *comm, mca_coll_han_module_t * han_module,
|
||||
int num_topo_level)
|
||||
{
|
||||
int size;
|
||||
size = ompi_comm_size(comm);
|
||||
int *topo;
|
||||
if ((han_module->cached_topo != NULL) && (han_module->cached_comm == comm)) {
|
||||
topo = han_module->cached_topo;
|
||||
}
|
||||
else {
|
||||
if (han_module->cached_topo != NULL) {
|
||||
free(han_module->cached_topo);
|
||||
han_module->cached_topo = NULL;
|
||||
}
|
||||
topo = (int *) malloc(sizeof(int) * size * num_topo_level);
|
||||
/* Get topo infomation */
|
||||
mca_coll_han_topo_get(topo, comm, num_topo_level);
|
||||
mca_coll_han_topo_print(topo, comm, num_topo_level);
|
||||
|
||||
/* Check if the processes are mapped by core */
|
||||
han_module->is_mapbycore = mca_coll_han_topo_is_mapbycore(topo, comm, num_topo_level);
|
||||
/* Sort the topo such that each group is contiguous */
|
||||
if (!han_module->is_mapbycore) {
|
||||
mca_coll_han_topo_sort(topo, 0, size - 1, size, 0, num_topo_level);
|
||||
}
|
||||
han_module->cached_topo = topo;
|
||||
han_module->cached_comm = comm;
|
||||
}
|
||||
|
||||
mca_coll_han_topo_print(topo, comm, num_topo_level);
|
||||
return topo;
|
||||
}
|
||||
|
||||
/* Print out the topology info, for debugging purpose */
|
||||
void mca_coll_han_topo_print(int *topo, struct ompi_communicator_t *comm, int num_topo_level)
|
||||
{
|
||||
int rank = ompi_comm_rank(comm);
|
||||
int size = ompi_comm_size(comm);
|
||||
|
||||
if (rank == 0) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: HAN topo: ", rank));
|
||||
int i;
|
||||
for (i = 0; i < size * num_topo_level; i++) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "%d ", topo[i]));
|
||||
}
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "\n"));
|
||||
|
||||
}
|
||||
}
|
192
ompi/mca/coll/han/coll_han_reduce.c
Обычный файл
192
ompi/mca/coll/han/coll_han_reduce.c
Обычный файл
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
void mac_coll_han_set_reduce_argu(mca_reduce_argu_t * argu, mca_coll_task_t * cur_task, void *sbuf, void *rbuf,
|
||||
int seg_count, struct ompi_datatype_t *dtype, struct ompi_op_t *op,
|
||||
int root_up_rank, int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int num_segments, int cur_seg, int w_rank, int last_seg_count,
|
||||
bool noop)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->sbuf = sbuf;
|
||||
argu->rbuf = rbuf;
|
||||
argu->seg_count = seg_count;
|
||||
argu->dtype = dtype;
|
||||
argu->op = op;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->root_up_rank = root_up_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->num_segments = num_segments;
|
||||
argu->cur_seg = cur_seg;
|
||||
argu->w_rank = w_rank;
|
||||
argu->last_seg_count = last_seg_count;
|
||||
argu->noop = noop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each segment of the messsage needs to go though 2 steps to perform MPI_Reduce:
|
||||
* lb: low level (shared-memory or intra-node) reduce.
|
||||
* ub: upper level (inter-node) reduce
|
||||
* Hence, in each iteration, there is a combination of collective operations which is called a task.
|
||||
* | seg 0 | seg 1 | seg 2 | seg 3 |
|
||||
* iter 0 | lr | | | | task: t0, contains lr
|
||||
* iter 1 | ur | lr | | | task: t1, contains ur and lr
|
||||
* iter 2 | | ur | lr | | task: t1, contains ur and lr
|
||||
* iter 3 | | | ur | lr | task: t1, contains ur and lr
|
||||
* iter 4 | | | | ur | task: t1, contains ur
|
||||
*/
|
||||
int
|
||||
mca_coll_han_reduce_intra(const void *sbuf,
|
||||
void *rbuf,
|
||||
int count,
|
||||
struct ompi_datatype_t *dtype,
|
||||
ompi_op_t* op,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm,
|
||||
mca_coll_base_module_t * module)
|
||||
{
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(dtype, &lb, &extent);
|
||||
int w_rank;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
int seg_count = count;
|
||||
size_t typelng;
|
||||
ompi_datatype_type_size(dtype, &typelng);
|
||||
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm;
|
||||
ompi_communicator_t *up_comm;
|
||||
|
||||
/* use MCA parameters for now */
|
||||
low_comm = han_module->cached_low_comms[mca_coll_han_component.han_reduce_low_module];
|
||||
up_comm = han_module->cached_up_comms[mca_coll_han_component.han_reduce_up_module];
|
||||
COLL_BASE_COMPUTED_SEGCOUNT(mca_coll_han_component.han_reduce_segsize, typelng,
|
||||
seg_count);
|
||||
|
||||
int num_segments = (count + seg_count - 1) / seg_count;
|
||||
OPAL_OUTPUT_VERBOSE((20, mca_coll_han_component.han_output,
|
||||
"In HAN seg_count %d count %d num_seg %d\n",
|
||||
seg_count, count, num_segments));
|
||||
|
||||
int *vranks = han_module->cached_vranks;
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
int low_size = ompi_comm_size(low_comm);
|
||||
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank);
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: root_low_rank %d root_up_rank %d\n", w_rank, root_low_rank,
|
||||
root_up_rank));
|
||||
|
||||
/* Create t0 tasks for the first segment */
|
||||
mca_coll_task_t *t0 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t0 task arguments */
|
||||
mca_reduce_argu_t *t = malloc(sizeof(mca_reduce_argu_t));
|
||||
mac_coll_han_set_reduce_argu(t, t0, (char *) sbuf, (char *) rbuf, seg_count, dtype,
|
||||
op, root_up_rank, root_low_rank, up_comm, low_comm,
|
||||
num_segments, 0, w_rank, count - (num_segments - 1) * seg_count,
|
||||
low_rank != root_low_rank);
|
||||
/* Init the first task */
|
||||
init_task(t0, mca_coll_han_reduce_t0_task, (void *) t);
|
||||
issue_task(t0);
|
||||
|
||||
/* Create t1 task */
|
||||
mca_coll_task_t *t1 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t1 task arguments */
|
||||
t->cur_task = t1;
|
||||
/* Init the t1 task */
|
||||
init_task(t1, mca_coll_han_reduce_t1_task, (void *) t);
|
||||
issue_task(t1);
|
||||
|
||||
while (t->cur_seg <= t->num_segments - 2) {
|
||||
/* Create t1 task */
|
||||
mca_coll_task_t *t1 = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up t1 task arguments */
|
||||
t->cur_task = t1;
|
||||
t->sbuf = (char *) t->sbuf + extent * t->seg_count;
|
||||
t->rbuf = (char *) t->rbuf + extent * t->seg_count;
|
||||
t->cur_seg = t->cur_seg + 1;
|
||||
/* Init the t1 task */
|
||||
init_task(t1, mca_coll_han_reduce_t1_task, (void *) t);
|
||||
issue_task(t1);
|
||||
}
|
||||
|
||||
free(t);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t0 task: issue and wait for the low level reduce of segment 0 */
|
||||
int mca_coll_han_reduce_t0_task(void *task_argu)
|
||||
{
|
||||
mca_reduce_argu_t *t = (mca_reduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: in t0 %d\n", t->w_rank,
|
||||
t->cur_seg));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf, (char *) t->rbuf, t->seg_count, t->dtype,
|
||||
t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* t1 task */
|
||||
int mca_coll_han_reduce_t1_task(void *task_argu) {
|
||||
mca_reduce_argu_t *t = (mca_reduce_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: in t1 %d\n", t->w_rank,
|
||||
t->cur_seg));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
ptrdiff_t extent, lb;
|
||||
ompi_datatype_get_extent(t->dtype, &lb, &extent);
|
||||
ompi_request_t *ireduce_req = NULL;
|
||||
int tmp_count = t->seg_count;
|
||||
if (!t->noop) {
|
||||
int up_rank = ompi_comm_rank(t->up_comm);
|
||||
/* ur of cur_seg */
|
||||
if (up_rank == t->root_up_rank) {
|
||||
t->up_comm->c_coll->coll_ireduce(MPI_IN_PLACE, (char *) t->rbuf, t->seg_count, t->dtype,
|
||||
t->op, t->root_up_rank, t->up_comm, &ireduce_req,
|
||||
t->up_comm->c_coll->coll_ireduce_module);
|
||||
} else {
|
||||
t->up_comm->c_coll->coll_ireduce((char *) t->rbuf, (char *) t->rbuf, t->seg_count,
|
||||
t->dtype, t->op, t->root_up_rank, t->up_comm,
|
||||
&ireduce_req, t->up_comm->c_coll->coll_ireduce_module);
|
||||
}
|
||||
}
|
||||
/* lr of cur_seg+1 */
|
||||
if (t->cur_seg <= t->num_segments - 2) {
|
||||
if (t->cur_seg == t->num_segments - 2 && t->last_seg_count != t->seg_count) {
|
||||
tmp_count = t->last_seg_count;
|
||||
}
|
||||
t->low_comm->c_coll->coll_reduce((char *) t->sbuf + extent * t->seg_count,
|
||||
(char *) t->rbuf + extent * t->seg_count, tmp_count,
|
||||
t->dtype, t->op, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_reduce_module);
|
||||
|
||||
}
|
||||
if (!t->noop && ireduce_req) {
|
||||
ompi_request_wait(&ireduce_req, MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
222
ompi/mca/coll/han/coll_han_scatter.c
Обычный файл
222
ompi/mca/coll/han/coll_han_scatter.c
Обычный файл
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
/* Only work with regular situation (each node has equal number of processes) */
|
||||
|
||||
void mac_coll_han_set_scatter_argu(mca_scatter_argu_t * argu,
|
||||
mca_coll_task_t * cur_task,
|
||||
void *sbuf,
|
||||
void *sbuf_inter_free,
|
||||
void *sbuf_reorder_free,
|
||||
int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf,
|
||||
int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
int root_up_rank,
|
||||
int root_low_rank,
|
||||
struct ompi_communicator_t *up_comm,
|
||||
struct ompi_communicator_t *low_comm,
|
||||
int w_rank, bool noop, ompi_request_t * req)
|
||||
{
|
||||
argu->cur_task = cur_task;
|
||||
argu->sbuf = sbuf;
|
||||
argu->sbuf_inter_free = sbuf_inter_free;
|
||||
argu->sbuf_reorder_free = sbuf_reorder_free;
|
||||
argu->scount = scount;
|
||||
argu->sdtype = sdtype;
|
||||
argu->rbuf = rbuf;
|
||||
argu->rcount = rcount;
|
||||
argu->rdtype = rdtype;
|
||||
argu->root = root;
|
||||
argu->root_up_rank = root_up_rank;
|
||||
argu->root_low_rank = root_low_rank;
|
||||
argu->up_comm = up_comm;
|
||||
argu->low_comm = low_comm;
|
||||
argu->w_rank = w_rank;
|
||||
argu->noop = noop;
|
||||
argu->req = req;
|
||||
}
|
||||
|
||||
int
|
||||
mca_coll_han_scatter_intra(const void *sbuf, int scount,
|
||||
struct ompi_datatype_t *sdtype,
|
||||
void *rbuf, int rcount,
|
||||
struct ompi_datatype_t *rdtype,
|
||||
int root,
|
||||
struct ompi_communicator_t *comm, mca_coll_base_module_t * module)
|
||||
{
|
||||
int i, j;
|
||||
int w_rank, w_size;
|
||||
w_rank = ompi_comm_rank(comm);
|
||||
w_size = ompi_comm_size(comm);
|
||||
|
||||
/* Create the subcommunicators */
|
||||
mca_coll_han_module_t *han_module = (mca_coll_han_module_t *) module;
|
||||
mca_coll_han_comm_create(comm, han_module);
|
||||
ompi_communicator_t *low_comm =
|
||||
han_module->cached_low_comms[mca_coll_han_component.han_scatter_low_module];
|
||||
ompi_communicator_t *up_comm =
|
||||
han_module->cached_up_comms[mca_coll_han_component.han_scatter_up_module];
|
||||
int *vranks = han_module->cached_vranks;
|
||||
int low_rank = ompi_comm_rank(low_comm);
|
||||
int low_size = ompi_comm_size(low_comm);
|
||||
int up_size = ompi_comm_size(up_comm);
|
||||
|
||||
ompi_request_t *temp_request = NULL;
|
||||
/* Set up request */
|
||||
temp_request = OBJ_NEW(ompi_request_t);
|
||||
OMPI_REQUEST_INIT(temp_request, false);
|
||||
temp_request->req_state = OMPI_REQUEST_ACTIVE;
|
||||
temp_request->req_type = 0;
|
||||
temp_request->req_free = han_request_free;
|
||||
temp_request->req_status.MPI_SOURCE = 0;
|
||||
temp_request->req_status.MPI_TAG = 0;
|
||||
temp_request->req_status.MPI_ERROR = 0;
|
||||
temp_request->req_status._cancelled = 0;
|
||||
temp_request->req_status._ucount = 0;
|
||||
|
||||
int root_low_rank;
|
||||
int root_up_rank;
|
||||
mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank);
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Han Scatter root %d root_low_rank %d root_up_rank %d\n", w_rank,
|
||||
root, root_low_rank, root_up_rank));
|
||||
|
||||
/* Reorder sbuf based on rank.
|
||||
* Suppose, message is 0 1 2 3 4 5 6 7
|
||||
* and the processes are mapped on 2 nodes (the processes on the node 0 is 0 2 4 6 and the processes on the node 1 is 1 3 5 7),
|
||||
* so the message needs to be reordered to 0 2 4 6 1 3 5 7
|
||||
*/
|
||||
char *reorder_buf = NULL;
|
||||
char *reorder_sbuf = NULL;
|
||||
int *topo = mca_coll_han_topo_init(comm, han_module, 2);
|
||||
|
||||
if (w_rank == root) {
|
||||
/* If the processes are mapped-by core, no need to reorder */
|
||||
if (han_module->is_mapbycore) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Han Scatter is_bycore: ", w_rank));
|
||||
reorder_sbuf = (char *) sbuf;
|
||||
} else {
|
||||
ptrdiff_t ssize, sgap = 0, sextent;
|
||||
ompi_datatype_type_extent(sdtype, &sextent);
|
||||
ssize = opal_datatype_span(&sdtype->super, (int64_t) scount * w_size, &sgap);
|
||||
reorder_buf = (char *) malloc(ssize);
|
||||
reorder_sbuf = reorder_buf - sgap;
|
||||
for (i = 0; i < up_size; i++) {
|
||||
for (j = 0; j < low_size; j++) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d]: Han Scatter copy from %d %d\n", w_rank,
|
||||
(i * low_size + j) * 2 + 1,
|
||||
topo[(i * low_size + j) * 2 + 1]));
|
||||
ompi_datatype_copy_content_same_ddt(sdtype, (ptrdiff_t) scount,
|
||||
reorder_sbuf + sextent * (i * low_size +
|
||||
j) *
|
||||
(ptrdiff_t) scount,
|
||||
(char *) sbuf +
|
||||
sextent *
|
||||
(ptrdiff_t) topo[(i * low_size + j) * 2 +
|
||||
1] * (ptrdiff_t) scount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create us task */
|
||||
mca_coll_task_t *us = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup us task arguments */
|
||||
mca_scatter_argu_t *us_argu = malloc(sizeof(mca_scatter_argu_t));
|
||||
mac_coll_han_set_scatter_argu(us_argu, us, reorder_sbuf, NULL, reorder_buf, scount, sdtype,
|
||||
(char *) rbuf, rcount, rdtype, root, root_up_rank, root_low_rank,
|
||||
up_comm, low_comm, w_rank, low_rank != root_low_rank,
|
||||
temp_request);
|
||||
/* Init us task */
|
||||
init_task(us, mca_coll_han_scatter_us_task, (void *) (us_argu));
|
||||
/* Issure us task */
|
||||
issue_task(us);
|
||||
|
||||
ompi_request_wait(&temp_request, MPI_STATUS_IGNORE);
|
||||
return OMPI_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* us: upper level (intra-node) scatter task */
|
||||
int mca_coll_han_scatter_us_task(void *task_argu)
|
||||
{
|
||||
mca_scatter_argu_t *t = (mca_scatter_argu_t *) task_argu;
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
|
||||
if (t->noop) {
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Scatter: us noop\n",
|
||||
t->w_rank));
|
||||
} else {
|
||||
int low_size = ompi_comm_size(t->low_comm);
|
||||
ptrdiff_t rsize, rgap = 0;
|
||||
rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size, &rgap);
|
||||
char *tmp_buf = (char *) malloc(rsize);
|
||||
char *tmp_rbuf = tmp_buf - rgap;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output,
|
||||
"[%d] Han Scatter: us scatter\n", t->w_rank));
|
||||
/* Inter node scatter */
|
||||
t->up_comm->c_coll->coll_scatter((char *) t->sbuf, t->scount * low_size, t->sdtype,
|
||||
tmp_rbuf, t->rcount * low_size, t->rdtype, t->root_up_rank,
|
||||
t->up_comm, t->up_comm->c_coll->coll_scatter_module);
|
||||
t->sbuf = tmp_rbuf;
|
||||
t->sbuf_inter_free = tmp_buf;
|
||||
}
|
||||
|
||||
if (t->sbuf_reorder_free != NULL && t->root == t->w_rank) {
|
||||
free(t->sbuf_reorder_free);
|
||||
t->sbuf_reorder_free = NULL;
|
||||
}
|
||||
/* Create ls tasks for the current union segment */
|
||||
mca_coll_task_t *ls = OBJ_NEW(mca_coll_task_t);
|
||||
/* Setup up ls task arguments */
|
||||
t->cur_task = ls;
|
||||
/* Init ls task */
|
||||
init_task(ls, mca_coll_han_scatter_ls_task, (void *) t);
|
||||
/* Issure ls task */
|
||||
issue_task(ls);
|
||||
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* ls: lower level (shared memory) scatter task */
|
||||
int mca_coll_han_scatter_ls_task(void *task_argu)
|
||||
{
|
||||
mca_scatter_argu_t *t = (mca_scatter_argu_t *) task_argu;
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Scatter: ls\n",
|
||||
t->w_rank));
|
||||
OBJ_RELEASE(t->cur_task);
|
||||
/* Shared memory scatter */
|
||||
t->low_comm->c_coll->coll_scatter((char *) t->sbuf, t->scount, t->sdtype, (char *) t->rbuf,
|
||||
t->rcount, t->rdtype, t->root_low_rank, t->low_comm,
|
||||
t->low_comm->c_coll->coll_scatter_module);
|
||||
|
||||
if (t->sbuf_inter_free != NULL && t->noop != true) {
|
||||
free(t->sbuf_inter_free);
|
||||
t->sbuf_inter_free = NULL;
|
||||
}
|
||||
OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Scatter: ls finish\n",
|
||||
t->w_rank));
|
||||
ompi_request_t *temp_req = t->req;
|
||||
free(t);
|
||||
ompi_request_complete(temp_req, 1);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
42
ompi/mca/coll/han/coll_han_trigger.c
Обычный файл
42
ompi/mca/coll/han/coll_han_trigger.c
Обычный файл
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han_trigger.h"
|
||||
|
||||
static void mca_coll_task_constructor(mca_coll_task_t * t)
|
||||
{
|
||||
t->func_ptr = NULL;
|
||||
t->func_argu = NULL;
|
||||
}
|
||||
|
||||
static void mca_coll_task_destructor(mca_coll_task_t * t)
|
||||
{
|
||||
t->func_ptr = NULL;
|
||||
t->func_argu = NULL;
|
||||
}
|
||||
|
||||
OBJ_CLASS_INSTANCE(mca_coll_task_t, opal_object_t, mca_coll_task_constructor,
|
||||
mca_coll_task_destructor);
|
||||
|
||||
/* Init task */
|
||||
int init_task(mca_coll_task_t * t, task_func_ptr func_ptr, void *func_argu)
|
||||
{
|
||||
t->func_ptr = func_ptr;
|
||||
t->func_argu = func_argu;
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Issue the task */
|
||||
int issue_task(mca_coll_task_t * t)
|
||||
{
|
||||
t->func_ptr(t->func_argu);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
46
ompi/mca/coll/han/coll_han_trigger.h
Обычный файл
46
ompi/mca/coll/han/coll_han_trigger.h
Обычный файл
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef MCA_COLL_HAN_TRIGGER_EXPORT_H
|
||||
#define MCA_COLL_HAN_TRIGGER_EXPORT_H
|
||||
|
||||
#include "ompi_config.h"
|
||||
#include "mpi.h"
|
||||
#include "ompi/mca/mca.h"
|
||||
#include "ompi/mca/coll/coll.h"
|
||||
#include "ompi/communicator/communicator.h"
|
||||
#include "ompi/win/win.h"
|
||||
#include "ompi/mca/coll/base/coll_base_functions.h"
|
||||
#include "opal/util/info.h"
|
||||
#include "ompi/op/op.h"
|
||||
#include "opal/runtime/opal_progress.h"
|
||||
#include "ompi/mca/pml/pml.h"
|
||||
#include "ompi/mca/coll/base/coll_tags.h"
|
||||
|
||||
typedef int (*task_func_ptr) (void *);
|
||||
|
||||
struct mca_coll_task_s {
|
||||
opal_object_t super;
|
||||
task_func_ptr func_ptr;
|
||||
void *func_argu;
|
||||
};
|
||||
|
||||
typedef struct mca_coll_task_s mca_coll_task_t;
|
||||
|
||||
OBJ_CLASS_DECLARATION(mca_coll_task_t);
|
||||
|
||||
/* Init task */
|
||||
int init_task(mca_coll_task_t * t, task_func_ptr func_ptr, void *func_argu);
|
||||
|
||||
/* Issue the task */
|
||||
int issue_task(mca_coll_task_t * t);
|
||||
|
||||
#endif /* MCA_COLL_HAN_TRIGGER_EXPORT_H */
|
58
ompi/mca/coll/han/coll_han_utils.c
Обычный файл
58
ompi/mca/coll/han/coll_han_utils.c
Обычный файл
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "coll_han.h"
|
||||
|
||||
/* Get root's low_rank and up_rank from vranks array */
|
||||
void mca_coll_han_get_ranks(int *vranks, int root, int low_size, int *root_low_rank,
|
||||
int *root_up_rank)
|
||||
{
|
||||
*root_up_rank = vranks[root] / low_size;
|
||||
*root_low_rank = vranks[root] % low_size;
|
||||
}
|
||||
|
||||
uint32_t han_auto_tuned_get_n(uint32_t n)
|
||||
{
|
||||
uint32_t avail[5] = { 4, 8, 16, 32, 64 };
|
||||
uint32_t i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (avail[i] >= n) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
uint32_t han_auto_tuned_get_c(uint32_t c)
|
||||
{
|
||||
uint32_t avail[3] = { 4, 8, 12 };
|
||||
uint32_t i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (avail[i] >= c) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
uint32_t han_auto_tuned_get_m(uint32_t m)
|
||||
{
|
||||
uint32_t avail[21] =
|
||||
{ 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072,
|
||||
262144, 524288, 1048576, 2097152, 4194304 };
|
||||
uint32_t i;
|
||||
for (i = 0; i < 21; i++) {
|
||||
if (avail[i] >= m) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i - 1;
|
||||
}
|
Загрузка…
Ссылка в новой задаче
Block a user