diff --git a/control/control.c b/control/control.c
index 374ec1c873b68005d31746575135b94b2c2805cd..af8de2390d25bac1285d290e726a044b559e6aa4 100644
--- a/control/control.c
+++ b/control/control.c
@@ -102,12 +102,12 @@ int __chameleon_initpar(int ncpus, int ngpus, int nthreads_per_worker)
            * In testings, only StarPU's internal thread performs
            * communications, and *then* Chameleon performs communications in
            * the check step. */
-          const int required = MPI_THREAD_SERIALIZED;
+          const int required = MPI_THREAD_MULTIPLE;
           if ( MPI_Init_thread( NULL, NULL, required, &provided ) != MPI_SUCCESS) {
              chameleon_fatal_error("CHAMELEON_Init", "MPI_Init_thread() failed");
           }
           if ( provided < required ) {
-             chameleon_fatal_error("CHAMELEON_Init", "MPI_Init_thread() was not able to provide the requested thread support");
+             chameleon_fatal_error("CHAMELEON_Init", "MPI_Init_thread() was not able to provide the requested thread support (MPI_THREAD_MULTIPLE), this may be an issue if the level provided is not enough for the underlying runtime system.");
           }
       }
     }
diff --git a/control/descriptor.c b/control/descriptor.c
index 2cbd9fd18099538deb33dd3e493c377f5ea3e773..8c054d98d43b96f9e15c864452c933d3eec00762 100644
--- a/control/descriptor.c
+++ b/control/descriptor.c
@@ -943,30 +943,6 @@ int CHAMELEON_Desc_Flush( const CHAM_desc_t        *desc,
     return CHAMELEON_SUCCESS;
 }
 
