forked from openkylin/openmpi
252 lines
9.1 KiB
C
252 lines
9.1 KiB
C
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
|
/*
|
|
* Copyright (c) 2016 The University of Tennessee and The University
|
|
* of Tennessee Research Foundation. All rights
|
|
* reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ompi_config.h"
|
|
#include "ompi/datatype/ompi_datatype.h"
|
|
#include "opal/runtime/opal.h"
|
|
#include "opal/datatype/opal_convertor.h"
|
|
#include "opal/datatype/opal_datatype_internal.h"
|
|
#include <arpa/inet.h>
|
|
|
|
static int verbose = 0;
|
|
|
|
typedef int (*checker_t)(void*, void*, ompi_datatype_t *, int, void*);
|
|
|
|
int check_contiguous( void* send_buffer, void* packed,
|
|
ompi_datatype_t * datatype, int count, void* arg );
|
|
|
|
int check_vector( void* send_buffer, void* packed,
|
|
ompi_datatype_t * datatype, int count, void* arg );
|
|
|
|
static int pack_unpack_datatype( void* send_data, ompi_datatype_t *datatype, int count,
|
|
void* recv_data, checker_t validator, void *validator_arg );
|
|
|
|
static void
|
|
dump_hex(const char* msg, const void* vbuf, int nbytes,
|
|
int start_from, int stop_at, int vals_per_line)
|
|
{
|
|
const char* buf = (const char*)vbuf;
|
|
|
|
if( -1 == stop_at ) stop_at = nbytes;
|
|
|
|
for (int i = (start_from / vals_per_line) * vals_per_line; i < nbytes; ++i) {
|
|
if( i >= stop_at ) return;
|
|
if (0 == (i % vals_per_line)) {
|
|
if( NULL == msg) printf("\n");
|
|
else printf("\n%s", msg);
|
|
} else {
|
|
if (i % 4 == 0) {
|
|
printf(" ");
|
|
}
|
|
}
|
|
printf(" ");
|
|
if( i < start_from )
|
|
printf(" ");
|
|
else
|
|
printf("%02x", *((unsigned char *)(buf + i)));
|
|
}
|
|
}
|
|
|
|
int check_contiguous( void* send_buffer, void* packed,
|
|
ompi_datatype_t* datatype, int count, void* arg )
|
|
{
|
|
int i;
|
|
|
|
if( (datatype == &ompi_mpi_int.dt) || (datatype == &ompi_mpi_int32_t.dt) ) {
|
|
uint32_t val;
|
|
for( i = 0 ; i < count; i++ ) {
|
|
val = htonl(((uint32_t*)send_buffer)[i]);
|
|
if( val != ((uint32_t*)packed)[i] ) {
|
|
printf("Error at position %d expected %x found %x (type %s)\n",
|
|
i, ((uint32_t*)packed)[i], ((uint32_t*)send_buffer)[i], datatype->name);
|
|
return -1;
|
|
}
|
|
}
|
|
} else if( (datatype == &ompi_mpi_short.dt) || (datatype == &ompi_mpi_int16_t.dt) ) {
|
|
uint16_t val;
|
|
for( i = 0 ; i < count; i++ ) {
|
|
val = htons(((uint16_t*)send_buffer)[i]);
|
|
if( val != ((uint16_t*)packed)[i] ) {
|
|
printf("Error at position %d expected %x found %x (type %s)\n",
|
|
i, ((uint16_t*)packed)[i], ((uint16_t*)send_buffer)[i], datatype->name);
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
printf("Unknown type\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int check_vector( void* send_buffer, void* packed,
|
|
ompi_datatype_t* datatype, int count, void* arg )
|
|
{
|
|
int i;
|
|
ompi_datatype_t *origtype = (ompi_datatype_t *)arg;
|
|
|
|
if( (origtype == &ompi_mpi_int.dt) || (origtype == &ompi_mpi_int32_t.dt) ) {
|
|
uint32_t val;
|
|
for( i = 0 ; i < count; i++ ) {
|
|
val = htonl(((uint32_t*)send_buffer)[2*i]);
|
|
if( val != ((uint32_t*)packed)[i] ) {
|
|
printf("Error at position %d expected %x found %x (type %s)\n",
|
|
i, ((uint32_t*)packed)[i], ((uint32_t*)send_buffer)[2*i], datatype->name);
|
|
return -1;
|
|
}
|
|
}
|
|
} else if( (origtype == &ompi_mpi_short.dt) || (origtype == &ompi_mpi_int16_t.dt) ) {
|
|
uint16_t val;
|
|
for( i = 0 ; i < count; i++ ) {
|
|
val = htons(((uint16_t*)send_buffer)[2*i]);
|
|
if( val != ((uint16_t*)packed)[i] ) {
|
|
printf("Error at position %d expected %x found %x (type %s)\n",
|
|
i, ((uint16_t*)packed)[i], ((uint16_t*)send_buffer)[2*i], datatype->name);
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
printf("Unknown %s type\n", datatype->name);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int pack_unpack_datatype( void* send_data, ompi_datatype_t *datatype, int count,
|
|
void* recv_data,
|
|
checker_t validator, void* validator_arg)
|
|
{
|
|
MPI_Aint position = 0, buffer_size;
|
|
void* buffer;
|
|
int error;
|
|
|
|
error = ompi_datatype_pack_external_size("external32",
|
|
count, datatype, &buffer_size);
|
|
if( MPI_SUCCESS != error ) goto return_error_code;
|
|
|
|
buffer = (void*)malloc(buffer_size);
|
|
if( NULL == buffer ) { error = MPI_ERR_UNKNOWN; goto return_error_code; }
|
|
|
|
error = ompi_datatype_pack_external("external32", (void*)send_data, count, datatype,
|
|
buffer, buffer_size, &position);
|
|
if( MPI_SUCCESS != error ) goto return_error_code;
|
|
if( 0 != validator(send_data, buffer, datatype, count, validator_arg) ) {
|
|
printf("Error during pack external. Bailing out\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("packed %ld bytes into a %ld bytes buffer ", position, buffer_size);
|
|
dump_hex(NULL, buffer, position, 0, -1, 24); printf("\n");
|
|
|
|
position = 0;
|
|
error = ompi_datatype_unpack_external("external32", buffer, buffer_size, &position,
|
|
recv_data, count, datatype);
|
|
if( MPI_SUCCESS != error ) goto return_error_code;
|
|
free(buffer);
|
|
|
|
return_error_code:
|
|
return (error == MPI_SUCCESS ? 0 : -1);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
opal_init_util(&argc, &argv);
|
|
ompi_datatype_init();
|
|
|
|
/* Simple contiguous data: MPI_INT32_T */
|
|
{
|
|
int32_t send_data[2] = {1234, 5678};
|
|
int32_t recv_data[2] = {-1, -1};
|
|
|
|
if( verbose ) {
|
|
printf("send data %08x %08x \n", send_data[0], send_data[1]);
|
|
printf("data ");
|
|
dump_hex(NULL, &send_data, sizeof(int32_t) * 2, 0, -1, 24); printf("\n");
|
|
}
|
|
(void)pack_unpack_datatype( send_data, &ompi_mpi_int32_t.dt, 2,
|
|
recv_data, check_contiguous, (void*)&ompi_mpi_int32_t.dt );
|
|
if( verbose ) {
|
|
printf("recv ");
|
|
dump_hex(NULL, &recv_data, sizeof(int32_t) * 2, 0, -1, 24); printf("\n");
|
|
printf("recv data %08x %08x \n", recv_data[0], recv_data[1]);
|
|
}
|
|
if( (send_data[0] != recv_data[0]) || (send_data[1] != recv_data[1]) ) {
|
|
printf("Error during external32 pack/unack for contiguous types (MPI_INT32_T)\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
/* Simple contiguous data: MPI_INT16_T */
|
|
{
|
|
int16_t send_data[2] = {1234, 5678};
|
|
int16_t recv_data[2] = {-1, -1};
|
|
|
|
if( verbose ) {
|
|
printf("send data %08x %08x \n", send_data[0], send_data[1]);
|
|
printf("data ");
|
|
dump_hex(NULL, &send_data, sizeof(int16_t) * 2, 0, -1, 24); printf("\n");
|
|
}
|
|
(void)pack_unpack_datatype( send_data, &ompi_mpi_int16_t.dt, 2,
|
|
recv_data, check_contiguous, (void*)&ompi_mpi_int16_t.dt );
|
|
if( verbose ) {
|
|
printf("recv ");
|
|
dump_hex(NULL, &recv_data, sizeof(int16_t) * 2, 0, -1, 24); printf("\n");
|
|
printf("recv data %08x %08x \n", recv_data[0], recv_data[1]);
|
|
}
|
|
if( (send_data[0] != recv_data[0]) || (send_data[1] != recv_data[1]) ) {
|
|
printf("Error during external32 pack/unack for contiguous types\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
/* Vector datatype */
|
|
printf("\n\nVector datatype\n\n");
|
|
{
|
|
int count=2, blocklength=1, stride=2;
|
|
int send_data[3] = {1234, 0, 5678};
|
|
int recv_data[3] = {-1, -1, -1};
|
|
ompi_datatype_t *ddt;
|
|
|
|
ompi_datatype_create_vector ( count, blocklength, stride, &ompi_mpi_int.dt, &ddt );
|
|
{
|
|
const int* a_i[3] = {&count, &blocklength, &stride};
|
|
ompi_datatype_t *type = &ompi_mpi_int.dt;
|
|
|
|
ompi_datatype_set_args( ddt, 3, a_i, 0, NULL, 1, &type, MPI_COMBINER_VECTOR );
|
|
}
|
|
ompi_datatype_commit(&ddt);
|
|
|
|
if( verbose ) {
|
|
printf("send data %08x %x08x %08x \n", send_data[0], send_data[1], send_data[2]);
|
|
printf("data "); dump_hex(NULL, &send_data, sizeof(int32_t) * 3, 0, -1, 24); printf("\n");
|
|
}
|
|
(void)pack_unpack_datatype( send_data, ddt, 1, recv_data, check_vector, (void*)&ompi_mpi_int32_t.dt );
|
|
if( verbose ) {
|
|
printf("recv "); dump_hex(NULL, &recv_data, sizeof(int32_t) * 3, 0, -1, 24); printf("\n");
|
|
printf("recv data %08x %08x %08x \n", recv_data[0], recv_data[1], recv_data[2]);
|
|
}
|
|
ompi_datatype_destroy(&ddt);
|
|
if( (send_data[0] != recv_data[0]) || (send_data[2] != recv_data[2]) ) {
|
|
printf("Error during external32 pack/unack for vector types (MPI_INT32_T)\n");
|
|
printf("[0]: %d ? %d | [2]: %d ? %d ([1]: %d ? %d)\n", send_data[0], recv_data[0],
|
|
send_data[2], recv_data[2], send_data[1], recv_data[1]);
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
ompi_datatype_finalize();
|
|
|
|
return 0;
|
|
}
|