root/opal/datatype/opal_datatype_optimize.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_datatype_optimize_short
  2. opal_datatype_commit

   1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
   2 /*
   3  * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2017 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2006 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2009      Oak Ridge National Labs.  All rights reserved.
  14  * Copyright (c) 2014      Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2015-2018 Research Organization for Information Science
  16  *                         and Technology (RIST).  All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "opal_config.h"
  25 
  26 #include <stddef.h>
  27 #include <stdlib.h>
  28 
  29 #include "opal/datatype/opal_datatype.h"
  30 #include "opal/datatype/opal_convertor.h"
  31 #include "opal/datatype/opal_datatype_internal.h"
  32 
  33 #define SET_EMPTY_ELEMENT( ELEM )                 \
  34     do {                                          \
  35         ddt_elem_desc_t* _elem = (ELEM);          \
  36         _elem->common.flags = OPAL_DATATYPE_FLAG_BASIC;      \
  37         _elem->common.type  = OPAL_DATATYPE_LOOP; \
  38         _elem->count        = 0;                  \
  39         _elem->disp         = 0;                  \
  40         _elem->extent       = 0;                  \
  41     } while (0)
  42 
  43 static int32_t
  44 opal_datatype_optimize_short( opal_datatype_t* pData,
  45                               size_t count,
  46                               dt_type_desc_t* pTypeDesc )
  47 {
  48     dt_elem_desc_t* pElemDesc;
  49     ddt_elem_desc_t opt_elem;
  50     dt_stack_t* pOrigStack;
  51     dt_stack_t* pStack;            /* pointer to the position on the stack */
  52     int32_t pos_desc = 0;          /* actual position in the description of the derived datatype */
  53     int32_t stack_pos = 0, last_type = OPAL_DATATYPE_UINT1;
  54     int32_t type = OPAL_DATATYPE_LOOP, nbElems = 0, continuity;
  55     ptrdiff_t total_disp = 0, last_extent = 1, last_disp = 0;
  56     uint16_t last_flags = 0xFFFF;  /* keep all for the first datatype */
  57     uint32_t i;
  58     size_t last_length = 0;
  59 
  60     pOrigStack = pStack = (dt_stack_t*)malloc( sizeof(dt_stack_t) * (pData->loops+2) );
  61     SAVE_STACK( pStack, -1, 0, count, 0 );
  62 
  63     pTypeDesc->length = 2 * pData->desc.used + 1 /* for the fake OPAL_DATATYPE_END_LOOP at the end */;
  64     pTypeDesc->desc = pElemDesc = (dt_elem_desc_t*)malloc( sizeof(dt_elem_desc_t) * pTypeDesc->length );
  65     pTypeDesc->used = 0;
  66 
  67     SET_EMPTY_ELEMENT( &opt_elem );
  68     assert( OPAL_DATATYPE_END_LOOP == pData->desc.desc[pData->desc.used].elem.common.type );
  69     opt_elem.common.type = OPAL_DATATYPE_LOOP;
  70     opt_elem.common.flags = 0xFFFF;  /* keep all for the first datatype */
  71     opt_elem.count = 0;
  72     opt_elem.disp = pData->desc.desc[pData->desc.used].end_loop.first_elem_disp;
  73     opt_elem.extent = 0;
  74 
  75     while( stack_pos >= 0 ) {
  76         if( OPAL_DATATYPE_END_LOOP == pData->desc.desc[pos_desc].elem.common.type ) { /* end of the current loop */
  77             ddt_endloop_desc_t* end_loop = &(pData->desc.desc[pos_desc].end_loop);
  78             if( last_length != 0 ) {
  79                 CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC, last_length, last_disp, last_extent );
  80                 pElemDesc++; nbElems++;
  81                 last_disp += last_length;
  82                 last_length = 0;
  83             }
  84             CREATE_LOOP_END( pElemDesc, nbElems - pStack->index + 1,  /* # of elems in this loop */
  85                              end_loop->first_elem_disp, end_loop->size, end_loop->common.flags );
  86             pElemDesc++; nbElems++;
  87             if( --stack_pos >= 0 ) {  /* still something to do ? */
  88                 ddt_loop_desc_t* pStartLoop = &(pTypeDesc->desc[pStack->index - 1].loop);
  89                 pStartLoop->items = end_loop->items;
  90                 total_disp = pStack->disp;  /* update the displacement position */
  91             }
  92             pStack--;  /* go down one position on the stack */
  93             pos_desc++;
  94             continue;
  95         }
  96         if( OPAL_DATATYPE_LOOP == pData->desc.desc[pos_desc].elem.common.type ) {
  97             ddt_loop_desc_t* loop = (ddt_loop_desc_t*)&(pData->desc.desc[pos_desc]);
  98             ddt_endloop_desc_t* end_loop = (ddt_endloop_desc_t*)&(pData->desc.desc[pos_desc + loop->items]);
  99             int index = GET_FIRST_NON_LOOP( &(pData->desc.desc[pos_desc]) );
 100             ptrdiff_t loop_disp = pData->desc.desc[pos_desc + index].elem.disp;
 101 
 102             continuity = ((last_disp + (ptrdiff_t)last_length * (ptrdiff_t)opal_datatype_basicDatatypes[last_type]->size)
 103                           == (total_disp + loop_disp));
 104             if( loop->common.flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) {
 105                 /* the loop is contiguous or composed by contiguous elements with a gap */
 106                 if( loop->extent == (ptrdiff_t)end_loop->size ) {
 107                     /* the whole loop is contiguous */
 108                     if( !continuity ) {
 109                         if( 0 != last_length ) {
 110                             CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC,
 111                                          last_length, last_disp, last_extent );
 112                             pElemDesc++; nbElems++;
 113                             last_length = 0;
 114                         }
 115                         last_disp = total_disp + loop_disp;
 116                     }
 117                     last_length = (last_length * opal_datatype_basicDatatypes[last_type]->size
 118                                    + loop->loops * end_loop->size);
 119                     last_type   = OPAL_DATATYPE_UINT1;
 120                     last_extent = 1;
 121                 } else {
 122                     int counter = loop->loops;
 123                     ptrdiff_t merged_disp = 0;
 124                     /* if the previous data is contiguous with this piece and it has a length not ZERO */
 125                     if( last_length != 0 ) {
 126                         if( continuity ) {
 127                             last_length *= opal_datatype_basicDatatypes[last_type]->size;
 128                             last_length += end_loop->size;
 129                             last_type    = OPAL_DATATYPE_UINT1;
 130                             last_extent  = 1;
 131                             counter--;
 132                             merged_disp = loop->extent;  /* merged loop, update the disp of the remaining elems */
 133                         }
 134                         CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC,
 135                                      last_length, last_disp, last_extent );
 136                         pElemDesc++; nbElems++;
 137                         last_disp += last_length;
 138                         last_length = 0;
 139                         last_type = OPAL_DATATYPE_LOOP;
 140                     }
 141                     /**
 142                      * The content of the loop is contiguous (maybe with a gap before or after).
 143                      *
 144                      * If any of the loops have been merged with the previous element, then the
 145                      * displacement of the first element (or the displacement of all elements if the
 146                      * loop will be removed) must be updated accordingly.
 147                      */
 148                     if( counter <= 2 ) {
 149                         merged_disp += end_loop->first_elem_disp;
 150                         while( counter > 0 ) {
 151                             CREATE_ELEM( pElemDesc, OPAL_DATATYPE_UINT1, OPAL_DATATYPE_FLAG_BASIC,
 152                                          end_loop->size, merged_disp, 1);
 153                             pElemDesc++; nbElems++; counter--;
 154                             merged_disp += loop->extent;
 155                         }
 156                     } else {
 157                         CREATE_LOOP_START( pElemDesc, counter, 2, loop->extent, loop->common.flags );
 158                         pElemDesc++; nbElems++;
 159                         CREATE_ELEM( pElemDesc, OPAL_DATATYPE_UINT1, OPAL_DATATYPE_FLAG_BASIC,
 160                                      end_loop->size, loop_disp, 1);
 161                         pElemDesc++; nbElems++;
 162                         CREATE_LOOP_END( pElemDesc, 2, end_loop->first_elem_disp + merged_disp,
 163                                          end_loop->size, end_loop->common.flags );
 164                         pElemDesc++; nbElems++;
 165                     }
 166                 }
 167                 pos_desc += loop->items + 1;
 168             } else {
 169                 ddt_elem_desc_t* elem = (ddt_elem_desc_t*)&(pData->desc.desc[pos_desc+1]);
 170                 if( last_length != 0 ) {
 171                     CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC, last_length, last_disp, last_extent );
 172                     pElemDesc++; nbElems++;
 173                     last_disp  += last_length;
 174                     last_length = 0;
 175                     last_type   = OPAL_DATATYPE_LOOP;
 176                 }
 177                 if( 2 == loop->items ) { /* small loop */
 178                     if( (1 == elem->count)
 179                         && (elem->extent == (ptrdiff_t)opal_datatype_basicDatatypes[elem->common.type]->size) ) {
 180                         CREATE_ELEM( pElemDesc, elem->common.type, elem->common.flags & ~OPAL_DATATYPE_FLAG_CONTIGUOUS,
 181                                      loop->loops, elem->disp, loop->extent );
 182                         pElemDesc++; nbElems++;
 183                         pos_desc += loop->items + 1;
 184                         goto complete_loop;
 185                     } else if( loop->loops < 3 ) {
 186                         ptrdiff_t elem_displ = elem->disp;
 187                         for( i = 0; i < loop->loops; i++ ) {
 188                             CREATE_ELEM( pElemDesc, elem->common.type, elem->common.flags,
 189                                          elem->count, elem_displ, elem->extent );
 190                             elem_displ += loop->extent;
 191                             pElemDesc++; nbElems++;
 192                         }
 193                         pos_desc += loop->items + 1;
 194                         goto complete_loop;
 195                     }
 196                 }
 197                 CREATE_LOOP_START( pElemDesc, loop->loops, loop->items, loop->extent, loop->common.flags );
 198                 pElemDesc++; nbElems++;
 199                 PUSH_STACK( pStack, stack_pos, nbElems, OPAL_DATATYPE_LOOP, loop->loops, total_disp );
 200                 pos_desc++;
 201                 DDT_DUMP_STACK( pStack, stack_pos, pData->desc.desc, "advance loops" );
 202             }
 203         complete_loop:
 204             total_disp = pStack->disp;  /* update the displacement */
 205             continue;
 206         }
 207         while( pData->desc.desc[pos_desc].elem.common.flags & OPAL_DATATYPE_FLAG_DATA ) {  /* keep doing it until we reach a non datatype element */
 208             /* now here we have a basic datatype */
 209             type = pData->desc.desc[pos_desc].elem.common.type;
 210             continuity = ((last_disp + (ptrdiff_t)last_length * (ptrdiff_t)opal_datatype_basicDatatypes[last_type]->size)
 211                           == (total_disp + pData->desc.desc[pos_desc].elem.disp));
 212 
 213             if( (pData->desc.desc[pos_desc].elem.common.flags & OPAL_DATATYPE_FLAG_CONTIGUOUS) && continuity &&
 214                 (pData->desc.desc[pos_desc].elem.extent == (int32_t)opal_datatype_basicDatatypes[type]->size) ) {
 215                 if( type == last_type ) {
 216                     last_length += pData->desc.desc[pos_desc].elem.count;
 217                     last_extent = pData->desc.desc[pos_desc].elem.extent;
 218                 } else {
 219                     if( last_length == 0 ) {
 220                         last_type = type;
 221                         last_length = pData->desc.desc[pos_desc].elem.count;
 222                         last_extent = pData->desc.desc[pos_desc].elem.extent;
 223                     } else {
 224                         last_length = last_length * opal_datatype_basicDatatypes[last_type]->size +
 225                             pData->desc.desc[pos_desc].elem.count * opal_datatype_basicDatatypes[type]->size;
 226                         last_type = OPAL_DATATYPE_UINT1;
 227                         last_extent = 1;
 228                     }
 229                 }
 230                 last_flags &= pData->desc.desc[pos_desc].elem.common.flags;
 231             } else {
 232                 if( last_length != 0 ) {
 233                     CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC, last_length, last_disp, last_extent );
 234                     pElemDesc++; nbElems++;
 235                 }
 236                 last_disp = total_disp + pData->desc.desc[pos_desc].elem.disp;
 237                 last_length = pData->desc.desc[pos_desc].elem.count;
 238                 last_extent = pData->desc.desc[pos_desc].elem.extent;
 239                 last_type = type;
 240             }
 241             pos_desc++;  /* advance to the next data */
 242         }
 243     }
 244 
 245     if( last_length != 0 ) {
 246         CREATE_ELEM( pElemDesc, last_type, OPAL_DATATYPE_FLAG_BASIC, last_length, last_disp, last_extent );
 247         pElemDesc++; nbElems++;
 248     }
 249     /* cleanup the stack */
 250     pTypeDesc->used = nbElems - 1;  /* except the last fake END_LOOP */
 251     free(pOrigStack);
 252     return OPAL_SUCCESS;
 253 }
 254 
 255 int32_t opal_datatype_commit( opal_datatype_t * pData )
 256 {
 257     ddt_endloop_desc_t* pLast = &(pData->desc.desc[pData->desc.used].end_loop);
 258     ptrdiff_t first_elem_disp = 0;
 259 
 260     if( pData->flags & OPAL_DATATYPE_FLAG_COMMITTED ) return OPAL_SUCCESS;
 261     pData->flags |= OPAL_DATATYPE_FLAG_COMMITTED;
 262 
 263     /* We have to compute the displacement of the first non loop item in the
 264      * description.
 265      */
 266     if( 0 != pData->size ) {
 267         int index;
 268         dt_elem_desc_t* pElem = pData->desc.desc;
 269 
 270         index = GET_FIRST_NON_LOOP( pElem );
 271         assert( pElem[index].elem.common.flags & OPAL_DATATYPE_FLAG_DATA );
 272         first_elem_disp = pElem[index].elem.disp;
 273     }
 274 
 275     /* let's add a fake element at the end just to avoid useless comparaisons
 276      * in pack/unpack functions.
 277      */
 278     pLast->common.type     = OPAL_DATATYPE_END_LOOP;
 279     pLast->common.flags    = 0;
 280     pLast->items           = pData->desc.used;
 281     pLast->first_elem_disp = first_elem_disp;
 282     pLast->size            = pData->size;
 283 
 284     /* If there is no datatype description how can we have an optimized description ? */
 285     if( 0 == pData->desc.used ) {
 286         pData->opt_desc.length = 0;
 287         pData->opt_desc.desc   = NULL;
 288         pData->opt_desc.used   = 0;
 289         return OPAL_SUCCESS;
 290     }
 291 
 292     /* If the data is contiguous is useless to generate an optimized version. */
 293     /*if( pData->size == (pData->true_ub - pData->true_lb) ) return OPAL_SUCCESS; */
 294 
 295     (void)opal_datatype_optimize_short( pData, 1, &(pData->opt_desc) );
 296     if( 0 != pData->opt_desc.used ) {
 297         /* let's add a fake element at the end just to avoid useless comparaisons
 298          * in pack/unpack functions.
 299          */
 300         pLast = &(pData->opt_desc.desc[pData->opt_desc.used].end_loop);
 301         pLast->common.type     = OPAL_DATATYPE_END_LOOP;
 302         pLast->common.flags    = 0;
 303         pLast->items           = pData->opt_desc.used;
 304         pLast->first_elem_disp = first_elem_disp;
 305         pLast->size            = pData->size;
 306     }
 307     return OPAL_SUCCESS;
 308 }

/* [<][>][^][v][top][bottom][index][help] */