Changes to build on macos (#92) * update spqlios-airthmetic to latest e8aed63 * finally, builds on macos * clippy --------- Co-authored-by: Pro7ech <jeanphilippe.bossuat@gmail.com>
jump to
@@ -32,47 +32,6 @@
group.finish(); } -pub fn bench_fft_avx2_fma(c: &mut Criterion) { - let group_name: String = "fft_avx2_fma".to_string(); - - let mut group = c.benchmark_group(group_name); - - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] - #[target_feature(enable = "avx2,fma")] - fn runner(m: usize) -> impl FnMut() { - let mut values: Vec<f64> = vec![0f64; m << 1]; - - let scale = 1.0f64 / (2 * m) as f64; - values - .iter_mut() - .enumerate() - .for_each(|(i, x)| *x = (i + 1) as f64 * scale); - - let table: ReimFFTTable<f64> = ReimFFTTable::<f64>::new(m); - move || { - use poulpy_backend::cpu_fft64_avx::ReimFFTAvx; - - ReimFFTAvx::reim_dft_execute(&table, &mut values); - black_box(()); - } - } - - if std::is_x86_feature_detected!("avx2") { - for log_m in [9, 10, 11, 12, 13, 14, 15] { - let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); - unsafe { - let mut runner = runner(1 << log_m); - group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); - } - } - } else { - eprintln!("skipping: CPU lacks avx2"); - return; - } - - group.finish(); -} - pub fn bench_fft_spqlios(c: &mut Criterion) { let group_name: String = "fft_spqlios".to_string();@@ -136,13 +95,11 @@
group.finish(); } -pub fn bench_ifft_avx2_fma(c: &mut Criterion) { - let group_name: String = "ifft_avx2_fma".to_string(); +pub fn bench_ifft_spqlios(c: &mut Criterion) { + let group_name: String = "ifft_spqlios".to_string(); let mut group = c.benchmark_group(group_name); - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] - #[target_feature(enable = "avx2,fma")] fn runner(m: usize) -> impl FnMut() { let mut values: Vec<f64> = vec![0f64; m << 1];@@ -152,73 +109,119 @@ .iter_mut()
.enumerate() .for_each(|(i, x)| *x = (i + 1) as f64 * scale); - let table: ReimIFFTTable<f64> = ReimIFFTTable::<f64>::new(m); + unsafe { + reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void); + } + move || { - use poulpy_backend::cpu_fft64_avx::ReimIFFTAvx; - - ReimIFFTAvx::reim_dft_execute(&table, &mut values); + unsafe { + reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void); + } black_box(()); } } - if std::is_x86_feature_detected!("avx2") { - for log_m in [9, 10, 11, 12, 13, 14, 15] { - let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); - unsafe { + for log_m in [9, 10, 11, 12, 13, 14, 15] { + let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); + let mut runner = runner(1 << log_m); + group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); + } + + group.finish(); +} + +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +mod x86 { + use super::*; + + #[allow(dead_code)] + pub fn bench_ifft_avx2_fma(c: &mut Criterion) { + let group_name: String = "ifft_avx2_fma".to_string(); + + let mut group = c.benchmark_group(group_name); + + if std::is_x86_feature_detected!("avx2") { + fn runner(m: usize) -> impl FnMut() { + let mut values: Vec<f64> = vec![0f64; m << 1]; + + let scale = 1.0f64 / (2 * m) as f64; + values + .iter_mut() + .enumerate() + .for_each(|(i, x)| *x = (i + 1) as f64 * scale); + + let table: ReimIFFTTable<f64> = ReimIFFTTable::<f64>::new(m); + move || { + use poulpy_backend::cpu_fft64_avx::ReimIFFTAvx; + + ReimIFFTAvx::reim_dft_execute(&table, &mut values); + black_box(()); + } + } + + for log_m in [9, 10, 11, 12, 13, 14, 15] { + let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); + let mut runner = runner(1 << log_m); group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); } + } else { + eprintln!("skipping: CPU lacks avx2"); + return; } - } else { - eprintln!("skipping: CPU lacks avx2"); - return; + + group.finish(); } - group.finish(); -} + #[allow(dead_code)] + pub fn bench_fft_avx2_fma(c: &mut Criterion) { + let group_name: String = "fft_avx2_fma".to_string(); -pub fn bench_ifft_spqlios(c: &mut Criterion) { - let group_name: String = "ifft_spqlios".to_string(); + let mut group = c.benchmark_group(group_name); - let mut group = c.benchmark_group(group_name); + if std::is_x86_feature_detected!("avx2") { + fn runner(m: usize) -> impl FnMut() { + let mut values: Vec<f64> = vec![0f64; m << 1]; - fn runner(m: usize) -> impl FnMut() { - let mut values: Vec<f64> = vec![0f64; m << 1]; + let scale = 1.0f64 / (2 * m) as f64; + values + .iter_mut() + .enumerate() + .for_each(|(i, x)| *x = (i + 1) as f64 * scale); - let scale = 1.0f64 / (2 * m) as f64; - values - .iter_mut() - .enumerate() - .for_each(|(i, x)| *x = (i + 1) as f64 * scale); + let table: ReimFFTTable<f64> = ReimFFTTable::<f64>::new(m); + move || { + use poulpy_backend::cpu_fft64_avx::ReimFFTAvx; - unsafe { - reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void); - } + ReimFFTAvx::reim_dft_execute(&table, &mut values); + black_box(()); + } + } - move || { - unsafe { - reim::reim_ifft_simple(m as u32, values.as_mut_ptr() as *mut c_void); + for log_m in [9, 10, 11, 12, 13, 14, 15] { + let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); + + let mut runner = runner(1 << log_m); + group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); } - black_box(()); + } else { + eprintln!("skipping: CPU lacks avx2"); + return; } - } - for log_m in [9, 10, 11, 12, 13, 14, 15] { - let id: BenchmarkId = BenchmarkId::from_parameter(format!("n: {}", 2 << log_m)); - let mut runner = runner(1 << log_m); - group.bench_with_input(id, &(), |b, _| b.iter(&mut runner)); + group.finish(); } - group.finish(); + criterion_group!(benches_x86, bench_fft_avx2_fma, bench_ifft_avx2_fma,); + criterion_main!(benches_x86); } criterion_group!( benches, bench_fft_ref, - bench_fft_avx2_fma, bench_fft_spqlios, bench_ifft_ref, - bench_ifft_avx2_fma, bench_ifft_spqlios ); + criterion_main!(benches);
@@ -1,6 +1,6 @@
// poulpy-backend/benches/vec_znx_add.rs use criterion::{Criterion, criterion_group, criterion_main}; -use poulpy_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios}; +use poulpy_backend::{FFT64Ref, FFT64Spqlios}; use poulpy_hal::bench_suite::vmp::bench_vmp_apply_dft_to_dft; fn bench_vmp_apply_dft_to_dft_cpu_spqlios_fft64(c: &mut Criterion) {@@ -11,14 +11,23 @@ fn bench_vmp_apply_dft_to_dft_cpu_ref_fft64(c: &mut Criterion) {
bench_vmp_apply_dft_to_dft::<FFT64Ref>(c, "cpu_ref::fft64"); } -fn bench_vmp_apply_dft_to_dft_cpu_avx_fft64(c: &mut Criterion) { - bench_vmp_apply_dft_to_dft::<FFT64Avx>(c, "cpu_avx::fft64"); +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +mod x86 { + use super::*; + use poulpy_backend::FFT64Avx; + + #[allow(dead_code)] + fn bench_vmp_apply_dft_to_dft_cpu_avx_fft64(c: &mut Criterion) { + bench_vmp_apply_dft_to_dft::<FFT64Avx>(c, "cpu_avx::fft64"); + } + + criterion_group!(benches_x86, bench_vmp_apply_dft_to_dft_cpu_avx_fft64,); + criterion_main!(benches_x86); } criterion_group!( benches, bench_vmp_apply_dft_to_dft_cpu_spqlios_fft64, bench_vmp_apply_dft_to_dft_cpu_ref_fft64, - bench_vmp_apply_dft_to_dft_cpu_avx_fft64, ); criterion_main!(benches);
@@ -10,7 +10,6 @@ mod vmp;
mod zn; mod znx_avx; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] pub struct FFT64Avx {} pub use reim::*;
@@ -2,7 +2,6 @@ /// # Correctness
/// Ensured for inputs absolute value bounded by 2^50-1 /// # Safety /// Caller must ensure the CPU supports FMA (e.g., via `is_x86_feature_detected!("fma")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "fma")] pub fn reim_from_znx_i64_bnd50_fma(res: &mut [f64], a: &[i64]) { #[cfg(debug_assertions)]@@ -58,7 +57,6 @@ /// Only ensured for inputs absoluate value bounded by 2^63-1
/// # Safety /// Caller must ensure the CPU supports FMA (e.g., via `is_x86_feature_detected!("fma,avx2")`); #[allow(dead_code)] -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_to_znx_i64_bnd63_avx2_fma(res: &mut [i64], divisor: f64, a: &[f64]) { #[cfg(debug_assertions)]@@ -141,7 +139,6 @@ /// # Correctness
/// Only ensured for inputs absoluate value bounded by 2^63-1 /// # Safety /// Caller must ensure the CPU supports FMA (e.g., via `is_x86_feature_detected!("fma,avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_to_znx_i64_inplace_bnd63_avx2_fma(res: &mut [f64], divisor: f64) { let sign_mask: u64 = 0x8000000000000000u64;@@ -220,7 +217,6 @@ /// # Correctness
/// Only ensured for inputs absoluate value bounded by 2^50-1 /// # Safety /// Caller must ensure the CPU supports FMA (e.g., via `is_x86_feature_detected!("fma")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "fma")] #[allow(dead_code)] pub fn reim_to_znx_i64_avx2_bnd50_fma(res: &mut [i64], divisor: f64, a: &[f64]) {
@@ -5,7 +5,6 @@ };
use crate::cpu_fft64_avx::reim::{as_arr, as_arr_mut}; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub(crate) fn fft_avx2_fma(m: usize, omg: &[f64], data: &mut [f64]) { if m < 16 {@@ -35,7 +34,6 @@ unsafe extern "sysv64" {
unsafe fn fft16_avx2_fma_asm(re: *mut f64, im: *mut f64, omg: *const f64); } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn fft16_avx2_fma(re: &mut [f64; 16], im: &mut [f64; 16], omg: &[f64; 16]) { unsafe {@@ -43,7 +41,6 @@ fft16_avx2_fma_asm(re.as_mut_ptr(), im.as_mut_ptr(), omg.as_ptr());
} } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn fft_rec_16_avx2_fma(m: usize, re: &mut [f64], im: &mut [f64], omg: &[f64], mut pos: usize) -> usize { if m <= 2048 {@@ -58,7 +55,6 @@ pos = fft_rec_16_avx2_fma(h, &mut re[h..], &mut im[h..], omg, pos);
pos } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn fft_bfs_16_avx2_fma(m: usize, re: &mut [f64], im: &mut [f64], omg: &[f64], mut pos: usize) -> usize { let log_m: usize = (usize::BITS - (m - 1).leading_zeros()) as usize;@@ -99,7 +95,6 @@
pos } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn twiddle_fft_avx2_fma(h: usize, re: &mut [f64], im: &mut [f64], omg: [f64; 2]) { unsafe {@@ -140,7 +135,6 @@ }
} } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn bitwiddle_fft_avx2_fma(h: usize, re: &mut [f64], im: &mut [f64], omg: &[f64; 4]) { unsafe {@@ -228,7 +222,6 @@ #[test]
fn test_fft_avx2_fma() { use super::*; - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn internal(log_m: usize) { use poulpy_hal::reference::fft64::reim::ReimFFTRef;
@@ -1,6 +1,5 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_add_avx2_fma(res: &mut [f64], a: &[f64], b: &[f64]) { #[cfg(debug_assertions)]@@ -31,7 +30,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_add_inplace_avx2_fma(res: &mut [f64], a: &[f64]) { #[cfg(debug_assertions)]@@ -59,7 +57,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_sub_avx2_fma(res: &mut [f64], a: &[f64], b: &[f64]) { #[cfg(debug_assertions)]@@ -90,7 +87,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_sub_ab_inplace_avx2_fma(res: &mut [f64], a: &[f64]) { #[cfg(debug_assertions)]@@ -118,7 +114,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_sub_ba_inplace_avx2_fma(res: &mut [f64], a: &[f64]) { #[cfg(debug_assertions)]@@ -146,7 +141,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_negate_avx2_fma(res: &mut [f64], a: &[f64]) { #[cfg(debug_assertions)]@@ -177,7 +171,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_negate_inplace_avx2_fma(res: &mut [f64]) { use std::arch::x86_64::{__m256d, _mm256_loadu_pd, _mm256_storeu_pd, _mm256_xor_pd};@@ -200,7 +193,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_addmul_avx2_fma(res: &mut [f64], a: &[f64], b: &[f64]) { #[cfg(debug_assertions)]@@ -253,7 +245,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_mul_avx2_fma(res: &mut [f64], a: &[f64], b: &[f64]) { #[cfg(debug_assertions)]@@ -305,7 +296,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] pub fn reim_mul_inplace_avx2_fma(res: &mut [f64], a: &[f64]) { #[cfg(debug_assertions)]
@@ -5,7 +5,6 @@ };
use crate::cpu_fft64_avx::reim::{as_arr, as_arr_mut}; -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2,fma")] pub(crate) fn ifft_avx2_fma(m: usize, omg: &[f64], data: &mut [f64]) { if m < 16 {@@ -34,7 +33,6 @@ unsafe extern "sysv64" {
unsafe fn ifft16_avx2_fma_asm(re: *mut f64, im: *mut f64, omg: *const f64); } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn ifft16_avx2_fma(re: &mut [f64; 16], im: &mut [f64; 16], omg: &[f64; 16]) { unsafe {@@ -42,7 +40,6 @@ ifft16_avx2_fma_asm(re.as_mut_ptr(), im.as_mut_ptr(), omg.as_ptr());
} } -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2,fma")] fn ifft_rec_16_avx2_fma(m: usize, re: &mut [f64], im: &mut [f64], omg: &[f64], mut pos: usize) -> usize { if m <= 2048 {@@ -56,7 +53,6 @@ pos += 2;
pos } -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2,fma")] fn ifft_bfs_16_avx2_fma(m: usize, re: &mut [f64], im: &mut [f64], omg: &[f64], mut pos: usize) -> usize { let log_m: usize = (usize::BITS - (m - 1).leading_zeros()) as usize;@@ -95,7 +91,6 @@
pos } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn inv_twiddle_ifft_avx2_fma(h: usize, re: &mut [f64], im: &mut [f64], omg: [f64; 2]) { unsafe {@@ -133,7 +128,6 @@ }
} } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn inv_bitwiddle_ifft_avx2_fma(h: usize, re: &mut [f64], im: &mut [f64], omg: &[f64; 4]) { unsafe {@@ -221,7 +215,6 @@ #[test]
fn test_ifft_avx2_fma() { use super::*; - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2,fma")] fn internal(log_m: usize) { use poulpy_hal::reference::fft64::reim::ReimIFFTRef;
@@ -1,6 +1,5 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx")] pub fn reim4_extract_1blk_from_reim_avx(m: usize, rows: usize, blk: usize, dst: &mut [f64], src: &[f64]) { use core::arch::x86_64::{__m256d, _mm256_loadu_pd, _mm256_storeu_pd};@@ -23,7 +22,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2,fma")] pub fn reim4_save_1blk_to_reim_avx<const OVERWRITE: bool>(m: usize, blk: usize, dst: &mut [f64], src: &[f64]) { use core::arch::x86_64::{__m256d, _mm256_add_pd, _mm256_loadu_pd, _mm256_storeu_pd};@@ -51,7 +49,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2,fma")] pub fn reim4_save_2blk_to_reim_avx<const OVERWRITE: bool>( m: usize, //@@ -94,7 +91,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2", enable = "fma")] pub fn reim4_vec_mat1col_product_avx(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) { use core::arch::x86_64::{__m256d, _mm256_fmadd_pd, _mm256_loadu_pd, _mm256_setzero_pd, _mm256_storeu_pd};@@ -146,7 +142,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2", enable = "fma")] pub fn reim4_vec_mat2cols_product_avx(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) { use core::arch::x86_64::{__m256d, _mm256_fmadd_pd, _mm256_fmsub_pd, _mm256_loadu_pd, _mm256_setzero_pd, _mm256_storeu_pd};@@ -216,7 +211,6 @@ }
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2", enable = "fma")] pub fn reim4_vec_mat2cols_2ndcol_product_avx(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) { use core::arch::x86_64::{__m256d, _mm256_fmadd_pd, _mm256_fmsub_pd, _mm256_loadu_pd, _mm256_setzero_pd, _mm256_storeu_pd};
@@ -1,7 +1,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_add_avx(res: &mut [i64], a: &[i64], b: &[i64]) { #[cfg(debug_assertions)]@@ -41,7 +40,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_add_inplace_avx(res: &mut [i64], a: &[i64]) { #[cfg(debug_assertions)]
@@ -17,7 +17,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2", enable = "fma")] pub fn znx_automorphism_avx(p: i64, res: &mut [i64], a: &[i64]) { debug_assert_eq!(res.len(), a.len());@@ -99,12 +98,12 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(all(test, any(target_arch = "x86_64", target_arch = "x86")))] mod tests { use poulpy_hal::reference::znx::znx_automorphism_ref; use super::*; + #[allow(dead_code)] #[target_feature(enable = "avx2", enable = "fma")] fn test_znx_automorphism_internal() { let a: [i64; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
@@ -1,7 +1,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_negate_avx(res: &mut [i64], src: &[i64]) { #[cfg(debug_assertions)]@@ -37,7 +36,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_negate_inplace_avx(res: &mut [i64]) { let n: usize = res.len();
@@ -1,4 +1,3 @@
-#[cfg(target_arch = "x86_64")] use std::arch::x86_64::__m256i; /// Vector forms of those constants (broadcast to all lanes)@@ -6,7 +5,6 @@ ///
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] fn normalize_consts_avx(basek: usize) -> (__m256i, __m256i, __m256i, __m256i) { use std::arch::x86_64::_mm256_set1_epi64x;@@ -30,7 +28,6 @@ ///
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] fn get_digit_avx(x: __m256i, mask_k: __m256i, sign_k: __m256i) -> __m256i { use std::arch::x86_64::{_mm256_and_si256, _mm256_sub_epi64, _mm256_xor_si256};@@ -45,7 +42,6 @@ ///
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] unsafe fn get_carry_avx( x: __m256i,@@ -66,7 +62,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_normalize_first_step_carry_only_avx(basek: usize, lsh: usize, x: &[i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -118,7 +113,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_normalize_first_step_inplace_avx(basek: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -189,7 +183,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_normalize_first_step_avx(basek: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -272,7 +265,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] pub fn znx_normalize_middle_step_inplace_avx(basek: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -352,7 +344,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] pub fn znx_normalize_middle_step_carry_only_avx(basek: usize, lsh: usize, x: &[i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -430,7 +421,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] pub fn znx_normalize_middle_step_avx(basek: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -520,7 +510,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] pub fn znx_normalize_final_step_inplace_avx(basek: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -591,7 +580,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[target_feature(enable = "avx2")] pub fn znx_normalize_final_step_avx(basek: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) { #[cfg(debug_assertions)]@@ -668,7 +656,6 @@ );
} } -#[cfg(all(test, any(target_arch = "x86_64", target_arch = "x86")))] mod tests { use poulpy_hal::reference::znx::{ get_carry, get_digit, znx_normalize_final_step_inplace_ref, znx_normalize_final_step_ref,@@ -680,6 +667,7 @@ use super::*;
use std::arch::x86_64::{_mm256_loadu_si256, _mm256_storeu_si256}; + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_get_digit_avx_internal() { let basek: usize = 12;@@ -716,6 +704,7 @@ test_get_digit_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_get_carry_avx_internal() { let basek: usize = 12;@@ -754,6 +743,7 @@ test_get_carry_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_first_step_inplace_avx_internal() { let mut y0: [i64; 4] = [@@ -798,6 +788,7 @@ test_znx_normalize_first_step_inplace_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_middle_step_inplace_avx_internal() { let mut y0: [i64; 4] = [@@ -842,6 +833,7 @@ test_znx_normalize_middle_step_inplace_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_final_step_inplace_avx_internal() { let mut y0: [i64; 4] = [@@ -886,6 +878,7 @@ test_znx_normalize_final_step_inplace_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_first_step_avx_internal() { let mut y0: [i64; 4] = [@@ -931,6 +924,7 @@ test_znx_normalize_first_step_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_middle_step_avx_internal() { let mut y0: [i64; 4] = [@@ -976,6 +970,7 @@ test_znx_normalize_middle_step_avx_internal();
} } + #[allow(dead_code)] #[target_feature(enable = "avx2")] fn test_znx_normalize_final_step_avx_internal() { let mut y0: [i64; 4] = [
@@ -1,7 +1,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_sub_avx(res: &mut [i64], a: &[i64], b: &[i64]) { #[cfg(debug_assertions)]@@ -41,7 +40,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_sub_ab_inplace_avx(res: &mut [i64], a: &[i64]) { #[cfg(debug_assertions)]@@ -78,7 +76,6 @@
/// # Safety /// Caller must ensure the CPU supports AVX2 (e.g., via `is_x86_feature_detected!("avx2")`); /// all inputs must have the same length and must not alias. -#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub fn znx_sub_ba_inplace_avx(res: &mut [i64], a: &[i64]) { #[cfg(debug_assertions)]
@@ -1,4 +1,3 @@
-#[cfg(target_arch = "x86_64")] #[target_feature(enable = "avx2")] pub unsafe fn znx_switch_ring_avx(res: &mut [i64], a: &[i64]) { unsafe {
@@ -1,7 +1,11 @@
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] pub mod cpu_fft64_avx; + pub mod cpu_fft64_ref; pub mod cpu_spqlios; +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] pub use cpu_fft64_avx::FFT64Avx; + pub use cpu_fft64_ref::FFT64Ref; pub use cpu_spqlios::FFT64Spqlios;
@@ -122,6 +122,7 @@ lwe_to_glwe => crate::tests::test_suite::test_lwe_to_glwe,
} ); +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[cfg(test)] backend_test_suite!( mod cpu_avx,
@@ -7,13 +7,17 @@ },
}; use std::time::Instant; +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +use poulpy_backend::FFT64Avx as BackendImpl; + +#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] +use poulpy_backend::FFT64Ref as BackendImpl; + use poulpy_hal::{ api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, ZnNormalizeInplace}, layouts::{Module, ScalarZnx, ScratchOwned, ZnxView, ZnxViewMut}, source::Source, }; - -use poulpy_backend::FFT64Avx; use poulpy_schemes::tfhe::{ blind_rotation::CGGI,@@ -27,7 +31,7 @@ // GLWE ring degree
let n_glwe: usize = 1024; // Module provides access to the backend arithmetic - let module: Module<FFT64Avx> = Module::<FFT64Avx>::new(n_glwe as u64); + let module: Module<BackendImpl> = Module::<BackendImpl>::new(n_glwe as u64); // Base 2 loga let basek: usize = 13;@@ -75,7 +79,7 @@ // GGLWE tensor key modulus
let k_tsk: usize = (rows_tsk + 1) * basek; // Scratch space (4MB) - let mut scratch: ScratchOwned<FFT64Avx> = ScratchOwned::alloc(1 << 22); + let mut scratch: ScratchOwned<BackendImpl> = ScratchOwned::alloc(1 << 22); // Secret key sampling source let mut source_xs: Source = Source::new([1u8; 32]);@@ -97,7 +101,7 @@ sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
// sk_glwe.fill_zero(); // GLWE secret prepared (opaque backend dependant write only struct) - let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, FFT64Avx> = sk_glwe.prepare_alloc(&module, scratch.borrow()); + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, BackendImpl> = sk_glwe.prepare_alloc(&module, scratch.borrow()); // Plaintext value to circuit bootstrap let data: i64 = 1 % (1 << k_lwe_pt);@@ -142,7 +146,8 @@ // Output GGSW
let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n_glwe, basek, k_ggsw_res, rows_ggsw_res, 1, rank); // Circuit bootstrapping key prepared (opaque backend dependant write only struct) - let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, CGGI, FFT64Avx> = cbt_key.prepare_alloc(&module, scratch.borrow()); + let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, CGGI, BackendImpl> = + cbt_key.prepare_alloc(&module, scratch.borrow()); // Apply circuit bootstrapping: LWE(data * 2^{- (k_lwe_pt + 2)}) -> GGSW(data) let now: Instant = Instant::now();@@ -193,7 +198,7 @@ scratch.borrow(),
); // Prepare GGSW output of circuit bootstrapping (opaque backend dependant write only struct) - let res_prepared: GGSWCiphertextPrepared<Vec<u8>, FFT64Avx> = res.prepare_alloc(&module, scratch.borrow()); + let res_prepared: GGSWCiphertextPrepared<Vec<u8>, BackendImpl> = res.prepare_alloc(&module, scratch.borrow()); // Apply GLWE x GGSW ct_glwe.external_product_inplace(&module, &res_prepared, scratch.borrow());