mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
Update to non-avx builds
This commit is contained in:
@@ -9,6 +9,9 @@ repository = "https://github.com/phantomzone-org/poulpy"
|
||||
homepage = "https://github.com/phantomzone-org/poulpy"
|
||||
documentation = "https://docs.rs/poulpy"
|
||||
|
||||
[features]
|
||||
enable-avx = []
|
||||
|
||||
[dependencies]
|
||||
poulpy-hal = {workspace = true}
|
||||
poulpy-cpu-ref = {workspace = true}
|
||||
|
||||
@@ -1,8 +1,51 @@
|
||||
# 🐙 Poulpy-CPU-REF
|
||||
# 🐙 Poulpy-CPU-AVX
|
||||
|
||||
**Poulpy-Backend-CPU-AVX** is a Rust crate that provides an AVX accelerated CPU implementation of **`poulpy-hal`**. This crate is used to instantiate projects implemented with **`poulpy-hal`**, **`poulpy-core`** and/or **`poulpy-schemes`**.
|
||||
**Poulpy-CPU-AVX** is a Rust crate that provides an **AVX2 + FMA accelerated CPU backend for Poulpy**.
|
||||
|
||||
## Example
|
||||
This backend implements the Poulpy HAL extension traits and can be used by:
|
||||
|
||||
- [`poulpy-hal`](https://github.com/phantomzone-org/poulpy/tree/main/poulpy-hal)
|
||||
- [`poulpy-core`](https://github.com/phantomzone-org/poulpy/tree/main/poulpy-core)
|
||||
- [`poulpy-schemes`](https://github.com/phantomzone-org/poulpy/tree/main/poulpy-schemes)
|
||||
|
||||
## 🚩 Safety and Requirements
|
||||
|
||||
To avoid illegal hardware instructions (SIGILL) on unsupported CPUs, this backend is **opt-in** and **only builds when explicitly requested**.
|
||||
|
||||
| Requirement | Status |
|
||||
|------------|--------|
|
||||
| Cargo feature flag | `--features enable-avx` **must be enabled** |
|
||||
| CPU architecture | `x86_64` |
|
||||
| CPU target features | `AVX2` + `FMA` |
|
||||
|
||||
If `enable-avx` is enabled but the target does not provide these capabilities, the build **fails immediately with a clear error message**, rather than generating invalid binaries.
|
||||
|
||||
When `enable-avx` is **not** enabled, this crate is simply skipped and Poulpy automatically falls back to the portable `poulpy-cpu-ref` backend. This ensure that Poulpy's workspace remains portable (e.g. for macOS ARM).
|
||||
|
||||
## ⚙️ Building with the AVX backend enabled
|
||||
|
||||
Because the compiler must generate AVX2 + FMA instructions, both the Cargo feature and CPU target flags must be specified:
|
||||
|
||||
```bash
|
||||
RUSTFLAGS="-C target-feature=+avx2,+fma" \
|
||||
cargo build --features enable-avx
|
||||
````
|
||||
|
||||
### Running an example
|
||||
|
||||
```bash
|
||||
RUSTFLAGS="-C target-feature=+avx2,+fma" \
|
||||
cargo run --example <name> --features enable-avx
|
||||
```
|
||||
|
||||
### Running benchmarks
|
||||
|
||||
```bash
|
||||
RUSTFLAGS="-C target-feature=+avx2,+fma" \
|
||||
cargo bench --features enable-avx
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```rust
|
||||
use poulpy_backend_cpu_avx::FFT64Avx;
|
||||
@@ -12,7 +55,24 @@ let log_n: usize = 10;
|
||||
let module = Module<FFT64Avx> = Module<FFT64Avx>::new(1<<log_n);
|
||||
```
|
||||
|
||||
## Contributors
|
||||
Once compiled with `enable-avx`, the backend is usable transparently anywhere Poulpy expects a backend type (`poulpy-hal`, `poulpy-core`, `poulpy-schemes`).
|
||||
|
||||
To add your own backend, implement the open extension traits from **`poulpy-hal/oep`** for a struct that implements the `Backend` trait.
|
||||
This will automatically make your backend compatible with the API of **`poulpy-hal`**, **`poulpy-core`** and **`poulpy-schemes`**.
|
||||
## 🤝 Contributors
|
||||
|
||||
To implement your own Poulpy backend (SIMD or accelerator):
|
||||
|
||||
1. Define a backend struct
|
||||
2. Implement the open extension traits from `poulpy-hal/oep`
|
||||
3. Implement the `Backend` trait
|
||||
|
||||
Your backend will automatically integrate with:
|
||||
|
||||
* `poulpy-hal`
|
||||
* `poulpy-core`
|
||||
* `poulpy-schemes`
|
||||
|
||||
No modifications to those crates are required — the HAL provides the extension points.
|
||||
|
||||
---
|
||||
|
||||
For questions or guidance, feel free to open an issue or discussion in the repository.
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
#![cfg(target_arch = "x86_64")]
|
||||
use std::hint::black_box;
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
|
||||
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||
use poulpy_cpu_avx::{ReimFFTAvx, ReimIFFTAvx};
|
||||
use poulpy_hal::reference::fft64::reim::{ReimDFTExecute, ReimFFTTable, ReimIFFTTable};
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_ifft_avx2_fma(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX IFft benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
pub fn bench_ifft_avx2_fma(c: &mut Criterion) {
|
||||
use criterion::BenchmarkId;
|
||||
use poulpy_cpu_avx::ReimIFFTAvx;
|
||||
use poulpy_hal::reference::fft64::reim::{ReimDFTExecute, ReimIFFTTable};
|
||||
use std::hint::black_box;
|
||||
|
||||
let group_name: String = "ifft_avx2_fma".to_string();
|
||||
|
||||
let mut group = c.benchmark_group(group_name);
|
||||
@@ -41,7 +47,18 @@ pub fn bench_ifft_avx2_fma(c: &mut Criterion) {
|
||||
group.finish();
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_fft_avx2_fma(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX FFT benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
pub fn bench_fft_avx2_fma(c: &mut Criterion) {
|
||||
use criterion::BenchmarkId;
|
||||
use poulpy_cpu_avx::ReimFFTAvx;
|
||||
use poulpy_hal::reference::fft64::reim::{ReimDFTExecute, ReimFFTTable};
|
||||
use std::hint::black_box;
|
||||
|
||||
let group_name: String = "fft_avx2_fma".to_string();
|
||||
|
||||
let mut group = c.benchmark_group(group_name);
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
#![cfg(target_arch = "x86_64")]
|
||||
// poulpy-backend/benches/vec_znx_add.rs
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
use poulpy_hal::reference::vec_znx::{bench_vec_znx_add, bench_vec_znx_automorphism, bench_vec_znx_normalize_inplace};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_vec_znx_add_cpu_avx_fft64(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX IFft benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
fn bench_vec_znx_add_cpu_avx_fft64(c: &mut Criterion) {
|
||||
bench_vec_znx_add::<FFT64Avx>(c, "FFT64Avx");
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
poulpy_hal::reference::vec_znx::bench_vec_znx_add::<FFT64Avx>(c, "FFT64Avx");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_vec_znx_normalize_inplace_cpu_avx_fft64(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX IFft benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
fn bench_vec_znx_normalize_inplace_cpu_avx_fft64(c: &mut Criterion) {
|
||||
bench_vec_znx_normalize_inplace::<FFT64Avx>(c, "FFT64Avx");
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
poulpy_hal::reference::vec_znx::bench_vec_znx_normalize_inplace::<FFT64Avx>(c, "FFT64Avx");
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_vec_znx_automorphism_cpu_avx_fft64(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX IFft benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
fn bench_vec_znx_automorphism_cpu_avx_fft64(c: &mut Criterion) {
|
||||
bench_vec_znx_automorphism::<FFT64Avx>(c, "FFT64Avx");
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
poulpy_hal::reference::vec_znx::bench_vec_znx_automorphism::<FFT64Avx>(c, "FFT64Avx");
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
|
||||
@@ -1,27 +1,15 @@
|
||||
// poulpy-backend/benches/vec_znx_add.rs
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
use poulpy_cpu_ref::FFT64Ref;
|
||||
|
||||
use poulpy_hal::bench_suite::vmp::bench_vmp_apply_dft_to_dft;
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
fn bench_vmp_apply_dft_to_dft_cpu_avx_fft64(_c: &mut Criterion) {
|
||||
eprintln!("Skipping: AVX IFft benchmark requires x86_64 + AVX2 + FMA");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
fn bench_vmp_apply_dft_to_dft_cpu_avx_fft64(c: &mut Criterion) {
|
||||
bench_vmp_apply_dft_to_dft::<FFT64Avx>(c, "FFT64Avx");
|
||||
}
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
fn bench_vmp_apply_dft_to_dft_cpu_ref_fft64(c: &mut Criterion) {
|
||||
bench_vmp_apply_dft_to_dft::<FFT64Ref>(c, "FFT64Ref");
|
||||
use poulpy_cpu_avx::FFT64Avx;
|
||||
poulpy_hal::bench_suite::vmp::bench_vmp_apply_dft_to_dft::<FFT64Avx>(c, "FFT64Avx");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
criterion_group!(benches_x86, bench_vmp_apply_dft_to_dft_cpu_avx_fft64,);
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
criterion_group!(benches_ref, bench_vmp_apply_dft_to_dft_cpu_ref_fft64,);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
criterion_main!(benches_x86);
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
criterion_main!(benches_ref);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use itertools::izip;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
use poulpy_cpu_avx::FFT64Avx as BackendImpl;
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma")))]
|
||||
use poulpy_cpu_ref::FFT64Ref as BackendImpl;
|
||||
|
||||
use poulpy_hal::{
|
||||
@@ -143,4 +143,3 @@ fn main() {
|
||||
println!("{}: {} {}", i, a, (*b as f64) / scale);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
#![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Build the backend **only when ALL conditions are satisfied**
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
#![cfg(all(feature = "enable-avx", target_arch = "x86_64", target_feature = "avx2", target_feature = "fma"))]
|
||||
|
||||
// If the user enables this backend but targets a non-x86_64 CPU → abort
|
||||
#[cfg(all(feature = "enable-avx", not(target_arch = "x86_64")))]
|
||||
compile_error!("feature `enable-avx` requires target_arch = \"x86_64\".");
|
||||
|
||||
// If the user enables this backend but AVX2 isn't enabled in the target → abort
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", not(target_feature = "avx2")))]
|
||||
compile_error!("feature `enable-avx` requires AVX2. Build with RUSTFLAGS=\"-C target-feature=+avx2\".");
|
||||
|
||||
// If the user enables this backend but FMA isn't enabled in the target → abort
|
||||
#[cfg(all(feature = "enable-avx", target_arch = "x86_64", not(target_feature = "fma")))]
|
||||
compile_error!("feature `enable-avx` requires FMA. Build with RUSTFLAGS=\"-C target-feature=+fma\".");
|
||||
|
||||
mod module;
|
||||
mod reim;
|
||||
|
||||
Reference in New Issue
Block a user