From b15e2edf67261c750e87fbcf88d43ad40e954002 Mon Sep 17 00:00:00 2001
From: Mathieu Faverge <mathieu.faverge@inria.fr>
Date: Sun, 26 Mar 2023 21:04:53 +0200
Subject: [PATCH] starpu: Add new interface to manage tags

---
 include/chameleon/struct.h                   |   1 +
 runtime/starpu/CMakeLists.txt                |   1 +
 runtime/starpu/control/runtime_descriptor.c  |  77 +-----
 runtime/starpu/control/runtime_tags.c        | 261 +++++++++++++++++++
 runtime/starpu/include/chameleon_starpu.h.in |   7 +
 5 files changed, 282 insertions(+), 65 deletions(-)
 create mode 100644 runtime/starpu/control/runtime_tags.c

diff --git a/include/chameleon/struct.h b/include/chameleon/struct.h
index e5df8fa6d..289f4cad9 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/starpu/CMakeLists.txt b/runtime/starpu/CMakeLists.txt
index 0968de66d..c70669ba4 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/control/runtime_descriptor.c b/runtime/starpu/control/runtime_descriptor.c
index 385adc0df..46f3832a4 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 {                                                        \
@@ -221,23 +170,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 +226,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 +448,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 000000000..32c481a0d
--- /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 e92e23387..d967fac54 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
  */
-- 
GitLab