1
1

ALLOC_WITH_HINT: added implace realloc

- in some cases realloc operation may be completed without
  allocation of new buffer (and without additional data copy)
- added logic to reallocate buffer inplace if possible

Signed-off-by: Sergey Oblomov <sergeyo@mellanox.com>
Этот коммит содержится в:
Sergey Oblomov 2019-05-15 19:33:36 +03:00
родитель fe5ad67127
Коммит 277c2a9e5c
4 изменённых файлов: 88 добавлений и 12 удалений

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

@ -551,7 +551,8 @@ static int mca_spml_ucx_ctx_create_common(long options, mca_spml_ucx_ctx_t **ucx
{
ucp_worker_params_t params;
ucp_ep_params_t ep_params;
size_t i, j, nprocs = oshmem_num_procs();
size_t i, nprocs = oshmem_num_procs();
int j;
ucs_status_t err;
spml_ucx_mkey_t *ucx_mkey;
sshmem_mkey_t *mkey;

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

@ -49,10 +49,19 @@ sshmem_ucx_shadow_allocator_t *sshmem_ucx_shadow_create(unsigned count);
void sshmem_ucx_shadow_destroy(sshmem_ucx_shadow_allocator_t *allocator);
int sshmem_ucx_shadow_alloc(sshmem_ucx_shadow_allocator_t *allocator,
unsigned count, unsigned *index);
/* reallocate existing allocated buffer. if possible - used inplace
* reallocation.
* parameter 'inplace' - out, in case if zero - new buffer was allocated
* (inplace is not possible), user should remove original buffer after data
* is copied, else (if inplace == 0) - no additional action required */
int sshmem_ucx_shadow_realloc(sshmem_ucx_shadow_allocator_t *allocator,
unsigned count, unsigned old_index, unsigned *index,
int *inplace);
int sshmem_ucx_shadow_free(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index);
size_t sshmem_ucx_shadow_size(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index);
unsigned sshmem_ucx_shadow_size(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index);
END_C_DECLS

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

@ -190,7 +190,6 @@ static uct_ib_device_mem_h alloc_device_mem(mca_spml_ucx_t *spml, size_t size,
uct_md_h uct_md;
void *address;
size_t length;
int ret;
uct_md = ucp_context_find_tl_md(spml->ucp_context, "mlx5");
if (uct_md == NULL) {
@ -354,8 +353,9 @@ static int sshmem_ucx_memheap_realloc(map_segment_t *s, size_t size,
void* old_ptr, void** new_ptr)
{
mca_sshmem_ucx_segment_context_t *ctx = s->context;
unsigned alloc_count, index;
unsigned alloc_count, index, old_index, old_alloc_count;
int res;
int inplace;
if (size > s->seg_size) {
return OSHMEM_ERR_OUT_OF_RESOURCE;
@ -372,7 +372,15 @@ static int sshmem_ucx_memheap_realloc(map_segment_t *s, size_t size,
/* Allocate new element. Zero-size allocation should still return a unique
* pointer, so allocate 1 byte */
alloc_count = max((size + ALLOC_ELEM_SIZE - 1) / ALLOC_ELEM_SIZE, 1);
res = sshmem_ucx_shadow_alloc(ctx->shadow_allocator, alloc_count, &index);
if (!old_ptr) {
res = sshmem_ucx_shadow_alloc(ctx->shadow_allocator, alloc_count, &index);
} else {
old_index = sshmem_ucx_memheap_ptr2index(s, old_ptr);
res = sshmem_ucx_shadow_realloc(ctx->shadow_allocator, alloc_count,
old_index, &index, &inplace);
}
if (res != OSHMEM_SUCCESS) {
return res;
}
@ -380,10 +388,8 @@ static int sshmem_ucx_memheap_realloc(map_segment_t *s, size_t size,
*new_ptr = sshmem_ucx_memheap_index2ptr(s, index);
/* Copy to new segment and release old*/
if (old_ptr) {
unsigned old_index = sshmem_ucx_memheap_ptr2index(s, old_ptr);
unsigned old_alloc_count = sshmem_ucx_shadow_size(ctx->shadow_allocator,
old_index);
if (old_ptr && !inplace) {
old_alloc_count = sshmem_ucx_shadow_size(ctx->shadow_allocator, old_index);
sshmem_ucx_memheap_wordcopy(*new_ptr, old_ptr,
min(size, old_alloc_count * ALLOC_ELEM_SIZE));
sshmem_ucx_shadow_free(ctx->shadow_allocator, old_index);

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

@ -107,6 +107,66 @@ static void sshmem_ucx_shadow_merge_blocks(sshmem_ucx_shadow_allocator_t *alloca
}
}
int sshmem_ucx_shadow_realloc(sshmem_ucx_shadow_allocator_t *allocator,
unsigned count, unsigned old_index, unsigned *index,
int *inplace)
{
sshmem_ucx_shadow_alloc_elem_t *end = &allocator->elems[allocator->num_elems];
sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[old_index];
sshmem_ucx_shadow_alloc_elem_t *next = &elem[elem->block_size];
unsigned old_count = elem->block_size;
assert(count > 0);
assert(!sshmem_ucx_shadow_is_free(elem));
*inplace = 1;
if (count == old_count) {
*index = old_index;
return OSHMEM_SUCCESS;
}
if (count < elem->block_size) {
/* requested block is shorter than allocated block
* then just cut current buffer */
sshmem_ucx_shadow_set_elem(elem + count,
SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE,
elem->block_size - count);
elem->block_size = count;
*index = old_index;
sshmem_ucx_shadow_merge_blocks(allocator);
return OSHMEM_SUCCESS;
}
assert(count > old_count);
/* try to check if next element is free & has enough length */
if ((next < end) && /* non-last element? */
sshmem_ucx_shadow_is_free(next) && /* next is free */
(old_count + next->block_size >= count))
{
assert(elem < next);
assert(elem + count > next);
assert(elem + count <= end);
assert(next + next->block_size <= end);
if (old_count + next->block_size > count) {
sshmem_ucx_shadow_set_elem(elem + count, SSHMEM_UCX_SHADOW_ELEM_FLAG_FREE,
old_count + next->block_size - count);
}
sshmem_ucx_shadow_set_elem(next, 0, 0);
elem->block_size = count;
*index = old_index;
return OSHMEM_SUCCESS;
}
*inplace = 0;
return sshmem_ucx_shadow_alloc(allocator, count, index);
}
int sshmem_ucx_shadow_free(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index)
{
@ -117,8 +177,8 @@ int sshmem_ucx_shadow_free(sshmem_ucx_shadow_allocator_t *allocator,
return OSHMEM_SUCCESS;
}
size_t sshmem_ucx_shadow_size(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index)
unsigned sshmem_ucx_shadow_size(sshmem_ucx_shadow_allocator_t *allocator,
unsigned index)
{
sshmem_ucx_shadow_alloc_elem_t *elem = &allocator->elems[index];