1
1

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>
Этот коммит содержится в:
Xi Luo 2020-03-09 14:08:34 -04:00 коммит произвёл George Bosilca
родитель 5c16e968b1
Коммит feb5a7113c
13 изменённых файлов: 2847 добавлений и 0 удалений

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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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;
}