321 строка
9.4 KiB
C
321 строка
9.4 KiB
C
|
/*
|
||
|
* Copyright (c) 2009-2012 Oak Ridge National Laboratory. All rights reserved.
|
||
|
* Copyright (c) 2009-2012 Mellanox Technologies. All rights reserved.
|
||
|
* $COPYRIGHT$
|
||
|
*
|
||
|
* Additional copyrights may follow
|
||
|
*
|
||
|
* $HEADER$
|
||
|
*/
|
||
|
|
||
|
#include "ompi_config.h"
|
||
|
#include "opal/class/opal_list.h"
|
||
|
#include "opal/threads/mutex.h"
|
||
|
#include "coll_ml.h"
|
||
|
#include "coll_ml_mca.h"
|
||
|
#include "coll_ml_lmngr.h"
|
||
|
|
||
|
/* Constructor for list memory manager */
|
||
|
static void construct_lmngr(mca_coll_ml_lmngr_t *lmngr)
|
||
|
{
|
||
|
mca_coll_ml_component_t *cm = &mca_coll_ml_component;
|
||
|
|
||
|
ML_VERBOSE(7, ("Constructing new list manager %p", (void *)lmngr));
|
||
|
|
||
|
/* No real memory is allocated, only basic init.
|
||
|
The real memory will be allocated on demand, on first block allocation */
|
||
|
|
||
|
/* I caching this block size, alignment and list size
|
||
|
since maybe in future we will want to define different parameters
|
||
|
for lists */
|
||
|
lmngr->list_block_size = cm->lmngr_block_size;
|
||
|
lmngr->list_alignment = cm->lmngr_alignment;
|
||
|
lmngr->list_size = cm->lmngr_size;
|
||
|
lmngr->base_addr = NULL; /* If the base addr is not null, the struct was initilized
|
||
|
and memory was allocated */
|
||
|
/* Not sure that lock is required */
|
||
|
OBJ_CONSTRUCT(&lmngr->mem_lock, opal_mutex_t);
|
||
|
|
||
|
/* Only construct the list, no memry initialisation */
|
||
|
OBJ_CONSTRUCT(&lmngr->blocks_list, opal_list_t);
|
||
|
}
|
||
|
|
||
|
static void destruct_lmngr(mca_coll_ml_lmngr_t *lmngr)
|
||
|
{
|
||
|
int max_nc = lmngr->n_resources;
|
||
|
int rc, i;
|
||
|
bcol_base_network_context_t *nc;
|
||
|
opal_list_item_t *item;
|
||
|
|
||
|
ML_VERBOSE(6, ("Destructing list manager %p", (void *)lmngr));
|
||
|
|
||
|
while(!opal_list_is_empty(&lmngr->blocks_list)) {
|
||
|
item = opal_list_remove_first(&lmngr->blocks_list);
|
||
|
OBJ_DESTRUCT(item);
|
||
|
}
|
||
|
|
||
|
OBJ_DESTRUCT(&lmngr->blocks_list);
|
||
|
|
||
|
if (NULL != lmngr->base_addr) {
|
||
|
for( i = 0; i < max_nc; i++ ) {
|
||
|
nc = lmngr->net_context[i];
|
||
|
rc = nc->deregister_memory_fn(nc->context_data,
|
||
|
lmngr->reg_desc[nc->context_id]);
|
||
|
if(rc != OMPI_SUCCESS) {
|
||
|
ML_ERROR(("Failed to unregister , lmngr %p", (void *)lmngr));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ML_VERBOSE(10, ("Release base addr %p", lmngr->base_addr));
|
||
|
|
||
|
free(lmngr->base_addr);
|
||
|
lmngr->base_addr = NULL;
|
||
|
}
|
||
|
|
||
|
lmngr->list_block_size = 0;
|
||
|
lmngr->list_alignment = 0;
|
||
|
lmngr->list_size = 0;
|
||
|
|
||
|
OBJ_DESTRUCT(&lmngr->mem_lock);
|
||
|
}
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(mca_coll_ml_lmngr_t,
|
||
|
opal_object_t,
|
||
|
construct_lmngr,
|
||
|
destruct_lmngr);
|
||
|
|
||
|
static void lmngr_block_constructor(mca_coll_ml_lmngr_block_t *item)
|
||
|
{
|
||
|
item->base_addr = NULL;
|
||
|
}
|
||
|
|
||
|
static void lnmgr_block_destructor(mca_coll_ml_lmngr_block_t *item)
|
||
|
{
|
||
|
/* I have nothing to do here */
|
||
|
}
|
||
|
|
||
|
OBJ_CLASS_INSTANCE(mca_coll_ml_lmngr_block_t,
|
||
|
opal_list_item_t,
|
||
|
lmngr_block_constructor,
|
||
|
lnmgr_block_destructor);
|
||
|
|
||
|
|
||
|
int mca_coll_ml_lmngr_tune(mca_coll_ml_lmngr_t *lmngr,
|
||
|
size_t block_size, size_t list_size, size_t alignment)
|
||
|
{
|
||
|
ML_VERBOSE(7, ("Tunning list manager"));
|
||
|
|
||
|
if (OPAL_UNLIKELY(NULL == lmngr->base_addr)) {
|
||
|
ML_VERBOSE(7, ("The list manager is already initialized, you can not tune it"));
|
||
|
return OMPI_ERROR;
|
||
|
}
|
||
|
|
||
|
lmngr->list_block_size = block_size;
|
||
|
lmngr->list_alignment = alignment;
|
||
|
lmngr->list_size = list_size;
|
||
|
|
||
|
return OMPI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int mca_coll_ml_lmngr_reg(void)
|
||
|
{
|
||
|
int ival, tmp;
|
||
|
int ret = OMPI_SUCCESS;
|
||
|
|
||
|
mca_coll_ml_component_t *cm = &mca_coll_ml_component;
|
||
|
|
||
|
#define CHECK(expr) do {\
|
||
|
tmp = (expr); \
|
||
|
if (OMPI_SUCCESS != tmp) ret = tmp; \
|
||
|
} while (0)
|
||
|
|
||
|
ML_VERBOSE(7, ("Setting parameters for list manager"));
|
||
|
|
||
|
CHECK(reg_int("memory_manager_list_size", NULL,
|
||
|
"Memory manager list size", 8, &ival, 0));
|
||
|
cm->lmngr_size = ival;
|
||
|
|
||
|
/* The size list couldn't be less than possible max of ML modules,
|
||
|
it = max supported communicators by ML */
|
||
|
if (cm->lmngr_size < cm->max_comm) {
|
||
|
cm->lmngr_size = cm->max_comm;
|
||
|
}
|
||
|
|
||
|
CHECK(reg_int("memory_manager_block_size", NULL,
|
||
|
"Memory manager block size",
|
||
|
cm->payload_buffer_size *
|
||
|
cm->n_payload_buffs_per_bank *
|
||
|
cm->n_payload_mem_banks *
|
||
|
cm->lmngr_size, &ival, 0));
|
||
|
mca_coll_ml_component.lmngr_block_size = ival;
|
||
|
|
||
|
CHECK(reg_int("memory_manager_alignment", NULL,
|
||
|
"Memory manager alignment", 4 * 1024, &ival, 0));
|
||
|
cm->lmngr_alignment = ival;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int lmngr_register(mca_coll_ml_lmngr_t *lmngr, bcol_base_network_context_t *nc)
|
||
|
{
|
||
|
int rc, j;
|
||
|
int max_nc = lmngr->n_resources;
|
||
|
|
||
|
rc = nc->register_memory_fn(nc->context_data,
|
||
|
lmngr->base_addr,
|
||
|
lmngr->list_size * lmngr->list_block_size,
|
||
|
&lmngr->reg_desc[nc->context_id]);
|
||
|
|
||
|
if(rc != OMPI_SUCCESS) {
|
||
|
int ret_val;
|
||
|
ML_VERBOSE(7, ("Failed to register [%d], unrolling the registration", rc));
|
||
|
/* deregistser the successful registrations */
|
||
|
for( j = 0; j < max_nc; j++ ) {
|
||
|
/* set the registration parameter to point to the current
|
||
|
* resource description */
|
||
|
nc = lmngr->net_context[j];
|
||
|
ret_val = nc->deregister_memory_fn(nc->context_data,
|
||
|
lmngr->reg_desc[nc->context_id]);
|
||
|
if(ret_val != OMPI_SUCCESS) {
|
||
|
return ret_val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
return OMPI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static int mca_coll_ml_lmngr_init(mca_coll_ml_lmngr_t *lmngr)
|
||
|
{
|
||
|
int i, num_blocks;
|
||
|
int rc;
|
||
|
unsigned char *addr;
|
||
|
bcol_base_network_context_t *nc;
|
||
|
|
||
|
ML_VERBOSE(7, ("List initialization"));
|
||
|
|
||
|
#ifdef HAVE_POSIX_MEMALIGN
|
||
|
if((errno = posix_memalign(&lmngr->base_addr,
|
||
|
lmngr->list_alignment,
|
||
|
lmngr->list_size * lmngr->list_block_size)) != 0) {
|
||
|
ML_ERROR(("Failed to allocate memory: %s [%d]", errno, strerror(errno)));
|
||
|
return OMPI_ERROR;
|
||
|
}
|
||
|
#else
|
||
|
lmngr->base_addr =
|
||
|
malloc(lmngr->list_size * lmngr->list_block_size + lmngr->list_alignment);
|
||
|
if(NULL == lmngr->base_addr) {
|
||
|
ML_ERROR(("Failed to allocate memory: %s [%d]", errno, strerror(errno)));
|
||
|
return OMPI_ERROR;
|
||
|
}
|
||
|
|
||
|
lmngr->base_addr = (void*)OPAL_ALIGN((uintptr_t)lmngr->base_addr,
|
||
|
lmngr->list_align, uintptr_t);
|
||
|
#endif
|
||
|
|
||
|
assert(lmngr->n_resources < MCA_COLL_ML_MAX_REG_INFO);
|
||
|
|
||
|
for(i= 0 ;i < lmngr->n_resources ;i++) {
|
||
|
nc = lmngr->net_context[i];
|
||
|
ML_VERBOSE(7, ("Call registration for resource index %d", i));
|
||
|
rc = lmngr_register(lmngr, nc);
|
||
|
if (OMPI_SUCCESS != rc) {
|
||
|
ML_ERROR(("Failed to lmngr register: %s [%d]", errno, strerror(errno)));
|
||
|
return rc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* slice the memory to blocks */
|
||
|
addr = (unsigned char *) lmngr->base_addr;
|
||
|
for(num_blocks = 0; num_blocks < (int)lmngr->list_size; num_blocks++) {
|
||
|
mca_coll_ml_lmngr_block_t *item = OBJ_NEW(mca_coll_ml_lmngr_block_t);
|
||
|
item->base_addr = (void *)addr;
|
||
|
item->lmngr = lmngr;
|
||
|
/* ML_VERBOSE(10, ("Appending block # %d %p", num_blocks, (void *)addr)); */
|
||
|
opal_list_append(&lmngr->blocks_list, (opal_list_item_t *)item);
|
||
|
/* advance the address */
|
||
|
addr += lmngr->list_block_size;
|
||
|
}
|
||
|
|
||
|
ML_VERBOSE(7, ("List initialization done %d",
|
||
|
opal_list_get_size(&lmngr->blocks_list)));
|
||
|
return OMPI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
mca_coll_ml_lmngr_block_t* mca_coll_ml_lmngr_alloc (
|
||
|
mca_coll_ml_lmngr_t *lmngr)
|
||
|
{
|
||
|
int rc;
|
||
|
opal_list_t *list = &lmngr->blocks_list;
|
||
|
|
||
|
/* Check if the list manager was initialized */
|
||
|
if(OPAL_UNLIKELY(NULL == lmngr->base_addr)) {
|
||
|
ML_VERBOSE(7 ,("Starting memory initialization\n"));
|
||
|
rc = mca_coll_ml_lmngr_init(lmngr);
|
||
|
if (OMPI_SUCCESS != rc) {
|
||
|
ML_ERROR(("Failed to init memory\n"));
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(OPAL_UNLIKELY(opal_list_is_empty(list))) {
|
||
|
/* Upper layer need to handle the NULL */
|
||
|
ML_ERROR(("List manager is empty.\n"));
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return (mca_coll_ml_lmngr_block_t *)opal_list_remove_first(list);
|
||
|
}
|
||
|
|
||
|
void mca_coll_ml_lmngr_free(mca_coll_ml_lmngr_block_t *block)
|
||
|
{
|
||
|
opal_list_append(&block->lmngr->blocks_list, (opal_list_item_t *)block);
|
||
|
}
|
||
|
|
||
|
int mca_coll_ml_lmngr_append_nc(mca_coll_ml_lmngr_t *lmngr, bcol_base_network_context_t *nc)
|
||
|
{
|
||
|
int i, rc;
|
||
|
|
||
|
ML_VERBOSE(7, ("Append new network context %p to list manager %p",
|
||
|
nc, lmngr));
|
||
|
|
||
|
if (NULL == nc) {
|
||
|
return OMPI_ERROR;
|
||
|
}
|
||
|
|
||
|
/* check if we already have the context on the list.
|
||
|
if we do have - do not do anything, just return success
|
||
|
*/
|
||
|
if (OPAL_UNLIKELY(MCA_COLL_ML_MAX_REG_INFO == lmngr->n_resources)) {
|
||
|
ML_ERROR(("MPI overflows maximum supported network contexts is %d"));
|
||
|
return OMPI_ERROR;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < lmngr->n_resources; i++) {
|
||
|
if (lmngr->net_context[i] == nc) {
|
||
|
ML_VERBOSE(7, ("It is not new "));
|
||
|
return OMPI_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ML_VERBOSE(7, ("Adding new context"));
|
||
|
|
||
|
/* Setting context id */
|
||
|
nc->context_id = lmngr->n_resources;
|
||
|
lmngr->net_context[lmngr->n_resources] = nc;
|
||
|
|
||
|
lmngr->n_resources++;
|
||
|
|
||
|
/* Register the memory with new context */
|
||
|
if (NULL != lmngr->base_addr) {
|
||
|
rc = lmngr_register(lmngr, nc);
|
||
|
if (OMPI_SUCCESS == rc) {
|
||
|
return rc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return OMPI_SUCCESS;
|
||
|
}
|