Beispiel #1
0
static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype,
                                                    void** packed_buffer, int* next_index )
{
    int i, *position = (int*)*packed_buffer;
    ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args;
    char* next_packed = (char*)*packed_buffer;

    if( ompi_datatype_is_predefined(datatype) ) {
        position[0] = MPI_COMBINER_NAMED;
        position[1] = datatype->id;   /* On the OMPI - layer, copy the ompi_datatype.id */
        next_packed += (2 * sizeof(int));
        *packed_buffer = next_packed;
        return OMPI_SUCCESS;
    }
    /* For duplicated datatype we don't have to store all the information */
    if( MPI_COMBINER_DUP == args->create_type ) {
        ompi_datatype_t* temp_data = args->d[0];
        return __ompi_datatype_pack_description(temp_data,
                                                packed_buffer,
                                                next_index );
    }
    position[0] = args->create_type;
    position[1] = args->ci;
    position[2] = args->ca;
    position[3] = args->cd;
    next_packed += (4 * sizeof(int));
    /* Spoiler: We will access the data in this storage structure, and thus we
     * need to align it to the expected boundaries (special thanks to Sparc64).
     * The simplest way is to ensure that prior to each type that must be 64
     * bits aligned, we have a pointer that is 64 bits aligned. That will minimize
     * the memory requirements in all cases where no displacements are stored.
     */
    if( 0 < args->ca ) {
        /* description of the displacements must be 64 bits aligned */
        OMPI_DATATYPE_ALIGN_PTR(next_packed, char*);

        memcpy( next_packed, args->a, sizeof(OPAL_PTRDIFF_TYPE) * args->ca );
        next_packed += sizeof(OPAL_PTRDIFF_TYPE) * args->ca;
    }
    position = (int*)next_packed;
    next_packed += sizeof(int) * args->cd;

    /* copy the aray of counts (32 bits aligned) */
    memcpy( next_packed, args->i, sizeof(int) * args->ci );
    next_packed += args->ci * sizeof(int);

    /* copy the rest of the data */
    for( i = 0; i < args->cd; i++ ) {
        ompi_datatype_t* temp_data = args->d[i];
        if( ompi_datatype_is_predefined(temp_data) ) {
            position[i] = temp_data->id;  /* On the OMPI - layer, copy the ompi_datatype.id */
        } else {
            position[i] = *next_index;
            (*next_index)++;
            __ompi_datatype_pack_description( temp_data,
                                              (void**)&next_packed,
                                              next_index );
        }
    }
    *packed_buffer = next_packed;
    return OMPI_SUCCESS;
}
Beispiel #2
0
int ompi_datatype_get_pack_description( ompi_datatype_t* datatype,
                                        const void** packed_buffer )
{
    ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args;
    int next_index = OMPI_DATATYPE_MAX_PREDEFINED;
    void *packed_description = datatype->packed_description;
    void* recursive_buffer;

    if (NULL == packed_description) {
        if (opal_atomic_cmpset (&datatype->packed_description, NULL, (void *) 1)) {
            if( ompi_datatype_is_predefined(datatype) ) {
                packed_description = malloc(2 * sizeof(int));
            } else if( NULL == args ) {
                return OMPI_ERROR;
            } else {
                packed_description = malloc(args->total_pack_size);
            }
            recursive_buffer = packed_description;
            __ompi_datatype_pack_description( datatype, &recursive_buffer, &next_index );

            if (!ompi_datatype_is_predefined(datatype)) {
                args->total_pack_size = (uintptr_t)((char*)recursive_buffer - (char *) packed_description);
            }

            opal_atomic_wmb ();
            datatype->packed_description = packed_description;
        } else {
            /* another thread beat us to it */
            packed_description = datatype->packed_description;
        }
    }

    if ((void *) 1 == packed_description) {
        struct timespec interval = {.tv_sec = 0, .tv_nsec = 1000};

        /* wait until the packed description is updated */
        while ((void *) 1 == datatype->packed_description) {
            nanosleep (&interval, NULL);
        }

        packed_description = datatype->packed_description;
    }

    *packed_buffer = (const void *) packed_description;
    return OMPI_SUCCESS;
}

size_t ompi_datatype_pack_description_length( ompi_datatype_t* datatype )
{
    void *packed_description = datatype->packed_description;

    if( ompi_datatype_is_predefined(datatype) ) {
        return 2 * sizeof(int);
    }
    if( NULL == packed_description || (void *) 1 == packed_description) {
        const void* buf;
        int rc;

        rc = ompi_datatype_get_pack_description(datatype, &buf);
        if( OMPI_SUCCESS != rc ) {
            return 0;
        }
    }
    assert( NULL != (ompi_datatype_args_t*)datatype->args );
    assert( NULL != (ompi_datatype_args_t*)datatype->packed_description );
    return ((ompi_datatype_args_t*)datatype->args)->total_pack_size;
}
Beispiel #3
0
int ompi_datatype_get_pack_description( ompi_datatype_t* datatype,
                                        const void** packed_buffer )
{
    ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args;
    int next_index = OMPI_DATATYPE_MAX_PREDEFINED;
    void *packed_description = (void *) datatype->packed_description;
    void* recursive_buffer;

    if (NULL == packed_description) {
        void *_tmp_ptr = NULL;
        if (opal_atomic_compare_exchange_strong_ptr (&datatype->packed_description, (intptr_t *) &_tmp_ptr, 1)) {
            if( ompi_datatype_is_predefined(datatype) ) {
                packed_description = malloc(2 * sizeof(int));
            } else if( NULL == args ) {
                return OMPI_ERROR;
            } else {
                packed_description = malloc(args->total_pack_size);
            }
            recursive_buffer = packed_description;
            __ompi_datatype_pack_description( datatype, &recursive_buffer, &next_index );

            if (!ompi_datatype_is_predefined(datatype)) {
                /* If the precomputed size is not large enough we're already in troubles, we
                 * have overwritten outside of the allocated buffer. Raise the alarm !
                 * If not reassess the size of the packed buffer necessary for holding the
                 * datatype description.
                 */
                assert(args->total_pack_size >= (uintptr_t)((char*)recursive_buffer - (char *) packed_description));
                args->total_pack_size = (uintptr_t)((char*)recursive_buffer - (char *) packed_description);
            }

            opal_atomic_wmb ();
            datatype->packed_description = (intptr_t) packed_description;
        } else {
            /* another thread beat us to it */
            packed_description = (void *) datatype->packed_description;
        }
    }

    if ((void *) 1 == packed_description) {
        struct timespec interval = {.tv_sec = 0, .tv_nsec = 1000};

        /* wait until the packed description is updated */
        while (1 == datatype->packed_description) {
            nanosleep (&interval, NULL);
        }

        packed_description = (void *) datatype->packed_description;
    }

    *packed_buffer = (const void *) packed_description;
    return OMPI_SUCCESS;
}

size_t ompi_datatype_pack_description_length( ompi_datatype_t* datatype )
{
    void *packed_description = (void *) datatype->packed_description;

    if( ompi_datatype_is_predefined(datatype) ) {
        return 2 * sizeof(int);
    }
    if( NULL == packed_description || (void *) 1 == packed_description) {
        const void* buf;
        int rc;

        rc = ompi_datatype_get_pack_description(datatype, &buf);
        if( OMPI_SUCCESS != rc ) {
            return 0;
        }
    }
    assert( NULL != (ompi_datatype_args_t*)datatype->args );
    assert( NULL != (ompi_datatype_args_t*)datatype->packed_description );
    return ((ompi_datatype_args_t*)datatype->args)->total_pack_size;
}