1
1

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>
Этот коммит содержится в:
bosilca 2017-04-18 21:41:26 -04:00 коммит произвёл GitHub
родитель 23dad50d51
Коммит 872cf44c28
16 изменённых файлов: 260 добавлений и 120 удалений

Просмотреть файл

@ -86,15 +86,15 @@ int ompi_comm_init(void)
/* Setup communicator array */ /* Setup communicator array */
OBJ_CONSTRUCT(&ompi_mpi_communicators, opal_pointer_array_t); 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) ) { OMPI_FORTRAN_HANDLE_MAX, 64) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }
/* Setup f to c table (we can no longer use the cid as the fortran handle) */ /* 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); 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, if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_comm_f_to_c_table, 8,
OMPI_FORTRAN_HANDLE_MAX, 64) ) { OMPI_FORTRAN_HANDLE_MAX, 32) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }

Просмотреть файл

@ -29,9 +29,11 @@
static void __ompi_datatype_allocate( ompi_datatype_t* datatype ) static void __ompi_datatype_allocate( ompi_datatype_t* datatype )
{ {
datatype->args = NULL; datatype->args = NULL;
datatype->d_f_to_c_index = opal_pointer_array_add(&ompi_datatype_f_to_c_table, datatype); /* Do not add the newly created datatypes to the f2c translation table. We will add them only
/* Later generated datatypes will have their id according to the Fortran ID, as ALL types are registered */ * if necessary, basically upon the first call the MPI_Datatype_f2c.
datatype->id = datatype->d_f_to_c_index; */
datatype->d_f_to_c_index = -1;
datatype->id = -1;
datatype->d_keyhash = NULL; datatype->d_keyhash = NULL;
datatype->name[0] = '\0'; datatype->name[0] = '\0';
datatype->packed_description = NULL; datatype->packed_description = NULL;
@ -48,8 +50,9 @@ static void __ompi_datatype_release(ompi_datatype_t * datatype)
free( datatype->packed_description ); free( datatype->packed_description );
datatype->packed_description = NULL; 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 ); 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 ? */ /* any pending attributes ? */
if (NULL != datatype->d_keyhash) { 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) \ #define OMPI_DATATYPE_EMPTY_DATA(NAME) \
.id = OMPI_DATATYPE_MPI_ ## NAME, \ .id = OMPI_DATATYPE_MPI_ ## NAME, \
.d_f_to_c_index = 0, \ .d_f_to_c_index = -1, \
.d_keyhash = NULL, \ .d_keyhash = NULL, \
.args = NULL, \ .args = NULL, \
.packed_description = NULL, \ .packed_description = NULL, \

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
@ -457,7 +457,7 @@ int32_t ompi_datatype_init( void )
/* Create the f2c translation table */ /* Create the f2c translation table */
OBJ_CONSTRUCT(&ompi_datatype_f_to_c_table, opal_pointer_array_t); 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, 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; return OMPI_ERROR;
} }
/* All temporary datatypes created on the following statement will get registered /* 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 /* Copy the desc pointer from the <OMPI_DATATYPE_MPI_MAX_PREDEFINED datatypes to
the synonym types */ the synonym types */
/* Start to populate the f2c index translation table */ /* Start to populate the f2c index translation table */
/* The order of the data registration should be the same as the /* The order of the data registration should be the same as the
@ -524,13 +523,13 @@ int32_t ompi_datatype_init( void )
All hail the moog! :-) */ All hail the moog! :-) */
#define MOOG(name, index) \ #define MOOG(name, index) \
{ \ do { \
ompi_mpi_##name.dt.d_f_to_c_index = \ ompi_mpi_##name.dt.d_f_to_c_index = \
opal_pointer_array_add(&ompi_datatype_f_to_c_table, &ompi_mpi_##name); \ 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 ) \ 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; \ 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 * 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 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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 /* Initialize the pointer array, which will hold the references to
the error objects */ the error objects */
OBJ_CONSTRUCT(&ompi_mpi_errcodes, opal_pointer_array_t); OBJ_CONSTRUCT(&ompi_mpi_errcodes, opal_pointer_array_t);
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_errcodes, 0, if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_errcodes, 64,
OMPI_FORTRAN_HANDLE_MAX, 64) ) { OMPI_FORTRAN_HANDLE_MAX, 32) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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 */ /* initialize ompi_errhandler_f_to_c_table */
OBJ_CONSTRUCT( &ompi_errhandler_f_to_c_table, opal_pointer_array_t); 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, if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_errhandler_f_to_c_table, 8,
OMPI_FORTRAN_HANDLE_MAX, 64) ) { OMPI_FORTRAN_HANDLE_MAX, 16) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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); 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, 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; return OMPI_ERROR;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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 */ /* initialize ompi_group_f_to_c_table */
OBJ_CONSTRUCT( &ompi_group_f_to_c_table, opal_pointer_array_t); 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, if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_group_f_to_c_table, 4,
OMPI_FORTRAN_HANDLE_MAX, 64) ) { OMPI_FORTRAN_HANDLE_MAX, 16) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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); 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, 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; return OMPI_ERROR;
} }

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, * 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); 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 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, * 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_null, ompi_request_t);
OBJ_CONSTRUCT(&ompi_request_f_to_c_table, opal_pointer_array_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, 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; return OMPI_ERROR;
} }
ompi_request_null.request.req_type = OMPI_REQUEST_NULL; ompi_request_null.request.req_type = OMPI_REQUEST_NULL;

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, * Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
@ -110,7 +110,7 @@ int main(int argc, char *argv[])
/* setup the mca_types array */ /* setup the mca_types array */
OBJ_CONSTRUCT(&mca_types, opal_pointer_array_t); 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 */ /* add in the opal frameworks */
opal_info_register_types(&mca_types); opal_info_register_types(&mca_types);
@ -124,7 +124,7 @@ int main(int argc, char *argv[])
/* init the component map */ /* init the component map */
OBJ_CONSTRUCT(&component_map, opal_pointer_array_t); 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 */ /* Register OMPI's params */
if (OMPI_SUCCESS != (ret = ompi_info_register_framework_params(&component_map))) { 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 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
@ -79,8 +79,8 @@ ompi_win_init(void)
/* setup window Fortran array */ /* setup window Fortran array */
OBJ_CONSTRUCT(&ompi_mpi_windows, opal_pointer_array_t); OBJ_CONSTRUCT(&ompi_mpi_windows, opal_pointer_array_t);
if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_windows, 0, if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_windows, 4,
OMPI_FORTRAN_HANDLE_MAX, 64) ) { OMPI_FORTRAN_HANDLE_MAX, 16) ) {
return OMPI_ERROR; return OMPI_ERROR;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
@ -27,11 +27,9 @@
#include "opal/class/opal_pointer_array.h" #include "opal/class/opal_pointer_array.h"
#include "opal/util/output.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_construct(opal_pointer_array_t *);
static void opal_pointer_array_destruct(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, OBJ_CLASS_INSTANCE(opal_pointer_array_t, opal_object_t,
opal_pointer_array_construct, opal_pointer_array_construct,
@ -47,8 +45,9 @@ static void opal_pointer_array_construct(opal_pointer_array_t *array)
array->number_free = 0; array->number_free = 0;
array->size = 0; array->size = 0;
array->max_size = INT_MAX; array->max_size = INT_MAX;
array->block_size = 0; array->block_size = 8;
array->addr = 0; array->free_bits = NULL;
array->addr = NULL;
} }
/* /*
@ -57,6 +56,10 @@ static void opal_pointer_array_construct(opal_pointer_array_t *array)
static void opal_pointer_array_destruct(opal_pointer_array_t *array) static void opal_pointer_array_destruct(opal_pointer_array_t *array)
{ {
/* free table */ /* free table */
if( NULL != array->free_bits) {
free(array->free_bits);
array->free_bits = NULL;
}
if( NULL != array->addr ) { if( NULL != array->addr ) {
free(array->addr); free(array->addr);
array->addr = NULL; array->addr = NULL;
@ -67,6 +70,103 @@ static void opal_pointer_array_destruct(opal_pointer_array_t *array)
OBJ_DESTRUCT(&array->lock); 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 * initialize an array object
*/ */
@ -82,18 +182,24 @@ int opal_pointer_array_init(opal_pointer_array_t* array,
} }
array->max_size = max_size; 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); 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 */ /* 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 */ if (NULL == array->addr) { /* out of memory */
return OPAL_ERR_OUT_OF_RESOURCE; 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; 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 opal_pointer_array_add(opal_pointer_array_t *table, void *ptr)
{ {
int i, index; int index = table->size + 1;
OPAL_THREAD_LOCK(&(table->lock)); OPAL_THREAD_LOCK(&(table->lock));
if (table->number_free == 0) { if (table->number_free == 0) {
/* need to grow table */ /* need to grow table */
if (!grow_table(table, if (!grow_table(table, index) ) {
(NULL == table->addr ? TABLE_INIT : table->size * TABLE_GROW),
INT_MAX)) {
OPAL_THREAD_UNLOCK(&(table->lock)); OPAL_THREAD_UNLOCK(&(table->lock));
return OPAL_ERR_OUT_OF_RESOURCE; 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; index = table->lowest_free;
assert(table->addr[index] == NULL); assert(NULL == table->addr[index]);
table->addr[index] = ptr; table->addr[index] = ptr;
table->number_free--; table->number_free--;
SET_BIT(index);
if (table->number_free > 0) { if (table->number_free > 0) {
for (i = table->lowest_free + 1; i < table->size; i++) { FIND_FIRST_ZERO(index, table->lowest_free, 0);
if (table->addr[i] == NULL) { } else {
table->lowest_free = i;
break;
}
}
}
else {
table->lowest_free = table->size; table->lowest_free = table->size;
} }
#if 0
opal_pointer_array_validate(table);
#endif
OPAL_THREAD_UNLOCK(&(table->lock)); OPAL_THREAD_UNLOCK(&(table->lock));
return index; return index;
} }
@ -174,41 +276,37 @@ int opal_pointer_array_set_item(opal_pointer_array_t *table, int index,
OPAL_THREAD_LOCK(&(table->lock)); OPAL_THREAD_LOCK(&(table->lock));
if (table->size <= index) { if (table->size <= index) {
if (!grow_table(table, ((index / TABLE_GROW) + 1) * TABLE_GROW, if (!grow_table(table, index)) {
index)) {
OPAL_THREAD_UNLOCK(&(table->lock)); OPAL_THREAD_UNLOCK(&(table->lock));
return OPAL_ERROR; return OPAL_ERROR;
} }
} }
assert(table->size > index);
/* mark element as free, if NULL element */ /* mark element as free, if NULL element */
if( NULL == value ) { if( NULL == value ) {
if( NULL != table->addr[index] ) {
if (index < table->lowest_free) { if (index < table->lowest_free) {
table->lowest_free = index; table->lowest_free = index;
} }
if( NULL != table->addr[index] ) {
table->number_free++; table->number_free++;
UNSET_BIT(index);
} }
} else { } else {
if (NULL == table->addr[index]) { if (NULL == table->addr[index]) {
table->number_free--; table->number_free--;
} SET_BIT(index);
/* Reset lowest_free if required */ /* Reset lowest_free if required */
if ( index == table->lowest_free ) { if ( index == table->lowest_free ) {
int i; FIND_FIRST_ZERO(index, table->lowest_free, 0);
table->lowest_free = table->size;
for ( i=index + 1; i<table->size; i++) {
if ( NULL == table->addr[i] ){
table->lowest_free = i;
break;
}
} }
} else {
assert( index != table->lowest_free );
} }
} }
table->addr[index] = value; table->addr[index] = value;
#if 0 #if 0
opal_pointer_array_validate(table);
opal_output(0,"opal_pointer_array_set_item: OUT: " opal_output(0,"opal_pointer_array_set_item: OUT: "
" table %p (size %ld, lowest free %ld, number free %ld)" " table %p (size %ld, lowest free %ld, number free %ld)"
" addr[%d] = %p\n", " 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? */ /* Do we need to grow the table? */
if (table->size <= index) { if (table->size <= index) {
if (!grow_table(table, (((index / TABLE_GROW) + 1) * TABLE_GROW), if (!grow_table(table, index)) {
index)) {
OPAL_THREAD_UNLOCK(&(table->lock)); OPAL_THREAD_UNLOCK(&(table->lock));
return false; 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. * allow a specific index to be changed.
*/ */
assert(NULL == table->addr[index]);
table->addr[index] = value; table->addr[index] = value;
table->number_free--; table->number_free--;
SET_BIT(index);
/* Reset lowest_free if required */ /* Reset lowest_free if required */
if( table->number_free > 0 ) {
if ( index == table->lowest_free ) { if ( index == table->lowest_free ) {
int i; FIND_FIRST_ZERO(index, table->lowest_free, 0);
}
} else {
table->lowest_free = table->size; table->lowest_free = table->size;
for ( i=index; i<table->size; i++) {
if ( NULL == table->addr[i] ){
table->lowest_free = i;
break;
}
}
} }
#if 0 #if 0
opal_pointer_array_validate(table);
opal_output(0,"opal_pointer_array_test_and_set_item: OUT: " opal_output(0,"opal_pointer_array_test_and_set_item: OUT: "
" table %p (size %ld, lowest free %ld, number free %ld)" " table %p (size %ld, lowest free %ld, number free %ld)"
" addr[%d] = %p\n", " 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)); OPAL_THREAD_LOCK(&(array->lock));
if(new_size > array->size) { if(new_size > array->size) {
if (!grow_table(array, new_size, new_size)) { if (!grow_table(array, new_size)) {
OPAL_THREAD_UNLOCK(&(array->lock)); OPAL_THREAD_UNLOCK(&(array->lock));
return OPAL_ERROR; return OPAL_ERROR;
} }
@ -309,37 +405,45 @@ int opal_pointer_array_set_size(opal_pointer_array_t *array, int new_size)
return OPAL_SUCCESS; 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, new_size_int;
int i, new_size_int;
void *p; void *p;
/* new_size = ((table->size + num_needed + table->block_size - 1) / new_size = table->block_size * ((at_least + 1 + table->block_size - 1) / table->block_size);
table->block_size) * table->block_size; */
new_size = soft;
if( soft > table->max_size ) {
if( hard > table->max_size ) {
return false;
}
new_size = hard;
}
if( new_size >= table->max_size ) { if( new_size >= table->max_size ) {
new_size = table->max_size;
if( at_least >= table->max_size ) {
return false; return false;
} }
}
p = (void **) realloc(table->addr, new_size * sizeof(void *)); p = (void **) realloc(table->addr, new_size * sizeof(void *));
if (p == NULL) { if (NULL == p) {
return false; return false;
} }
new_size_int = (int) new_size; table->number_free += (new_size - table->size);
table->number_free += new_size_int - table->size;
table->addr = (void**)p; 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->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; return true;
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
@ -58,6 +58,8 @@ struct opal_pointer_array_t {
int max_size; int max_size;
/** block size for each allocation */ /** block size for each allocation */
int block_size; 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 */ /** pointer to array of pointers */
void **addr; void **addr;
}; };
@ -198,6 +200,9 @@ static inline void opal_pointer_array_remove_all(opal_pointer_array_t *array)
for(i = 0; i < array->size; i++) { for(i = 0; i < array->size; i++) {
array->addr[i] = NULL; 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); OPAL_THREAD_UNLOCK(&array->lock);
} }

Просмотреть файл

@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology * University Research and Technology
* Corporation. All rights reserved. * 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 * of Tennessee Research Foundation. All rights
* reserved. * reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * 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 */ /* test opal_pointer_array_get_item */
array->number_free=array->size; opal_pointer_array_remove_all(array);
array->lowest_free=0;
for(i=0 ; i < array->size ; i++ ) {
array->addr[i] = NULL;
}
error_cnt=0; error_cnt=0;
for(i=0 ; i < array->size ; i++ ) { for(i=0 ; i < array->size ; i++ ) {
value.ivalue = i + 2; value.ivalue = i + 2;
@ -141,7 +137,35 @@ static void test(bool thread_usage){
test_failure(" data check - 2nd "); 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); free(test_data);
} }