-/**
- *****************************************************************************
- *
- * @ingroup Descriptor
- *
- *  CHAMELEON_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.
- *
- ******************************************************************************
- *
- * @param[in] user_tag_width
- *          The new value for tag_width.
- *
- * @param[in] user_tag_sep
- *          The new value for tag_sep.
- *
- */
-void CHAMELEON_user_tag_size(int user_tag_width, int user_tag_sep) {
-    RUNTIME_comm_set_tag_sizes( user_tag_width, user_tag_sep );
-    return;
-}
-
 static void
 chameleon_desc_print( const CHAM_desc_t *desc, int shift )
 {
diff --git a/doc/user/chapters/using.org b/doc/user/chapters/using.org
index 0e729276989f8c1cb67049fe6102ea2145e8530f..18c2f1e74414368f72f1ad72eb5e9dce90dea93f 100644
--- a/doc/user/chapters/using.org
+++ b/doc/user/chapters/using.org
@@ -1050,14 +1050,6 @@
      int CHAMELEON_Desc_Flush(CHAM_desc_t  *desc, RUNTIME_sequence_t *sequence);
      #+end_src
 
-     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.
-     #+begin_src
-     void CHAMELEON_user_tag_size(int user_tag_width, int user_tag_sep);
-     #+end_src
-
 **** Sequences routines
 
      Create a sequence.
diff --git a/include/chameleon.h b/include/chameleon.h
index c0a9ea9a9f6896be35a78ffab0b2e264c2bf6772..8c3669af397ac25e53bdbd55c33feced0947a48e 100644
--- a/include/chameleon.h
+++ b/include/chameleon.h
@@ -161,7 +161,13 @@ int  CHAMELEON_Disable (int option);
 int  CHAMELEON_Set     (int param, int  value);
 int  CHAMELEON_Get     (int param, int *value);
 int  CHAMELEON_Set_update_progress_callback(void (*p)(int, int)) ;
-void CHAMELEON_user_tag_size(int, int);
+
+static inline void CHAMELEON_user_tag_size(int, int)  __attribute__((deprecated("This function is no longer needed")));;
+static inline void CHAMELEON_user_tag_size(int user_tag_width, int user_tag_sep) {
+    (void)user_tag_width;
+    (void)user_tag_sep;
+    return;
+}
 
 /* Sequences */
 int CHAMELEON_Sequence_Create  (RUNTIME_sequence_t **sequence);
diff --git a/include/chameleon/runtime.h b/include/chameleon/runtime.h
index 8d4570f3c24d3146cef2a206448be07b80ba504f..82818ba75fd6884940601b5e022a40ee96024a5a 100644
--- a/include/chameleon/runtime.h
+++ b/include/chameleon/runtime.h
@@ -214,22 +214,6 @@ RUNTIME_comm_rank( CHAM_context_t *ctxt );
 int
 RUNTIME_comm_size( CHAM_context_t *ctxt );
 
-/**
- * @brief Set the data tags bounds based on runtime tags limit.
- *
- * @param[in] user_tag_width
- *            Total number of bits used to defined the data tags (31 by default).
- *            Must be larger than 20.
- *
- * @param[in] user_tag_sep
- *            The number of bits dedicated to identify the pieces of data per
- *            descriptor.  (user_tag_width - user_tag_sep) defines the number of
- *            bits used to enumerate the descriptors.
- */
-void
-RUNTIME_comm_set_tag_sizes( int user_tag_width,
-                            int user_tag_sep );
-
 /**
  * @}
  *
diff --git a/include/chameleon/struct.h b/include/chameleon/struct.h
index e5df8fa6d030c831598cce505de55981bea35cca..289f4cad9c32e4602b1beda5503aa60ac72725ad 100644
--- a/include/chameleon/struct.h
+++ b/include/chameleon/struct.h
@@ -121,6 +121,7 @@ struct chameleon_desc_s {
     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
+    int64_t mpitag;   // First MPI tag used by the decriptor
     void *schedopt;   // scheduler (QUARK|StarPU) specific structure
 };
 
diff --git a/runtime/openmp/control/runtime_descriptor.c b/runtime/openmp/control/runtime_descriptor.c
index 4cfff1164994fe07fd3f9fa555b4dd8580f1319c..ecec4def24f49034cccf3b0eacf38e2ab0a6018e 100644
--- a/runtime/openmp/control/runtime_descriptor.c
+++ b/runtime/openmp/control/runtime_descriptor.c
@@ -21,13 +21,6 @@
  */
 #include "chameleon_openmp.h"
 
-void RUNTIME_comm_set_tag_sizes( int user_tag_width,
-                                 int user_tag_sep )
-{
-    (void)user_tag_width;
-    (void)user_tag_sep;
-}
-
 void *RUNTIME_malloc( size_t size )
 {
     return malloc( size );
diff --git a/runtime/parsec/control/runtime_descriptor.c b/runtime/parsec/control/runtime_descriptor.c
index 0faed4a68a4b318a8f9444ca4253563633e75d0c..84fecb36063093e3770b4ae55cff2eb9015994dd 100644
--- a/runtime/parsec/control/runtime_descriptor.c
+++ b/runtime/parsec/control/runtime_descriptor.c
@@ -41,13 +41,6 @@ static chameleon_parsec_arena_t chameleon_parsec_registered_arenas[CHAMELEON_PAR
 
 #endif
 
-void RUNTIME_comm_set_tag_sizes( int user_tag_width,
-                                 int user_tag_sep )
-{
-    (void)user_tag_width;
-    (void)user_tag_sep;
-}
-
 void *RUNTIME_malloc( size_t size )
 {
     return malloc(size);
diff --git a/runtime/quark/control/runtime_descriptor.c b/runtime/quark/control/runtime_descriptor.c
index fc3f28020621d32f9a82d0dcb89374463cccb64d..1e9be06faf1e072269dfeea60eda2ef463214d3e 100644
--- a/runtime/quark/control/runtime_descriptor.c
+++ b/runtime/quark/control/runtime_descriptor.c
@@ -22,13 +22,6 @@
  */
 #include "chameleon_quark.h"
 
-void RUNTIME_comm_set_tag_sizes( int user_tag_width,
-                                 int user_tag_sep )
-{
-    (void)user_tag_width;
-    (void)user_tag_sep;
-}
-
 void *RUNTIME_malloc( size_t size )
 {
     return malloc( size );
diff --git a/runtime/starpu/CMakeLists.txt b/runtime/starpu/CMakeLists.txt
index 0968de66d35b777f2efbbc2d75ebfdbc9ccdb475..c70669ba446ec0ef40cc53c3b3cd9721310ee942 100644
--- a/runtime/starpu/CMakeLists.txt
+++ b/runtime/starpu/CMakeLists.txt
@@ -222,6 +222,7 @@ set(RUNTIME_COMMON
   control/runtime_context.c
   control/runtime_control.c
   control/runtime_descriptor.c
+  control/runtime_tags.c
   control/runtime_options.c
   control/runtime_profiling.c
   control/runtime_workspace.c
diff --git a/runtime/starpu/codelets/codelet_zgemm.c b/runtime/starpu/codelets/codelet_zgemm.c
index 549c609ecf392fc5bb199a27fecfc85a7f5f1b54..53f241f899d219846396b802e54a27df9eeeb749 100644
--- a/runtime/starpu/codelets/codelet_zgemm.c
+++ b/runtime/starpu/codelets/codelet_zgemm.c
@@ -195,6 +195,7 @@ void INSERT_TASK_zgemm_Astat( const RUNTIME_option_t *options,
     }
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
@@ -271,9 +272,11 @@ void INSERT_TASK_zgemm( const RUNTIME_option_t *options,
     accessC = ( beta == 0. ) ? STARPU_W : (STARPU_RW | ((beta == 1.) ? STARPU_COMMUTE : 0));
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
-        chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
+        chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name,
+                            clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
         cl_name = cl_fullname;
     }
 #endif
diff --git a/runtime/starpu/codelets/codelet_zhemm.c b/runtime/starpu/codelets/codelet_zhemm.c
index de82bcce360c5d20759b66ff53316b54e361a496..52b923f98b8438431a8091adaee3294105158b29 100644
--- a/runtime/starpu/codelets/codelet_zhemm.c
+++ b/runtime/starpu/codelets/codelet_zhemm.c
@@ -186,6 +186,7 @@ void INSERT_TASK_zhemm_Astat( const RUNTIME_option_t *options,
     }
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
@@ -261,6 +262,7 @@ void INSERT_TASK_zhemm( const RUNTIME_option_t *options,
     accessC = ( beta == 0. ) ? STARPU_W : (STARPU_RW | ((beta == 1.) ? STARPU_COMMUTE : 0));
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
diff --git a/runtime/starpu/codelets/codelet_zherk.c b/runtime/starpu/codelets/codelet_zherk.c
index 29301b83097c8b61383c00861777c35917ac27cd..19bf62ba2146006361df47daef4c2f95e8e84850 100644
--- a/runtime/starpu/codelets/codelet_zherk.c
+++ b/runtime/starpu/codelets/codelet_zherk.c
@@ -151,6 +151,7 @@ void INSERT_TASK_zherk( const RUNTIME_option_t *options,
     accessC = ( beta == 0. ) ? STARPU_W : STARPU_RW;
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s )", cl_name, clargs->tileA->name, clargs->tileC->name );
diff --git a/runtime/starpu/codelets/codelet_zsymm.c b/runtime/starpu/codelets/codelet_zsymm.c
index 3000eb17d8f5795faa57ba48eef9c01a6c32a58b..0012ed7d1b67b339419ae437f5fd464e79d3a29e 100644
--- a/runtime/starpu/codelets/codelet_zsymm.c
+++ b/runtime/starpu/codelets/codelet_zsymm.c
@@ -187,6 +187,7 @@ void INSERT_TASK_zsymm_Astat( const RUNTIME_option_t *options,
     }
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
@@ -262,6 +263,7 @@ void INSERT_TASK_zsymm( const RUNTIME_option_t *options,
     accessC = ( beta == 0. ) ? STARPU_W : (STARPU_RW | ((beta == 1.) ? STARPU_COMMUTE : 0));
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name, clargs->tileC->name );
diff --git a/runtime/starpu/codelets/codelet_zsyrk.c b/runtime/starpu/codelets/codelet_zsyrk.c
index 4df1a23030b6fc74f5816197878a5854c07be3c0..863e28648b0745d347801078f2417a787ba7df6a 100644
--- a/runtime/starpu/codelets/codelet_zsyrk.c
+++ b/runtime/starpu/codelets/codelet_zsyrk.c
@@ -152,6 +152,7 @@ void INSERT_TASK_zsyrk( const RUNTIME_option_t *options,
     accessC = ( beta == 0. ) ? STARPU_W : STARPU_RW;
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s )", cl_name, clargs->tileA->name, clargs->tileC->name );
diff --git a/runtime/starpu/codelets/codelet_ztrmm.c b/runtime/starpu/codelets/codelet_ztrmm.c
index ec98d97574cb16d54704264a14d9120e5571a979..c9f4ea32b5fb2fc4c22811247a3b9907182523e1 100644
--- a/runtime/starpu/codelets/codelet_ztrmm.c
+++ b/runtime/starpu/codelets/codelet_ztrmm.c
@@ -142,6 +142,7 @@ void INSERT_TASK_ztrmm( const RUNTIME_option_t *options,
     callback = options->profiling ? cl_ztrmm_callback : NULL;
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name );
diff --git a/runtime/starpu/codelets/codelet_ztrsm.c b/runtime/starpu/codelets/codelet_ztrsm.c
index d4c063b0d3069276c251e0f47f33556c0cb11ab2..1ce23594d3f7928c03ba049e9ee043abee4c7c5a 100644
--- a/runtime/starpu/codelets/codelet_ztrsm.c
+++ b/runtime/starpu/codelets/codelet_ztrsm.c
@@ -147,6 +147,7 @@ void INSERT_TASK_ztrsm( const RUNTIME_option_t *options,
     callback = options->profiling ? cl_ztrsm_callback : NULL;
 
 #if defined(CHAMELEON_KERNELS_TRACE)
+    if ( clargs != NULL )
     {
         char *cl_fullname;
         chameleon_asprintf( &cl_fullname, "%s( %s, %s )", cl_name, clargs->tileA->name, clargs->tileB->name );
diff --git a/runtime/starpu/control/runtime_descriptor.c b/runtime/starpu/control/runtime_descriptor.c
index 385adc0df81a1a87de81971fe3590853b5214287..3438d0cb28cd51e549a488987ccd3d17e8afdaa2 100644
--- a/runtime/starpu/control/runtime_descriptor.c
+++ b/runtime/starpu/control/runtime_descriptor.c
@@ -30,57 +30,6 @@
  */
 #if defined(CHAMELEON_USE_MPI)
 
-/* Take 24 bits for the tile id, and 7 bits for descriptor id.
- These values can be changed through the call CHAMELEON_user_tag_size(int tag_width, int tag_sep) */
-#define TAG_WIDTH_MIN 20
-static int tag_width = 64;
-static int tag_sep   = 40;
-static int _tag_mpi_initialized_ = 0;
-
-static inline int
-chameleon_starpu_tag_init( int user_tag_width,
-                           int user_tag_sep )
-{
-    if (!_tag_mpi_initialized_) {
-        int ok = 0;
-        uintptr_t tag_ub;
-
-        tag_width = user_tag_width;
-        tag_sep   = user_tag_sep;
-
-        void *tag_ub_p = NULL;
-#if defined(HAVE_STARPU_MPI_COMM_GET_ATTR)
-        starpu_mpi_comm_get_attr(MPI_COMM_WORLD, STARPU_MPI_TAG_UB, &tag_ub_p, &ok);
-#else
-        MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &tag_ub_p, &ok);
-#endif
-        tag_ub = (uintptr_t)tag_ub_p;
-
-        if ( !ok ) {
-            chameleon_error("RUNTIME_desc_create", "MPI_TAG_UB not known by StarPU");
-        }
-
-        while ( ((uintptr_t)((1UL<<tag_width) - 1) > tag_ub ) &&
-                (tag_width >= TAG_WIDTH_MIN) )
-        {
-            tag_width--;
-            tag_sep--;
-        }
-
-        if ( tag_width < TAG_WIDTH_MIN ) {
-            chameleon_error("RUNTIME_desc_create", "MPI_TAG_UB too small to identify all the data");
-            return CHAMELEON_ERR_OUT_OF_RESOURCES;
-        }
-
-        _tag_mpi_initialized_ = 1;
-        return CHAMELEON_SUCCESS;
-    }
-    else {
-        return CHAMELEON_ERR_REINITIALIZED;
-    }
-}
-
-
 #ifndef HAVE_STARPU_MPI_DATA_REGISTER
 #define starpu_mpi_data_register( handle_, tag_, owner_ )       \
     do {                                                        \
@@ -91,20 +40,6 @@ chameleon_starpu_tag_init( int user_tag_width,
 
 #endif
 
-void RUNTIME_comm_set_tag_sizes( int user_tag_width,
-                                 int user_tag_sep )
-{
-#if defined(CHAMELEON_USE_MPI)
-    int rc;
-    rc = chameleon_starpu_tag_init( user_tag_width, user_tag_sep );
-    if ( rc != CHAMELEON_SUCCESS ) {
-        chameleon_error("RUNTIME_user_tag_size",
-                    "must be called before creating any Cham descriptor with CHAMELEON_Desc_create(). The tag sizes will not be modified.");
-    }
-#endif
-    (void)user_tag_width; (void)user_tag_sep;
-}
-
 /**
  *  Malloc/Free of the data
  */
@@ -221,23 +156,16 @@ void RUNTIME_desc_create( CHAM_desc_t *desc )
 
 #if defined(CHAMELEON_USE_MPI)
     /*
-     * Check that we are not going over MPI tag limitations
+     * Book the number of tags required to describe this matrix
      */
     {
-        chameleon_starpu_tag_init( tag_width, tag_sep );
+        chameleon_starpu_tag_init();
+        desc->mpitag = chameleon_starpu_tag_book( (int64_t)lnt * (int64_t)lmt );
 
-        /* Check that we won't create overflow in tags used */
-        if ( ((uintptr_t)(lnt*lmt)) > ((uintptr_t)(1UL<<tag_sep)) ) {
-            chameleon_fatal_error("RUNTIME_desc_create", "Too many tiles in the descriptor for MPI tags");
+        if ( desc->mpitag == -1 ) {
+            chameleon_fatal_error("RUNTIME_desc_create", "Can't pursue computation since no more tags are available");
             return;
         }
-        assert( ((uintptr_t)(lnt*lmt)) <= ((uintptr_t)(1UL<<tag_sep)) );
-
-        if ( ((uintptr_t)desc->id) >= (uintptr_t)(1UL<<(tag_width-tag_sep)) ) {
-            chameleon_fatal_error("RUNTIME_desc_create", "Number of descriptor available in MPI mode out of stock");
-            return;
-        }
-        assert( ((uintptr_t)desc->id) < (uintptr_t)(1UL<<(tag_width-tag_sep)) );
     }
 #endif
 }
@@ -284,8 +212,9 @@ void RUNTIME_desc_destroy( CHAM_desc_t *desc )
         }
 #endif
 #endif
+        chameleon_starpu_tag_release( desc->mpitag );
 
-        free(desc->schedopt);
+        free( desc->schedopt );
     }
 }
 
@@ -505,10 +434,14 @@ void *RUNTIME_data_getaddr( const CHAM_desc_t *A, int m, int n )
 #if defined(CHAMELEON_USE_MPI)
     {
         int64_t block_ind = A->lmt * nn + mm;
-        starpu_mpi_data_register(*ptrtile, (((int64_t)A->id) << tag_sep) | block_ind, owner);
+        starpu_mpi_data_register( *ptrtile, A->mpitag + block_ind, owner );
     }
 #endif /* defined(CHAMELEON_USE_MPI) */
 
+#if defined(CHAMELEON_KERNELS_TRACE)
+    fprintf( stderr, "%s - %p registered with tag %ld\n",
+             tile->name, *ptrtile, A->mpitag + A->lmt * nn + mm );
+#endif
     assert( *ptrtile );
     return *ptrtile;
 }
diff --git a/runtime/starpu/control/runtime_tags.c b/runtime/starpu/control/runtime_tags.c
new file mode 100644
index 0000000000000000000000000000000000000000..32c481a0d11a0970bd502bfc5800f0de4a6ead1d
--- /dev/null
+++ b/runtime/starpu/control/runtime_tags.c
@@ -0,0 +1,261 @@
+/**
+ *
+ * @file starpu/runtime_tags.c
+ *
+ * @copyright 2017-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
+ *                      Univ. Bordeaux. All rights reserved.
+ *
+ * @version 1.3.0
+ * @author Pierre Ramet
+ * @author Mathieu Faverge
+ * @date 2021-10-04
+ *
+ * Functions to manage the MPI data tags with StarPU (originated from PaStiX).
+ *
+ * @addtogroup chameleon_starpu
+ * @{
+ *
+ **/
+#include "chameleon_starpu.h"
+
+#if defined(CHAMELEON_USE_MPI)
+
+/**
+ * @brief Structure Chameleon StarPU tag
+ *
+ * List structure to manage the set of available tags.
+ */
+struct cst_range_;
+typedef struct cst_range_ cst_range_t;
+
+struct cst_range_ {
+    int64_t      min;  /**< Minimal value in the range     */
+    int64_t      max;  /**< Maximal value in the range     */
+    cst_range_t *next; /**< Pointer to the following range */
+};
+
+/**
+ * @brief Pointer to the first set or registered tags
+ */
+static cst_range_t *cst_first     = NULL;
+
+/**
+ * @brief StarPU tag upper bound
+ */
+static int64_t starpu_tag_ub = 0;
+
+/**
+ *******************************************************************************
+ *
+ * @brief Initialize the StarPU tags manager.
+ *
+ *******************************************************************************
+ *
+ * @retval TODO
+ *
+ ******************************************************************************/
+int
+chameleon_starpu_tag_init( void )
+{
+    if (!starpu_tag_ub) {
+        int          ok       = 0;
+        void        *tag_ub_p = NULL;
+
+        starpu_mpi_comm_get_attr( MPI_COMM_WORLD, STARPU_MPI_TAG_UB, &tag_ub_p, &ok );
+        starpu_tag_ub = (uint64_t)((intptr_t)tag_ub_p);
+
+        if ( !ok ) {
+            chameleon_error("chameleon_starpu_tag_init", "MPI_TAG_UB not known by StarPU\n");
+        }
+
+        return CHAMELEON_SUCCESS;
+    }
+    else {
+        return CHAMELEON_ERR_REINITIALIZED;
+    }
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief Book a range of StarPU unique tags of size nbtags.
+ *
+ * This function returns the minimal tag value available to allow the
+ * registration of nbtags data in a continuous range.
+ *
+ * Note that this function must be called exactly the same way on all nodes to
+ * make sure the tags are identical from one node to another.
+ *
+ *******************************************************************************
+ *
+ * @param[in] nbtags
+ *          The number of tags required to register the sparse matrix or right
+ *          hand side.
+ *
+ *******************************************************************************
+ *
+ * @return V, the minimal tag value to use. The range [V:V+nbtags-1] is booked.
+ *
+ ********************************************************************************/
+int64_t
+chameleon_starpu_tag_book( int64_t nbtags )
+{
+    cst_range_t *new;
+    cst_range_t *prev    = NULL;
+    cst_range_t *current = cst_first;
+    int64_t      min = 0;
+    int64_t      max = ( current == NULL ) ? starpu_tag_ub : current->min;
+
+    if ( nbtags == 0 ) {
+        return -1;
+    }
+    assert( starpu_tag_ub != 0 ); /* StarPU tag must be initialized */
+
+    while ( ((max - min) < nbtags) && (current != NULL) ) {
+        min     = current->max;
+        prev    = current;
+        current = current->next;
+        max     = ( current == NULL ) ? starpu_tag_ub : current->min;
+    }
+
+    if ( (max - min) < nbtags ) {
+        /* chameleon_error( "chameleon_starpu_tag_book: No space left in tags (looking for %ld tags)\n", */
+        /*                  nbtags ); */
+        return -1;
+    }
+
+    new = malloc( sizeof( cst_range_t ) );
+    new->min  = min;
+    new->max  = min + nbtags;
+    new->next = current;
+    if ( prev == NULL ) {
+        cst_first = new;
+    }
+    else {
+        assert( prev->next == current );
+        prev->next = new;
+    }
+
+#if defined(CHAMELEON_DEBUG_STARPU)
+    fprintf( stderr, "chameleon_starpu_tag: Book %ld - %ld\n",
+             min, min + nbtags );
+#endif
+
+    assert( cst_first != NULL );
+    return new->min;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief Release the set of tags starting by min.
+ *
+ * This function releases the range of tags that starts by the min value.
+ *
+ *******************************************************************************
+ *
+ * @param[in] min
+ *          The initial value in the range
+ *
+ ******************************************************************************/
+void
+chameleon_starpu_tag_release( int64_t min )
+{
+    cst_range_t *prev    = NULL;
+    cst_range_t *current = cst_first;
+
+    assert( cst_first != NULL ); /* At least one range must be registered */
+
+    while ( (current != NULL) && (current->min < min) ) {
+        prev    = current;
+        current = current->next;
+    }
+
+    assert( current != NULL );
+    assert( current->min == min );
+
+    if ( prev ) {
+        prev->next = current->next;
+    }
+    else {
+        assert( current == cst_first );
+        cst_first = current->next;
+    }
+
+#if defined(CHAMELEON_DEBUG_STARPU)
+    fprintf( stderr, "chameleon_starpu_tag: Release %ld - %ld\n",
+             current->min, current->max );
+#endif
+
+    free( current );
+
+    return;
+}
+
+#else /* defined(CHAMELEON_USE_MPI) */
+
+/**
+ *******************************************************************************
+ *
+ * @brief Initialize the StarPU tags manager.
+ *
+ *******************************************************************************
+ *
+ * @retval TODO
+ *
+ ******************************************************************************/
+int
+chameleon_starpu_tag_init( ) {
+    return CHAMELEON_SUCCESS;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief Book a range of StarPU unique tags of size nbtags.
+ *
+ * This function returns the minimal tag value available to allow the
+ * registration of nbtags data in a continuous range.
+ *
+ * Note that this function must be called exactly the same way on all nodes to
+ * make sure the tags are identical from one node to another.
+ *
+ *******************************************************************************
+ *
+ * @param[in] nbtags
+ *          The number of tags required to register the sparse matrix or right
+ *          hand side.
+ *
+ *******************************************************************************
+ *
+ * @return V, the minimal tag value to use. The range [V:V+nbtags-1] is booked.
+ *
+ ********************************************************************************/
+int64_t
+chameleon_starpu_tag_book( __attribute__((unused)) int64_t nbtags ) {
+    return 0;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief Release the set of tags starting by min.
+ *
+ * This function releases the range of tags that starts by the min value.
+ *
+ *******************************************************************************
+ *
+ * @param[in] min
+ *          The initial value in the range
+ *
+ ******************************************************************************/
+void
+chameleon_starpu_tag_release( __attribute__((unused)) int64_t min ) {
+    return;
+}
+
+#endif
+
+/**
+ * @}
+ */
diff --git a/runtime/starpu/include/chameleon_starpu.h.in b/runtime/starpu/include/chameleon_starpu.h.in
index e92e23387f1f20912e3d28f910047c2d9629dfd4..d967fac54efab35815205367f4b65fe082b48366 100644
--- a/runtime/starpu/include/chameleon_starpu.h.in
+++ b/runtime/starpu/include/chameleon_starpu.h.in
@@ -149,6 +149,13 @@ typedef struct starpu_option_request_s {
 #define CHAMELEON_CODELETS_HAVE_NAME
 #endif
 
+/**
+ * MPI tag management
+ */
+int     chameleon_starpu_tag_init( );
+int64_t chameleon_starpu_tag_book( int64_t nbtags );
+void    chameleon_starpu_tag_release( int64_t min );
+
 /**
  * Access to block pointer and leading dimension
  */
diff --git a/testing/test_fembem b/testing/test_fembem
index 1e9813068d15dbc570d16da086151e66dc670975..906d73c7abb0821e8df787f05fab2d503a2e76ff 160000
--- a/testing/test_fembem
+++ b/testing/test_fembem
@@ -1 +1 @@
-Subproject commit 1e9813068d15dbc570d16da086151e66dc670975
+Subproject commit 906d73c7abb0821e8df787f05fab2d503a2e76ff