Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
serialize.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
21#include "shamcomm/logs.hpp"
22
23// Layout of the SerializeHelper is
24// aligned on base 64 bits
25
26// pre head (header length)
27// header
28// content
29
30// The idea is to move pre head and the header to the host
31// to avoid multiplying queries to the device
32
33u64 extract_preahead(sham::DeviceQueue &q, sham::DeviceBuffer<u8> &storage) {
34
35 if (storage.get_size() == 0) {
37 ("the buffer is not allocated, the head cannot be moved"));
38 }
39
41
42 u64 ret;
43 {
44
45 sham::EventList depends_list;
46 auto accbufstg = storage.get_read_access(depends_list);
47
48 auto dest = &ret;
49 auto source = accbufstg;
50
51 auto e = q.submit(depends_list, [dest, source](sycl::handler &cgh) {
52 cgh.memcpy(dest, source, sizeof(u64));
53 });
54
55 e.wait_and_throw();
56 storage.complete_event_state(sycl::event{});
57 }
58
59 return ret;
60}
61
62void write_prehead(sham::DeviceQueue &q, u64 prehead, sham::DeviceBuffer<u8> &storage) {
63
64 sham::EventList depends_list;
65 auto accbufstg = storage.get_write_access(depends_list);
66
67 auto dest = accbufstg;
68 auto source = &prehead;
69
70 auto e = q.submit(depends_list, [dest, source](sycl::handler &cgh) {
71 cgh.memcpy(dest, source, sizeof(u64));
72 });
73
74 e.wait_and_throw();
75 storage.complete_event_state(sycl::event{});
76}
77
78// this is the real fix this time
79// race conditions in compilers
80// i will never miss those ...
81#ifdef SYCL_COMP_ACPP
82 #define ACPP_WAIT .wait()
83#else
84 #define ACPP_WAIT
85#endif
86
87std::vector<u8> extract_header(
88 sham::DeviceQueue &q, sham::DeviceBuffer<u8> &storage, u64 header_size, u64 pre_head_length) {
89
90 std::vector<u8> storage_header = std::vector<u8>(header_size);
91
92 if (header_size > 0) {
93 sycl::buffer<u8> attach(storage_header.data(), header_size);
94
95 sham::EventList depends_list;
96 auto accbufstg = storage.get_read_access(depends_list);
97
98 auto e = q.submit(depends_list, [&, pre_head_length](sycl::handler &cgh) {
99 sycl::accessor buf_header{attach, cgh, sycl::write_only, sycl::no_init};
100
101 cgh.parallel_for(sycl::range<1>{header_size}, [=](sycl::item<1> id) {
102 buf_header[id] = accbufstg[id + pre_head_length];
103 });
104 });
105
106 e.wait_and_throw();
107 storage.complete_event_state(sycl::event{});
108 }
109
110 // std::cout << "extract header" << std::endl;
111
112 return storage_header;
113}
114
115void write_header(
117 sham::DeviceBuffer<u8> &storage,
118 std::vector<u8> &storage_header,
119 u64 header_size,
120 u64 pre_head_length) {
121
122 if (header_size > 0) {
123 sycl::buffer<u8> attach(storage_header.data(), header_size);
124
125 sham::EventList depends_list;
126 auto accbufstg = storage.get_write_access(depends_list);
127
128 auto e = q.submit(depends_list, [&, pre_head_length](sycl::handler &cgh) {
129 sycl::accessor buf_header{attach, cgh, sycl::read_only};
130
131 cgh.parallel_for(sycl::range<1>{header_size}, [=](sycl::item<1> id) {
132 accbufstg[id + pre_head_length] = buf_header[id];
133 });
134 });
135
136 e.wait_and_throw();
137 storage.complete_event_state(sycl::event{});
138 }
139 // std::cout << "write header" << std::endl;
140}
141
142u64 shamalgs::SerializeHelper::pre_head_length() {
143 return shamalgs::details::serialize_byte_size<shamalgs::SerializeHelper::alignment, u64>()
144 .head_size;
145}
146
147void shamalgs::SerializeHelper::allocate(SerializeSize szinfo) {
148 StackEntry stack_loc{false};
149 u64 bytelen = szinfo.head_size + szinfo.content_size + pre_head_length();
150
151 storage.resize(shambase::narrow_or_throw<u32>(bytelen));
152 header_size = szinfo.head_size;
153 storage_header.resize(header_size);
154
155 shamlog_debug_sycl_ln("SerializeHelper", "allocate()", bytelen, header_size);
156
157 write_prehead(dev_sched->get_queue(), szinfo.head_size, storage);
158 // std::cout << "prehead write :" << szinfo.head_size << std::endl;
159
160 head_device = pre_head_length() + header_size;
161}
162
163sham::DeviceBuffer<u8> shamalgs::SerializeHelper::finalize() {
164 StackEntry stack_loc{false};
165
166 shamlog_debug_sycl_ln("SerializeHelper", "finalize()", storage.get_size(), header_size);
167
168 write_header(dev_sched->get_queue(), storage, storage_header, header_size, pre_head_length());
169
170 return std::move(storage);
171}
172
173shamalgs::SerializeHelper::SerializeHelper(std::shared_ptr<sham::DeviceScheduler> _dev_sched)
174 : dev_sched(std::move(_dev_sched)), storage(0, _dev_sched) {}
175
176shamalgs::SerializeHelper::SerializeHelper(
177 std::shared_ptr<sham::DeviceScheduler> _dev_sched, sham::DeviceBuffer<u8> &&input)
178 : dev_sched(std::move(_dev_sched)), storage(std::forward<sham::DeviceBuffer<u8>>(input)) {
179
180 header_size = extract_preahead(dev_sched->get_queue(), storage);
181
182 shamlog_debug_sycl_ln(
183 "SerializeHelper",
184 shambase::format(
185 "Init SerializeHelper from buffer\n storage size : {},\n header_size : {}",
186 storage.get_size(),
187 header_size));
188
189 storage_header
190 = extract_header(dev_sched->get_queue(), storage, header_size, pre_head_length());
191
192 head_device = pre_head_length() + header_size;
193}
std::uint8_t u8
8 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory)
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
void resize(size_t new_size, bool keep_data=true)
Resizes the buffer to a given size.
T * get_write_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{})
Get a read-write pointer to the buffer's data.
size_t get_size() const
Gets the number of elements in the buffer.
const T * get_read_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{}) const
Get a read-only pointer to the buffer's data.
A SYCL queue associated with a device and a context.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
Class to manage a list of SYCL events.
Definition EventList.hpp:31
namespace for backends this one is named only sham since shambackends is too long to write
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
STL namespace.
Utilities for safe type narrowing conversions.
void write_header(MPI_File fh, std::string s, u64 &file_head_ptr)
Writes a string to a file using MPI and updates the file head pointer. The string is preceded by its ...
Definition io.hpp:206