diff --git a/control/auxiliary.c b/control/auxiliary.c index 14fd016ed7a9da87227a87502f7b43c87ca91a08..b00ed6efe4e6db2664278575696bf6b8b52fe119 100644 --- a/control/auxiliary.c +++ b/control/auxiliary.c @@ -53,7 +53,7 @@ * Warning message to display. * ******************************************************************************/ -void morse_warning(const char *func_name, char* msg_text) +void morse_warning(const char *func_name, const char *msg_text) { MORSE_context_t *morse; @@ -78,7 +78,7 @@ void morse_warning(const char *func_name, char* msg_text) * Warning message to display. * ******************************************************************************/ -void morse_error(const char *func_name, char* msg_text) +void morse_error(const char *func_name, const char *msg_text) { fprintf(stderr, "MORSE ERROR: %s(): %s\n", func_name, msg_text); } @@ -96,7 +96,7 @@ void morse_error(const char *func_name, char* msg_text) * Warning message to display. * ******************************************************************************/ -void morse_fatal_error(const char *func_name, char* msg_text) +void morse_fatal_error(const char *func_name, const char *msg_text) { fprintf(stderr, "MORSE FATAL ERROR: %s(): %s\n", func_name, msg_text); exit(0); diff --git a/control/auxiliary.h b/control/auxiliary.h index 653bb38a037cd8188ca450947ba6b2652421043a..147fe1694635c905accafddd9c847ff930f05914 100644 --- a/control/auxiliary.h +++ b/control/auxiliary.h @@ -36,9 +36,9 @@ extern "C" { /******************************************************************************* * Internal routines **/ -void morse_warning (const char *func_name, char* msg_text); -void morse_error (const char *func_name, char* msg_text); -void morse_fatal_error (const char *func_name, char* msg_text); +void morse_warning (const char *func_name, const char* msg_text); +void morse_error (const char *func_name, const char* msg_text); +void morse_fatal_error (const char *func_name, const char* msg_text); int morse_rank (MORSE_context_t *morse); int morse_tune (MORSE_enum func, int M, int N, int NRHS); diff --git a/control/descriptor.c b/control/descriptor.c index e5f4146b2f24538adb9ff3e11cdc18640af3cfaf..b7963cf76d9173c5e11dde119e525827fd514e73 100644 --- a/control/descriptor.c +++ b/control/descriptor.c @@ -38,49 +38,89 @@ static int nbdesc = 0; -/******************************************************************************* - * Internal static descriptor initializer - **/ -MORSE_desc_t morse_desc_init(MORSE_enum dtyp, int mb, int nb, int bsiz, - int lm, int ln, int i, int j, - int m, int n, int p, int q) -{ - return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, - morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d); -} - -/******************************************************************************* - * Internal static descriptor initializer for a block diagonal matrix - **/ -MORSE_desc_t morse_desc_init_diag(MORSE_enum dtyp, int mb, int nb, int bsiz, - int lm, int ln, int i, int j, - int m, int n, int p, int q) -{ - return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, - morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d_diag); -} - -/******************************************************************************* - * Static descriptor initializer for users - **/ +/** + ****************************************************************************** + * + * @ingroup Descriptor + * + * morse_desc_init_user - Internal function to create tiled matrix descriptor + * with generic function for data distribution and storage format. + * + ****************************************************************************** + * + * @param[in] dtyp + * Data type of the matrix: + * @arg MorseRealFloat: single precision real (S), + * @arg MorseRealDouble: double precision real (D), + * @arg MorseComplexFloat: single precision complex (C), + * @arg MorseComplexDouble: double precision complex (Z). + * + * @param[in] mb + * Number of rows in a tile. + * + * @param[in] nb + * Number of columns in a tile. + * + * @param[in] bsiz + * Size in bytes including padding. + * + * @param[in] lm + * Number of rows of the entire matrix. + * + * @param[in] ln + * Number of columns of the entire matrix. + * + * @param[in] i + * Row index to the beginning of the submatrix. + * + * @param[in] j + * Column indes to the beginning of the submatrix. + * + * @param[in] m + * Number of rows of the submatrix. + * + * @param[in] n + * Number of columns of the submatrix. + * + * @param[in] p + * 2D-block cyclic distribution in rows. + * + * @param[in] q + * 2D-block cyclic distribution in columns. + * + * @param[in] (*get_blkaddr)( const MORSE_desc_t *A, int m, int n) + * A function which return the address of the data corresponding to + * the tile A(m,n). + * + * @param[in] (*get_blkldd)( const MORSE_desc_t *A, int m ) + * A function that return the leading dimension of the tile A(m,*). + * + * @param[in] (*get_rankof)( const MORSE_desc_t *A, int m, int n) + * A function that return the MPI rank of the tile A(m,n). + * + ****************************************************************************** + * + * @return The descriptor with the matrix description parameters set. + * + *****************************************************************************/ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz, int lm, int ln, int i, int j, int m, int n, int p, int q, void* (*get_blkaddr)( const MORSE_desc_t*, int, int ), - int (*get_blkldd)( const MORSE_desc_t*, int ), - int (*get_rankof)( const MORSE_desc_t*, int, int )) + int (*get_blkldd) ( const MORSE_desc_t*, int ), + int (*get_rankof) ( const MORSE_desc_t*, int, int )) { MORSE_desc_t desc; // If one of the function get_* is NULL, we switch back to the default, like in morse_desc_init() desc.get_blkaddr = get_blkaddr ? get_blkaddr : morse_getaddr_ccrb; - desc.get_blkldd = get_blkldd ? get_blkldd : morse_getblkldd_ccrb; - desc.get_rankof = get_rankof ? get_rankof : morse_getrankof_2d; + desc.get_blkldd = get_blkldd ? get_blkldd : morse_getblkldd_ccrb; + desc.get_rankof = get_rankof ? get_rankof : morse_getrankof_2d; // Matrix properties desc.dtyp = dtyp; - // seems useless + // Should be given as parameter to follow get_blkaddr (unused) desc.styp = MorseCCRB; - desc.mb = mb; - desc.nb = nb; + desc.mb = mb; + desc.nb = nb; desc.bsiz = bsiz; // Large matrix parameters desc.lm = lm; @@ -99,9 +139,10 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz, desc.id = nbdesc; nbdesc++; desc.occurences = 0; - desc.use_mat = 1; - desc.alloc_mat = 1; + desc.use_mat = 1; + desc.alloc_mat = 1; desc.register_mat = 1; + desc.ooc = 0; RUNTIME_comm_rank( &(desc.myrank) ); @@ -130,12 +171,12 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz, desc.llm1 = (desc.llm/mb); desc.lln1 = (desc.lln/nb); } else { - desc.llmt = 0; - desc.llnt = 0; - desc.llm = 0; - desc.lln = 0; - desc.llm1 = 0; - desc.lln1 = 0; + desc.llmt = 0; + desc.llnt = 0; + desc.llm = 0; + desc.lln = 0; + desc.llm1 = 0; + desc.lln1 = 0; } // Matrix address @@ -149,10 +190,32 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz, return desc; } +/******************************************************************************* + * Internal static descriptor initializer + **/ +MORSE_desc_t morse_desc_init(MORSE_enum dtyp, int mb, int nb, int bsiz, + int lm, int ln, int i, int j, + int m, int n, int p, int q) +{ + return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, + morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d); +} + +/******************************************************************************* + * Internal static descriptor initializer for a block diagonal matrix + **/ +MORSE_desc_t morse_desc_init_diag(MORSE_enum dtyp, int mb, int nb, int bsiz, + int lm, int ln, int i, int j, + int m, int n, int p, int q) +{ + return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, + morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d_diag); +} + /******************************************************************************* * Internal static descriptor initializer for submatrices **/ -MORSE_desc_t* morse_desc_submatrix(MORSE_desc_t *descA, int i, int j, int m, int n ) +MORSE_desc_t* morse_desc_submatrix(MORSE_desc_t *descA, int i, int j, int m, int n) { MORSE_desc_t *descB = malloc(sizeof(MORSE_desc_t)); int mb, nb; @@ -237,7 +300,7 @@ int morse_desc_mat_alloc( MORSE_desc_t *desc ) { size_t size = (size_t)(desc->llm) * (size_t)(desc->lln) - * (size_t)MORSE_Element_Size(desc->dtyp); + * (size_t)MORSE_Element_Size(desc->dtyp); if ((desc->mat = RUNTIME_mat_alloc(size)) == NULL) { morse_error("morse_desc_mat_alloc", "malloc() failed"); return MORSE_ERR_OUT_OF_RESOURCES; @@ -255,12 +318,12 @@ int morse_desc_mat_alloc( MORSE_desc_t *desc ) **/ int morse_desc_mat_free( MORSE_desc_t *desc ) { - RUNTIME_desc_destroy( desc ); - if (desc->mat != NULL && - desc->use_mat == 1 && - desc->alloc_mat == 1) { + if ( (desc->mat != NULL) && + (desc->use_mat == 1 ) && + (desc->alloc_mat == 1 ) ) + { size_t size = (size_t)(desc->llm) * (size_t)(desc->lln) * (size_t)MORSE_Element_Size(desc->dtyp); @@ -270,11 +333,12 @@ int morse_desc_mat_free( MORSE_desc_t *desc ) return MORSE_SUCCESS; } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * - * MORSE_Desc_Create - Create matrix descriptor. + * MORSE_Desc_Create - Create tiled matrix descriptor. * ****************************************************************************** * @@ -331,59 +395,71 @@ int morse_desc_mat_free( MORSE_desc_t *desc ) * \retval MORSE_SUCCESS successful exit * *****************************************************************************/ -int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz, +int MORSE_Desc_Create(MORSE_desc_t **descptr, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz, int lm, int ln, int i, int j, int m, int n, int p, int q) { MORSE_context_t *morse; + MORSE_desc_t *desc; int status; + *descptr = NULL; + morse = morse_context_self(); if (morse == NULL) { morse_error("MORSE_Desc_Create", "MORSE not initialized"); return MORSE_ERR_NOT_INITIALIZED; } + /* Allocate memory and initialize the descriptor */ - *desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t)); - if (*desc == NULL) { + desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t)); + if (desc == NULL) { morse_error("MORSE_Desc_Create", "malloc() failed"); return MORSE_ERR_OUT_OF_RESOURCES; } - **desc = morse_desc_init(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q); + *desc = morse_desc_init(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q); if (mat == NULL) { - size_t size = (size_t)((*desc)->llm) * (size_t)((*desc)->lln) - * (size_t)MORSE_Element_Size((*desc)->dtyp); + size_t size = (size_t)(desc->llm) * (size_t)(desc->lln) + * (size_t)MORSE_Element_Size(desc->dtyp); - if (((*desc)->mat = RUNTIME_mat_alloc(size)) == NULL) { + if ((desc->mat = RUNTIME_mat_alloc(size)) == NULL) { morse_error("MORSE_Desc_Create", "malloc() failed"); return MORSE_ERR_OUT_OF_RESOURCES; } - (*desc)->alloc_mat = 1; + desc->use_mat = 1; + desc->alloc_mat = 1; + desc->register_mat = 0; } else { - (*desc)->mat = mat; - /* memory of the matrix is handle by users */ - (*desc)->alloc_mat = 0; + desc->mat = mat; + /* memory of the matrix is handled by users */ + desc->alloc_mat = 0; + desc->use_mat = 1; + desc->register_mat = 0; } /* Create scheduler structure like registering data */ - RUNTIME_desc_create( *desc ); + RUNTIME_desc_create( desc ); - status = morse_desc_check(*desc); + status = morse_desc_check( desc ); if (status != MORSE_SUCCESS) { morse_error("MORSE_Desc_Create", "invalid descriptor"); + MORSE_Desc_Destroy( &desc ); return status; } + *descptr = desc; return MORSE_SUCCESS; } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * - * MORSE_Desc_Create_User - Create matrix descriptor for general applications. + * MORSE_Desc_Create_User - Create generic tiled matrix descriptor for general + * applications. * ****************************************************************************** * @@ -410,7 +486,7 @@ int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, i * @param[in] n * Number of columns of the entire matrix. * - * @param[in] p + * @param[in] p * 2d-block cyclic partitioning, number of tiles in rows. * * @param[in] q @@ -432,53 +508,205 @@ int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, i * \retval MORSE_SUCCESS successful exit * *****************************************************************************/ -int MORSE_Desc_Create_User(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz, +int MORSE_Desc_Create_User(MORSE_desc_t **descptr, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz, int lm, int ln, int i, int j, int m, int n, int p, int q, void* (*get_blkaddr)( const MORSE_desc_t*, int, int ), - int (*get_blkldd)( const MORSE_desc_t*, int ), - int (*get_rankof)( const MORSE_desc_t*, int, int )) + int (*get_blkldd) ( const MORSE_desc_t*, int ), + int (*get_rankof) ( const MORSE_desc_t*, int, int )) { MORSE_context_t *morse; + MORSE_desc_t *desc; int status; + *descptr = NULL; + morse = morse_context_self(); if (morse == NULL) { - morse_error("MORSE_Desc_Create", "MORSE not initialized"); + morse_error("MORSE_Desc_Create_User", "MORSE not initialized"); return MORSE_ERR_NOT_INITIALIZED; } + /* Allocate memory and initialize the descriptor */ - *desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t)); - if (*desc == NULL) { - morse_error("MORSE_Desc_Create", "malloc() failed"); + desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t)); + if (desc == NULL) { + morse_error("MORSE_Desc_Create_User", "malloc() failed"); return MORSE_ERR_OUT_OF_RESOURCES; } - **desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, - get_blkaddr, get_blkldd, get_rankof); + + *desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, + get_blkaddr, get_blkldd, get_rankof); /* if the user gives a pointer to the overall data (tiles) we can use it */ - (**desc).use_mat = (mat == NULL) ? 0 : 1; + desc->use_mat = (mat == NULL) ? 0 : 1; - /* memory of the matrix is handle by users */ - (**desc).alloc_mat = 0; + /* memory of the matrix is handled by the user */ + desc->alloc_mat = 0; /* users data can have multiple forms: let him register tiles */ - (**desc).register_mat = 0; + desc->register_mat = 0; + + desc->mat = mat; + + /* Create runtime specific structure like registering data */ + RUNTIME_desc_create( desc ); + + status = morse_desc_check( desc ); + if (status != MORSE_SUCCESS) { + morse_error("MORSE_Desc_Create_User", "invalid descriptor"); + MORSE_Desc_Destroy( &desc ); + return status; + } + + *descptr = desc; + return MORSE_SUCCESS; +} + +/** + ***************************************************************************** + * + * @ingroup Descriptor + * + * MORSE_Desc_Create_OOC_User - Create matrix descriptor for tiled matrix which + * may not fit memory. + * + ****************************************************************************** + * + * @param[out] desc + * On exit, descriptor of the matrix. + * + * @param[in] dtyp + * Data type of the matrix: + * @arg MorseRealFloat: single precision real (S), + * @arg MorseRealDouble: double precision real (D), + * @arg MorseComplexFloat: single precision complex (C), + * @arg MorseComplexDouble: double precision complex (Z). + * + * @param[in] nb + * Number of rows and columns in a tile. + * + * @param[in] m + * Number of rows of the entire matrix. + * + * @param[in] n + * Number of columns of the entire matrix. + * + * @param[in] p + * 2d-block cyclic partitioning, number of tiles in rows. + * + * @param[in] q + * 2d-block cyclic partitioning, number of tiles in columns. + * + * @param[in] (*get_rankof)( const MORSE_desc_t *A, int m, int n) + * A function that return the MPI rank of the tile A(m,n). + * + ****************************************************************************** + * + * @return + * \retval MORSE_SUCCESS successful exit + * + *****************************************************************************/ +int MORSE_Desc_Create_OOC_User(MORSE_desc_t **descptr, MORSE_enum dtyp, int mb, int nb, int bsiz, + int lm, int ln, int i, int j, int m, int n, int p, int q, + int (*get_rankof)( const MORSE_desc_t*, int, int )) +{ +#if !defined (CHAMELEON_SCHED_STARPU) + morse_error("MORSE_Desc_Create_OOC_User", "Only StarPU supports on-demand tile allocation"); + return MORSE_ERR_NOT_INITIALIZED; +#else + MORSE_context_t *morse; + MORSE_desc_t *desc; + int status; - (**desc).mat = mat; + *descptr = NULL; + + morse = morse_context_self(); + if (morse == NULL) { + morse_error("MORSE_Desc_Create_OOC_User", "MORSE not initialized"); + return MORSE_ERR_NOT_INITIALIZED; + } + /* Allocate memory and initialize the descriptor */ + desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t)); + if (desc == NULL) { + morse_error("MORSE_Desc_Create_OOC_User", "malloc() failed"); + return MORSE_ERR_OUT_OF_RESOURCES; + } + *desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q, + morse_getaddr_null, NULL, get_rankof); + + /* memory of the matrix is completely handled by runtime */ + desc->use_mat = 0; + desc->alloc_mat = 0; + desc->register_mat = 0; + + desc->mat = NULL; + desc->ooc = 1; /* Create scheduler structure like registering data */ - RUNTIME_desc_create( *desc ); + RUNTIME_desc_create( desc ); - status = morse_desc_check(*desc); + status = morse_desc_check( desc ); if (status != MORSE_SUCCESS) { - morse_error("MORSE_Desc_Create", "invalid descriptor"); + morse_error("MORSE_Desc_Create_OOC_User", "invalid descriptor"); + MORSE_Desc_Destroy( &desc ); return status; } + *descptr = desc; return MORSE_SUCCESS; +#endif } -/** *************************************************************************** +/** + ***************************************************************************** + * + * @ingroup Descriptor + * + * MORSE_Desc_Create_OOC - Create matrix descriptor for tiled matrix which may + * not fit memory. + * + ****************************************************************************** + * + * @param[out] desc + * On exit, descriptor of the matrix. + * + * @param[in] dtyp + * Data type of the matrix: + * @arg MorseRealFloat: single precision real (S), + * @arg MorseRealDouble: double precision real (D), + * @arg MorseComplexFloat: single precision complex (C), + * @arg MorseComplexDouble: double precision complex (Z). + * + * @param[in] nb + * Number of rows and columns in a tile. + * + * @param[in] m + * Number of rows of the entire matrix. + * + * @param[in] n + * Number of columns of the entire matrix. + * + * @param[in] p + * 2d-block cyclic partitioning, number of tiles in rows. + * + * @param[in] q + * 2d-block cyclic partitioning, number of tiles in columns. + * + ****************************************************************************** + * + * @return + * \retval MORSE_SUCCESS successful exit + * + *****************************************************************************/ +int MORSE_Desc_Create_OOC(MORSE_desc_t **descptr, MORSE_enum dtyp, int mb, int nb, int bsiz, + int lm, int ln, int i, int j, int m, int n, int p, int q) +{ + return MORSE_Desc_Create_OOC_User( descptr, dtyp, mb, nb, bsiz, + lm, ln, i, j, m, n, p, q, + morse_getrankof_2d ); +} + +/** + ***************************************************************************** * * @ingroup Descriptor * @@ -516,7 +744,8 @@ int MORSE_Desc_Destroy(MORSE_desc_t **desc) return MORSE_SUCCESS; } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * @@ -535,10 +764,11 @@ int MORSE_Desc_Destroy(MORSE_desc_t **desc) * *****************************************************************************/ int MORSE_Desc_Acquire (MORSE_desc_t *desc) { - return RUNTIME_desc_acquire( desc ); + return RUNTIME_desc_acquire( desc ); } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * @@ -558,10 +788,11 @@ int MORSE_Desc_Acquire (MORSE_desc_t *desc) { * *****************************************************************************/ int MORSE_Desc_Release (MORSE_desc_t *desc) { - return RUNTIME_desc_release( desc ); + return RUNTIME_desc_release( desc ); } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * @@ -580,17 +811,18 @@ int MORSE_Desc_Release (MORSE_desc_t *desc) { * *****************************************************************************/ int MORSE_Desc_Getoncpu(MORSE_desc_t *desc) { - return RUNTIME_desc_getoncpu( desc ); + return RUNTIME_desc_getoncpu( desc ); } -/** *************************************************************************** +/** + ***************************************************************************** * * @ingroup Descriptor * * MORSE_user_tag_size - Set the sizes for the MPI tags - * Default value: tag_width=31, tag_sep=24, meaning that the MPI tag is stored in 31 bits, - * with 24 bits for the tile tag and 7 for the descriptor. - * This function must be called before any descriptor creation. + * Default value: tag_width=31, tag_sep=24, meaning that the MPI tag is stored + * in 31 bits, with 24 bits for the tile tag and 7 for the descriptor. This + * function must be called before any descriptor creation. * ****************************************************************************** * @@ -607,6 +839,6 @@ int MORSE_Desc_Getoncpu(MORSE_desc_t *desc) { * *****************************************************************************/ void MORSE_user_tag_size(int user_tag_width, int user_tag_sep) { - RUNTIME_user_tag_size(user_tag_width, user_tag_sep); - return; + RUNTIME_user_tag_size(user_tag_width, user_tag_sep); + return; } diff --git a/control/descriptor.h b/control/descriptor.h index 7d1cb20577e03e7c25e45a93f2253d295130f784..0d3d2173bd130d2dea2722eda16b2d4ffb56231b 100644 --- a/control/descriptor.h +++ b/control/descriptor.h @@ -41,6 +41,7 @@ extern "C" { inline static void* morse_geteltaddr(const MORSE_desc_t *A, int m, int n, int eltsize); inline static void* morse_getaddr_cm (const MORSE_desc_t *A, int m, int n); inline static void* morse_getaddr_ccrb (const MORSE_desc_t *A, int m, int n); +inline static void* morse_getaddr_null (const MORSE_desc_t *A, int m, int n); inline static int morse_getblkldd_cm (const MORSE_desc_t *A, int m); inline static int morse_getblkldd_ccrb(const MORSE_desc_t *A, int m); @@ -120,6 +121,15 @@ inline static void *morse_getaddr_cm(const MORSE_desc_t *A, int m, int n) return (void*)((intptr_t)A->mat + (offset*eltsize) ); } +/******************************************************************************* + * Internal function to return address of block (m,n) with m,n = block indices + * This version lets the runtime allocate on-demand. + **/ +inline static void *morse_getaddr_null(const MORSE_desc_t *A, int m, int n) +{ + return NULL; +} + /******************************************************************************* * Internal function to return address of element A(m,n) with m,n = matrix indices **/ diff --git a/docs/texinfo/chapters/configuration.texi b/docs/texinfo/chapters/configuration.texi index a147cf1f9cdfee0626d03a279d62a2f8daadb745..d57a476a99607ec8b487539c8af94afac8a945ae 100644 --- a/docs/texinfo/chapters/configuration.texi +++ b/docs/texinfo/chapters/configuration.texi @@ -344,3 +344,26 @@ Database of models is subject to change, it should be enrich in a near future. One can additionally decide to enable the magma kernels by setting the cmake option @option{-DCHAMELEON_SIMULATION_MAGMA=ON} . + +@node Use out of core support with StarPU +@section Use out of core support with StarPU + +If the matrix can not fit in the main memory, StarPU can automatically evict +tiles to the disk. The following variables need to be set: +@itemize @bullet +@item @env{STARPU_DISK_SWAP} environment variable to a place where to store +evicted tiles, for example: + @example + @env{STARPU_DISK_SWAP}=/tmp + @end example +@item @env{STARPU_DISK_SWAP_BACKEND} environment variable to the I/O method, +for example: + @example + @env{STARPU_DISK_SWAP_BACKEND}=unistd_o_direct + @end example +@item @env{STARPU_LIMIT_CPU_MEM} environment variable to the amount of memory +that can be used in MBytes, for example: + @example + @env{STARPU_LIMIT_CPU_MEM}=1000 + @end example +@end itemize diff --git a/docs/texinfo/chapters/using.texi b/docs/texinfo/chapters/using.texi index 47bf96ddf5a6e25c14fc9cb4225c3a391865649f..4cfd8e6626b79a17baaf587765ffbeb527fb5cf0 100644 --- a/docs/texinfo/chapters/using.texi +++ b/docs/texinfo/chapters/using.texi @@ -435,6 +435,9 @@ This can be achieved from different ways. @item Use the existing function @code{MORSE_Desc_Create}: means the matrix data are considered contiguous in memory as it is considered in PLASMA (@ref{Tile Data Layout}). +@item Use the existing function @code{MORSE_Desc_Create_OOC}: means the +matrix data is allocated on-demand in memory tile by tile, and possibly pushed +to disk if that does not fit memory. @item Use the existing function @code{MORSE_Desc_Create_User}: it is more flexible than @code{Desc_Create} because you can give your own way to access to tile data so that your tiles can be allocated wherever you want in memory, see diff --git a/example/out_of_core/out_of_core.h b/example/out_of_core/out_of_core.h index dcb9e970292bb2ec1ca5c803b69fb42bcbf8454e..95a25dcbcf149999e1ad5046a7f03ea783c97406 100644 --- a/example/out_of_core/out_of_core.h +++ b/example/out_of_core/out_of_core.h @@ -260,13 +260,4 @@ print_o_direct_wont_work(void) { "multiples of 4096. Tip : chose 'n' and 'nb' as both multiples of 32.\n"); } -/****************************************************************************** - * Ffunction to return address of block (m,n) -> here NULL because memory is - * directly handled by StarPU - **/ -inline static void* morse_getaddr_null(const MORSE_desc_t *A, int m, int n) -{ - return (void*)( NULL ); -} - #endif /* OOC_H */ diff --git a/include/morse.h.in b/include/morse.h.in index 9473b6e1cb8754b10e636f725ce5a550fae62586..b0460b6950bfbf8c3f5967742c730421143cec7b 100644 --- a/include/morse.h.in +++ b/include/morse.h.in @@ -90,6 +90,13 @@ int MORSE_Desc_Create_User(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int void* (*get_blkaddr)( const MORSE_desc_t*, int, int ), int (*get_blkldd)( const MORSE_desc_t*, int ), int (*get_rankof)( const MORSE_desc_t*, int, int )); +int MORSE_Desc_Create_OOC(MORSE_desc_t **desc, MORSE_enum dtyp, + int mb, int nb, int bsiz, int lm, int ln, + int i, int j, int m, int n, int p, int q); +int MORSE_Desc_Create_OOC_User(MORSE_desc_t **desc, MORSE_enum dtyp, + int mb, int nb, int bsiz, int lm, int ln, + int i, int j, int m, int n, int p, int q, + int (*get_rankof)( const MORSE_desc_t*, int, int )); int MORSE_Desc_Destroy (MORSE_desc_t **desc); int MORSE_Desc_Acquire (MORSE_desc_t *desc); int MORSE_Desc_Release (MORSE_desc_t *desc); diff --git a/include/morse_struct.h b/include/morse_struct.h index f307645d27a6b5ab39cbc36963b8dee547409cd3..2aacefcdf501d36326ba63fbc2081400fae2af65 100644 --- a/include/morse_struct.h +++ b/include/morse_struct.h @@ -108,6 +108,7 @@ struct morse_desc_s { int alloc_mat; // 1 if we handle the allocation of mat - else 0 int register_mat; // 1 if we have to register mat - else 0 (handled by the application) int myrank; // MPI rank of the descriptor + int ooc; // 1 if the matrix is not to fit in memory void *schedopt; // scheduler (QUARK|StarPU) specific structure }; diff --git a/runtime/starpu/control/runtime_descriptor.c b/runtime/starpu/control/runtime_descriptor.c index 3f6a1e28502f67435c3ce7446f175a9e3d120805..62b84a75286729194f2037807fd2405ad2ca11e6 100644 --- a/runtime/starpu/control/runtime_descriptor.c +++ b/runtime/starpu/control/runtime_descriptor.c @@ -22,6 +22,7 @@ * **/ #include <stdlib.h> +#include <unistd.h> #include "runtime/starpu/include/morse_starpu.h" #if defined(CHAMELEON_USE_MPI) @@ -118,6 +119,21 @@ void RUNTIME_desc_create( MORSE_desc_t *desc ) } } #endif + if (desc->ooc) { + int lastmm = desc->lm - (desc->lmt-1) * desc->mb; + int lastnn = desc->ln - (desc->lnt-1) * desc->nb; + int64_t eltsze = MORSE_Element_Size(desc->dtyp); + int pagesize = getpagesize(); + + if ((desc->mb * desc->nb * eltsze) % pagesize != 0 + || (lastmm * desc->nb * eltsze) % pagesize != 0 + || (desc->mb * lastnn * eltsze) % pagesize != 0 + || (lastmm * lastnn * eltsze) % pagesize != 0) + { + morse_error("RUNTIME_desc_create", "Matrix and tile size not suitable for out-of-core: all tiles have to be multiples of 4096. Tip : choose 'n' and 'nb' as both multiples of 32."); + return; + } + } #if defined(CHAMELEON_USE_MPI) /* @@ -279,6 +295,10 @@ int RUNTIME_desc_getoncpu( MORSE_desc_t *desc ) int lnt = desc->lnt; int m, n; + if (desc->ooc) + /* May not even fit */ + return MORSE_SUCCESS; + for (n = 0; n < lnt; n++) for (m = 0; m < lmt; m++) { diff --git a/timing/timing.c b/timing/timing.c index d271202961ae3c3200abd8aa1d7a61efdf7b8c19..d2b73d49b7963115401402b1c94957f8c5b2c5f9 100644 --- a/timing/timing.c +++ b/timing/timing.c @@ -475,6 +475,7 @@ main(int argc, char *argv[]) { iparam[IPARAM_TRACE ] = 0; iparam[IPARAM_DAG ] = 0; iparam[IPARAM_ASYNC ] = 1; + iparam[IPARAM_OOC ] = 0; iparam[IPARAM_MX ] = -1; iparam[IPARAM_NX ] = -1; iparam[IPARAM_RHBLK ] = 0; @@ -549,6 +550,10 @@ main(int argc, char *argv[]) { iparam[IPARAM_ASYNC] = 0; } else if (startswith( argv[i], "--async" )) { iparam[IPARAM_ASYNC] = 1; + } else if (startswith( argv[i], "--ooc" )) { + iparam[IPARAM_OOC] = 1; + } else if (startswith( argv[i], "--noooc" )) { + iparam[IPARAM_OOC] = 0; } else if (startswith( argv[i], "--n_range=" )) { get_range( strchr( argv[i], '=' ) + 1, &start, &stop, &step ); } else if (startswith( argv[i], "--m=" )) { diff --git a/timing/timing.h b/timing/timing.h index 3d33748a61ec65e73fc2f4e5e5410d9e5e15a04e..1b4bacb354e3613422833eaddeb9650202bb0055 100644 --- a/timing/timing.h +++ b/timing/timing.h @@ -38,6 +38,7 @@ enum iparam_timing { IPARAM_TRACE, /* Generate trace on the first non warmup run */ IPARAM_DAG, /* Do we require to output the DOT file? */ IPARAM_ASYNC, /* Asynchronous calls */ + IPARAM_OOC, /* Out of Core */ IPARAM_MX, /* */ IPARAM_NX, /* */ IPARAM_RHBLK, /* Householder reduction parameter for QR/LQ */ @@ -97,6 +98,7 @@ enum dparam_timing { int64_t MT = (M%MB==0) ? (M/MB) : (M/MB+1); \ int64_t NT = (N%NB==0) ? (N/NB) : (N/NB+1); \ int bigmat = iparam[IPARAM_BIGMAT]; \ + int ooc = iparam[IPARAM_OOC]; \ int check = iparam[IPARAM_CHECK]; \ int loud = iparam[IPARAM_VERBOSE]; \ (void)M;(void)N;(void)K;(void)NRHS; \ @@ -107,15 +109,18 @@ enum dparam_timing { /* Paste code to allocate a matrix in desc if cond_init is true */ #define PASTE_CODE_ALLOCATE_MATRIX_TILE(_desc_, _cond_, _type_, _type2_, _lda_, _m_, _n_) \ MORSE_desc_t *_desc_ = NULL; \ - int status ## _desc_ ; \ + int status ## _desc_ ; \ if( _cond_ ) { \ - if (!bigmat) \ - status ## _desc_ = MORSE_Desc_Create_User(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \ - P, Q, morse_getaddr_null, NULL, NULL);\ - else \ - status ## _desc_ = MORSE_Desc_Create(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \ - P, Q);\ - if (status ## _desc_ != MORSE_SUCCESS) return (status ## _desc_); \ + if (ooc) \ + status ## _desc_ = MORSE_Desc_Create_OOC(&(_desc_), _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \ + P, Q); \ + else if (!bigmat) \ + status ## _desc_ = MORSE_Desc_Create_User(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \ + P, Q, morse_getaddr_null, NULL, NULL); \ + else \ + status ## _desc_ = MORSE_Desc_Create(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \ + P, Q); \ + if (status ## _desc_ != MORSE_SUCCESS) return (status ## _desc_); \ } #define PASTE_CODE_FREE_MATRIX(_desc_) \