Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
TreeTraversalCache.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
19#include "shamalgs/numeric.hpp"
20#include "shambackends/sycl.hpp"
23
24namespace shamrock::tree {
25
27
30
31 std::function<ObjectCache(u64)> generator;
32 std::deque<u64> last_device_builds;
33
34 u64 max_device_memsize;
35 u64 current_device_memsize = 0;
36 u64 current_host_memsize = 0;
37
38 public:
39 ObjectCacheHandler(u64 max_memsize, std::function<ObjectCache(u64)> &&generator)
40 : max_device_memsize(max_memsize), generator(generator) {}
41
42 private:
43 inline bool offload_exist(u64 id) { return cache_offload.has_key(id); }
44
45 inline bool cache_entry_exist(u64 id) { return cache.has_key(id); }
46
47 inline ObjectCache pop_offload(u64 id) {
48 ObjectCache tmp = ObjectCache::build_from_host(cache_offload.get(id));
49 cache_offload.erase(id);
50 current_host_memsize -= tmp.get_memsize();
51 return tmp;
52 }
53
54 inline HostObjectCache pop_cache(u64 id) {
55 ObjectCache &tmp = cache.get(id);
56
57 HostObjectCache ret = tmp.copy_to_host();
58
59 current_device_memsize -= tmp.get_memsize();
60 cache.erase(id);
61
62 return ret;
63 }
64
65 inline void push_offload(u64 id, HostObjectCache &&c) {
66 current_host_memsize += c.get_memsize();
67 cache_offload.add_obj(id, std::forward<HostObjectCache>(c));
68 }
69
70 inline void push_cache(u64 id, ObjectCache &&c) {
71 current_device_memsize += c.get_memsize();
72 cache.add_obj(id, std::forward<ObjectCache>(c));
73 last_device_builds.push_back(id);
74 }
75
76 inline void offload_entry(u64 id) {
77 HostObjectCache tmp = pop_cache(id);
78 push_offload(id, std::move(tmp));
79 }
80
81 inline ObjectCache load_or_build_cache(u64 id) {
82 if (cache_offload.has_key(id)) {
83 return pop_offload(id);
84 } else {
85 return generator(id);
86 }
87 }
88
93 inline void offload_oldest() {
94
95 bool successful_pop = false;
96 do {
97
98 if (cache.is_empty()) {
100 "the cache is empty no entry can be popped");
101 }
102
103 u64 last_id = last_device_builds.front();
104 last_device_builds.pop_front();
105
106 if (cache.has_key(last_id)) {
107
108 offload_entry(last_id);
109
110 successful_pop = true;
111 shamlog_debug_ln(
112 "ObjectCacheHandler",
113 "offloaded cache for id =",
114 last_id,
115 "cachesize =",
116 shambase::readable_sizeof(current_device_memsize),
117 "hostsize =",
118 shambase::readable_sizeof(current_host_memsize));
119 }
120
121 } while (!successful_pop);
122 }
123
130 inline void push_new(u64 id, ObjectCache &&c) {
131 u64 add_sz = c.get_memsize();
132
133 if (add_sz + current_device_memsize > max_device_memsize) {
135 "their is no space within the imposed limit, try freeing some space in the "
136 "cache, or increase the size limit");
137 }
138
139 push_cache(id, std::forward<ObjectCache>(c));
140 last_device_builds.push_back(id);
141 }
142
143 public:
150 inline void build_cache(u64 id) {
151
152 ObjectCache new_cache = load_or_build_cache(id);
153
154 u64 new_sz = new_cache.get_memsize();
155
156 while (new_sz + current_device_memsize > max_device_memsize) {
157 if (cache.is_empty()) {
159 "their no space left to allocate a cache, try with smaller objects, or "
160 "increase the size limit");
161 }
162 logger::warn_ln(
163 "ObjectCacheHandler",
164 "The cache is too small, or the objects too big, some caches will "
165 "have to be recomputed on the fly");
166 offload_oldest();
167 }
168
169 push_new(id, std::move(new_cache));
170 shamlog_debug_ln(
171 "ObjectCacheHandler",
172 "built cache for id =",
173 id,
174 "cachesize =",
175 shambase::readable_sizeof(current_device_memsize),
176 "hostsize =",
177 shambase::readable_sizeof(current_host_memsize));
178 }
179
187 if (cache.has_key(id)) {
188 return cache.get(id);
189 } else {
190 build_cache(id);
191 return cache.get(id);
192 }
193 }
194
195 inline void preload(u64 id) { get_cache(id); }
196
197 inline void reset() {
198 last_device_builds.clear();
199 cache.reset();
200 cache_offload.reset();
201 current_device_memsize = 0;
202 current_host_memsize = 0;
203 }
204 };
205
206} // namespace shamrock::tree
std::uint64_t u64
64 bit unsigned integer
Represents a collection of objects distributed across patches identified by a u64 id.
iterator add_obj(u64 id, T &&obj)
Adds a new object to the collection.
bool is_empty()
Returns true if the collection is empty.
void erase(u64 id)
Removes an object from the collection.
T & get(u64 id)
Returns a reference to an object in the collection.
bool has_key(u64 id)
Checks if an object exists in the collection.
void reset()
Reset the collection to its initial state.
ObjectCache & get_cache(u64 id)
Get a cache entry and build it if it is not already in the cache.
void build_cache(u64 id)
build a new entry in the cache and free enough entry to make space for it if necessary
std::string readable_sizeof(double size)
given a sizeof value return a readble string Example : readable_sizeof(1024*1024*1024) -> "1....
Definition string.hpp:139
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.