Skip to content

Commit 73d64cb

Browse files
committed
Reenable the heterogeneous support.
This commit fixes the support for heterogeneous environments and specifically for external32. The root cause was that during the datatype optimization process types that are contiguous in memory are collapsed together in order to decrease the number of conversion (or memcpy) function calls. The resulting type however, does not have the same conversion rules as the types it replaced, leading to an incorrect (or absent) conversion in some cases. This patch marks the datatypes where types have been collapsed during the optimization process with a flag, allowing the convertor to detect if the optimized type can be used in heterogeneous setups. Signed-off-by: George Bosilca <[email protected]>
1 parent c747a1b commit 73d64cb

7 files changed

+220
-53
lines changed

opal/datatype/opal_convertor.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,8 @@ size_t opal_convertor_compute_remote_size(opal_convertor_t *pConvertor)
484484
pConvertor->remote_size = pConvertor->local_size;
485485
if (OPAL_UNLIKELY(datatype->bdt_used & pConvertor->master->hetero_mask)) {
486486
pConvertor->flags &= (~CONVERTOR_HOMOGENEOUS);
487-
if (!(pConvertor->flags & CONVERTOR_SEND
488-
&& pConvertor->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS)) {
487+
/* Can we use the optimized description? */
488+
if (pConvertor->flags & OPAL_DATATYPE_OPTIMIZED_RESTRICTED) {
489489
pConvertor->use_desc = &(datatype->desc);
490490
}
491491
if (0 == (pConvertor->flags & CONVERTOR_HAS_REMOTE_SIZE)) {

opal/datatype/opal_datatype.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ BEGIN_C_DECLS
8484
#define OPAL_DATATYPE_FLAG_BASIC \
8585
(OPAL_DATATYPE_FLAG_PREDEFINED | OPAL_DATATYPE_FLAG_CONTIGUOUS | OPAL_DATATYPE_FLAG_NO_GAPS \
8686
| OPAL_DATATYPE_FLAG_DATA | OPAL_DATATYPE_FLAG_COMMITTED)
87+
/*
88+
* If during the datatype optimization process we collapse contiguous elements with
89+
* different types, we cannot use this optimized description for any communication
90+
* in a heterogeneous setting, especially not for the exteranl32 support.
91+
*
92+
* A datatype with this flag cannot use the optimized description in heterogeneous
93+
* setups.
94+
*/
95+
#define OPAL_DATATYPE_OPTIMIZED_RESTRICTED 0x1000
8796

8897
/**
8998
* The number of supported entries in the data-type definition and the

opal/datatype/opal_datatype_dump.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ int opal_datatype_dump_data_flags(unsigned short usflags, char *ptr, size_t leng
9999
}
100100
if ((usflags & OPAL_DATATYPE_FLAG_BASIC) == OPAL_DATATYPE_FLAG_BASIC) {
101101
ptr[9] = 'B';
102+
} else if (usflags & OPAL_DATATYPE_OPTIMIZED_RESTRICTED) {
103+
ptr[9] = 'H'; /* optimized description restricted to homogeneous cases */
102104
}
103105
/* We know nothing about the upper level language or flags! */
104106
/* ... */

opal/datatype/opal_datatype_optimize.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ static int32_t opal_datatype_optimize_short(opal_datatype_t *pData, size_t count
9494
assert(1 == current->count);
9595
if ((current->common.type == OPAL_DATATYPE_LOOP)
9696
|| compress.common.type != current->common.type) {
97-
compress.common.type = OPAL_DATATYPE_UINT1;
97+
compress.common.type = OPAL_DATATYPE_UINT1;
98+
compress.common.flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
99+
pData->flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
98100
compress.blocklen = end_loop->size;
99101
break;
100102
}
@@ -194,7 +196,9 @@ static int32_t opal_datatype_optimize_short(opal_datatype_t *pData, size_t count
194196
ddt_elem_desc_t save = last; /* safekeep the type and blocklen */
195197
if (last.common.type != current->common.type) {
196198
last.blocklen *= opal_datatype_basicDatatypes[last.common.type]->size;
197-
last.common.type = OPAL_DATATYPE_UINT1;
199+
last.common.type = OPAL_DATATYPE_UINT1;
200+
last.common.flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
201+
pData->flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
198202
}
199203

200204
if ((last.extent * (ptrdiff_t) last.count + last.disp) == current->disp) {
@@ -248,7 +252,9 @@ static int32_t opal_datatype_optimize_short(opal_datatype_t *pData, size_t count
248252
+ (current->blocklen
249253
* opal_datatype_basicDatatypes[current->common.type]
250254
->size));
251-
last.common.type = OPAL_DATATYPE_UINT1;
255+
last.common.type = OPAL_DATATYPE_UINT1;
256+
last.common.flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
257+
pData->flags |= OPAL_DATATYPE_OPTIMIZED_RESTRICTED;
252258
}
253259
last.extent += current->extent;
254260
if (current->count != 1) {

opal/datatype/opal_datatype_pack.c

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -402,43 +402,84 @@ int32_t opal_generic_simple_pack_function(opal_convertor_t *pConvertor, struct i
402402
* -1 something wrong occurs.
403403
*/
404404

405-
static inline void pack_predefined_heterogeneous(opal_convertor_t *CONVERTOR,
406-
const dt_elem_desc_t *ELEM, size_t *COUNT,
407-
unsigned char **SOURCE,
408-
unsigned char **DESTINATION, size_t *SPACE)
405+
static inline void
406+
pack_predefined_heterogeneous(opal_convertor_t *CONVERTOR,
407+
const dt_elem_desc_t *ELEM, size_t *COUNT,
408+
unsigned char **memory,
409+
unsigned char **packed, size_t *SPACE)
409410
{
410411
const opal_convertor_master_t *master = (CONVERTOR)->master;
411412
const ddt_elem_desc_t *_elem = &((ELEM)->elem);
412-
unsigned char *_source = (*SOURCE) + _elem->disp;
413-
ptrdiff_t advance;
414-
size_t _count = *(COUNT);
415-
size_t _r_blength;
416-
417-
_r_blength = master->remote_sizes[_elem->common.type];
418-
if ((_count * _r_blength) > *(SPACE)) {
419-
_count = (*(SPACE) / _r_blength);
420-
if (0 == _count) {
421-
return; /* nothing to do */
422-
}
413+
size_t cando_count = *(COUNT), do_now_bytes;
414+
size_t local_elem_size = opal_datatype_basicDatatypes[_elem->common.type]->size;
415+
size_t remote_elem_size = master->remote_sizes[_elem->common.type];
416+
size_t blocklen_bytes = remote_elem_size;
417+
unsigned char *_memory = (*memory) + _elem->disp;
418+
unsigned char *_packed = *packed;
419+
ptrdiff_t advance = 0;
420+
421+
assert(0 == (cando_count % _elem->blocklen)); /* no partials here */
422+
assert(*(COUNT) <= ((size_t) _elem->count * _elem->blocklen));
423+
424+
if ((remote_elem_size * cando_count) > *(SPACE))
425+
cando_count = (*SPACE) / blocklen_bytes;
426+
427+
/* premptively update the number of COUNT we will return. */
428+
*(COUNT) -= cando_count;
429+
430+
if (_elem->blocklen == 1) {
431+
master->pFunctions[_elem->common.type](CONVERTOR, cando_count,
432+
_memory, *SPACE, _elem->extent,
433+
_packed, *SPACE, remote_elem_size,
434+
&advance);
435+
_memory += cando_count * _elem->extent;
436+
_packed += cando_count * remote_elem_size;
437+
goto update_and_return;
438+
}
439+
440+
if ((1 < _elem->count) && (_elem->blocklen <= cando_count)) {
441+
blocklen_bytes = remote_elem_size * _elem->blocklen;
442+
443+
do { /* Do as many full blocklen as possible */
444+
OPAL_DATATYPE_SAFEGUARD_POINTER(_memory, blocklen_bytes, (CONVERTOR)->pBaseBuf,
445+
(CONVERTOR)->pDesc, (CONVERTOR)->count);
446+
DO_DEBUG(opal_output(0, "pack 2. memcpy( %p, %p, %lu ) => space %lu\n",
447+
(void *) _packed, (void *) _memory, (unsigned long) blocklen_bytes,
448+
(unsigned long) (*(SPACE) - (_packed - *(packed)))););
449+
master->pFunctions[_elem->common.type](CONVERTOR, _elem->blocklen,
450+
_memory, *SPACE, local_elem_size,
451+
_packed, *SPACE, remote_elem_size,
452+
&advance);
453+
_packed += blocklen_bytes;
454+
_memory += _elem->extent;
455+
cando_count -= _elem->blocklen;
456+
} while (_elem->blocklen <= cando_count);
457+
}
458+
459+
/**
460+
* As an epilog do anything left from the last blocklen.
461+
*/
462+
if (0 != cando_count) {
463+
assert((cando_count < _elem->blocklen)
464+
|| ((1 == _elem->count) && (cando_count <= _elem->blocklen)));
465+
do_now_bytes = cando_count * remote_elem_size;
466+
OPAL_DATATYPE_SAFEGUARD_POINTER(_memory, do_now_bytes, (CONVERTOR)->pBaseBuf,
467+
(CONVERTOR)->pDesc, (CONVERTOR)->count);
468+
DO_DEBUG(opal_output(0, "pack 3. memcpy( %p, %p, %lu ) => space %lu [epilog]\n",
469+
(void *) _packed, (void *) _memory, (unsigned long) do_now_bytes,
470+
(unsigned long) (*(SPACE) - (_packed - *(packed)))););
471+
master->pFunctions[_elem->common.type](CONVERTOR, cando_count,
472+
_memory, *SPACE, local_elem_size,
473+
_packed, *SPACE, remote_elem_size,
474+
&advance);
475+
_memory += do_now_bytes;
476+
_packed += do_now_bytes;
423477
}
424478

425-
OPAL_DATATYPE_SAFEGUARD_POINTER(_source, (_count * _elem->extent), (CONVERTOR)->pBaseBuf,
426-
(CONVERTOR)->pDesc, (CONVERTOR)->count);
427-
DO_DEBUG(opal_output(0, "pack [l %s r %s] memcpy( %p, %p, %lu ) => space %lu\n",
428-
((ptrdiff_t)(opal_datatype_basicDatatypes[_elem->common.type]->size)
429-
== _elem->extent)
430-
? "cont"
431-
: "----",
432-
((ptrdiff_t) _r_blength == _elem->extent) ? "cont" : "----",
433-
(void *) *(DESTINATION), (void *) _source, (unsigned long) _r_blength,
434-
(unsigned long) (*(SPACE))););
435-
master->pFunctions[_elem->common.type](CONVERTOR, _count, _source, *SPACE, _elem->extent,
436-
*DESTINATION, *SPACE, _r_blength, &advance);
437-
_r_blength *= _count; /* update the remote length to encompass all the elements */
438-
*(SOURCE) += _count * _elem->extent;
439-
*(DESTINATION) += _r_blength;
440-
*(SPACE) -= _r_blength;
441-
*(COUNT) -= _count;
479+
update_and_return:
480+
*(memory) = _memory - _elem->disp;
481+
*(SPACE) -= (_packed - *packed);
482+
*(packed) = _packed;
442483
}
443484

444485
int32_t opal_pack_general_function(opal_convertor_t *pConvertor, struct iovec *iov,

opal/datatype/opal_datatype_unpack.c

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,86 @@ int32_t opal_generic_simple_unpack_function(opal_convertor_t *pConvertor, struct
449449
* 1 if everything went fine and the data was completly converted
450450
* -1 something wrong occurs.
451451
*/
452+
static inline void
453+
unpack_predefined_heterogeneous(opal_convertor_t *CONVERTOR,
454+
const dt_elem_desc_t *ELEM, size_t *COUNT,
455+
unsigned char **memory,
456+
unsigned char **packed, size_t *SPACE)
457+
{
458+
const opal_convertor_master_t *master = (CONVERTOR)->master;
459+
const ddt_elem_desc_t *_elem = &((ELEM)->elem);
460+
size_t cando_count = *(COUNT), do_now_bytes;
461+
size_t local_elem_size = opal_datatype_basicDatatypes[_elem->common.type]->size;
462+
size_t remote_elem_size = master->remote_sizes[_elem->common.type];
463+
size_t blocklen_bytes = remote_elem_size;
464+
unsigned char *_memory = (*memory) + _elem->disp;
465+
unsigned char *_packed = *packed;
466+
ptrdiff_t advance = 0;
467+
468+
assert(0 == (cando_count % _elem->blocklen)); /* no partials here */
469+
assert(*(COUNT) <= ((size_t) _elem->count * _elem->blocklen));
470+
471+
if ((remote_elem_size * cando_count) > *(SPACE))
472+
cando_count = (*SPACE) / blocklen_bytes;
473+
474+
/* premptively update the number of COUNT we will return. */
475+
*(COUNT) -= cando_count;
476+
477+
if (_elem->blocklen == 1) {
478+
master->pFunctions[_elem->common.type](CONVERTOR, cando_count,
479+
_packed, *SPACE, remote_elem_size,
480+
_memory, *SPACE, _elem->extent,
481+
&advance);
482+
_memory += cando_count * _elem->extent;
483+
_packed += cando_count * local_elem_size;
484+
goto update_and_return;
485+
}
486+
487+
if ((1 < _elem->count) && (_elem->blocklen <= cando_count)) {
488+
blocklen_bytes = remote_elem_size * _elem->blocklen;
489+
490+
do { /* Do as many full blocklen as possible */
491+
OPAL_DATATYPE_SAFEGUARD_POINTER(_memory, blocklen_bytes, (CONVERTOR)->pBaseBuf,
492+
(CONVERTOR)->pDesc, (CONVERTOR)->count);
493+
DO_DEBUG(opal_output(0, "pack 2. memcpy( %p, %p, %lu ) => space %lu\n",
494+
(void *) _packed, (void *) _memory, (unsigned long) blocklen_bytes,
495+
(unsigned long) (*(SPACE) - (_packed - *(packed)))););
496+
master->pFunctions[_elem->common.type](CONVERTOR, _elem->blocklen,
497+
_packed, *SPACE, remote_elem_size,
498+
_memory, *SPACE, local_elem_size,
499+
&advance);
500+
_packed += blocklen_bytes;
501+
_memory += _elem->extent;
502+
cando_count -= _elem->blocklen;
503+
} while (_elem->blocklen <= cando_count);
504+
}
505+
506+
/**
507+
* As an epilog do anything left from the last blocklen.
508+
*/
509+
if (0 != cando_count) {
510+
assert((cando_count < _elem->blocklen)
511+
|| ((1 == _elem->count) && (cando_count <= _elem->blocklen)));
512+
do_now_bytes = cando_count * remote_elem_size;
513+
OPAL_DATATYPE_SAFEGUARD_POINTER(_memory, do_now_bytes, (CONVERTOR)->pBaseBuf,
514+
(CONVERTOR)->pDesc, (CONVERTOR)->count);
515+
DO_DEBUG(opal_output(0, "pack 3. memcpy( %p, %p, %lu ) => space %lu [epilog]\n",
516+
(void *) _packed, (void *) _memory, (unsigned long) do_now_bytes,
517+
(unsigned long) (*(SPACE) - (_packed - *(packed)))););
518+
master->pFunctions[_elem->common.type](CONVERTOR, cando_count,
519+
_packed, *SPACE, remote_elem_size,
520+
_memory, *SPACE, local_elem_size,
521+
&advance);
522+
_memory += do_now_bytes;
523+
_packed += do_now_bytes;
524+
}
525+
526+
update_and_return:
527+
*(memory) = _memory - _elem->disp;
528+
*(SPACE) -= (_packed - *packed);
529+
*(packed) = _packed;
530+
}
531+
452532
int32_t opal_unpack_general_function(opal_convertor_t *pConvertor, struct iovec *iov,
453533
uint32_t *out_size, size_t *max_data)
454534
{
@@ -463,9 +543,10 @@ int32_t opal_unpack_general_function(opal_convertor_t *pConvertor, struct iovec
463543
unsigned char *conv_ptr, *iov_ptr;
464544
uint32_t iov_count;
465545
size_t iov_len_local;
466-
546+
#if 0
467547
const opal_convertor_master_t *master = pConvertor->master;
468548
ptrdiff_t advance; /* number of bytes that we should advance the buffer */
549+
#endif
469550
size_t rc;
470551

471552
DO_DEBUG(opal_output(0, "opal_convertor_general_unpack( %p, {%p, %lu}, %d )\n",
@@ -509,6 +590,9 @@ int32_t opal_unpack_general_function(opal_convertor_t *pConvertor, struct iovec
509590
conv_ptr + pElem->elem.disp - pConvertor->pBaseBuf, count_desc,
510591
description[pos_desc].elem.extent,
511592
opal_datatype_basicDatatypes[type]->name););
593+
unpack_predefined_heterogeneous(pConvertor, pElem, &count_desc, &conv_ptr, &iov_ptr,
594+
&iov_len_local);
595+
#if 0
512596
rc = master->pFunctions[type](pConvertor, count_desc, iov_ptr, iov_len_local,
513597
opal_datatype_basicDatatypes[type]->size,
514598
conv_ptr + pElem->elem.disp,
@@ -518,6 +602,7 @@ int32_t opal_unpack_general_function(opal_convertor_t *pConvertor, struct iovec
518602
iov_len_local -= advance; /* decrease the available space in the buffer */
519603
iov_ptr += advance; /* increase the pointer to the buffer */
520604
count_desc -= rc; /* compute leftovers */
605+
#endif
521606
if (0 == count_desc) { /* completed */
522607
conv_ptr = pConvertor->pBaseBuf + pStack->disp;
523608
pos_desc++; /* advance to the next data */
@@ -527,16 +612,17 @@ int32_t opal_unpack_general_function(opal_convertor_t *pConvertor, struct iovec
527612
}
528613
continue;
529614
}
615+
#if 0
530616
conv_ptr += rc * description[pos_desc].elem.extent;
617+
#endif
531618
assert(pElem->elem.common.type < OPAL_DATATYPE_MAX_PREDEFINED);
532619
assert(0 == iov_len_local);
533620
if (0 != iov_len_local) {
534621
unsigned char *temp = conv_ptr;
535622
/* We have some partial data here. Let's copy it into the convertor
536623
* and keep it hot until the next round.
537624
*/
538-
assert(iov_len_local
539-
< opal_datatype_basicDatatypes[pElem->elem.common.type]->size);
625+
assert(iov_len_local < opal_datatype_basicDatatypes[pElem->elem.common.type]->size);
540626
COMPUTE_CSUM(iov_ptr, iov_len_local, pConvertor);
541627

542628
opal_unpack_partial_datatype(pConvertor, pElem, iov_ptr, 0, iov_len_local,

0 commit comments

Comments
 (0)