-
Nathan Précigout authoredNathan Précigout authored
cham_tile_interface.c 24.87 KiB
/**
*
* @file starpu/cham_tile_interface.c
*
* @copyright 2012-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
* Univ. Bordeaux. All rights reserved.
*
***
*
* @brief Chameleon tile interface for StarPU
*
* @version 1.2.0
* @author Mathieu Faverge
* @author Gwenole Lucas
* @author Samuel Thibault
* @date 2022-02-22
*
*/
#include "chameleon_starpu.h"
#if defined(CHAMELEON_USE_HMAT)
#include "coreblas/hmat.h"
static inline void
cti_hmat_destroy( starpu_cham_tile_interface_t *cham_tile_interface )
{
switch( cham_tile_interface->flttype ) {
case ChamComplexDouble:
hmat_zdestroy( cham_tile_interface->tile.mat );
break;
case ChamComplexFloat:
hmat_cdestroy( cham_tile_interface->tile.mat );
break;
case ChamRealDouble:
hmat_ddestroy( cham_tile_interface->tile.mat );
break;
case ChamRealFloat:
hmat_sdestroy( cham_tile_interface->tile.mat );
break;
default:
STARPU_ASSERT_MSG( 0, "cti_hmat_destroy(): unknown flttype\n" );
}
cham_tile_interface->tile.mat = NULL;
}
static inline size_t
cti_get_hmat_required_size( starpu_cham_tile_interface_t *cham_tile_interface )
{
size_t size = 0;
if ( (cham_tile_interface->tile.format & CHAMELEON_TILE_HMAT) &&
(cham_tile_interface->tile.mat != NULL ) )
{
switch( cham_tile_interface->flttype ) {
case ChamComplexDouble:
size = hmat_zsize( cham_tile_interface->tile.mat );
break;
case ChamComplexFloat:
size = hmat_csize( cham_tile_interface->tile.mat );
break;
case ChamRealDouble:
size = hmat_dsize( cham_tile_interface->tile.mat );
break;
case ChamRealFloat:
size = hmat_ssize( cham_tile_interface->tile.mat );
break;
default:
STARPU_ASSERT_MSG( 0, "cti_get_hmat_required_size(cham_tile_interface): unknown flttype\n" );
}
}
return size;
}
#else
static inline size_t
cti_get_hmat_required_size( starpu_cham_tile_interface_t *cham_tile_interface __attribute__((unused)) ) {
return 0;
}
#endif
static inline CHAM_tile_t *
cti_handle_get( starpu_data_handle_t handle )
{
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node( handle, STARPU_MAIN_RAM );
#ifdef STARPU_DEBUG
STARPU_ASSERT_MSG( cham_tile_interface->id == STARPU_CHAM_TILE_INTERFACE_ID,
"Error. The given data is not a cham_tile." );
#endif
return &(cham_tile_interface->tile);
}
int
cti_handle_get_m( starpu_data_handle_t handle )
{
CHAM_tile_t *tile = cti_handle_get( handle );
return tile->m;
}
int
cti_handle_get_n( starpu_data_handle_t handle )
{
CHAM_tile_t *tile = cti_handle_get( handle );
return tile->n;
}
static void
cti_init( void *data_interface )
{
starpu_cham_tile_interface_t *cham_tile_interface = data_interface;
cham_tile_interface->id = STARPU_CHAM_TILE_INTERFACE_ID;
cham_tile_interface->allocsize = -1;
}
static void
cti_register_data_handle( starpu_data_handle_t handle,
int home_node,
void *data_interface )
{
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *) data_interface;
int node;
for (node = 0; node < STARPU_MAXNODES; node++)
{
starpu_cham_tile_interface_t *local_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node(handle, node);
memcpy( local_interface, cham_tile_interface,
sizeof( starpu_cham_tile_interface_t ) );
if ( node != home_node )
{
local_interface->dev_handle = 0;
local_interface->tile.mat = NULL;
local_interface->tile.ld = -1;
}
}
}
static starpu_ssize_t
cti_allocate_data_on_node( void *data_interface, unsigned node )
{
uintptr_t addr = 0, handle;
starpu_cham_tile_interface_t *cham_tile_interface =
(starpu_cham_tile_interface_t *) data_interface;
uint32_t ld = cham_tile_interface->tile.m;
starpu_ssize_t allocated_memory;
allocated_memory = cham_tile_interface->allocsize;
if ( allocated_memory <= 0 ) {
return 0;
}
handle = starpu_malloc_on_node( node, allocated_memory );
if ( !handle ) {
return -ENOMEM;
}
if ( starpu_node_get_kind(node) != STARPU_OPENCL_RAM ) {
addr = handle;
}
/* update the data properly */
cham_tile_interface->tile.mat = (void*)addr;
cham_tile_interface->tile.ld = ld;
cham_tile_interface->dev_handle = handle;
return allocated_memory;
}
static void
cti_free_data_on_node( void *data_interface, unsigned node )
{
starpu_cham_tile_interface_t *cham_tile_interface =
(starpu_cham_tile_interface_t *) data_interface;
#if defined(CHAMELEON_USE_HMAT)
if ( (cham_tile_interface->tile.format & CHAMELEON_TILE_HMAT) &&
(cham_tile_interface->tile.mat != NULL ) )
{
cti_hmat_destroy( cham_tile_interface );
}
else
#endif
{
assert( (uintptr_t)(cham_tile_interface->tile.mat) == cham_tile_interface->dev_handle );
}
starpu_free_on_node( node, cham_tile_interface->dev_handle, cham_tile_interface->allocsize );
cham_tile_interface->tile.mat = NULL;
cham_tile_interface->dev_handle = 0;
}
#if defined(HAVE_STARPU_REUSE_DATA_ON_NODE)
static void
cti_reuse_data_on_node( void *dst_data_interface, const void *cached_interface, unsigned node )
{
(void)node;
starpu_cham_tile_interface_t *dst_cham_tile =
(starpu_cham_tile_interface_t *) dst_data_interface;
starpu_cham_tile_interface_t *cached_cham_tile =
(starpu_cham_tile_interface_t *) cached_interface;
/* update the data properly */
dst_cham_tile->tile.mat = cached_cham_tile->tile.mat;
dst_cham_tile->tile.ld = dst_cham_tile->tile.m;
dst_cham_tile->dev_handle = cached_cham_tile->dev_handle;
}
#endif
static void *
cti_to_pointer( void *data_interface, unsigned node )
{
(void) node;
starpu_cham_tile_interface_t *cham_tile_interface = data_interface;
return (void*)(cham_tile_interface->tile.mat);
}
static size_t
cti_get_size(starpu_data_handle_t handle)
{
starpu_cham_tile_interface_t *cham_tile_interface =
starpu_data_get_interface_on_node( handle, STARPU_MAIN_RAM );
size_t elemsize = CHAMELEON_Element_Size( cham_tile_interface->flttype );
#ifdef STARPU_DEBUG
STARPU_ASSERT_MSG( cham_tile_interface->id == STARPU_CHAM_TILE_INTERFACE_ID,
"Error. The given data is not a cham_tile." );
#endif
return cham_tile_interface->tile.m * cham_tile_interface->tile.n * elemsize;
}
static size_t
cti_get_alloc_size(starpu_data_handle_t handle)
{
starpu_cham_tile_interface_t *cham_tile_interface =
starpu_data_get_interface_on_node( handle, STARPU_MAIN_RAM );
#ifdef STARPU_DEBUG
STARPU_ASSERT_MSG( cham_tile_interface->id == STARPU_CHAM_TILE_INTERFACE_ID,
"Error. The given data is not a cham_tile." );
#endif
STARPU_ASSERT_MSG( cham_tile_interface->allocsize != (size_t)-1,
"The cham_tile allocation size needs to be defined" );
return cham_tile_interface->allocsize;
}
static uint32_t
cti_footprint( starpu_data_handle_t handle )
{
CHAM_tile_t *tile = cti_handle_get( handle );
return starpu_hash_crc32c_be( tile->m, tile->n );
}
#if defined(HAVE_STARPU_REUSE_DATA_ON_NODE)
static uint32_t
cti_alloc_footprint( starpu_data_handle_t handle )
{
return starpu_hash_crc32c_be( cti_handle_get_allocsize(handle), 0 );
}
#endif
static int
cti_compare( void *data_interface_a, void *data_interface_b )
{
starpu_cham_tile_interface_t *cham_tile_a = (starpu_cham_tile_interface_t *) data_interface_a;
starpu_cham_tile_interface_t *cham_tile_b = (starpu_cham_tile_interface_t *) data_interface_b;
/* Two matrices are considered compatible if they have the same size */
return ( cham_tile_a->tile.m == cham_tile_b->tile.m )
&& ( cham_tile_a->tile.n == cham_tile_b->tile.n )
&& ( cham_tile_a->flttype == cham_tile_b->flttype );
}
#if defined(HAVE_STARPU_REUSE_DATA_ON_NODE)
static int
cti_alloc_compare(void *data_interface_a, void *data_interface_b)
{
starpu_cham_tile_interface_t *cham_tile_a = (starpu_cham_tile_interface_t *) data_interface_a;
starpu_cham_tile_interface_t *cham_tile_b = (starpu_cham_tile_interface_t *) data_interface_b;
/* Two matrices are considered compatible if they have the same allocated size */
return ( cham_tile_a->allocsize == cham_tile_b->allocsize );
}
#endif
static void
cti_display( starpu_data_handle_t handle, FILE *f )
{
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node(handle, STARPU_MAIN_RAM);
#if defined(CHAMELEON_KERNELS_TRACE)
fprintf( f, "%s{.m=%u,.n=%u}",
cham_tile_interface->tile.name,
cham_tile_interface->tile.m,
cham_tile_interface->tile.n );
#else
fprintf( f, "%u\t%u\t",
cham_tile_interface->tile.m,
cham_tile_interface->tile.n );
#endif
}
static int
cti_pack_data_fullrank( starpu_cham_tile_interface_t *cham_tile_interface,
void *ptr )
{
char *matrix = (void *)cham_tile_interface->tile.mat;
if ( cham_tile_interface->tile.m == cham_tile_interface->tile.ld ) {
memcpy( ptr, matrix, cham_tile_interface->allocsize );
}
else {
int n;
char *tmpptr = ptr;
for(n=0; n<cham_tile_interface->tile.n; n++)
{
size_t elemsize = CHAMELEON_Element_Size( cham_tile_interface->flttype );
size_t size = cham_tile_interface->tile.m * elemsize;
memcpy( tmpptr, matrix, size );
tmpptr += size;
matrix += cham_tile_interface->tile.ld * elemsize;
}
}
return 0;
}
static int
cti_pack_data_hmat( starpu_cham_tile_interface_t *cham_tile_interface,
void *ptr )
{
#if !defined(CHAMELEON_USE_HMAT)
assert( 0 );
(void)cham_tile_interface;
(void)ptr;
#else
hmat_matrix_t *mat = cham_tile_interface->tile.mat;
STARPU_ASSERT_MSG( mat != NULL, "cti_pack_data_hmat: Try to pack a NULL pointer\n" );
switch( cham_tile_interface->flttype ) {
case ChamComplexDouble:
hmat_zwrite( mat, ptr );
break;
case ChamComplexFloat:
hmat_cwrite( mat, ptr );
break;
case ChamRealDouble:
hmat_dwrite( mat, ptr );
break;
case ChamRealFloat:
hmat_swrite( mat, ptr );
break;
default:
STARPU_ASSERT_MSG( 0, "cti_pack_data_hmat: unknown flttype\n" );
}
#endif
return 0;
}
static int
cti_pack_data( starpu_data_handle_t handle, unsigned node, void **ptr, starpu_ssize_t *count )
{
STARPU_ASSERT(starpu_data_test_if_allocated_on_node(handle, node));
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node(handle, node);
size_t size;
size = (starpu_ssize_t)(cham_tile_interface->allocsize);
size += cti_get_hmat_required_size( cham_tile_interface );
*count = size + sizeof(size_t) + sizeof(CHAM_tile_t);
if ( ptr != NULL )
{
char *tmp;
*ptr = (void *)starpu_malloc_on_node_flags( node, *count, 0 );
tmp = (char*)(*ptr);
/* Start by the size to allocate on reception */
memcpy( tmp, &size, sizeof(size_t) );
tmp += sizeof(size_t);
/* Copy the tile metadata */
memcpy( tmp, &(cham_tile_interface->tile), sizeof(CHAM_tile_t) );
tmp += sizeof(CHAM_tile_t);
/* Pack the real data */
if ( cham_tile_interface->tile.format & CHAMELEON_TILE_FULLRANK ) {
cti_pack_data_fullrank( cham_tile_interface, tmp );
}
else if ( cham_tile_interface->tile.format & CHAMELEON_TILE_HMAT ) {
cti_pack_data_hmat( cham_tile_interface, tmp );
}
else {
STARPU_ASSERT_MSG( 1, "Unsupported format for pack." );
}
}
return 0;
}
static int
cti_unpack_data_fullrank( starpu_cham_tile_interface_t *cham_tile_interface,
void *ptr )
{
char *matrix = (void *)cham_tile_interface->tile.mat;
assert( cham_tile_interface->tile.format & CHAMELEON_TILE_FULLRANK );
assert( matrix != NULL );
if ( cham_tile_interface->tile.m == cham_tile_interface->tile.ld ) {
memcpy( matrix, ptr, cham_tile_interface->allocsize );
}
else {
int n;
char *tmpptr = ptr;
for(n=0 ; n<cham_tile_interface->tile.n; n++)
{
size_t elemsize = CHAMELEON_Element_Size( cham_tile_interface->flttype );
size_t size = cham_tile_interface->tile.m * elemsize;
memcpy( matrix, tmpptr, size );
tmpptr += size;
matrix += cham_tile_interface->tile.ld * elemsize;
}
}
return 0;
}
static int
cti_unpack_data_hmat( starpu_cham_tile_interface_t *cham_tile_interface,
void *ptr )
{
assert( cham_tile_interface->tile.format & CHAMELEON_TILE_HMAT );
#if !defined(CHAMELEON_USE_HMAT)
assert( 0 );
(void)cham_tile_interface;
(void)ptr;
#else
hmat_matrix_t *mat = NULL;
switch( cham_tile_interface->flttype ) {
case ChamComplexDouble:
mat = hmat_zread( ptr );
break;
case ChamComplexFloat:
mat = hmat_cread( ptr );
break;
case ChamRealDouble:
mat = hmat_dread( ptr );
break;
case ChamRealFloat:
mat = hmat_sread( ptr );
break;
default:
STARPU_ASSERT_MSG( 0, "cti_unpack_data_hmat: unknown flttype\n" );
}
cham_tile_interface->tile.mat = mat;
#endif
return 0;
}
static int
cti_peek_data( starpu_data_handle_t handle, unsigned node, void *ptr, size_t count )
{
STARPU_ASSERT(starpu_data_test_if_allocated_on_node(handle, node));
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node(handle, node);
char *tmp = ptr;
#if defined(CHAMELEON_USE_MPI_DATATYPES)
/*
* We may end up here if an early reception occured before the handle of the
* received data has been registered. Thus, datatype was not existant and we
* need to unpack the data ourselves
*/
STARPU_ASSERT( count == cham_tile_interface->allocsize );
STARPU_ASSERT( cham_tile_interface->tile.format & CHAMELEON_TILE_FULLRANK );
#else
{
CHAM_tile_t dsttile;
size_t size;
/* Extract the size of the information to unpack */
memcpy( &size, tmp, sizeof(size_t) );
tmp += sizeof(size_t);
/* Extract the tile metadata of the remote tile */
memcpy( &dsttile, tmp, sizeof(CHAM_tile_t) );
tmp += sizeof(CHAM_tile_t);
assert( ( (dsttile.format & CHAMELEON_TILE_HMAT) && (cham_tile_interface->allocsize == 0 )) ||
(!(dsttile.format & CHAMELEON_TILE_HMAT) && (cham_tile_interface->allocsize == size)) );
/*
* Update with the local information. Data is packed now, and do not
* need leading dimension anymore
*/
cham_tile_interface->tile.format = dsttile.format;
cham_tile_interface->tile.ld = cham_tile_interface->tile.m;
STARPU_ASSERT( cham_tile_interface->tile.m == dsttile.m );
STARPU_ASSERT( cham_tile_interface->tile.n == dsttile.n );
STARPU_ASSERT( count == cham_tile_interface->allocsize + sizeof(size_t) + sizeof(CHAM_tile_t) );
}
#endif
/* Unpack the real data */
if ( cham_tile_interface->tile.format & CHAMELEON_TILE_FULLRANK ) {
cti_unpack_data_fullrank( cham_tile_interface, tmp );
}
else if ( cham_tile_interface->tile.format & CHAMELEON_TILE_HMAT ) {
cti_unpack_data_hmat( cham_tile_interface, tmp );
}
else {
STARPU_ASSERT_MSG( 1, "Unsupported format for unpack." );
}
return 0;
}
static int
cti_unpack_data( starpu_data_handle_t handle, unsigned node, void *ptr, size_t count )
{
cti_peek_data( handle, node, ptr, count );
/* Free the received information */
starpu_free_on_node_flags( node, (uintptr_t)ptr, count, 0 );
return 0;
}
static starpu_ssize_t
cti_describe( void *data_interface, char *buf, size_t size )
{
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *) data_interface;
#if defined(CHAMELEON_KERNELS_TRACE)
return snprintf( buf, size, "M%ux%ux%u %s",
(unsigned) cham_tile_interface->tile.m,
(unsigned) cham_tile_interface->tile.n,
(unsigned) cham_tile_interface->flttype,
cham_tile_interface->tile.name);
#else
return snprintf( buf, size, "M%ux%ux%u",
(unsigned) cham_tile_interface->tile.m,
(unsigned) cham_tile_interface->tile.n,
(unsigned) cham_tile_interface->flttype );
#endif
}
static int cti_copy_any_to_any( void *src_interface, unsigned src_node,
void *dst_interface, unsigned dst_node, void *async_data )
{
starpu_cham_tile_interface_t *cham_tile_src = (starpu_cham_tile_interface_t *) src_interface;
starpu_cham_tile_interface_t *cham_tile_dst = (starpu_cham_tile_interface_t *) dst_interface;
size_t elemsize = CHAMELEON_Element_Size( cham_tile_src->flttype );
size_t m = (size_t)(cham_tile_src->tile.m);
size_t n = (size_t)(cham_tile_src->tile.n);
size_t ld_src = (size_t)(cham_tile_src->tile.ld);
size_t ld_dst = (size_t)(cham_tile_dst->tile.ld);
int ret = 0;
void *src_mat = CHAM_tile_get_ptr( &(cham_tile_src->tile) );
void *dst_mat = CHAM_tile_get_ptr( &(cham_tile_dst->tile) );
assert( ld_src >= m );
assert( ld_dst >= m );
assert( m == (size_t)(cham_tile_dst->tile.m) );
assert( n == (size_t)(cham_tile_dst->tile.n) );
#if defined(CHAMELEON_KERNELS_TRACE)
fprintf( stderr,
"[ANY->ANY] src(%s, type:%s, m=%d, n=%d, ld=%d, ptr:%p) dest(%s, type:%s, m=%d, n=%d, ld=%d, ptr:%p)\n",
cham_tile_src->tile.name, CHAM_tile_get_typestr( &(cham_tile_src->tile) ),
cham_tile_src->tile.m, cham_tile_src->tile.n, cham_tile_src->tile.ld, src_mat,
cham_tile_dst->tile.name, CHAM_tile_get_typestr( &(cham_tile_dst->tile) ),
cham_tile_dst->tile.m, cham_tile_dst->tile.n, cham_tile_dst->tile.ld, dst_mat );
#endif
m = m * elemsize;
ld_src = ld_src * elemsize;
ld_dst = ld_dst * elemsize;
#if defined(HAVE_STARPU_INTERFACE_COPY2D)
if (starpu_interface_copy2d( (uintptr_t) src_mat, 0, src_node,
(uintptr_t) dst_mat, 0, dst_node,
m, n, ld_src, ld_dst, async_data ) ) {
ret = -EAGAIN;
}
#else
if ( (ld_src == m) && (ld_dst == m) )
{
/* Optimize unpartitioned and y-partitioned cases */
if ( starpu_interface_copy( (uintptr_t) src_mat, 0, src_node,
(uintptr_t) dst_mat, 0, dst_node,
m * n, async_data ) )
{
ret = -EAGAIN;
}
}
else
{
unsigned y;
for (y = 0; y < n; y++)
{
uint32_t src_offset = y * ld_src;
uint32_t dst_offset = y * ld_dst;
if ( starpu_interface_copy( (uintptr_t) src_mat, src_offset, src_node,
(uintptr_t) dst_mat, dst_offset, dst_node,
m, async_data ) )
{
ret = -EAGAIN;
}
}
}
#endif
starpu_interface_data_copy( src_node, dst_node, m * n );
return ret;
}
static const struct starpu_data_copy_methods cti_copy_methods =
{
.any_to_any = cti_copy_any_to_any,
};
struct starpu_data_interface_ops starpu_interface_cham_tile_ops =
{
.init = cti_init,
.register_data_handle = cti_register_data_handle,
.allocate_data_on_node = cti_allocate_data_on_node,
.free_data_on_node = cti_free_data_on_node,
#if defined(HAVE_STARPU_REUSE_DATA_ON_NODE)
.reuse_data_on_node = cti_reuse_data_on_node,
.alloc_compare = cti_alloc_compare,
.alloc_footprint = cti_alloc_footprint,
#endif
.to_pointer = cti_to_pointer,
.get_size = cti_get_size,
.get_alloc_size = cti_get_alloc_size,
.footprint = cti_footprint,
.compare = cti_compare,
.display = cti_display,
.pack_data = cti_pack_data,
#if defined(HAVE_STARPU_DATA_PEEK)
.peek_data = cti_peek_data,
#endif
.unpack_data = cti_unpack_data,
.describe = cti_describe,
.copy_methods =&cti_copy_methods,
.interfaceid = STARPU_UNKNOWN_INTERFACE_ID,
.interface_size = sizeof(starpu_cham_tile_interface_t),
.name = "STARPU_CHAM_TILE_INTERFACE"
};
void
starpu_cham_tile_register( starpu_data_handle_t *handleptr,
int home_node,
CHAM_tile_t *tile,
cham_flttype_t flttype )
{
size_t elemsize = CHAMELEON_Element_Size( flttype );
starpu_cham_tile_interface_t cham_tile_interface =
{
.id = STARPU_CHAM_TILE_INTERFACE_ID,
.flttype = flttype,
.dev_handle = (intptr_t)(tile->mat),
.allocsize = -1,
.tilesize = tile->m * tile->n * elemsize,
};
memcpy( &(cham_tile_interface.tile), tile, sizeof( CHAM_tile_t ) );
if ( tile->format & CHAMELEON_TILE_FULLRANK ) {
cham_tile_interface.allocsize = tile->m * tile->n * elemsize;
}
else if ( tile->format & CHAMELEON_TILE_DESC ) { /* Needed in case starpu ask for it */
cham_tile_interface.allocsize = tile->m * tile->n * elemsize;
}
else if ( tile->format & CHAMELEON_TILE_HMAT ) {
/* For hmat, allocated data will be handled by hmat library. StarPU cannot allocate it for the library */
cham_tile_interface.allocsize = 0;
}
starpu_data_register( handleptr, home_node, &cham_tile_interface, &starpu_interface_cham_tile_ops );
}
size_t
cti_handle_get_allocsize( starpu_data_handle_t handle )
{
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node( handle, STARPU_MAIN_RAM );
#ifdef STARPU_DEBUG
STARPU_ASSERT_MSG( cham_tile_interface->id == STARPU_CHAM_TILE_INTERFACE_ID,
"Error. The given data is not a cham_tile." );
#endif
return cham_tile_interface->allocsize;
}
#if defined(CHAMELEON_USE_MPI_DATATYPES)
int
cti_allocate_datatype_node( starpu_data_handle_t handle,
unsigned node,
MPI_Datatype *datatype )
{
int ret;
starpu_cham_tile_interface_t *cham_tile_interface = (starpu_cham_tile_interface_t *)
starpu_data_get_interface_on_node( handle, node );
size_t m = cham_tile_interface->tile.m;
size_t n = cham_tile_interface->tile.n;
size_t ld = cham_tile_interface->tile.ld;
size_t elemsize = CHAMELEON_Element_Size( cham_tile_interface->flttype );
ret = MPI_Type_vector( n, m * elemsize, ld * elemsize, MPI_BYTE, datatype );
STARPU_ASSERT_MSG(ret == MPI_SUCCESS, "MPI_Type_vector failed");
ret = MPI_Type_commit( datatype );
STARPU_ASSERT_MSG(ret == MPI_SUCCESS, "MPI_Type_commit failed");
return 0;
}
int
cti_allocate_datatype( starpu_data_handle_t handle,
MPI_Datatype *datatype )
{
return cti_allocate_datatype_node( handle, STARPU_MAIN_RAM, datatype );
}
void
cti_free_datatype( MPI_Datatype *datatype )
{
MPI_Type_free( datatype );
}
#endif
void
starpu_cham_tile_interface_init()
{
if ( starpu_interface_cham_tile_ops.interfaceid == STARPU_UNKNOWN_INTERFACE_ID )
{
starpu_interface_cham_tile_ops.interfaceid = starpu_data_interface_get_next_id();
#if defined(CHAMELEON_USE_MPI_DATATYPES)
#if defined(HAVE_STARPU_MPI_INTERFACE_DATATYPE_NODE_REGISTER)
starpu_mpi_interface_datatype_node_register( starpu_interface_cham_tile_ops.interfaceid,
cti_allocate_datatype_node,
cti_free_datatype );
#else
starpu_mpi_interface_datatype_register( starpu_interface_cham_tile_ops.interfaceid,
cti_allocate_datatype,
cti_free_datatype );
#endif
#endif
}
}
void
starpu_cham_tile_interface_fini()
{
if ( starpu_interface_cham_tile_ops.interfaceid != STARPU_UNKNOWN_INTERFACE_ID )
{
#if defined(CHAMELEON_USE_MPI_DATATYPES)
starpu_mpi_interface_datatype_unregister( starpu_interface_cham_tile_ops.interfaceid );
#endif
}
}