Repository: NVIDIA/cccl
Pull request #4306: [STF] Refactor  CUDASTF allocators
Author: login: andralex
Labels: name: stf
description: Sequential Task Flow programming model
Created: 2025-04-01T18:31:17Z | Merged: 2025-04-15T13:18:27Z

## Refactor all CUDASTF allocators

Main purpose is to group together all allocator code, which over time had diverged in various headers.



Diff:
diff --git a/cudax/include/cuda/experimental/__stf/allocators/block_allocator.cuh b/cudax/include/cuda/experimental/__stf/allocators/block_allocator.cuh
index 3eaf9090f9a..0f70aad6f90 100644
--- a/cudax/include/cuda/experimental/__stf/allocators/block_allocator.cuh
+++ b/cudax/include/cuda/experimental/__stf/allocators/block_allocator.cuh
@@ -174,7 +174,7 @@ class block_allocator : public block_allocator_untyped
 {
 public:
   template <typename ctx_t, typename... Args>
-  block_allocator(ctx_t& ctx, Args... args)
+  block_allocator(ctx_t& ctx, Args&&... args)
       : block_allocator_untyped(ctx, ::std::make_shared<T>(::std::forward<Args>(args)...))
   {}
 
diff --git a/cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh b/cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
index 4978bdb01bc..c290c5f866f 100644
--- a/cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
+++ b/cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
@@ -63,26 +63,21 @@ private:
 
 public:
   buddy_allocator_metadata(size_t size, event_list init_prereqs)
+      : free_lists_(int_log2(next_power_of_two(size)) + 1)
   {
-    total_size_ = next_power_of_two(size);
-    assert(total_size_ == size);
-
-    max_level_ = int_log2(total_size_);
-
-    free_lists_.resize(max_level_ + 1);
-
+    _CCCL_ASSERT(size && (size & (size - 1)) == 0,
+                 "Allocation requests for this allocator must pass a size that is a power of two.");
     // Initially, the whole memory is free, but depends on init_prereqs
-    free_lists_[max_level_].emplace_back(0, init_prereqs);
+    free_lists_.back().emplace_back(0, mv(init_prereqs));
   }
 
   ::std::ptrdiff_t allocate(size_t size, event_list& prereqs)
   {
-    size         = next_power_of_two(size);
-    size_t level = int_log2(size);
-
-    if (level > max_level_)
+    size               = next_power_of_two(size);
+    const size_t level = int_log2(size);
+    if (level >= free_lists_.size())
     {
-      fprintf(stderr, "Level %zu > max level %zu\n", level, max_level_);
+      fprintf(stderr, "Level %zu > max level %zu\n", level, free_lists_.size() - 1);
       return -1;
     }
 
@@ -104,11 +99,11 @@ public:
     // Deallocated blocks will depend on these, and we will merge the
     // previous dependencies when merging buddies
     event_list block_prereqs(prereqs);
-
-    while (level < max_level_)
+    const size_t max_level = free_lists_.size() - 1;
+    while (level < max_level)
     {
-      size_t buddy_index = get_buddy_index(index, level);
-      auto& buddy_list   = free_lists_[level];
+      const size_t buddy_index = get_buddy_index(index, level);
+      auto& buddy_list         = free_lists_[level];
       auto it = ::std::find_if(buddy_list.begin(), buddy_list.end(), [buddy_index](const avail_block& block) {
         return block.index == buddy_index;
       });
@@ -144,7 +139,7 @@ public:
   void debug_print() const
   {
     size_t power = 1;
-    for (size_t i = 0; i <= max_level_; ++i, power *= 2)
+    for (size_t i = 0; i < free_lists_.size(); ++i, power *= 2)
     {
       if (!free_lists_[i].empty())
       {
@@ -161,16 +156,22 @@ public:
 private:
   static size_t next_power_of_two(size_t size)
   {
+    static_assert(sizeof(size_t) <= 8, "You must be from the future. Review and adjust this code.");
     if (size == 0)
     {
       return 1;
     }
-    size_t power = 1;
-    while (power < size)
+    --size;
+    size |= size >> 1;
+    size |= size >> 2;
+    size |= size >> 4;
+    size |= size >> 8;
+    size |= size >> 16;
+    if constexpr (sizeof(size_t) == 8)
     {
-      power *= 2;
+      size |= size >> 32;
     }
-    return power;
+    return size + 1;
   }
 
   static size_t int_log2(size_t n)
@@ -187,7 +188,7 @@ private:
 
   ::std::ptrdiff_t find_free_block(size_t level, event_list& prereqs)
   {
-    for (size_t current_level : each(level, max_level_ + 1))
+    for (size_t current_level : each(level, free_lists_.size()))
     {
       if (free_lists_[current_level].empty())
       {
@@ -222,8 +223,6 @@ private:
   }
 
   ::std::vector<::std::vector<avail_block>> free_lists_;
-  size_t total_size_ = 0;
-  size_t max_level_  = 0;
 };
 
 } // end namespace reserved
@@ -244,16 +243,20 @@ private:
   // Per data place buffer and its corresponding metadata
   struct per_place
   {
-    per_place(void* base_, size_t size, event_list& prereqs)
+    per_place(void* base_, size_t size, event_list prereqs)
         : base(base_)
         , buffer_size(size)
-    {
-      metadata = ::std::make_shared<reserved::buddy_allocator_metadata>(buffer_size, prereqs);
-    }
+        , metadata(buffer_size, mv(prereqs))
+    {}
+
+    per_place& operator=(const per_place&) = delete;
+    per_place& operator=(per_place&&)      = default;
+    per_place(const per_place&)            = delete;
+    per_place(per_place&&)                 = default;
 
     void* base         = nullptr;
     size_t buffer_size = 0;
-    ::std::shared_ptr<reserved::buddy_allocator_metadata> metadata;
+    reserved::buddy_allocator_metadata metadata;
   };
 
 public:
@@ -270,16 +273,16 @@ public:
       void* base          = a.allocate(ctx, memory_node, sz, prereqs);
 
       // 2. creates meta data for that buffer, and 3. associate it to the data place
-      it = map.emplace(memory_node, ::std::make_shared<per_place>(base, sz, prereqs)).first;
+      it = map.emplace(memory_node, per_place(base, sz, prereqs)).first;
     }
 
     // There should be exactly one entry in the map
     assert(map.count(memory_node) == 1);
     auto& m = it->second;
 
-    ::std::ptrdiff_t offset = m->metadata->allocate(s, prereqs);
+    ::std::ptrdiff_t offset = m.metadata.allocate(s, prereqs);
     assert(offset != -1);
-    return static_cast<char*>(m->base) + offset;
+    return static_cast<char*>(m.base) + offset;
   }
 
   void
@@ -287,11 +290,11 @@ public:
   {
     // There should be exactly one entry in the map
     assert(map.count(memory_node) == 1);
-    auto& m = map[memory_node];
+    auto& m = map.find(memory_node)->second;
 
-    size_t offset = static_cast<char*>(ptr) - static_cast<char*>(m->base);
+    size_t offset = static_cast<char*>(ptr) - static_cast<char*>(m.base);
 
-    m->metadata->deallocate(offset, sz, prereqs);
+    m.metadata.deallocate(offset, sz, prereqs);
   }
 
   event_list deinit(backend_ctx_untyped& ctx) override
@@ -303,11 +306,11 @@ public:
       event_list local_prereqs;
 
       // Deinitialize the metadata of the buddy allocator for this place
-      pp->metadata->deinit(local_prereqs);
+      pp.metadata.deinit(local_prereqs);
 
       // Deallocate the underlying buffer for this buddy allocator
       auto& a = root_allocator ? root_allocator : ctx.get_uncached_allocator();
-      a.deallocate(ctx, memory_node, local_prereqs, pp->base, pp->buffer_size);
+      a.deallocate(ctx, memory_node, local_prereqs, pp.base, pp.buffer_size);
 
       result.merge(local_prereqs);
     }
@@ -320,7 +323,7 @@ public:
   }
 
 private:
-  ::std::unordered_map<data_place, ::std::shared_ptr<per_place>, hash<data_place>> map;
+  ::std::unordered_map<data_place, per_place, hash<data_place>> map;
 
   block_allocator_untyped root_allocator;
 };
diff --git a/cudax/include/cuda/experimental/__stf/allocators/cached_allocator.cuh b/cudax/include/cuda/experimental/__stf/allocators/cached_allocator.cuh
index 8031707dfb5..6133cc100e2 100644
--- a/cudax/include/cuda/experimental/__stf/allocators/cached_allocator.cuh
+++ b/cudax/include/cuda/experimental/__stf/allocators/cached_allocator.cuh
@@ -143,15 +143,197 @@ public:
     return "cached_block_allocator";
   }
 
