Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
pyShamalgs.cpp
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
15
17#include "shambase/time.hpp"
28#include "shamalgs/random.hpp"
32#include "shamcomm/logs.hpp"
34#include <pybind11/complex.h>
35#include <utility>
36
38 auto &m = root_module;
39
40 py::module shamalgs_module = m.def_submodule("algs", "algorithmic library");
41
42 py::class_<std::mt19937>(shamalgs_module, "rng");
43
44 py::class_<shamalgs::impl_param>(shamalgs_module, "impl_param")
45 .def(py::init([]() {
46 return shamalgs::impl_param{.impl_name = "", .params = ""};
47 }))
48 .def_readwrite(
49 "impl_name",
50 &shamalgs::impl_param::impl_name,
51 py::return_value_policy::reference_internal)
52 .def_readwrite(
53 "params", &shamalgs::impl_param::params, py::return_value_policy::reference_internal)
54 .def(
55 "__str__",
56 [](const shamalgs::impl_param &impl_param) {
57 return sham::format(
58 "impl_param(impl_name=\"{}\", params=\"{}\")",
59 impl_param.impl_name,
60 impl_param.params);
61 })
62 .def("__repr__", [](const shamalgs::impl_param &impl_param) {
63 return sham::format(
64 "impl_param(impl_name=\"{}\", params=\"{}\")",
65 impl_param.impl_name,
66 impl_param.params);
67 });
68
69 shamalgs_module.def("gen_seed", [](u64 seed) {
70 return std::mt19937(seed);
71 });
72
73 shamalgs_module.def("mock_gaussian", [](std::mt19937 &eng) {
74 return shamalgs::random::mock_gaussian<f64>(eng);
75 });
76 shamalgs_module.def("mock_gaussian_f64_2", [](std::mt19937 &eng) {
77 return shamalgs::random::mock_gaussian_multidim<f64_2>(eng);
78 });
79 shamalgs_module.def("mock_gaussian_f64_3", [](std::mt19937 &eng) {
80 return shamalgs::random::mock_gaussian_multidim<f64_3>(eng);
81 });
82 shamalgs_module.def("mock_unit_vector_f64_3", [](std::mt19937 &eng) {
83 return shamalgs::random::mock_unit_vector<f64_3>(eng);
84 });
85
86 shamalgs_module.def("mock_buffer_f64", [](u64 seed, u32 len, f64 min_bound, f64 max_bound) {
87 return shamalgs::random::mock_buffer_usm<f64>(
88 shamsys::instance::get_compute_scheduler_ptr(), seed, len, min_bound, max_bound);
89 });
90 shamalgs_module.def("mock_buffer_u8", [](u64 seed, u32 len, u8 min_bound, u8 max_bound) {
91 return shamalgs::random::mock_buffer_usm<u8>(
92 shamsys::instance::get_compute_scheduler_ptr(), seed, len, min_bound, max_bound);
93 });
94 shamalgs_module.def("mock_buffer_u32", [](u64 seed, u32 len, u32 min_bound, u32 max_bound) {
95 return shamalgs::random::mock_buffer_usm<u32>(
96 shamsys::instance::get_compute_scheduler_ptr(), seed, len, min_bound, max_bound);
97 });
98 shamalgs_module.def(
99 "mock_buffer_f64_2", [](u64 seed, u32 len, f64_2 min_bound, f64_2 max_bound) {
100 return shamalgs::random::mock_buffer_usm<f64_2>(
101 shamsys::instance::get_compute_scheduler_ptr(), seed, len, min_bound, max_bound);
102 });
103 shamalgs_module.def(
104 "mock_buffer_f64_3", [](u64 seed, u32 len, f64_3 min_bound, f64_3 max_bound) {
105 return shamalgs::random::mock_buffer_usm<f64_3>(
106 shamsys::instance::get_compute_scheduler_ptr(), seed, len, min_bound, max_bound);
107 });
108
109 { // is_all_true
110
111 shamalgs_module.def("is_all_true", [](sham::DeviceBuffer<u8> &buf, u32 len) {
112 return shamalgs::primitives::is_all_true(buf, len);
113 });
114
115 shamalgs_module.def("benchmark_is_all_true", [](sham::DeviceBuffer<u8> &buf, u32 len) {
116 buf.synchronize();
117 shambase::Timer timer;
118 timer.start();
119 bool result = shamalgs::primitives::is_all_true(buf, len);
120 buf.synchronize();
121 timer.stop();
122 return timer.elapsed_sec();
123 });
124
125 shamalgs_module.def("set_impl_is_all_true", [](const std::string &impl) {
127 });
128
129 shamalgs_module.def("get_current_impl_is_all_true", []() {
131 });
132
133 shamalgs_module.def("get_default_impl_list_is_all_true", []() {
135 });
136
137 shamalgs_module.def("is_impl_set_is_all_true", []() {
139 });
140
141 shamalgs_module.def("autoselect_impl_is_all_true", []() {
143 shamsys::instance::get_compute_scheduler_ptr());
144 });
145 }
146
147 { // reductions
148 shamalgs_module.def("sum", [](sham::DeviceBuffer<f64> &buf, u32 start_id, u32 end_id) {
150 shamsys::instance::get_compute_scheduler_ptr(), buf, start_id, end_id);
151 });
152
153 shamalgs_module.def("benchmark_reduction_sum", [](sham::DeviceBuffer<f64> &buf, u32 len) {
154 buf.synchronize();
155 shambase::Timer timer;
156 timer.start();
158 shamsys::instance::get_compute_scheduler_ptr(), buf, 0, len);
159 timer.stop();
160 return timer.elapsed_sec();
161 });
162
163 shamalgs_module.def("benchmark_reduction_sum", [](sham::DeviceBuffer<f32> &buf, u32 len) {
164 buf.synchronize();
165 shambase::Timer timer;
166 timer.start();
168 shamsys::instance::get_compute_scheduler_ptr(), buf, 0, len);
169 timer.stop();
170 return timer.elapsed_sec();
171 });
172
173 shamalgs_module.def("set_impl_reduction", [](const std::string &impl) {
175 });
176
177 shamalgs_module.def("get_current_impl_reduction", []() {
179 });
180
181 shamalgs_module.def("get_default_impl_list_reduction", []() {
183 });
184
185 shamalgs_module.def("is_impl_set_reduction", []() {
187 });
188
189 shamalgs_module.def("autoselect_impl_reduction", []() {
191 shamsys::instance::get_compute_scheduler_ptr());
192 });
193 }
194
195 { // scan_exclusive_sum_in_place
196
197 shamalgs_module.def(
198 "scan_exclusive_sum_in_place", [](sham::DeviceBuffer<u32> &buf, u32 len) {
200 });
201
202 shamalgs_module.def(
203 "benchmark_scan_exclusive_sum_in_place", [](sham::DeviceBuffer<u32> &buf, u32 len) {
204 buf.synchronize();
205 shambase::Timer timer;
206 timer.start();
208 buf.synchronize();
209 timer.stop();
210 return timer.elapsed_sec();
211 });
212
213 shamalgs_module.def("set_impl_scan_exclusive_sum_in_place", [](const std::string &impl) {
215 });
216
217 shamalgs_module.def("get_current_impl_scan_exclusive_sum_in_place", []() {
219 });
220
221 shamalgs_module.def("get_default_impl_list_scan_exclusive_sum_in_place", []() {
223 });
224
225 shamalgs_module.def("is_impl_set_scan_exclusive_sum_in_place", []() {
227 });
228
229 shamalgs_module.def("autoselect_impl_scan_exclusive_sum_in_place", []() {
231 shamsys::instance::get_compute_scheduler_ptr());
232 });
233 }
234
235 { // segmented_sort_in_place
236 shamalgs_module.def(
237 "segmented_sort_in_place",
238 [](sham::DeviceBuffer<u32> &buf, const sham::DeviceBuffer<u32> &offsets) {
239 shamalgs::primitives::segmented_sort_in_place(buf, offsets);
240 });
241
242 shamalgs_module.def(
243 "benchmark_segmented_sort_in_place",
244 [](sham::DeviceBuffer<u32> &buf, const sham::DeviceBuffer<u32> &offsets) {
245 auto buf_copy = buf.copy();
246 auto offsets_copy = offsets.copy();
247
248 buf_copy.synchronize();
249 offsets_copy.synchronize();
250
251 shambase::Timer timer;
252 timer.start();
253
254 shamalgs::primitives::segmented_sort_in_place(buf_copy, offsets_copy);
255 buf_copy.synchronize();
256 offsets_copy.synchronize();
257
258 timer.stop();
259 return timer.elapsed_sec();
260 });
261
262 shamalgs_module.def("set_impl_segmented_sort_in_place", [](const std::string &impl) {
264 });
265
266 shamalgs_module.def("get_current_impl_segmented_sort_in_place", []() {
268 });
269
270 shamalgs_module.def("get_default_impl_list_segmented_sort_in_place", []() {
272 });
273 }
274
275 { // sort_by_keys
276 shamalgs_module.def(
277 "sort_by_keys",
278 [](sham::DeviceBuffer<u32> &buf_key, sham::DeviceBuffer<u32> &buf_values, u32 len) {
279 shamalgs::primitives::sort_by_keys(buf_key, buf_values, len);
280 });
281
282 shamalgs_module.def(
283 "benchmark_sort_by_keys",
284 [](sham::DeviceBuffer<u32> &buf_key, sham::DeviceBuffer<u32> &buf_values, u32 len) {
285 auto buf_key_copy = buf_key.copy();
286 auto buf_values_copy = buf_values.copy();
287
288 buf_key_copy.synchronize();
289 buf_values_copy.synchronize();
290
291 shambase::Timer timer;
292 timer.start();
293
294 shamalgs::primitives::sort_by_keys(buf_key_copy, buf_values_copy, len);
295 buf_key_copy.synchronize();
296 buf_values_copy.synchronize();
297
298 timer.stop();
299 return timer.elapsed_sec();
300 });
301
302 shamalgs_module.def("set_impl_sort_by_keys", [](const std::string &impl) {
304 });
305
306 shamalgs_module.def("get_current_impl_sort_by_keys", []() {
308 });
309
310 shamalgs_module.def("get_default_impl_list_sort_by_keys", []() {
312 });
313
314 shamalgs_module.def("is_impl_set_sort_by_keys", []() {
316 });
317
318 shamalgs_module.def("autoselect_impl_sort_by_keys", []() {
320 shamsys::instance::get_compute_scheduler_ptr());
321 });
322 }
323
324 { // sort_by_key_pow2_len
325 shamalgs_module.def(
326 "sort_by_key_pow2_len",
327 [](sham::DeviceBuffer<u32> &buf_key, sham::DeviceBuffer<u32> &buf_values, u32 len) {
329 shamsys::instance::get_compute_scheduler_ptr(), buf_key, buf_values, len);
330 });
331
332 shamalgs_module.def(
333 "benchmark_sort_by_key_pow2_len",
334 [](sham::DeviceBuffer<u32> &buf_key, sham::DeviceBuffer<u32> &buf_values, u32 len) {
335 auto buf_key_copy = buf_key.copy();
336 auto buf_values_copy = buf_values.copy();
337
338 buf_key_copy.synchronize();
339 buf_values_copy.synchronize();
340
341 shambase::Timer timer;
342 timer.start();
343
345 shamsys::instance::get_compute_scheduler_ptr(),
346 buf_key_copy,
347 buf_values_copy,
348 len);
349 buf_key_copy.synchronize();
350 buf_values_copy.synchronize();
351
352 timer.stop();
353 return timer.elapsed_sec();
354 });
355
356 shamalgs_module.def("set_impl_sort_by_key_pow2_len", [](const std::string &impl) {
358 });
359
360 shamalgs_module.def("get_current_impl_sort_by_key_pow2_len", []() {
362 });
363
364 shamalgs_module.def("get_default_impl_list_sort_by_key_pow2_len", []() {
366 });
367
368 shamalgs_module.def("is_impl_set_sort_by_key_pow2_len", []() {
370 });
371
372 shamalgs_module.def("autoselect_impl_sort_by_key_pow2_len", []() {
374 shamsys::instance::get_compute_scheduler_ptr());
375 });
376 }
377
378 { // compute_histogram
379
380 shamalgs_module.def("set_impl_compute_histogram", [](const std::string &impl) {
382 });
383
384 shamalgs_module.def("get_current_impl_compute_histogram", []() {
386 });
387
388 shamalgs_module.def("get_default_impl_list_compute_histogram", []() {
390 });
391
392 shamalgs_module.def("is_impl_set_compute_histogram", []() {
394 });
395
396 shamalgs_module.def("autoselect_impl_compute_histogram", []() {
398 shamsys::instance::get_compute_scheduler_ptr());
399 });
400 }
401
402 shamalgs_module.def(
403 "compute_histogram_basic_f64",
404 [](sham::DeviceBuffer<f64> &bin_edge_inf,
405 sham::DeviceBuffer<f64> &bin_edge_sup,
406 sham::DeviceBuffer<f64> &positions) {
407 return shamalgs::primitives::compute_histogram_basic<f64>(
408 shamsys::instance::get_compute_scheduler_ptr(),
409 bin_edge_inf,
410 bin_edge_sup,
411 positions);
412 });
413 shamalgs_module.def(
414 "compute_histogram_basic_f32",
415 [](sham::DeviceBuffer<f32> &bin_edge_inf,
416 sham::DeviceBuffer<f32> &bin_edge_sup,
417 sham::DeviceBuffer<f32> &positions) {
418 return shamalgs::primitives::compute_histogram_basic<f32>(
419 shamsys::instance::get_compute_scheduler_ptr(),
420 bin_edge_inf,
421 bin_edge_sup,
422 positions);
423 });
424
425 shamalgs_module.def(
426 "benchmark_compute_histogram_basic_f64",
427 [](sham::DeviceBuffer<f64> &bin_edge_inf,
428 sham::DeviceBuffer<f64> &bin_edge_sup,
429 sham::DeviceBuffer<f64> &positions) {
430 bin_edge_inf.synchronize();
431 bin_edge_sup.synchronize();
432 positions.synchronize();
433
434 auto run = [&]() {
435 auto result = shamalgs::primitives::compute_histogram_basic<f64>(
436 shamsys::instance::get_compute_scheduler_ptr(),
437 bin_edge_inf,
438 bin_edge_sup,
439 positions);
440 result.synchronize();
441 };
442
443 run();
444
445 return shambase::timeitfor(run);
446 });
447 shamalgs_module.def(
448 "benchmark_compute_histogram_basic_f32",
449 [](sham::DeviceBuffer<f32> &bin_edge_inf,
450 sham::DeviceBuffer<f32> &bin_edge_sup,
451 sham::DeviceBuffer<f32> &positions) {
452 bin_edge_inf.synchronize();
453 bin_edge_sup.synchronize();
454 positions.synchronize();
455
456 auto run = [&]() {
457 auto result = shamalgs::primitives::compute_histogram_basic<f32>(
458 shamsys::instance::get_compute_scheduler_ptr(),
459 bin_edge_inf,
460 bin_edge_sup,
461 positions);
462 result.synchronize();
463 };
464
465 run();
466
467 return shambase::timeitfor(run);
468 });
469
470 shamalgs_module.def(
471 "string_histogram",
472 [](const std::vector<std::string> &inputs, std::string delimiter, bool hash_based) {
473 return shamalgs::collective::string_histogram(inputs, std::move(delimiter), hash_based);
474 },
475 py::arg("inputs"),
476 py::arg("delimiter") = "\n",
477 py::arg("hash_based") = false);
478
479 shamalgs_module.def(
480 "all_string_histogram",
481 [](const std::vector<std::string> &inputs, std::string delimiter, bool hash_based) {
483 inputs, std::move(delimiter), hash_based);
484 },
485 py::arg("inputs"),
486 py::arg("delimiter") = "\n",
487 py::arg("hash_based") = false);
488}
Header file describing a Node Instance.
double f64
Alias for double.
float f32
Alias for float.
std::uint8_t u8
8 bit unsigned integer
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
void synchronize() const
Wait for all the events associated with the buffer to be completed.
DeviceBuffer< T, target > copy() const
Copy the current buffer.
Class Timer measures the time elapsed since the timer was started.
Definition Timer.hpp:36
f64 elapsed_sec() const
Converts the stored nanosecond time to a floating point representation in seconds.
Definition Timer.hpp:88
void start()
Starts the timer.
Definition Timer.hpp:51
void stop()
Stops the timer and stores the elapsed time in nanoseconds.
Definition Timer.hpp:65
Boolean reduction algorithm for checking if all elements are non-zero.
std::vector< std::string > get_default_impl_list_sort_by_key_pow2_len()
Get list of available sort by key pow2 len implementations, as config json strings.
void autoselect_impl_sort_by_key_pow2_len(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for sort by key pow2 len.
std::vector< std::string > get_default_impl_list_sort_by_keys()
Get list of available sort by keys implementations, as config json strings.
bool is_impl_set_is_all_true()
Check if an implementation has been selected for is_all_true.
void set_impl_segmented_sort_in_place(const std::string &impl)
Set the implementation for segmented sort in place, from a config json string.
bool is_impl_set_reduction()
Check if an implementation has been selected for reduction.
std::string get_current_impl_sort_by_keys()
Get the current implementation for sort by keys, as a config json string.
void autoselect_impl_reduction(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for reduction.
std::string get_current_impl_reduction()
Get the current implementation for reduction, as a config json string.
Definition reduction.cpp:99
void autoselect_impl_compute_histogram(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for compute_histogram.
std::string get_current_impl_segmented_sort_in_place()
Get the current implementation for segmented sort in place, as a config json string.
void set_impl_compute_histogram(const std::string &impl)
Set the implementation for compute_histogram.
std::vector< std::string > get_default_impl_list_scan_exclusive_sum_in_place()
Get list of available scan_exclusive_sum_in_place implementations.
bool is_impl_set_scan_exclusive_sum_in_place()
Check if an implementation has been selected for scan_exclusive_sum_in_place.
std::string get_current_impl_sort_by_key_pow2_len()
Get the current implementation for sort by key pow2 len, as a config json string.
void autoselect_impl_sort_by_keys(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for sort by keys.
bool is_impl_set_sort_by_key_pow2_len()
Check if an implementation has been selected for sort by key pow2 len.
void set_impl_scan_exclusive_sum_in_place(const std::string &impl)
Set the implementation for scan_exclusive_sum_in_place, from a config json string.
std::string get_current_impl_compute_histogram()
Get the current implementation for compute_histogram.
std::vector< std::string > get_default_impl_list_compute_histogram()
Get list of available compute_histogram implementations.
void set_impl_sort_by_keys(const std::string &impl)
Set the implementation for sort by keys, from a config json string.
bool is_impl_set_sort_by_keys()
Check if an implementation has been selected for sort by keys.
void autoselect_impl_is_all_true(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for is_all_true.
void set_impl_is_all_true(const std::string &impl)
Set the implementation for is_all_true, from a config json string.
std::vector< std::string > get_default_impl_list_reduction()
Get list of available reduction implementations, as config json strings.
Definition reduction.cpp:94
void set_impl_sort_by_key_pow2_len(const std::string &impl)
Set the implementation for sort by key pow2 len, from a config json string.
void autoselect_impl_scan_exclusive_sum_in_place(const sham::DeviceScheduler_ptr &dev_sched)
Select the default implementation for scan_exclusive_sum_in_place.
std::string get_current_impl_scan_exclusive_sum_in_place()
Get the current implementation for scan_exclusive_sum_in_place.
bool is_impl_set_compute_histogram()
Check if an implementation has been selected for compute_histogram.
void set_impl_reduction(const std::string &impl)
Set the implementation for reduction, from a config json string.
std::string get_current_impl_is_all_true()
Get the current implementation for is_all_true, as a config json string.
std::vector< std::string > get_default_impl_list_is_all_true()
Get list of available is_all_true implementations, as config json strings.
std::vector< std::string > get_default_impl_list_segmented_sort_in_place()
Get list of available segmented sort in place implementations, as config json strings.
T sum(const sham::DeviceScheduler_ptr &sched, const sham::DeviceBuffer< T > &buf1, u32 start_id, u32 end_id)
Compute the sum of elements in a device buffer within a specified range.
void sort_by_keys(sham::DeviceBuffer< Tkey > &buf_key, sham::DeviceBuffer< Tval > &buf_values, u32 len)
Sort key-value pairs using USM buffers (general length).
bool is_all_true(sycl::buffer< T > &buf, u32 cnt)
Check if all elements in a sycl::buffer are non-zero.
void sort_by_key_pow2_len(sycl::queue &q, sycl::buffer< Tkey > &buf_key, sycl::buffer< Tval > &buf_values, u32 len)
Sort key-value pairs using sycl::buffers (power-of-2 optimized).
void scan_exclusive_sum_in_place(sham::DeviceBuffer< T > &buf1, u32 len)
Compute exclusive prefix sum in-place on a device buffer.
f64 timeitfor(Func &&f, f64 max_duration=1)
Measures the average time it takes to execute a function until a maximum duration is reached.
Definition time.hpp:105
Pybind11 include and definitions.
#define ON_PYTHON_INIT
Register a Python module init function using static initialization.
In-place exclusive scan (prefix sum) algorithm for device buffers.
Sort by keys algorithms.
Sort by keys algorithms.
MPI string gather / allgather helpers (declarations; implementations in shamalgs/src/collective/gathe...
std::unordered_map< std::string, int > string_histogram(const std::vector< std::string > &inputs, std::string delimiter, bool hash_based)
Constructs a histogram from a vector of strings, counting occurrences of each unique string.
std::unordered_map< std::string, int > all_string_histogram(const std::vector< std::string > &inputs, std::string delimiter, bool hash_based)
same as string_histogram but with result return on every rank