poulpy/poulpy-backend/src/implementation/cpu_spqlios/scratch.rs
poulpy-backend/src/implementation/cpu_spqlios/scratch.rsRaw
1use std::marker::PhantomData;
2
3use crate::{
4 DEFAULTALIGN, alloc_aligned,
5 hal::{
6 api::ScratchFromBytes,
7 layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
8 oep::{
9 ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, SvpPPolAllocBytesImpl,
10 TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl,
11 TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl, VecZnxBigAllocBytesImpl,
12 VecZnxDftAllocBytesImpl, VmpPMatAllocBytesImpl,
13 },
14 },
15 implementation::cpu_spqlios::CPUAVX,
16};
17
18unsafe impl<B: Backend> ScratchOwnedAllocImpl<B> for B
19where
20 B: CPUAVX,
21{
22 fn scratch_owned_alloc_impl(size: usize) -> ScratchOwned<B> {
23 let data: Vec<u8> = alloc_aligned(size);
24 ScratchOwned {
25 data,
26 _phantom: PhantomData,
27 }
28 }
29}
30
31unsafe impl<B: Backend> ScratchOwnedBorrowImpl<B> for B
32where
33 B: CPUAVX,
34{
35 fn scratch_owned_borrow_impl(scratch: &mut ScratchOwned<B>) -> &mut Scratch<B> {
36 Scratch::from_bytes(&mut scratch.data)
37 }
38}
39
40unsafe impl<B: Backend> ScratchFromBytesImpl<B> for B
41where
42 B: CPUAVX,
43{
44 fn scratch_from_bytes_impl(data: &mut [u8]) -> &mut Scratch<B> {
45 unsafe { &mut *(data as *mut [u8] as *mut Scratch<B>) }
46 }
47}
48
49unsafe impl<B: Backend> ScratchAvailableImpl<B> for B
50where
51 B: CPUAVX,
52{
53 fn scratch_available_impl(scratch: &Scratch<B>) -> usize {
54 let ptr: *const u8 = scratch.data.as_ptr();
55 let self_len: usize = scratch.data.len();
56 let aligned_offset: usize = ptr.align_offset(DEFAULTALIGN);
57 self_len.saturating_sub(aligned_offset)
58 }
59}
60
61unsafe impl<B: Backend> TakeSliceImpl<B> for B
62where
63 B: CPUAVX,
64{
65 fn take_slice_impl<T>(scratch: &mut Scratch<B>, len: usize) -> (&mut [T], &mut Scratch<B>) {
66 let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, len * std::mem::size_of::<T>());
67
68 unsafe {
69 (
70 &mut *(std::ptr::slice_from_raw_parts_mut(take_slice.as_mut_ptr() as *mut T, len)),
71 Scratch::from_bytes(rem_slice),
72 )
73 }
74 }
75}
76
77unsafe impl<B: Backend> TakeScalarZnxImpl<B> for B
78where
79 B: CPUAVX,
80{
81 fn take_scalar_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Scratch<B>) {
82 let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, ScalarZnx::alloc_bytes(n, cols));
83 (
84 ScalarZnx::from_data(take_slice, n, cols),
85 Scratch::from_bytes(rem_slice),
86 )
87 }
88}
89
90unsafe impl<B: Backend> TakeSvpPPolImpl<B> for B
91where
92 B: CPUAVX + SvpPPolAllocBytesImpl<B>,
93{
94 fn take_svp_ppol_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Scratch<B>) {
95 let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, B::svp_ppol_alloc_bytes_impl(n, cols));
96 (
97 SvpPPol::from_data(take_slice, n, cols),
98 Scratch::from_bytes(rem_slice),
99 )
100 }
101}
102
103unsafe impl<B: Backend> TakeVecZnxImpl<B> for B
104where
105 B: CPUAVX,
106{
107 fn take_vec_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Scratch<B>) {
108 let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, VecZnx::alloc_bytes(n, cols, size));
109 (
110 VecZnx::from_data(take_slice, n, cols, size),
111 Scratch::from_bytes(rem_slice),
112 )
113 }
114}
115
116unsafe impl<B: Backend> TakeVecZnxBigImpl<B> for B
117where
118 B: CPUAVX + VecZnxBigAllocBytesImpl<B>,
119{
120 fn take_vec_znx_big_impl(
121 scratch: &mut Scratch<B>,
122 n: usize,
123 cols: usize,
124 size: usize,
125 ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>) {
126 let (take_slice, rem_slice) = take_slice_aligned(
127 &mut scratch.data,
128 B::vec_znx_big_alloc_bytes_impl(n, cols, size),
129 );
130 (
131 VecZnxBig::from_data(take_slice, n, cols, size),
132 Scratch::from_bytes(rem_slice),
133 )
134 }
135}
136
137unsafe impl<B: Backend> TakeVecZnxDftImpl<B> for B
138where
139 B: CPUAVX + VecZnxDftAllocBytesImpl<B>,
140{
141 fn take_vec_znx_dft_impl(
142 scratch: &mut Scratch<B>,
143 n: usize,
144 cols: usize,
145 size: usize,
146 ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>) {
147 let (take_slice, rem_slice) = take_slice_aligned(
148 &mut scratch.data,
149 B::vec_znx_dft_alloc_bytes_impl(n, cols, size),
150 );
151
152 (
153 VecZnxDft::from_data(take_slice, n, cols, size),
154 Scratch::from_bytes(rem_slice),
155 )
156 }
157}
158
159unsafe impl<B: Backend> TakeVecZnxDftSliceImpl<B> for B
160where
161 B: CPUAVX + VecZnxDftAllocBytesImpl<B>,
162{
163 fn take_vec_znx_dft_slice_impl(
164 scratch: &mut Scratch<B>,
165 len: usize,
166 n: usize,
167 cols: usize,
168 size: usize,
169 ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>) {
170 let mut scratch: &mut Scratch<B> = scratch;
171 let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len);
172 for _ in 0..len {
173 let (znx, new_scratch) = B::take_vec_znx_dft_impl(scratch, n, cols, size);
174 scratch = new_scratch;
175 slice.push(znx);
176 }
177 (slice, scratch)
178 }
179}
180
181unsafe impl<B: Backend> TakeVecZnxSliceImpl<B> for B
182where
183 B: CPUAVX,
184{
185 fn take_vec_znx_slice_impl(
186 scratch: &mut Scratch<B>,
187 len: usize,
188 n: usize,
189 cols: usize,
190 size: usize,
191 ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>) {
192 let mut scratch: &mut Scratch<B> = scratch;
193 let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len);
194 for _ in 0..len {
195 let (znx, new_scratch) = B::take_vec_znx_impl(scratch, n, cols, size);
196 scratch = new_scratch;
197 slice.push(znx);
198 }
199 (slice, scratch)
200 }
201}
202
203unsafe impl<B: Backend> TakeVmpPMatImpl<B> for B
204where
205 B: CPUAVX + VmpPMatAllocBytesImpl<B>,
206{
207 fn take_vmp_pmat_impl(
208 scratch: &mut Scratch<B>,
209 n: usize,
210 rows: usize,
211 cols_in: usize,
212 cols_out: usize,
213 size: usize,
214 ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>) {
215 let (take_slice, rem_slice) = take_slice_aligned(
216 &mut scratch.data,
217 B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size),
218 );
219 (
220 VmpPMat::from_data(take_slice, n, rows, cols_in, cols_out, size),
221 Scratch::from_bytes(rem_slice),
222 )
223 }
224}
225
226unsafe impl<B: Backend> TakeMatZnxImpl<B> for B
227where
228 B: CPUAVX,
229{
230 fn take_mat_znx_impl(
231 scratch: &mut Scratch<B>,
232 n: usize,
233 rows: usize,
234 cols_in: usize,
235 cols_out: usize,
236 size: usize,
237 ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>) {
238 let (take_slice, rem_slice) = take_slice_aligned(
239 &mut scratch.data,
240 MatZnx::alloc_bytes(n, rows, cols_in, cols_out, size),
241 );
242 (
243 MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size),
244 Scratch::from_bytes(rem_slice),
245 )
246 }
247}
248
249fn take_slice_aligned(data: &mut [u8], take_len: usize) -> (&mut [u8], &mut [u8]) {
250 let ptr: *mut u8 = data.as_mut_ptr();
251 let self_len: usize = data.len();
252
253 let aligned_offset: usize = ptr.align_offset(DEFAULTALIGN);
254 let aligned_len: usize = self_len.saturating_sub(aligned_offset);
255
256 if let Some(rem_len) = aligned_len.checked_sub(take_len) {
257 unsafe {
258 let rem_ptr: *mut u8 = ptr.add(aligned_offset).add(take_len);
259 let rem_slice: &mut [u8] = &mut *std::ptr::slice_from_raw_parts_mut(rem_ptr, rem_len);
260
261 let take_slice: &mut [u8] = &mut *std::ptr::slice_from_raw_parts_mut(ptr.add(aligned_offset), take_len);
262
263 (take_slice, rem_slice)
264 }
265 } else {
266 panic!(
267 "Attempted to take {} from scratch with {} aligned bytes left",
268 take_len, aligned_len,
269 );
270 }
271}