+protected:
+  /**
+   * @brief Underlying root allocator for base buffers
+   */
+  block_allocator_untyped root_allocator;
+
   /**
-   * @brief Prints additional information about the allocator.
+   * @brief Struct representing an entry in the cache.
    *
-   * This function currently prints no additional information.
+   * Holds the address of the allocated memory and a list of prerequisites for its reuse.
    */
-  void print_info() const override
+  struct alloc_cache_entry
   {
-    const auto s = to_string();
-    fprintf(stderr, "No additional info for allocator of kind \"%.*s\".\n", static_cast<int>(s.size()), s.data());
+    void* ptr; ///< Pointer to the allocated memory block.
+    event_list prereq; ///< Prerequisites for reusing this block.
+  };
+
+  /// Maps sizes to cache entries for a given data_place.
+  using per_place_map_t = ::std::unordered_multimap<size_t, alloc_cache_entry>;
+
+  /// Top-level cache map mapping data_place to per_place_map_t.
+  ::std::unordered_map<data_place, per_place_map_t, hash<data_place>> free_cache;
+
+  ::std::mutex allocator_mutex;
+};
+
+/**
+ * @brief A block allocator with FIFO caching strategy.
+ *
+ * This allocator wraps a root allocator and implements a caching mechanism
+ * to efficiently reuse previously allocated memory blocks.
+ *
+ * When a memory block is requested, it first attempts to find a suitable block
+ * in the internal cache (`free_cache`). If no suitable block is found, a larger
+ * buffer is allocated from the root allocator, split into smaller blocks, and
+ * stored in the cache for future reuse.
+ *
+ * The caching policy is FIFO (First-In-First-Out): freed blocks are appended
+ * to a queue and reused in the order they were deallocated.
+ *
+ * At deinitialization (`deinit()`), all cached blocks and their associated large
+ * allocations are properly released by delegating to the root allocator.
+ *
+ * @note The allocator is thread-safe and uses a mutex to protect access
+ * to its internal cache.
+ *
+ * @note Deallocation does not immediately release memory back to the root allocator.
+ * Instead, deallocated blocks are stored in the cache for future reuse.
+ *
+ * @see block_allocator_interface
+ */
+class cached_block_allocator_fifo : public block_allocator_interface
+{
+public:
+  /**
+   * @brief This constructor takes a root allocator which performs
+   *        allocations when there is a cache miss
+   */
+  cached_block_allocator_fifo(block_allocator_untyped root_allocator_)
+      : root_allocator(mv(root_allocator_))
+  {}
+
+  /**
+   * @brief Allocates a memory block.
+   *
+   * Attempts to allocate a memory block from the internal cache if available.
+   *
+   * @param ctx The backend context (unused in this implementation).
+   * @param memory_node Memory location where the allocation should happen.
+   * @param s Pointer to the size of memory required.
+   * @param prereqs List of events that this allocation depends on.
+   * @return void* A pointer to the allocated memory block or nullptr if allocation fails.
+   */
+  void*
+  allocate(backend_ctx_untyped& ctx, const data_place& memory_node, ::std::ptrdiff_t& s, event_list& prereqs) override
+  {
+    EXPECT(s > 0);
+
+    ::std::lock_guard<::std::mutex> g(allocator_mutex);
+    if (auto it = free_cache.find(memory_node); it != free_cache.end())
+    {
+      per_place_map_t& size_map = it->second;
+      if (auto it2 = size_map.find(s); it2 != size_map.end() && !it2->second.empty())
+      {
+        // Retrieve the first (oldest) entry.
+        alloc_cache_entry e = std::move(it2->second.front());
+        it2->second.pop();
+
+        // Optionally, remove the key if the queue is now empty.
+        if (it2->second.empty())
+        {
+          size_map.erase(it2);
+        }
+
+        prereqs.merge(std::move(e.prereq));
+        return e.ptr;
+      }
+    }
+
+    // That is a miss, we need to allocate data using the root allocator
+
+    /* Create one large block of memory */
+    size_t cnt                = 50;
+    ::std::ptrdiff_t large_sz = cnt * s;
+    auto* base                = root_allocator.allocate(ctx, memory_node, large_sz, prereqs);
+    _CCCL_ASSERT(large_sz >= 0, "failed to allocate large buffer");
+
+    large_allocations[memory_node].push_back(::std::make_pair(base, large_sz));
+
+    /* Populate the cache with sub-entries from this large block, except the
+     * first entry which is used immediately */
+    auto& per_node = free_cache[memory_node][s];
+    for (size_t k = 1; k < cnt; k++)
+    {
+      per_node.push(alloc_cache_entry{(char*) base + s * k, prereqs});
+    }
+
+    return base;
+  }
+
+  /**
+   * @brief Deallocates a memory block.
+   *
+   * Puts the deallocated block back into the internal cache for future reuse.
+   *
+   * @param ctx The backend context (unused in this implementation).
+   * @param memory_node Memory location where the deallocation should happen.
+   * @param prereqs List of events that this deallocation depends on.
+   * @param ptr Pointer to the memory block to be deallocated.
+   * @param sz Size of the memory block.
+   */
+  void
+  deallocate(backend_ctx_untyped&, const data_place& memory_node, event_list& prereqs, void* ptr, size_t sz) override
+  {
+    ::std::lock_guard<::std::mutex> g(allocator_mutex);
+    // We do not call the deallocate method of the root allocator, we discard buffers instead.
+    // Note that we do not need to keep track of the "large buffer" from which this originated
+    free_cache[memory_node][sz].push(alloc_cache_entry{ptr, prereqs});
+  }
+
+  /**
+   * @brief De-initializes the allocator.
+   *
+   */
+  event_list deinit(backend_ctx_untyped& ctx) override
+  {
+    decltype(free_cache) free_cache_janitor;
+    {
+      ::std::lock_guard<::std::mutex> g(allocator_mutex);
+      free_cache.swap(free_cache_janitor);
+    }
+
+    event_list result;
+    for (auto& [where, size_map] : free_cache_janitor)
+    {
+      event_list per_place_result;
+
+      // For each size key, iterate over the associated queue
+      for (auto& [sz, queue] : size_map)
+      {
+        // We first go through all suballocations to "collect" prereqs
+        while (!queue.empty())
+        {
+          alloc_cache_entry ace = std::move(queue.front());
+          queue.pop();
+
+          per_place_result.merge(mv(ace.prereq));
+        }
+      }
+
+      // Then we actually deallocate memory: for each place, there is a vector of large allocations
+      for (auto& alloc : large_allocations[where])
+      {
+        void* base      = alloc.first;
+        size_t large_sz = alloc.second;
+        root_allocator.deallocate(ctx, where, per_place_result, base, large_sz);
+      }
+
+      result.merge(mv(per_place_result));
+    }
+    return result;
+  }
+
+  /**
+   * @brief Returns a string representation of the allocator.
+   *
+   * @return std::string The string "cached_block_allocator".
+   */
+  ::std::string to_string() const override
+  {
+    return "cached_block_allocator_fifo";
   }
 
 protected:
@@ -172,10 +354,14 @@ protected:
   };
 
   /// Maps sizes to cache entries for a given data_place.
-  using per_place_map_t = ::std::unordered_multimap<size_t, alloc_cache_entry>;
+  using per_place_map_t = ::std::unordered_map<size_t, ::std::queue<alloc_cache_entry>>;
 
-  /// Top-level cache map mapping data_place to per_place_map_t.
+  /// We track actually allocated blocks (per data place), and then a map of
+  // suballocations. The deallocate method only return ptr/sz so we loose track
+  // of the connection between large blocks from the root allocator, and
+  // small allocations, but we simply clear these blocks at the end.
   ::std::unordered_map<data_place, per_place_map_t, hash<data_place>> free_cache;
+  ::std::unordered_map<data_place, ::std::vector<::std::pair<void*, size_t>>, hash<data_place>> large_allocations;
 
   ::std::mutex allocator_mutex;
 };
