arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/backend/src/implementation/cpu_spqlios/scratch.rs
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            ScalarZnxAllocBytesImpl, ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl,
 10            SvpPPolAllocBytesImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl,
 11            TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl,
 12            VecZnxAllocBytesImpl, VecZnxBigAllocBytesImpl, 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 + ScalarZnxAllocBytesImpl<B>,
 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, B::scalar_znx_alloc_bytes_impl(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 + VecZnxAllocBytesImpl<B>,
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(
109            &mut scratch.data,
110            B::vec_znx_alloc_bytes_impl(n, cols, size),
111        );
112        (
113            VecZnx::from_data(take_slice, n, cols, size),
114            Scratch::from_bytes(rem_slice),
115        )
116    }
117}
118
119unsafe impl<B: Backend> TakeVecZnxBigImpl<B> for B
120where
121    B: CPUAVX + VecZnxBigAllocBytesImpl<B>,
122{
123    fn take_vec_znx_big_impl(
124        scratch: &mut Scratch<B>,
125        n: usize,
126        cols: usize,
127        size: usize,
128    ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>) {
129        let (take_slice, rem_slice) = take_slice_aligned(
130            &mut scratch.data,
131            B::vec_znx_big_alloc_bytes_impl(n, cols, size),
132        );
133        (
134            VecZnxBig::from_data(take_slice, n, cols, size),
135            Scratch::from_bytes(rem_slice),
136        )
137    }
138}
139
140unsafe impl<B: Backend> TakeVecZnxDftImpl<B> for B
141where
142    B: CPUAVX + VecZnxDftAllocBytesImpl<B>,
143{
144    fn take_vec_znx_dft_impl(
145        scratch: &mut Scratch<B>,
146        n: usize,
147        cols: usize,
148        size: usize,
149    ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>) {
150        let (take_slice, rem_slice) = take_slice_aligned(
151            &mut scratch.data,
152            B::vec_znx_dft_alloc_bytes_impl(n, cols, size),
153        );
154
155        (
156            VecZnxDft::from_data(take_slice, n, cols, size),
157            Scratch::from_bytes(rem_slice),
158        )
159    }
160}
161
162unsafe impl<B: Backend> TakeVecZnxDftSliceImpl<B> for B
163where
164    B: CPUAVX + VecZnxDftAllocBytesImpl<B>,
165{
166    fn take_vec_znx_dft_slice_impl(
167        scratch: &mut Scratch<B>,
168        len: usize,
169        n: usize,
170        cols: usize,
171        size: usize,
172    ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>) {
173        let mut scratch: &mut Scratch<B> = scratch;
174        let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len);
175        for _ in 0..len {
176            let (znx, new_scratch) = B::take_vec_znx_dft_impl(scratch, n, cols, size);
177            scratch = new_scratch;
178            slice.push(znx);
179        }
180        (slice, scratch)
181    }
182}
183
184unsafe impl<B: Backend> TakeVecZnxSliceImpl<B> for B
185where
186    B: CPUAVX,
187{
188    fn take_vec_znx_slice_impl(
189        scratch: &mut Scratch<B>,
190        len: usize,
191        n: usize,
192        cols: usize,
193        size: usize,
194    ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>) {
195        let mut scratch: &mut Scratch<B> = scratch;
196        let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len);
197        for _ in 0..len {
198            let (znx, new_scratch) = B::take_vec_znx_impl(scratch, n, cols, size);
199            scratch = new_scratch;
200            slice.push(znx);
201        }
202        (slice, scratch)
203    }
204}
205
206unsafe impl<B: Backend> TakeVmpPMatImpl<B> for B
207where
208    B: CPUAVX + VmpPMatAllocBytesImpl<B>,
209{
210    fn take_vmp_pmat_impl(
211        scratch: &mut Scratch<B>,
212        n: usize,
213        rows: usize,
214        cols_in: usize,
215        cols_out: usize,
216        size: usize,
217    ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>) {
218        let (take_slice, rem_slice) = take_slice_aligned(
219            &mut scratch.data,
220            B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size),
221        );
222        (
223            VmpPMat::from_data(take_slice, n, rows, cols_in, cols_out, size),
224            Scratch::from_bytes(rem_slice),
225        )
226    }
227}
228
229unsafe impl<B: Backend> TakeMatZnxImpl<B> for B
230where
231    B: CPUAVX,
232{
233    fn take_mat_znx_impl(
234        scratch: &mut Scratch<B>,
235        n: usize,
236        rows: usize,
237        cols_in: usize,
238        cols_out: usize,
239        size: usize,
240    ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>) {
241        let (take_slice, rem_slice) = take_slice_aligned(
242            &mut scratch.data,
243            MatZnx::<Vec<u8>>::bytes_of(n, rows, cols_in, cols_out, size),
244        );
245        (
246            MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size),
247            Scratch::from_bytes(rem_slice),
248        )
249    }
250}
251
252fn take_slice_aligned(data: &mut [u8], take_len: usize) -> (&mut [u8], &mut [u8]) {
253    let ptr: *mut u8 = data.as_mut_ptr();
254    let self_len: usize = data.len();
255
256    let aligned_offset: usize = ptr.align_offset(DEFAULTALIGN);
257    let aligned_len: usize = self_len.saturating_sub(aligned_offset);
258
259    if let Some(rem_len) = aligned_len.checked_sub(take_len) {
260        unsafe {
261            let rem_ptr: *mut u8 = ptr.add(aligned_offset).add(take_len);
262            let rem_slice: &mut [u8] = &mut *std::ptr::slice_from_raw_parts_mut(rem_ptr, rem_len);
263
264            let take_slice: &mut [u8] = &mut *std::ptr::slice_from_raw_parts_mut(ptr.add(aligned_offset), take_len);
265
266            return (take_slice, rem_slice);
267        }
268    } else {
269        panic!(
270            "Attempted to take {} from scratch with {} aligned bytes left",
271            take_len, aligned_len,
272        );
273    }
274}