Improve the opal_pointer_array & more (#3369)
* Complete rewrite of opal_pointer_array Instead of a cache oblivious linear search use a bits array to speed up the management of the free space. As a result we slightly increase the memory used by the structure, but we get a significant boost in performance. Signed-off-by: George Bosilca <bosilca@icl.utk.edu> * Do not register datatypes in the f2c translation table. The registration is now done up into the Fortran layer, by forcing a call to MPI_Type_c2f. Signed-off-by: George Bosilca <bosilca@icl.utk.edu>
This commit is contained in:
parent
23dad50d51
commit
872cf44c28
@ -86,15 +86,15 @@ int ompi_comm_init(void)
|
||||
|
||||
/* Setup communicator array */
|
||||
OBJ_CONSTRUCT(&ompi_mpi_communicators, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_communicators, 0,
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_communicators, 16,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
/* Setup f to c table (we can no longer use the cid as the fortran handle) */
|
||||
OBJ_CONSTRUCT(&ompi_comm_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_comm_f_to_c_table, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_comm_f_to_c_table, 8,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 32) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,11 @@
|
||||
static void __ompi_datatype_allocate( ompi_datatype_t* datatype )
|
||||
{
|
||||
datatype->args = NULL;
|
||||
datatype->d_f_to_c_index = opal_pointer_array_add(&ompi_datatype_f_to_c_table, datatype);
|
||||
/* Later generated datatypes will have their id according to the Fortran ID, as ALL types are registered */
|
||||
datatype->id = datatype->d_f_to_c_index;
|
||||
/* Do not add the newly created datatypes to the f2c translation table. We will add them only
|
||||
* if necessary, basically upon the first call the MPI_Datatype_f2c.
|
||||
*/
|
||||
datatype->d_f_to_c_index = -1;
|
||||
datatype->id = -1;
|
||||
datatype->d_keyhash = NULL;
|
||||
datatype->name[0] = '\0';
|
||||
datatype->packed_description = NULL;
|
||||
@ -48,8 +50,9 @@ static void __ompi_datatype_release(ompi_datatype_t * datatype)
|
||||
free( datatype->packed_description );
|
||||
datatype->packed_description = NULL;
|
||||
}
|
||||
if( NULL != opal_pointer_array_get_item(&ompi_datatype_f_to_c_table, datatype->d_f_to_c_index) ){
|
||||
if( datatype->d_f_to_c_index >= 0 ) {
|
||||
opal_pointer_array_set_item( &ompi_datatype_f_to_c_table, datatype->d_f_to_c_index, NULL );
|
||||
datatype->d_f_to_c_index = -1;
|
||||
}
|
||||
/* any pending attributes ? */
|
||||
if (NULL != datatype->d_keyhash) {
|
||||
|
@ -403,7 +403,7 @@ extern const ompi_datatype_t* ompi_datatype_basicDatatypes[OMPI_DATATYPE_MPI_MAX
|
||||
|
||||
#define OMPI_DATATYPE_EMPTY_DATA(NAME) \
|
||||
.id = OMPI_DATATYPE_MPI_ ## NAME, \
|
||||
.d_f_to_c_index = 0, \
|
||||
.d_f_to_c_index = -1, \
|
||||
.d_keyhash = NULL, \
|
||||
.args = NULL, \
|
||||
.packed_description = NULL, \
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2016 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
|
||||
@ -457,7 +457,7 @@ int32_t ompi_datatype_init( void )
|
||||
/* Create the f2c translation table */
|
||||
OBJ_CONSTRUCT(&ompi_datatype_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_datatype_f_to_c_table,
|
||||
0, OMPI_FORTRAN_HANDLE_MAX, 64)) {
|
||||
64, OMPI_FORTRAN_HANDLE_MAX, 32)) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
/* All temporary datatypes created on the following statement will get registered
|
||||
@ -512,7 +512,6 @@ int32_t ompi_datatype_init( void )
|
||||
/* Copy the desc pointer from the <OMPI_DATATYPE_MPI_MAX_PREDEFINED datatypes to
|
||||
the synonym types */
|
||||
|
||||
|
||||
/* Start to populate the f2c index translation table */
|
||||
|
||||
/* The order of the data registration should be the same as the
|
||||
@ -523,14 +522,14 @@ int32_t ompi_datatype_init( void )
|
||||
/* This macro makes everything significantly easier to read below.
|
||||
All hail the moog! :-) */
|
||||
|
||||
#define MOOG(name, index) \
|
||||
{ \
|
||||
ompi_mpi_##name.dt.d_f_to_c_index = \
|
||||
opal_pointer_array_add(&ompi_datatype_f_to_c_table, &ompi_mpi_##name); \
|
||||
#define MOOG(name, index) \
|
||||
do { \
|
||||
ompi_mpi_##name.dt.d_f_to_c_index = \
|
||||
opal_pointer_array_add(&ompi_datatype_f_to_c_table, &ompi_mpi_##name); \
|
||||
if( ompi_datatype_number_of_predefined_data < (ompi_mpi_##name).dt.d_f_to_c_index ) \
|
||||
ompi_datatype_number_of_predefined_data = (ompi_mpi_##name).dt.d_f_to_c_index; \
|
||||
assert( (index) == ompi_mpi_##name.dt.d_f_to_c_index ); \
|
||||
}
|
||||
assert( (index) == ompi_mpi_##name.dt.d_f_to_c_index ); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* This MUST match the order of ompi/include/mpif-values.pl
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -133,8 +133,8 @@ int ompi_mpi_errcode_init (void)
|
||||
/* Initialize the pointer array, which will hold the references to
|
||||
the error objects */
|
||||
OBJ_CONSTRUCT(&ompi_mpi_errcodes, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_errcodes, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_errcodes, 64,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 32) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2014 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -83,8 +83,8 @@ int ompi_errhandler_init(void)
|
||||
/* initialize ompi_errhandler_f_to_c_table */
|
||||
|
||||
OBJ_CONSTRUCT( &ompi_errhandler_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_errhandler_f_to_c_table, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_errhandler_f_to_c_table, 8,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 16) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -73,7 +73,7 @@ int ompi_file_init(void)
|
||||
|
||||
OBJ_CONSTRUCT(&ompi_file_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_file_f_to_c_table, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
OMPI_FORTRAN_HANDLE_MAX, 16) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -319,8 +319,8 @@ int ompi_group_init(void)
|
||||
{
|
||||
/* initialize ompi_group_f_to_c_table */
|
||||
OBJ_CONSTRUCT( &ompi_group_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_group_f_to_c_table, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_group_f_to_c_table, 4,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 16) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -102,7 +102,7 @@ int ompi_info_init(void)
|
||||
|
||||
OBJ_CONSTRUCT(&ompi_info_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_info_f_to_c_table, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
OMPI_FORTRAN_HANDLE_MAX, 16) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
|
||||
@ -55,5 +55,10 @@ MPI_Fint MPI_Type_c2f(MPI_Datatype datatype)
|
||||
}
|
||||
}
|
||||
|
||||
/* If necessary add the datatype to the f2c translation table */
|
||||
if( -1 == datatype->d_f_to_c_index ) {
|
||||
datatype->d_f_to_c_index = opal_pointer_array_add(&ompi_datatype_f_to_c_table, datatype);
|
||||
/* We don't check for error as returning a negative value is considered as an error */
|
||||
}
|
||||
return OMPI_INT_2_FINT(datatype->d_f_to_c_index);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2016 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
|
||||
@ -108,7 +108,7 @@ int ompi_request_init(void)
|
||||
OBJ_CONSTRUCT(&ompi_request_null, ompi_request_t);
|
||||
OBJ_CONSTRUCT(&ompi_request_f_to_c_table, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_request_f_to_c_table,
|
||||
0, OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
0, OMPI_FORTRAN_HANDLE_MAX, 32) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
ompi_request_null.request.req_type = OMPI_REQUEST_NULL;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2016 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
|
||||
@ -110,7 +110,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* setup the mca_types array */
|
||||
OBJ_CONSTRUCT(&mca_types, opal_pointer_array_t);
|
||||
opal_pointer_array_init(&mca_types, 256, INT_MAX, 128);
|
||||
opal_pointer_array_init(&mca_types, 128, INT_MAX, 64);
|
||||
|
||||
/* add in the opal frameworks */
|
||||
opal_info_register_types(&mca_types);
|
||||
@ -124,7 +124,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* init the component map */
|
||||
OBJ_CONSTRUCT(&component_map, opal_pointer_array_t);
|
||||
opal_pointer_array_init(&component_map, 256, INT_MAX, 128);
|
||||
opal_pointer_array_init(&component_map, 64, INT_MAX, 32);
|
||||
|
||||
/* Register OMPI's params */
|
||||
if (OMPI_SUCCESS != (ret = ompi_info_register_framework_params(&component_map))) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -79,8 +79,8 @@ ompi_win_init(void)
|
||||
|
||||
/* setup window Fortran array */
|
||||
OBJ_CONSTRUCT(&ompi_mpi_windows, opal_pointer_array_t);
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_windows, 0,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 64) ) {
|
||||
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_windows, 4,
|
||||
OMPI_FORTRAN_HANDLE_MAX, 16) ) {
|
||||
return OMPI_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -27,11 +27,9 @@
|
||||
#include "opal/class/opal_pointer_array.h"
|
||||
#include "opal/util/output.h"
|
||||
|
||||
enum { TABLE_INIT = 1, TABLE_GROW = 2 };
|
||||
|
||||
static void opal_pointer_array_construct(opal_pointer_array_t *);
|
||||
static void opal_pointer_array_destruct(opal_pointer_array_t *);
|
||||
static bool grow_table(opal_pointer_array_t *table, int soft, int hard);
|
||||
static bool grow_table(opal_pointer_array_t *table, int at_least);
|
||||
|
||||
OBJ_CLASS_INSTANCE(opal_pointer_array_t, opal_object_t,
|
||||
opal_pointer_array_construct,
|
||||
@ -47,8 +45,9 @@ static void opal_pointer_array_construct(opal_pointer_array_t *array)
|
||||
array->number_free = 0;
|
||||
array->size = 0;
|
||||
array->max_size = INT_MAX;
|
||||
array->block_size = 0;
|
||||
array->addr = 0;
|
||||
array->block_size = 8;
|
||||
array->free_bits = NULL;
|
||||
array->addr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -57,7 +56,11 @@ static void opal_pointer_array_construct(opal_pointer_array_t *array)
|
||||
static void opal_pointer_array_destruct(opal_pointer_array_t *array)
|
||||
{
|
||||
/* free table */
|
||||
if( NULL != array->addr) {
|
||||
if( NULL != array->free_bits) {
|
||||
free(array->free_bits);
|
||||
array->free_bits = NULL;
|
||||
}
|
||||
if( NULL != array->addr ) {
|
||||
free(array->addr);
|
||||
array->addr = NULL;
|
||||
}
|
||||
@ -67,6 +70,103 @@ static void opal_pointer_array_destruct(opal_pointer_array_t *array)
|
||||
OBJ_DESTRUCT(&array->lock);
|
||||
}
|
||||
|
||||
#define TYPE_ELEM_COUNT(TYPE, CAP) (((CAP) + 8 * sizeof(TYPE) - 1) / (8 * sizeof(TYPE)))
|
||||
|
||||
/**
|
||||
* Translate an index position into the free bits array into 2 values, the
|
||||
* index of the element and the index of the bit position.
|
||||
*/
|
||||
#define GET_BIT_POS(IDX, BIDX, PIDX) \
|
||||
do { \
|
||||
uint32_t __idx = (uint32_t)(IDX); \
|
||||
(BIDX) = (__idx / (8 * sizeof(uint64_t))); \
|
||||
(PIDX) = (__idx % (8 * sizeof(uint64_t))); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* A classical find first zero bit (ffs) on a large array. It checks starting
|
||||
* from the indicated position until it finds a zero bit. If SET is true,
|
||||
* the bit is set. The position of the bit is returned in store.
|
||||
*/
|
||||
#define FIND_FIRST_ZERO(START_IDX, STORE, SET) \
|
||||
do { \
|
||||
uint32_t __b_idx, __b_pos; \
|
||||
GET_BIT_POS((START_IDX), __b_idx, __b_pos); \
|
||||
for (; table->free_bits[__b_idx] == 0xFFFFFFFFFFFFFFFFULL; __b_idx++); \
|
||||
assert(__b_idx < (uint32_t)table->size); \
|
||||
uint64_t __check_value = table->free_bits[__b_idx]; \
|
||||
__b_pos = 0; \
|
||||
\
|
||||
if( 0x00000000FFFFFFFFULL == (__check_value & 0x00000000FFFFFFFFULL) ) { \
|
||||
__check_value >>= 32; __b_pos += 32; \
|
||||
} \
|
||||
if( 0x000000000000FFFFULL == (__check_value & 0x000000000000FFFFULL) ) { \
|
||||
__check_value >>= 16; __b_pos += 16; \
|
||||
} \
|
||||
if( 0x00000000000000FFULL == (__check_value & 0x00000000000000FFULL) ) { \
|
||||
__check_value >>= 8; __b_pos += 8; \
|
||||
} \
|
||||
if( 0x000000000000000FULL == (__check_value & 0x000000000000000FULL) ) { \
|
||||
__check_value >>= 4; __b_pos += 4; \
|
||||
} \
|
||||
if( 0x0000000000000003ULL == (__check_value & 0x0000000000000003ULL) ) { \
|
||||
__check_value >>= 2; __b_pos += 2; \
|
||||
} \
|
||||
if( 0x0000000000000001ULL == (__check_value & 0x0000000000000001ULL) ) { \
|
||||
__b_pos += 1; \
|
||||
} \
|
||||
if( (SET) ) { \
|
||||
table->free_bits[__b_idx] |= (1ULL << __b_pos); \
|
||||
} \
|
||||
(STORE) = (__b_idx * 8 * sizeof(uint64_t)) + __b_pos; \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Set the IDX bit in the free_bits array. The bit should be previously unset.
|
||||
*/
|
||||
#define SET_BIT(IDX) \
|
||||
do { \
|
||||
uint32_t __b_idx, __b_pos; \
|
||||
GET_BIT_POS((IDX), __b_idx, __b_pos); \
|
||||
assert( 0 == (table->free_bits[__b_idx] & (1UL << __b_pos))); \
|
||||
table->free_bits[__b_idx] |= (1ULL << __b_pos); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Unset the IDX bit in the free_bits array. The bit should be previously set.
|
||||
*/
|
||||
#define UNSET_BIT(IDX) \
|
||||
do { \
|
||||
uint32_t __b_idx, __b_pos; \
|
||||
GET_BIT_POS((IDX), __b_idx, __b_pos); \
|
||||
assert( (table->free_bits[__b_idx] & (1UL << __b_pos))); \
|
||||
table->free_bits[__b_idx] ^= (1ULL << __b_pos); \
|
||||
} while(0)
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Validate the pointer array by making sure that the elements and
|
||||
* the free bits array are in sync. It also check that the number
|
||||
* of remaining free element is consistent.
|
||||
*/
|
||||
static void opal_pointer_array_validate(opal_pointer_array_t *array)
|
||||
{
|
||||
int i, cnt = 0;
|
||||
uint32_t b_idx, p_idx;
|
||||
|
||||
for( i = 0; i < array->size; i++ ) {
|
||||
GET_BIT_POS(i, b_idx, p_idx);
|
||||
if( NULL == array->addr[i] ) {
|
||||
cnt++;
|
||||
assert( 0 == (array->free_bits[b_idx] & (1ULL << p_idx)) );
|
||||
} else {
|
||||
assert( 0 != (array->free_bits[b_idx] & (1ULL << p_idx)) );
|
||||
}
|
||||
}
|
||||
assert(cnt == array->number_free);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* initialize an array object
|
||||
*/
|
||||
@ -82,18 +182,24 @@ int opal_pointer_array_init(opal_pointer_array_t* array,
|
||||
}
|
||||
|
||||
array->max_size = max_size;
|
||||
array->block_size = block_size;
|
||||
array->block_size = (0 == block_size ? 8 : block_size);
|
||||
array->lowest_free = 0;
|
||||
|
||||
num_bytes = (0 < initial_allocation ? initial_allocation : block_size);
|
||||
array->number_free = num_bytes;
|
||||
array->size = num_bytes;
|
||||
num_bytes *= sizeof(void*);
|
||||
|
||||
/* Allocate and set the array to NULL */
|
||||
array->addr = (void **)calloc(num_bytes, 1);
|
||||
array->addr = (void **)calloc(num_bytes, sizeof(void*));
|
||||
if (NULL == array->addr) { /* out of memory */
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
array->free_bits = (uint64_t*)calloc(TYPE_ELEM_COUNT(uint64_t, num_bytes), sizeof(uint64_t));
|
||||
if (NULL == array->free_bits) { /* out of memory */
|
||||
free(array->addr);
|
||||
array->addr = NULL;
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
array->number_free = num_bytes;
|
||||
array->size = num_bytes;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
@ -108,15 +214,13 @@ int opal_pointer_array_init(opal_pointer_array_t* array,
|
||||
*/
|
||||
int opal_pointer_array_add(opal_pointer_array_t *table, void *ptr)
|
||||
{
|
||||
int i, index;
|
||||
int index = table->size + 1;
|
||||
|
||||
OPAL_THREAD_LOCK(&(table->lock));
|
||||
|
||||
if (table->number_free == 0) {
|
||||
/* need to grow table */
|
||||
if (!grow_table(table,
|
||||
(NULL == table->addr ? TABLE_INIT : table->size * TABLE_GROW),
|
||||
INT_MAX)) {
|
||||
if (!grow_table(table, index) ) {
|
||||
OPAL_THREAD_UNLOCK(&(table->lock));
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
@ -131,21 +235,19 @@ int opal_pointer_array_add(opal_pointer_array_t *table, void *ptr)
|
||||
*/
|
||||
|
||||
index = table->lowest_free;
|
||||
assert(table->addr[index] == NULL);
|
||||
assert(NULL == table->addr[index]);
|
||||
table->addr[index] = ptr;
|
||||
table->number_free--;
|
||||
SET_BIT(index);
|
||||
if (table->number_free > 0) {
|
||||
for (i = table->lowest_free + 1; i < table->size; i++) {
|
||||
if (table->addr[i] == NULL) {
|
||||
table->lowest_free = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FIND_FIRST_ZERO(index, table->lowest_free, 0);
|
||||
} else {
|
||||
table->lowest_free = table->size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
opal_pointer_array_validate(table);
|
||||
#endif
|
||||
OPAL_THREAD_UNLOCK(&(table->lock));
|
||||
return index;
|
||||
}
|
||||
@ -174,41 +276,37 @@ int opal_pointer_array_set_item(opal_pointer_array_t *table, int index,
|
||||
|
||||
OPAL_THREAD_LOCK(&(table->lock));
|
||||
if (table->size <= index) {
|
||||
if (!grow_table(table, ((index / TABLE_GROW) + 1) * TABLE_GROW,
|
||||
index)) {
|
||||
if (!grow_table(table, index)) {
|
||||
OPAL_THREAD_UNLOCK(&(table->lock));
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
assert(table->size > index);
|
||||
/* mark element as free, if NULL element */
|
||||
if( NULL == value ) {
|
||||
if (index < table->lowest_free) {
|
||||
table->lowest_free = index;
|
||||
}
|
||||
if( NULL != table->addr[index] ) {
|
||||
if (index < table->lowest_free) {
|
||||
table->lowest_free = index;
|
||||
}
|
||||
table->number_free++;
|
||||
UNSET_BIT(index);
|
||||
}
|
||||
} else {
|
||||
if (NULL == table->addr[index]) {
|
||||
table->number_free--;
|
||||
}
|
||||
/* Reset lowest_free if required */
|
||||
if ( index == table->lowest_free ) {
|
||||
int i;
|
||||
|
||||
table->lowest_free = table->size;
|
||||
for ( i=index + 1; i<table->size; i++) {
|
||||
if ( NULL == table->addr[i] ){
|
||||
table->lowest_free = i;
|
||||
break;
|
||||
}
|
||||
SET_BIT(index);
|
||||
/* Reset lowest_free if required */
|
||||
if ( index == table->lowest_free ) {
|
||||
FIND_FIRST_ZERO(index, table->lowest_free, 0);
|
||||
}
|
||||
} else {
|
||||
assert( index != table->lowest_free );
|
||||
}
|
||||
}
|
||||
table->addr[index] = value;
|
||||
|
||||
#if 0
|
||||
opal_pointer_array_validate(table);
|
||||
opal_output(0,"opal_pointer_array_set_item: OUT: "
|
||||
" table %p (size %ld, lowest free %ld, number free %ld)"
|
||||
" addr[%d] = %p\n",
|
||||
@ -259,8 +357,7 @@ bool opal_pointer_array_test_and_set_item (opal_pointer_array_t *table,
|
||||
/* Do we need to grow the table? */
|
||||
|
||||
if (table->size <= index) {
|
||||
if (!grow_table(table, (((index / TABLE_GROW) + 1) * TABLE_GROW),
|
||||
index)) {
|
||||
if (!grow_table(table, index)) {
|
||||
OPAL_THREAD_UNLOCK(&(table->lock));
|
||||
return false;
|
||||
}
|
||||
@ -269,22 +366,21 @@ bool opal_pointer_array_test_and_set_item (opal_pointer_array_t *table,
|
||||
/*
|
||||
* allow a specific index to be changed.
|
||||
*/
|
||||
assert(NULL == table->addr[index]);
|
||||
table->addr[index] = value;
|
||||
table->number_free--;
|
||||
SET_BIT(index);
|
||||
/* Reset lowest_free if required */
|
||||
if ( index == table->lowest_free ) {
|
||||
int i;
|
||||
|
||||
table->lowest_free = table->size;
|
||||
for ( i=index; i<table->size; i++) {
|
||||
if ( NULL == table->addr[i] ){
|
||||
table->lowest_free = i;
|
||||
break;
|
||||
}
|
||||
if( table->number_free > 0 ) {
|
||||
if ( index == table->lowest_free ) {
|
||||
FIND_FIRST_ZERO(index, table->lowest_free, 0);
|
||||
}
|
||||
} else {
|
||||
table->lowest_free = table->size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
opal_pointer_array_validate(table);
|
||||
opal_output(0,"opal_pointer_array_test_and_set_item: OUT: "
|
||||
" table %p (size %ld, lowest free %ld, number free %ld)"
|
||||
" addr[%d] = %p\n",
|
||||
@ -300,7 +396,7 @@ int opal_pointer_array_set_size(opal_pointer_array_t *array, int new_size)
|
||||
{
|
||||
OPAL_THREAD_LOCK(&(array->lock));
|
||||
if(new_size > array->size) {
|
||||
if (!grow_table(array, new_size, new_size)) {
|
||||
if (!grow_table(array, new_size)) {
|
||||
OPAL_THREAD_UNLOCK(&(array->lock));
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
@ -309,37 +405,45 @@ int opal_pointer_array_set_size(opal_pointer_array_t *array, int new_size)
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static bool grow_table(opal_pointer_array_t *table, int soft, int hard)
|
||||
static bool grow_table(opal_pointer_array_t *table, int at_least)
|
||||
{
|
||||
int new_size;
|
||||
int i, new_size_int;
|
||||
int i, new_size, new_size_int;
|
||||
void *p;
|
||||
|
||||
/* new_size = ((table->size + num_needed + table->block_size - 1) /
|
||||
table->block_size) * table->block_size; */
|
||||
new_size = soft;
|
||||
if( soft > table->max_size ) {
|
||||
if( hard > table->max_size ) {
|
||||
new_size = table->block_size * ((at_least + 1 + table->block_size - 1) / table->block_size);
|
||||
if( new_size >= table->max_size ) {
|
||||
new_size = table->max_size;
|
||||
if( at_least >= table->max_size ) {
|
||||
return false;
|
||||
}
|
||||
new_size = hard;
|
||||
}
|
||||
if( new_size >= table->max_size ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p = (void **) realloc(table->addr, new_size * sizeof(void *));
|
||||
if (p == NULL) {
|
||||
if (NULL == p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
new_size_int = (int) new_size;
|
||||
table->number_free += new_size_int - table->size;
|
||||
table->number_free += (new_size - table->size);
|
||||
table->addr = (void**)p;
|
||||
for (i = table->size; i < new_size_int; ++i) {
|
||||
for (i = table->size; i < new_size; ++i) {
|
||||
table->addr[i] = NULL;
|
||||
}
|
||||
table->size = new_size_int;
|
||||
|
||||
new_size_int = TYPE_ELEM_COUNT(uint64_t, new_size);
|
||||
if( (int)(TYPE_ELEM_COUNT(uint64_t, table->size)) != new_size_int ) {
|
||||
p = (uint64_t*)realloc(table->free_bits, new_size_int * sizeof(uint64_t));
|
||||
if (NULL == p) {
|
||||
return false;
|
||||
}
|
||||
table->free_bits = (uint64_t*)p;
|
||||
for (i = TYPE_ELEM_COUNT(uint64_t, table->size);
|
||||
i < new_size_int; i++ ) {
|
||||
table->free_bits[i] = 0;
|
||||
}
|
||||
}
|
||||
table->size = new_size;
|
||||
#if 0
|
||||
opal_output(0, "grow_table %p to %d (max_size %d, block %d, number_free %d)\n",
|
||||
(void*)table, table->size, table->max_size, table->block_size, table->number_free);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2008 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -58,6 +58,8 @@ struct opal_pointer_array_t {
|
||||
int max_size;
|
||||
/** block size for each allocation */
|
||||
int block_size;
|
||||
/** pointer to an array of bits to speed up the research for an empty position. */
|
||||
uint64_t* free_bits;
|
||||
/** pointer to array of pointers */
|
||||
void **addr;
|
||||
};
|
||||
@ -195,9 +197,12 @@ static inline void opal_pointer_array_remove_all(opal_pointer_array_t *array)
|
||||
OPAL_THREAD_LOCK(&array->lock);
|
||||
array->lowest_free = 0;
|
||||
array->number_free = array->size;
|
||||
for(i=0; i<array->size; i++) {
|
||||
for(i = 0; i < array->size; i++) {
|
||||
array->addr[i] = NULL;
|
||||
}
|
||||
for(i = 0; i < (int)((array->size + 8*sizeof(uint64_t) - 1) / (8*sizeof(uint64_t))); i++) {
|
||||
array->free_bits[i] = 0;
|
||||
}
|
||||
OPAL_THREAD_UNLOCK(&array->lock);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
* University Research and Technology
|
||||
* Corporation. All rights reserved.
|
||||
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
||||
* Copyright (c) 2004-2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
@ -109,11 +109,7 @@ static void test(bool thread_usage){
|
||||
}
|
||||
|
||||
/* test opal_pointer_array_get_item */
|
||||
array->number_free=array->size;
|
||||
array->lowest_free=0;
|
||||
for(i=0 ; i < array->size ; i++ ) {
|
||||
array->addr[i] = NULL;
|
||||
}
|
||||
opal_pointer_array_remove_all(array);
|
||||
error_cnt=0;
|
||||
for(i=0 ; i < array->size ; i++ ) {
|
||||
value.ivalue = i + 2;
|
||||
@ -141,7 +137,35 @@ static void test(bool thread_usage){
|
||||
test_failure(" data check - 2nd ");
|
||||
}
|
||||
|
||||
free (array);
|
||||
OBJ_RELEASE(array);
|
||||
assert(NULL == array);
|
||||
|
||||
array=OBJ_NEW(opal_pointer_array_t);
|
||||
assert(array);
|
||||
opal_pointer_array_init(array, 0, 4, 2);
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
value.ivalue = i + 1;
|
||||
if( 0 > opal_pointer_array_add( array, value.cvalue ) ) {
|
||||
test_failure("Add/Remove: failure during initial data_add ");
|
||||
}
|
||||
}
|
||||
for( i = i-1; i >= 0; i-- ) {
|
||||
if( i % 2 )
|
||||
if( 0 != opal_pointer_array_set_item(array, i, NULL) )
|
||||
test_failure("Add/Remove: failure during item removal ");
|
||||
}
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
if( !opal_pointer_array_add( array, (void*)(uintptr_t)(i+1) ) ) {
|
||||
if( i != 2 ) {
|
||||
test_failure("Add/Remove: failure during the readd ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
opal_pointer_array_remove_all(array);
|
||||
OBJ_RELEASE(array);
|
||||
assert(NULL == array);
|
||||
|
||||
free(test_data);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user