diff --git a/cudax/include/cuda/experimental/__stf/allocators/pooled_allocator.cuh b/cudax/include/cuda/experimental/__stf/allocators/pooled_allocator.cuh
index 16367880acf..7c3cb9c1c82 100644
--- a/cudax/include/cuda/experimental/__stf/allocators/pooled_allocator.cuh
+++ b/cudax/include/cuda/experimental/__stf/allocators/pooled_allocator.cuh
@@ -170,7 +170,7 @@ public:
   {
     const ptrdiff_t offset = static_cast<char*>(ptr) - static_cast<char*>(base);
     // Add an assertion that offset % block_size == 0 ?
-    return (offset >= 0 && offset < static_cast<ptrdiff_t>(entries.size() * block_size));
+    return offset >= 0 && offset < static_cast<ptrdiff_t>(entries.size() * block_size);
   }
 
   // Free the memory allocated for this block of allocations


Reviews:
user: login: miscco
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T07:20:17Z
user: login: miscco
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T07:31:47Z

Review comments:
diff_hunk: @@ -63,26 +63,21 @@ private:
 
 public:
   buddy_allocator_metadata(size_t size, event_list init_prereqs)
+      : free_lists_(int_log2(next_power_of_two(size)) + 1)
   {
-    total_size_ = next_power_of_two(size);
-    assert(total_size_ == size);
-
-    max_level_ = int_log2(total_size_);
-
-    free_lists_.resize(max_level_ + 1);
-
+    assert(size && (size & (size - 1)) == 0
path: cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
user: login: miscco
body: We should replace plain uses of `assert` with `_CCCL_ASSERT`
created_at: 2025-04-14T07:17:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -104,11 +99,11 @@ public:
     // Deallocated blocks will depend on these, and we will merge the
     // previous dependencies when merging buddies
     event_list block_prereqs(prereqs);
-
-    while (level < max_level_)
+    const size_t max_level = free_lists_.size() - 1;
path: cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
user: login: miscco
body: This skips the last level, is that intentional?
created_at: 2025-04-14T07:19:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -244,16 +243,18 @@ private:
   // Per data place buffer and its corresponding metadata
   struct per_place
   {
-    per_place(void* base_, size_t size, event_list& prereqs)
+    per_place(void* base_, size_t size, event_list prereqs)
         : base(base_)
         , buffer_size(size)
-    {
-      metadata = ::std::make_shared<reserved::buddy_allocator_metadata>(buffer_size, prereqs);
-    }
+        , metadata(buffer_size, mv(prereqs))
+    {}
+
+    per_place(const per_place&) = delete;
+    per_place(per_place&&)      = default;
path: cudax/include/cuda/experimental/__stf/allocators/buddy_allocator.cuh
user: login: miscco
body: We probably should also default / delete the assignment operators
created_at: 2025-04-14T07:20:04Z
author_association: CONTRIBUTOR

PR comments:
user: login: copy-pr-bot[bot]
created_at: 2025-04-01T18:31:20Z
body: This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities [here](https://docs.gha-runners.nvidia.com/cpr/vetters).

Contributors can view more details about this message [here](https://docs.gha-runners.nvidia.com/cpr/contributors).

author_association: CONTRIBUTOR
user: login: andralex
created_at: 2025-04-01T18:35:32Z
body: Note: the commit noise will go away once #4275 is merged.
author_association: CONTRIBUTOR
user: login: andralex
created_at: 2025-04-01T18:35:37Z
body: /ok to test

author_association: CONTRIBUTOR
user: login: andralex
created_at: 2025-04-01T18:36:47Z
body: /ok to test
author_association: CONTRIBUTOR
user: login: andralex
created_at: 2025-04-01T18:56:27Z
body: /ok to test

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-02T10:06:20Z
body: <details><summary>🟩 CI finished in 15h 06m: Pass: 100%/166 | Total:  1d 10h | Avg: 12m 29s | Max:  1h 21m | Hits:  91%/254711</summary>

<ul>
<li>
<details><summary><h3>🟩 cub: Pass: 100%/45  | Total: 12h 10m | Avg: 16m 14s | Max:  1h 21m | Hits:  92%/53899 </h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/43  | Total: 11h 59m | Avg: 16m 43s | Max:  1h 21m | Hits:  92%/51449 
  🟩 arm64              Pass: 100%/2   | Total: 11m 45s | Avg:  5m 52s | Max:  6m 13s | Hits:  99%/2450  
🟩 ctk
  🟩 12.0               Pass: 100%/5   | Total:  1h 37m | Avg: 19m 26s | Max:  1h 13m | Hits:  84%/5953  
  🟩 12.6               Pass: 100%/2   | Total: 22m 31s | Avg: 11m 15s | Max: 11m 52s | Hits:  98%/2262  
  🟩 12.8               Pass: 100%/38  | Total: 10h 11m | Avg: 16m 04s | Max:  1h 21m | Hits:  93%/45684 
🟩 cudacxx
  🟩 ClangCUDA18        Pass: 100%/2   | Total: 10m 14s | Avg:  5m 07s | Max:  5m 11s | Hits: 100%/2110  
  🟩 nvcc12.0           Pass: 100%/5   | Total:  1h 37m | Avg: 19m 26s | Max:  1h 13m | Hits:  84%/5953  
  🟩 nvcc12.6           Pass: 100%/2   | Total: 22m 31s | Avg: 11m 15s | Max: 11m 52s | Hits:  98%/2262  
  🟩 nvcc12.8           Pass: 100%/36  | Total: 10h 00m | Avg: 16m 41s | Max:  1h 21m | Hits:  93%/43574 
🟩 cudacxx_family
  🟩 ClangCUDA          Pass: 100%/2   | Total: 10m 14s | Avg:  5m 07s | Max:  5m 11s | Hits: 100%/2110  
  🟩 nvcc               Pass: 100%/43  | Total: 12h 00m | Avg: 16m 45s | Max:  1h 21m | Hits:  92%/51789 
🟩 cxx
  🟩 Clang14            Pass: 100%/4   | Total: 23m 57s | Avg:  5m 59s | Max:  6m 14s | Hits: 100%/4908  
  🟩 Clang15            Pass: 100%/2   | Total: 12m 54s | Avg:  6m 27s | Max:  6m 30s | Hits: 100%/2450  
  🟩 Clang16            Pass: 100%/2   | Total: 13m 07s | Avg:  6m 33s | Max:  6m 46s | Hits: 100%/2450  
  🟩 Clang17            Pass: 100%/2   | Total: 12m 29s | Avg:  6m 14s | Max:  6m 19s | Hits: 100%/2450  
  🟩 Clang18            Pass: 100%/7   | Total:  1h 16m | Avg: 10m 56s | Max: 26m 28s | Hits: 100%/8235  
  🟩 GCC7               Pass: 100%/2   | Total: 12m 37s | Avg:  6m 18s | Max:  6m 29s | Hits:  99%/2454  
  🟩 GCC8               Pass: 100%/1   | Total:  6m 23s | Avg:  6m 23s | Max:  6m 23s | Hits:  99%/1227  
  🟩 GCC9               Pass: 100%/2   | Total: 12m 54s | Avg:  6m 27s | Max:  6m 31s | Hits:  99%/2454  
  🟩 GCC10              Pass: 100%/2   | Total: 13m 19s | Avg:  6m 39s | Max:  6m 44s | Hits:  99%/2454  
  🟩 GCC11              Pass: 100%/2   | Total: 13m 54s | Avg:  6m 57s | Max:  7m 00s | Hits:  99%/2450  
  🟩 GCC12              Pass: 100%/2   | Total: 14m 16s | Avg:  7m 08s | Max:  7m 18s | Hits:  99%/2450  
  🟩 GCC13              Pass: 100%/11  | Total:  3h 00m | Avg: 16m 25s | Max: 28m 40s | Hits:  99%/13475 
  🟩 MSVC14.29          Pass: 100%/2   | Total:  2h 34m | Avg:  1h 17m | Max:  1h 21m | Hits:  12%/2090  
  🟩 MSVC14.42          Pass: 100%/2   | Total:  2h 40m | Avg:  1h 20m | Max:  1h 20m | Hits:  12%/2090  
  🟩 NVHPC25.1          Pass: 100%/2   | Total: 22m 31s | Avg: 11m 15s | Max: 11m 52s | Hits:  98%/2262  
🟩 cxx_family
  🟩 Clang              Pass: 100%/17  | Total:  2h 19m | Avg:  8m 10s | Max: 26m 28s | Hits: 100%/20493 
  🟩 GCC                Pass: 100%/22  | Total:  4h 14m | Avg: 11m 32s | Max: 28m 40s | Hits:  99%/26964 
  🟩 MSVC               Pass: 100%/4   | Total:  5h 15m | Avg:  1h 18m | Max:  1h 21m | Hits:  12%/4180  
  🟩 NVHPC              Pass: 100%/2   | Total: 22m 31s | Avg: 11m 15s | Max: 11m 52s | Hits:  98%/2262  
🟩 gpu
  🟩 h100               Pass: 100%/3   | Total: 55m 30s | Avg: 18m 30s | Max: 28m 40s | Hits:  99%/3675  
  🟩 rtx2080            Pass: 100%/34  | Total:  8h 36m | Avg: 15m 11s | Max:  1h 21m | Hits:  90%/40424 
  🟩 rtxa6000           Pass: 100%/8   | Total:  2h 38m | Avg: 19m 51s | Max: 26m 29s | Hits:  99%/9800  
🟩 jobs
  🟩 Build              Pass: 100%/37  | Total:  8h 54m | Avg: 14m 27s | Max:  1h 21m | Hits:  91%/44099 
  🟩 DeviceLaunch       Pass: 100%/1   | Total: 26m 29s | Avg: 26m 29s | Max: 26m 29s | Hits:  99%/1225  
  🟩 GraphCapture       Pass: 100%/1   | Total: 20m 37s | Avg: 20m 37s | Max: 20m 37s | Hits:  99%/1225  
  🟩 HostLaunch         Pass: 100%/3   | Total:  1h 21m | Avg: 27m 11s | Max: 28m 40s | Hits:  99%/3675  
  🟩 TestGPU            Pass: 100%/3   | Total:  1h 07m | Avg: 22m 25s | Max: 23m 38s | Hits:  99%/3675  
🟩 sm
  🟩 90                 Pass: 100%/3   | Total: 55m 30s | Avg: 18m 30s | Max: 28m 40s | Hits:  99%/3675  
  🟩 90;90a;100         Pass: 100%/1   | Total:  7m 27s | Avg:  7m 27s | Max:  7m 27s | Hits:  99%/1225  
🟩 std
  🟩 17                 Pass: 100%/20  | Total:  5h 49m | Avg: 17m 27s | Max:  1h 21m | Hits:  88%/23712 
  🟩 20                 Pass: 100%/25  | Total:  6h 21m | Avg: 15m 15s | Max:  1h 20m | Hits:  96%/30187 
```

</details>

<li>
<details><summary><h3>🟩 thrust: Pass: 100%/45  | Total:  9h 16m | Avg: 12m 22s | Max:  1h 07m | Hits:  92%/79911 </h3></summary>

```
🟩 cmake_options
  🟩 -DTHRUST_DISPATCH_TYPE=Force32bit Pass: 100%/2   | Total: 17m 14s | Avg:  8m 37s | Max: 11m 25s | Hits:  99%/3554  
🟩 cpu
  🟩 amd64              Pass: 100%/43  | Total:  9h 06m | Avg: 12m 43s | Max:  1h 07m | Hits:  91%/76358 
  🟩 arm64              Pass: 100%/2   | Total:  9m 58s | Avg:  4m 59s | Max:  5m 20s | Hits:  99%/3553  
🟩 ctk
  🟩 12.0               Pass: 100%/5   | Total:  1h 27m | Avg: 17m 34s | Max:  1h 07m | Hits:  81%/8876  
  🟩 12.6               Pass: 100%/2   | Total: 31m 08s | Avg: 15m 34s | Max: 16m 18s | Hits:  99%/3552  
  🟩 12.8               Pass: 100%/38  | Total:  7h 17m | Avg: 11m 31s | Max:  1h 05m | Hits:  93%/67483 
🟩 cudacxx
  🟩 ClangCUDA18        Pass: 100%/2   | Total: 10m 37s | Avg:  5m 18s | Max:  5m 33s | Hits: 100%/3552  
  🟩 nvcc12.0           Pass: 100%/5   | Total:  1h 27m | Avg: 17m 34s | Max:  1h 07m | Hits:  81%/8876  
  🟩 nvcc12.6           Pass: 100%/2   | Total: 31m 08s | Avg: 15m 34s | Max: 16m 18s | Hits:  99%/3552  
  🟩 nvcc12.8           Pass: 100%/36  | Total:  7h 07m | Avg: 11m 52s | Max:  1h 05m | Hits:  92%/63931 
🟩 cudacxx_family
  🟩 ClangCUDA          Pass: 100%/2   | Total: 10m 37s | Avg:  5m 18s | Max:  5m 33s | Hits: 100%/3552  
  🟩 nvcc               Pass: 100%/43  | Total:  9h 06m | Avg: 12m 42s | Max:  1h 07m | Hits:  91%/76359 
🟩 cxx
  🟩 Clang14            Pass: 100%/4   | Total: 21m 00s | Avg:  5m 15s | Max:  5m 37s | Hits: 100%/7104  
  🟩 Clang15            Pass: 100%/2   | Total: 11m 35s | Avg:  5m 47s | Max:  6m 02s | Hits: 100%/3552  
  🟩 Clang16            Pass: 100%/2   | Total: 11m 23s | Avg:  5m 41s | Max:  5m 55s | Hits: 100%/3552  
  🟩 Clang17            Pass: 100%/2   | Total: 11m 26s | Avg:  5m 43s | Max:  5m 51s | Hits: 100%/3552  
  🟩 Clang18            Pass: 100%/7   | Total: 44m 29s | Avg:  6m 21s | Max: 10m 16s | Hits: 100%/12432 
  🟩 GCC7               Pass: 100%/2   | Total: 10m 31s | Avg:  5m 15s | Max:  5m 24s | Hits:  99%/3554  
  🟩 GCC8               Pass: 100%/1   | Total:  6m 03s | Avg:  6m 03s | Max:  6m 03s | Hits:  99%/1777  
  🟩 GCC9               Pass: 100%/2   | Total: 10m 39s | Avg:  5m 19s | Max:  5m 29s | Hits:  99%/3554  
  🟩 GCC10              Pass: 100%/2   | Total: 11m 36s | Avg:  5m 48s | Max:  5m 58s | Hits:  99%/3554  
  🟩 GCC11              Pass: 100%/2   | Total: 12m 08s | Avg:  6m 04s | Max:  6m 07s | Hits:  99%/3554  
  🟩 GCC12              Pass: 100%/2   | Total: 12m 38s | Avg:  6m 19s | Max:  6m 35s | Hits:  99%/3554  
  🟩 GCC13              Pass: 100%/10  | Total:  1h 18m | Avg:  7m 52s | Max: 11m 49s | Hits:  99%/17770 
  🟩 MSVC14.29          Pass: 100%/2   | Total:  2h 07m | Avg:  1h 03m | Max:  1h 07m | Hits:  24%/3540  
  🟩 MSVC14.42          Pass: 100%/3   | Total:  2h 36m | Avg: 52m 02s | Max:  1h 05m | Hits:  34%/5310  
  🟩 NVHPC25.1          Pass: 100%/2   | Total: 31m 08s | Avg: 15m 34s | Max: 16m 18s | Hits:  99%/3552  
🟩 cxx_family
  🟩 Clang              Pass: 100%/17  | Total:  1h 39m | Avg:  5m 52s | Max: 10m 16s | Hits: 100%/30192 
  🟩 GCC                Pass: 100%/21  | Total:  2h 22m | Avg:  6m 46s | Max: 11m 49s | Hits:  99%/37317 
  🟩 MSVC               Pass: 100%/5   | Total:  4h 43m | Avg: 56m 40s | Max:  1h 07m | Hits:  30%/8850  
  🟩 NVHPC              Pass: 100%/2   | Total: 31m 08s | Avg: 15m 34s | Max: 16m 18s | Hits:  99%/3552  
🟩 gpu
  🟩 h100               Pass: 100%/2   | Total: 16m 31s | Avg:  8m 15s | Max: 11m 49s | Hits:  99%/3554  
  🟩 rtx2080            Pass: 100%/33  | Total:  6h 21m | Avg: 11m 33s | Max:  1h 07m | Hits:  92%/58604 
  🟩 rtx4090            Pass: 100%/10  | Total:  2h 38m | Avg: 15m 52s | Max:  1h 05m | Hits:  90%/17753 
🟩 jobs
  🟩 Build              Pass: 100%/38  | Total:  7h 48m | Avg: 12m 20s | Max:  1h 07m | Hits:  90%/67481 
  🟩 TestCPU            Pass: 100%/3   | Total: 42m 39s | Avg: 14m 13s | Max: 25m 41s | Hits:  99%/5323  
  🟩 TestGPU            Pass: 100%/4   | Total: 45m 17s | Avg: 11m 19s | Max: 11m 49s | Hits:  99%/7107  
🟩 sm
  🟩 90                 Pass: 100%/2   | Total: 16m 31s | Avg:  8m 15s | Max: 11m 49s | Hits:  99%/3554  
  🟩 90;90a;100         Pass: 100%/1   | Total:  6m 25s | Avg:  6m 25s | Max:  6m 25s | Hits:  99%/1777  
🟩 std
  🟩 17                 Pass: 100%/20  | Total:  4h 59m | Avg: 14m 57s | Max:  1h 07m | Hits:  87%/35511 
  🟩 20                 Pass: 100%/23  | Total:  4h 00m | Avg: 10m 26s | Max:  1h 05m | Hits:  95%/40846 
```

</details>

<li>
<details><summary><h3>🟩 libcudacxx: Pass: 100%/43  | Total:  6h 47m | Avg:  9m 28s | Max: 36m 30s | Hits:  91%/108269</h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/41  | Total:  6h 39m | Avg:  9m 44s | Max: 36m 30s | Hits:  90%/102348
  🟩 arm64              Pass: 100%/2   | Total:  8m 03s | Avg:  4m 01s | Max:  4m 10s | Hits:  99%/5921  
🟩 ctk
  🟩 12.0               Pass: 100%/5   | Total: 36m 50s | Avg:  7m 22s | Max: 20m 24s | Hits:  98%/14424 
  🟩 12.6               Pass: 100%/2   | Total:  1h 09m | Avg: 34m 40s | Max: 36m 30s | Hits:  29%/5868  
  🟩 12.8               Pass: 100%/36  | Total:  5h 01m | Avg:  8m 22s | Max: 25m 38s | Hits:  93%/87977 
🟩 cudacxx
  🟩 ClangCUDA18        Pass: 100%/2   | Total: 46m 22s | Avg: 23m 11s | Max: 25m 38s | Hits:  27%/5882  
  🟩 nvcc12.0           Pass: 100%/5   | Total: 36m 50s | Avg:  7m 22s | Max: 20m 24s | Hits:  98%/14424 
  🟩 nvcc12.6           Pass: 100%/2   | Total:  1h 09m | Avg: 34m 40s | Max: 36m 30s | Hits:  29%/5868  
  🟩 nvcc12.8           Pass: 100%/34  | Total:  4h 15m | Avg:  7m 30s | Max: 22m 27s | Hits:  98%/82095 
🟩 cudacxx_family
  🟩 ClangCUDA          Pass: 100%/2   | Total: 46m 22s | Avg: 23m 11s | Max: 25m 38s | Hits:  27%/5882  
  🟩 nvcc               Pass: 100%/41  | Total:  6h 01m | Avg:  8m 48s | Max: 36m 30s | Hits:  94%/102387
🟩 cxx
  🟩 Clang14            Pass: 100%/4   | Total: 18m 10s | Avg:  4m 32s | Max:  5m 07s | Hits:  98%/11732 
  🟩 Clang15            Pass: 100%/2   | Total:  9m 59s | Avg:  4m 59s | Max:  5m 20s | Hits:  98%/5878  
  🟩 Clang16            Pass: 100%/2   | Total:  9m 36s | Avg:  4m 48s | Max:  4m 59s | Hits:  99%/5878  
  🟩 Clang17            Pass: 100%/2   | Total:  9m 51s | Avg:  4m 55s | Max:  5m 16s | Hits:  98%/5878  
  🟩 Clang18            Pass: 100%/6   | Total:  1h 09m | Avg: 11m 32s | Max: 25m 38s | Hits:  70%/14720 
  🟩 GCC7               Pass: 100%/2   | Total:  8m 51s | Avg:  4m 25s | Max:  4m 40s | Hits:  98%/5815  
  🟩 GCC8               Pass: 100%/1   | Total:  4m 12s | Avg:  4m 12s | Max:  4m 12s | Hits:  99%/2918  
  🟩 GCC9               Pass: 100%/2   | Total:  8m 38s | Avg:  4m 19s | Max:  4m 27s | Hits:  98%/5827  
  🟩 GCC10              Pass: 100%/2   | Total:  9m 37s | Avg:  4m 48s | Max:  4m 59s | Hits:  98%/5884  
  🟩 GCC11              Pass: 100%/2   | Total:  8m 57s | Avg:  4m 28s | Max:  4m 57s | Hits:  98%/5880  
  🟩 GCC12              Pass: 100%/2   | Total:  8m 47s | Avg:  4m 23s | Max:  4m 37s | Hits:  98%/5880  
  🟩 GCC13              Pass: 100%/10  | Total:  1h 26m | Avg:  8m 41s | Max: 22m 27s | Hits:  98%/14981 
  🟩 MSVC14.29          Pass: 100%/2   | Total: 42m 49s | Avg: 21m 24s | Max: 22m 25s | Hits:  99%/5529  
  🟩 MSVC14.42          Pass: 100%/2   | Total: 42m 35s | Avg: 21m 17s | Max: 21m 36s | Hits:  99%/5601  
  🟩 NVHPC25.1          Pass: 100%/2   | Total:  1h 09m | Avg: 34m 40s | Max: 36m 30s | Hits:  29%/5868  
🟩 cxx_family
  🟩 Clang              Pass: 100%/16  | Total:  1h 56m | Avg:  7m 18s | Max: 25m 38s | Hits:  89%/44086 
  🟩 GCC                Pass: 100%/21  | Total:  2h 15m | Avg:  6m 28s | Max: 22m 27s | Hits:  98%/47185 
  🟩 MSVC               Pass: 100%/4   | Total:  1h 25m | Avg: 21m 21s | Max: 22m 25s | Hits:  99%/11130 
  🟩 NVHPC              Pass: 100%/2   | Total:  1h 09m | Avg: 34m 40s | Max: 36m 30s | Hits:  29%/5868  
🟩 gpu
  🟩 h100               Pass: 100%/2   | Total: 17m 02s | Avg:  8m 31s | Max: 12m 26s | Hits:  99%/3050  
  🟩 rtx2080            Pass: 100%/41  | Total:  6h 30m | Avg:  9m 31s | Max: 36m 30s | Hits:  90%/105219
🟩 jobs
  🟩 Build              Pass: 100%/37  | Total:  5h 34m | Avg:  9m 02s | Max: 36m 30s | Hits:  91%/108229
  🟩 NVRTC              Pass: 100%/2   | Total: 39m 04s | Avg: 19m 32s | Max: 22m 27s | Hits:  90%/40    
  🟩 Test               Pass: 100%/3   | Total: 31m 50s | Avg: 10m 36s | Max: 12m 26s
  🟩 VerifyCodegen      Pass: 100%/1   | Total:  2m 12s | Avg:  2m 12s | Max:  2m 12s
🟩 sm
  🟩 75                 Pass: 100%/2   | Total: 39m 04s | Avg: 19m 32s | Max: 22m 27s | Hits:  90%/40    
  🟩 90                 Pass: 100%/2   | Total: 17m 02s | Avg:  8m 31s | Max: 12m 26s | Hits:  99%/3050  
  🟩 90;90a;100         Pass: 100%/1   | Total:  5m 14s | Avg:  5m 14s | Max:  5m 14s | Hits:  98%/3050  
🟩 std
  🟩 17                 Pass: 100%/21  | Total:  3h 22m | Avg:  9m 39s | Max: 32m 50s | Hits:  91%/57887 
  🟩 20                 Pass: 100%/21  | Total:  3h 22m | Avg:  9m 38s | Max: 36m 30s | Hits:  90%/50382 
```

</details>

<li>
<details><summary><h3>🟩 cudax: Pass: 100%/22  | Total:  4h 20m | Avg: 11m 49s | Max: 23m 42s | Hits:  80%/12304 </h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/18  | Total:  3h 45m | Avg: 12m 30s | Max: 23m 42s | Hits:  80%/9956  
  🟩 arm64              Pass: 100%/4   | Total: 35m 00s | Avg:  8m 45s | Max:  9m 32s | Hits:  80%/2348  
🟩 ctk
  🟩 12.0               Pass: 100%/1   | Total:  9m 57s | Avg:  9m 57s | Max:  9m 57s | Hits:  95%/282   
  🟩 12.6               Pass: 100%/2   | Total: 44m 59s | Avg: 22m 29s | Max: 23m 42s | Hits:  69%/1170  
  🟩 12.8               Pass: 100%/19  | Total:  3h 25m | Avg: 10m 48s | Max: 19m 13s | Hits:  81%/10852 
🟩 cudacxx
  🟩 nvcc12.0           Pass: 100%/1   | Total:  9m 57s | Avg:  9m 57s | Max:  9m 57s | Hits:  95%/282   
  🟩 nvcc12.6           Pass: 100%/2   | Total: 44m 59s | Avg: 22m 29s | Max: 23m 42s | Hits:  69%/1170  
  🟩 nvcc12.8           Pass: 100%/19  | Total:  3h 25m | Avg: 10m 48s | Max: 19m 13s | Hits:  81%/10852 
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/22  | Total:  4h 20m | Avg: 11m 49s | Max: 23m 42s | Hits:  80%/12304 
🟩 cxx
  🟩 Clang14            Pass: 100%/1   | Total:  9m 14s | Avg:  9m 14s | Max:  9m 14s | Hits:  80%/589   
  🟩 Clang15            Pass: 100%/1   | Total: 10m 52s | Avg: 10m 52s | Max: 10m 52s | Hits:  80%/587   
  🟩 Clang16            Pass: 100%/1   | Total: 10m 03s | Avg: 10m 03s | Max: 10m 03s | Hits:  80%/587   
  🟩 Clang17            Pass: 100%/1   | Total: 10m 09s | Avg: 10m 09s | Max: 10m 09s | Hits:  80%/587   
  🟩 Clang18            Pass: 100%/4   | Total: 50m 09s | Avg: 12m 32s | Max: 19m 13s | Hits:  80%/2348  
  🟩 GCC10              Pass: 100%/1   | Total: 10m 19s | Avg: 10m 19s | Max: 10m 19s | Hits:  80%/589   
  🟩 GCC11              Pass: 100%/1   | Total:  9m 50s | Avg:  9m 50s | Max:  9m 50s | Hits:  80%/587   
  🟩 GCC12              Pass: 100%/2   | Total: 27m 57s | Avg: 13m 58s | Max: 15m 17s | Hits:  80%/1174  
  🟩 GCC13              Pass: 100%/6   | Total: 56m 23s | Avg:  9m 23s | Max: 11m 33s | Hits:  80%/3522  
  🟩 MSVC14.39          Pass: 100%/1   | Total:  9m 57s | Avg:  9m 57s | Max:  9m 57s | Hits:  95%/282   
  🟩 MSVC14.42          Pass: 100%/1   | Total: 10m 21s | Avg: 10m 21s | Max: 10m 21s | Hits:  95%/282   
  🟩 NVHPC25.1          Pass: 100%/2   | Total: 44m 59s | Avg: 22m 29s | Max: 23m 42s | Hits:  69%/1170  
🟩 cxx_family
  🟩 Clang              Pass: 100%/8   | Total:  1h 30m | Avg: 11m 18s | Max: 19m 13s | Hits:  80%/4698  
  🟩 GCC                Pass: 100%/10  | Total:  1h 44m | Avg: 10m 26s | Max: 15m 17s | Hits:  80%/5872  
  🟩 MSVC               Pass: 100%/2   | Total: 20m 18s | Avg: 10m 09s | Max: 10m 21s | Hits:  95%/564   
  🟩 NVHPC              Pass: 100%/2   | Total: 44m 59s | Avg: 22m 29s | Max: 23m 42s | Hits:  69%/1170  
🟩 gpu
  🟩 h100               Pass: 100%/2   | Total: 22m 38s | Avg: 11m 19s | Max: 11m 33s | Hits:  80%/1174  
  🟩 rtx2080            Pass: 100%/20  | Total:  3h 57m | Avg: 11m 52s | Max: 23m 42s | Hits:  80%/11130 
🟩 jobs
  🟩 Build              Pass: 100%/19  | Total:  3h 36m | Avg: 11m 24s | Max: 23m 42s | Hits:  77%/10543 
  🟩 Test               Pass: 100%/3   | Total: 43m 26s | Avg: 14m 28s | Max: 19m 13s | Hits:  99%/1761  
🟩 sm
  🟩 90                 Pass: 100%/3   | Total: 29m 59s | Avg:  9m 59s | Max: 11m 33s | Hits:  80%/1761  
  🟩 90a                Pass: 100%/1   | Total:  8m 20s | Avg:  8m 20s | Max:  8m 20s | Hits:  80%/587   
🟩 std
  🟩 17                 Pass: 100%/4   | Total: 45m 17s | Avg: 11m 19s | Max: 21m 17s | Hits:  77%/2346  
  🟩 20                 Pass: 100%/18  | Total:  3h 34m | Avg: 11m 56s | Max: 23m 42s | Hits:  80%/9958  
```

</details>

<li>
<details><summary><h3>🟩 cccl: Pass: 100%/4   | Total: 13m 42s | Avg:  3m 25s | Max:  3m 49s</h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/4   | Total: 13m 42s | Avg:  3m 25s | Max:  3m 49s
🟩 ctk
  🟩 12.0               Pass: 100%/2   | Total:  6m 22s | Avg:  3m 11s | Max:  3m 35s
  🟩 12.8               Pass: 100%/2   | Total:  7m 20s | Avg:  3m 40s | Max:  3m 49s
🟩 cudacxx
  🟩 nvcc12.0           Pass: 100%/2   | Total:  6m 22s | Avg:  3m 11s | Max:  3m 35s
  🟩 nvcc12.8           Pass: 100%/2   | Total:  7m 20s | Avg:  3m 40s | Max:  3m 49s
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/4   | Total: 13m 42s | Avg:  3m 25s | Max:  3m 49s
🟩 cxx
  🟩 Clang14            Pass: 100%/1   | Total:  3m 35s | Avg:  3m 35s | Max:  3m 35s
  🟩 Clang18            Pass: 100%/1   | Total:  3m 49s | Avg:  3m 49s | Max:  3m 49s
  🟩 GCC12              Pass: 100%/1   | Total:  2m 47s | Avg:  2m 47s | Max:  2m 47s
  🟩 GCC13              Pass: 100%/1   | Total:  3m 31s | Avg:  3m 31s | Max:  3m 31s
🟩 cxx_family
  🟩 Clang              Pass: 100%/2   | Total:  7m 24s | Avg:  3m 42s | Max:  3m 49s
  🟩 GCC                Pass: 100%/2   | Total:  6m 18s | Avg:  3m 09s | Max:  3m 31s
🟩 gpu
  🟩 rtx2080            Pass: 100%/4   | Total: 13m 42s | Avg:  3m 25s | Max:  3m 49s
🟩 jobs
  🟩 Infra              Pass: 100%/4   | Total: 13m 42s | Avg:  3m 25s | Max:  3m 49s
```

</details>

<li>
<details><summary><h3>🟩 stdpar: Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s</h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/2   | Total:  9m 56s | Avg:  4m 58s | Max:  5m 06s
  🟩 arm64              Pass: 100%/2   | Total:  6m 30s | Avg:  3m 15s | Max:  3m 17s
🟩 ctk
  🟩 12.6               Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 cudacxx
  🟩 nvcc12.6           Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 cxx
  🟩 NVHPC25.1          Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 cxx_family
  🟩 NVHPC              Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 gpu
  🟩 rtx2080            Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 jobs
  🟩 Build              Pass: 100%/4   | Total: 16m 26s | Avg:  4m 06s | Max:  5m 06s
🟩 std
  🟩 17                 Pass: 100%/2   | Total:  8m 19s | Avg:  4m 09s | Max:  5m 06s
  🟩 20                 Pass: 100%/2   | Total:  8m 07s | Avg:  4m 03s | Max:  4m 50s
```

</details>

<li>
<details><summary><h3>🟩 cccl_c_parallel: Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   </h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 ctk
  🟩 12.8               Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 cudacxx
  🟩 nvcc12.8           Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 cxx
  🟩 GCC13              Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 cxx_family
  🟩 GCC                Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 gpu
  🟩 rtx2080            Pass: 100%/2   | Total: 19m 33s | Avg:  9m 46s | Max: 17m 09s | Hits:  98%/328   
🟩 jobs
  🟩 Build              Pass: 100%/1   | Total:  2m 24s | Avg:  2m 24s | Max:  2m 24s | Hits:  98%/164   
  🟩 Test               Pass: 100%/1   | Total: 17m 09s | Avg: 17m 09s | Max: 17m 09s | Hits:  98%/164   
```

</details>

<li>
<details><summary><h3>🟩 python: Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m</h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 ctk
  🟩 12.8               Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 cudacxx
  🟩 nvcc12.8           Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 cxx
  🟩 GCC13              Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 cxx_family
  🟩 GCC                Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 gpu
  🟩 rtx2080            Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
🟩 jobs
  🟩 Test               Pass: 100%/1   | Total:  1h 08m | Avg:  1h 08m | Max:  1h 08m
```

</details>

</ul>

<details><summary><h3>👃 Inspect Changes</h3></summary>

### Modifications in project?

|     | Project
|-----|---------
| +/- | CCCL Infrastructure
| +/- | libcu++
| +/- | CUB
| +/- | Thrust
| +/- | CUDA Experimental
|     | stdpar
| +/- | python
|     | CCCL C Parallel Library
|     | Catch2Helper

### Modifications in project or dependencies?

|     | Project
|-----|---------
| +/- | CCCL Infrastructure
| +/- | libcu++
| +/- | CUB
| +/- | Thrust
| +/- | CUDA Experimental
| +/- | stdpar
| +/- | python
| +/- | CCCL C Parallel Library
| +/- | Catch2Helper
</details>


<details><summary><h2>🏃‍ Runner counts (total jobs: 166)</h2></summary>

|  #   | Runner
|------|------
|  113 | `linux-amd64-cpu16`
|   15 | `windows-amd64-cpu16`
|   12 | `linux-amd64-gpu-rtx2080-latest-1`
|   12 | `linux-arm64-cpu16`
|    6 | `linux-amd64-gpu-rtxa6000-latest-1`
|    5 | `linux-amd64-gpu-h100-latest-1`
|    3 | `linux-amd64-gpu-rtx4090-latest-1`


</details>

</details>

author_association: CONTRIBUTOR
user: login: caugonnet
created_at: 2025-04-13T07:05:23Z
body: /ok to test
author_association: CONTRIBUTOR
user: login: copy-pr-bot[bot]
created_at: 2025-04-13T07:05:26Z
body: > /ok to test

@caugonnet, there was an error processing your request: `E1`

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/
author_association: CONTRIBUTOR
user: login: caugonnet
created_at: 2025-04-13T15:33:19Z
body: /ok to test 9d0ab048a
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-13T17:56:34Z
body: <details><summary>🟩 CI finished in 2h 21m: Pass: 100%/26  | Total:  6h 20m | Avg: 14m 38s | Max: 29m 21s | Hits:  67%/14540</summary>

<ul>
<li>
<details><summary><h3>🟩 cudax: Pass: 100%/26  | Total:  6h 20m | Avg: 14m 38s | Max: 29m 21s | Hits:  67%/14540 </h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/22  | Total:  5h 30m | Avg: 15m 01s | Max: 29m 21s | Hits:  68%/12212 
  🟩 arm64              Pass: 100%/4   | Total: 50m 12s | Avg: 12m 33s | Max: 13m 11s | Hits:  62%/2328  
🟩 ctk
  🟩 12.0               Pass: 100%/3   | Total: 40m 47s | Avg: 13m 35s | Max: 14m 44s | Hits:  69%/1452  
  🟩 12.8               Pass: 100%/23  | Total:  5h 39m | Avg: 14m 46s | Max: 29m 21s | Hits:  67%/13088 
🟩 cudacxx
  🟩 nvcc12.0           Pass: 100%/3   | Total: 40m 47s | Avg: 13m 35s | Max: 14m 44s | Hits:  69%/1452  
  🟩 nvcc12.8           Pass: 100%/23  | Total:  5h 39m | Avg: 14m 46s | Max: 29m 21s | Hits:  67%/13088 
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/26  | Total:  6h 20m | Avg: 14m 38s | Max: 29m 21s | Hits:  67%/14540 
🟩 cxx
  🟩 Clang14            Pass: 100%/2   | Total: 25m 05s | Avg: 12m 32s | Max: 13m 02s | Hits:  63%/1168  
  🟩 Clang15            Pass: 100%/1   | Total: 14m 26s | Avg: 14m 26s | Max: 14m 26s | Hits:  63%/582   
  🟩 Clang16            Pass: 100%/1   | Total: 14m 14s | Avg: 14m 14s | Max: 14m 14s | Hits:  63%/582   
  🟩 Clang17            Pass: 100%/1   | Total: 13m 44s | Avg: 13m 44s | Max: 13m 44s | Hits:  63%/582   
  🟩 Clang18            Pass: 100%/1   | Total: 14m 58s | Avg: 14m 58s | Max: 14m 58s | Hits:  63%/582   
  🟩 Clang19            Pass: 100%/4   | Total: 54m 02s | Avg: 13m 30s | Max: 16m 24s | Hits:  72%/2328  
  🟩 GCC10              Pass: 100%/2   | Total: 28m 53s | Avg: 14m 26s | Max: 14m 44s | Hits:  62%/1168  
  🟩 GCC11              Pass: 100%/1   | Total: 14m 18s | Avg: 14m 18s | Max: 14m 18s | Hits:  62%/582   
  🟩 GCC12              Pass: 100%/1   | Total: 15m 15s | Avg: 15m 15s | Max: 15m 15s | Hits:  62%/582   
  🟩 GCC13              Pass: 100%/8   | Total:  1h 41m | Avg: 12m 44s | Max: 15m 44s | Hits:  70%/4656  
  🟩 MSVC14.39          Pass: 100%/1   | Total: 14m 00s | Avg: 14m 00s | Max: 14m 00s | Hits:  95%/284   
  🟩 MSVC14.42          Pass: 100%/1   | Total: 12m 10s | Avg: 12m 10s | Max: 12m 10s | Hits:  95%/284   
  🟩 NVHPC25.3          Pass: 100%/2   | Total: 57m 47s | Avg: 28m 53s | Max: 29m 21s | Hits:  60%/1160  
🟩 cxx_family
  🟩 Clang              Pass: 100%/10  | Total:  2h 16m | Avg: 13m 38s | Max: 16m 24s | Hits:  66%/5824  
  🟩 GCC                Pass: 100%/12  | Total:  2h 40m | Avg: 13m 21s | Max: 15m 44s | Hits:  67%/6988  
  🟩 MSVC               Pass: 100%/2   | Total: 26m 10s | Avg: 13m 05s | Max: 14m 00s | Hits:  95%/568   
  🟩 NVHPC              Pass: 100%/2   | Total: 57m 47s | Avg: 28m 53s | Max: 29m 21s | Hits:  60%/1160  
🟩 gpu
  🟩 h100               Pass: 100%/2   | Total: 23m 37s | Avg: 11m 48s | Max: 11m 56s | Hits:  77%/1164  
  🟩 rtx2080            Pass: 100%/24  | Total:  5h 57m | Avg: 14m 52s | Max: 29m 21s | Hits:  66%/13376 
🟩 jobs
  🟩 Build              Pass: 100%/23  | Total:  5h 39m | Avg: 14m 46s | Max: 29m 21s | Hits:  63%/12794 
  🟩 Test               Pass: 100%/3   | Total: 40m 59s | Avg: 13m 39s | Max: 15m 44s | Hits:  99%/1746  
🟩 sm
  🟩 90                 Pass: 100%/3   | Total: 33m 55s | Avg: 11m 18s | Max: 11m 56s | Hits:  70%/1746  
  🟩 90a                Pass: 100%/1   | Total: 10m 57s | Avg: 10m 57s | Max: 10m 57s | Hits:  62%/582   
🟩 std
  🟩 17                 Pass: 100%/4   | Total:  1h 04m | Avg: 16m 01s | Max: 29m 21s | Hits:  60%/2326  
  🟩 20                 Pass: 100%/22  | Total:  5h 16m | Avg: 14m 23s | Max: 28m 26s | Hits:  69%/12214 
```

</details>

</ul>

<details><summary><h3>👃 Inspect Changes</h3></summary>

### Modifications in project?

|     | Project
|-----|---------
|     | CCCL Infrastructure
|     | libcu++
|     | CUB
|     | Thrust
| +/- | CUDA Experimental
|     | stdpar
|     | python
|     | CCCL C Parallel Library
|     | Catch2Helper

### Modifications in project or dependencies?

|     | Project
|-----|---------
|     | CCCL Infrastructure
|     | libcu++
|     | CUB
|     | Thrust
| +/- | CUDA Experimental
|     | stdpar
|     | python
|     | CCCL C Parallel Library
|     | Catch2Helper
</details>


<details><summary><h2>🏃‍ Runner counts (total jobs: 26)</h2></summary>

|  #   | Runner
|------|------
|   17 | `linux-amd64-cpu16`
|    4 | `linux-arm64-cpu16`
|    2 | `windows-amd64-cpu16`
|    2 | `linux-amd64-gpu-rtx2080-latest-1`
|    1 | `linux-amd64-gpu-h100-latest-1`


</details>

</details>

author_association: CONTRIBUTOR
user: login: caugonnet
created_at: 2025-04-15T08:57:16Z
body: /ok to test 75a057963
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-15T13:18:12Z
body: <details><summary>🟩 CI finished in 4h 19m: Pass: 100%/26  | Total:  6h 18m | Avg: 14m 33s | Max: 30m 43s | Hits:  68%/14540</summary>

<ul>
<li>
<details><summary><h3>🟩 cudax: Pass: 100%/26  | Total:  6h 18m | Avg: 14m 33s | Max: 30m 43s | Hits:  68%/14540 </h3></summary>

```
🟩 cpu
  🟩 amd64              Pass: 100%/22  | Total:  5h 28m | Avg: 14m 56s | Max: 30m 43s | Hits:  69%/12212 
  🟩 arm64              Pass: 100%/4   | Total: 49m 45s | Avg: 12m 26s | Max: 13m 33s | Hits:  63%/2328  
🟩 ctk
  🟩 12.0               Pass: 100%/3   | Total: 36m 10s | Avg: 12m 03s | Max: 13m 44s | Hits:  70%/1452  
  🟩 12.8               Pass: 100%/23  | Total:  5h 42m | Avg: 14m 52s | Max: 30m 43s | Hits:  68%/13088 
🟩 cudacxx
  🟩 nvcc12.0           Pass: 100%/3   | Total: 36m 10s | Avg: 12m 03s | Max: 13m 44s | Hits:  70%/1452  
  🟩 nvcc12.8           Pass: 100%/23  | Total:  5h 42m | Avg: 14m 52s | Max: 30m 43s | Hits:  68%/13088 
🟩 cudacxx_family
  🟩 nvcc               Pass: 100%/26  | Total:  6h 18m | Avg: 14m 33s | Max: 30m 43s | Hits:  68%/14540 
🟩 cxx
  🟩 Clang14            Pass: 100%/2   | Total: 25m 23s | Avg: 12m 41s | Max: 13m 17s | Hits:  63%/1168  
  🟩 Clang15            Pass: 100%/1   | Total: 14m 08s | Avg: 14m 08s | Max: 14m 08s | Hits:  63%/582   
  🟩 Clang16            Pass: 100%/1   | Total: 15m 31s | Avg: 15m 31s | Max: 15m 31s | Hits:  63%/582   
  🟩 Clang17            Pass: 100%/1   | Total: 15m 03s | Avg: 15m 03s | Max: 15m 03s | Hits:  63%/582   
  🟩 Clang18            Pass: 100%/1   | Total: 13m 34s | Avg: 13m 34s | Max: 13m 34s | Hits:  63%/582   
  🟩 Clang19            Pass: 100%/4   | Total: 50m 37s | Avg: 12m 39s | Max: 13m 43s | Hits:  72%/2328  
  🟩 GCC10              Pass: 100%/2   | Total: 28m 31s | Avg: 14m 15s | Max: 14m 47s | Hits:  63%/1168  
  🟩 GCC11              Pass: 100%/1   | Total: 17m 50s | Avg: 17m 50s | Max: 17m 50s | Hits:  63%/582   
  🟩 GCC12              Pass: 100%/1   | Total: 15m 42s | Avg: 15m 42s | Max: 15m 42s | Hits:  63%/582   
  🟩 GCC13              Pass: 100%/8   | Total:  1h 39m | Avg: 12m 27s | Max: 14m 57s | Hits:  72%/4656  
  🟩 MSVC14.39          Pass: 100%/1   | Total: 10m 20s | Avg: 10m 20s | Max: 10m 20s | Hits:  95%/284   
  🟩 MSVC14.42          Pass: 100%/1   | Total: 14m 26s | Avg: 14m 26s | Max: 14m 26s | Hits:  95%/284   
  🟩 NVHPC25.3          Pass: 100%/2   | Total: 57m 45s | Avg: 28m 52s | Max: 30m 43s | Hits:  60%/1160  
🟩 cxx_family
  🟩 Clang              Pass: 100%/10  | Total:  2h 14m | Avg: 13m 25s | Max: 15m 31s | Hits:  67%/5824  
  🟩 GCC                Pass: 100%/12  | Total:  2h 41m | Avg: 13m 28s | Max: 17m 50s | Hits:  69%/6988  
  🟩 MSVC               Pass: 100%/2   | Total: 24m 46s | Avg: 12m 23s | Max: 14m 26s | Hits:  95%/568   
  🟩 NVHPC              Pass: 100%/2   | Total: 57m 45s | Avg: 28m 52s | Max: 30m 43s | Hits:  60%/1160  
🟩 gpu
  🟩 h100               Pass: 100%/2   | Total: 24m 48s | Avg: 12m 24s | Max: 14m 20s | Hits:  81%/1164  
  🟩 rtx2080            Pass: 100%/24  | Total:  5h 53m | Avg: 14m 44s | Max: 30m 43s | Hits:  67%/13376 
🟩 jobs
  🟩 Build              Pass: 100%/23  | Total:  5h 38m | Avg: 14m 43s | Max: 30m 43s | Hits:  64%/12794 
  🟩 Test               Pass: 100%/3   | Total: 39m 50s | Avg: 13m 16s | Max: 14m 20s | Hits:  99%/1746  
🟩 sm
  🟩 90                 Pass: 100%/3   | Total: 35m 02s | Avg: 11m 40s | Max: 14m 20s | Hits:  75%/1746  
  🟩 90a                Pass: 100%/1   | Total: 11m 18s | Avg: 11m 18s | Max: 11m 18s | Hits:  63%/582   
🟩 std
  🟩 17                 Pass: 100%/4   | Total:  1h 00m | Avg: 15m 12s | Max: 27m 02s | Hits:  62%/2326  
  🟩 20                 Pass: 100%/22  | Total:  5h 17m | Avg: 14m 26s | Max: 30m 43s | Hits:  70%/12214 
```

</details>

</ul>

<details><summary><h3>👃 Inspect Changes</h3></summary>

### Modifications in project?

|     | Project
|-----|---------
|     | CCCL Infrastructure
|     | libcu++
|     | CUB
|     | Thrust
| +/- | CUDA Experimental
|     | stdpar
|     | python
|     | CCCL C Parallel Library
|     | Catch2Helper

### Modifications in project or dependencies?

|     | Project
|-----|---------
|     | CCCL Infrastructure
|     | libcu++
|     | CUB
|     | Thrust
| +/- | CUDA Experimental
|     | stdpar
|     | python
|     | CCCL C Parallel Library
|     | Catch2Helper
</details>


<details><summary><h2>🏃‍ Runner counts (total jobs: 26)</h2></summary>

|  #   | Runner
|------|------
|   17 | `linux-amd64-cpu16`
|    4 | `linux-arm64-cpu16`
|    2 | `windows-amd64-cpu16`
|    2 | `linux-amd64-gpu-rtx2080-latest-1`
|    1 | `linux-amd64-gpu-h100-latest-1`


</details>

</details>

author_association: CONTRIBUTOR