Skip to content

Commit

Permalink
add avx compile-time feature
Browse files Browse the repository at this point in the history
  • Loading branch information
alindima committed Dec 12, 2023
1 parent 69612f1 commit a0cdeb9
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 42 deletions.
52 changes: 50 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,28 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: check
args: --workspace --all-features
args: --workspace

check:
name: Check AVX
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Rust Cache
uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1

- uses: actions-rs/cargo@v1
env:
RUSTFLAGS: "-C target-cpu=native"
with:
command: check
args: --features avx --workspace

test:
name: Test
Expand All @@ -51,6 +72,33 @@ jobs:
command: test
args: --workspace

test:
name: Test AVX
runs-on: ubuntu-latest
strategy:
matrix:
os:
- ubuntu-latest
- macOS-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Rust Cache
uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1

- name: Test with avx feature
uses: actions-rs/cargo@v1
env:
RUSTFLAGS: "-C target-cpu=native"
with:
command: test
args: --workspace --features avx

test_windows:
name: Test Windows
runs-on: windows-latest
Expand Down Expand Up @@ -98,4 +146,4 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-features
args: --workspace --all-features -- -D warnings
6 changes: 3 additions & 3 deletions reed-solomon-novelpoly-fuzzit/src/additive_mpy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct FieldMpyParams {
idx_to_test: usize,
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
impl<'a> Arbitrary<'a> for FieldMpyParams {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let additive = Additive(u.int_in_range(0..=u16::MAX)?);
Expand All @@ -26,14 +26,14 @@ impl<'a> Arbitrary<'a> for FieldMpyParams {
}

fn main() {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
run();

#[cfg(not(target_feature = "avx"))]
panic!("Nothing to do for non avx enabled targets")
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
fn run() {
// You have full control over the loop but
// you're supposed to call `fuzz` ad vitam aeternam
Expand Down
4 changes: 2 additions & 2 deletions reed-solomon-novelpoly-fuzzit/src/afft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ impl<'a> Arbitrary<'a> for AfftParams {
}

fn main() {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
run();

#[cfg(not(target_feature = "avx"))]
panic!("Nothing to do for non avx enabled targets")
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
fn run() {
// You have full control over the loop but
// you're supposed to call `fuzz` ad vitam aeternam
Expand Down
4 changes: 2 additions & 2 deletions reed-solomon-novelpoly-fuzzit/src/inverse_afft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ impl<'a> Arbitrary<'a> for InverseAfftParams {
}

fn main() {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
run();

#[cfg(not(target_feature = "avx"))]
panic!("Nothing to do for non avx enabled targets")
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
fn run() {
// You have full control over the loop but
// you're supposed to call `fuzz` ad vitam aeternam
Expand Down
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/field/f256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ impl std::fmt::Debug for Additive {
}

#[cfg(table_bootstrap_complete)]
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub use faster8::f256::*;
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/field/f2e16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ impl std::fmt::Debug for Additive {
}

#[cfg(table_bootstrap_complete)]
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub use crate::field::faster8::f2e16::*;
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/field/faster8/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![cfg(target_feature = "avx")]
#![cfg(all(target_feature = "avx", feature = "avx"))]

#[cfg(feature = "f256")]
pub mod f256;
Expand Down
30 changes: 15 additions & 15 deletions reed-solomon-novelpoly/src/field/inc_afft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn inverse_afft(data: &mut [Additive], size: usize, index: usize) {
unsafe { &AFFT }.inverse_afft(data,size,index)
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn inverse_afft_faster8(data: &mut [Additive], size: usize, index: usize) {
unsafe { &AFFT }.inverse_afft_faster8(data,size,index)
}
Expand All @@ -104,7 +104,7 @@ pub fn afft(data: &mut [Additive], size: usize, index: usize) {
unsafe { &AFFT }.afft(data,size,index)
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
/// Additive FFT in the "novel polynomial basis"
pub fn afft_faster8(data: &mut [Additive], size: usize, index: usize) {
unsafe { &AFFT }.afft_faster8(data,size,index)
Expand All @@ -114,7 +114,7 @@ pub fn afft_faster8(data: &mut [Additive], size: usize, index: usize) {
impl AdditiveFFT {

/// `data[i + depart_no] ^= data[i];`
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[inline(always)]
fn butterfly_down(data: &mut [Additive], i_8x: usize, depart_no_8x: usize) {
let rhs = Additive8x::load(&data[(i_8x * Additive8x::LANE) .. ][.. Additive8x::LANE]);
Expand All @@ -125,7 +125,7 @@ impl AdditiveFFT {
}

// `data[i] ^= data[i + depart_no].mul(skew)`;
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[inline(always)]
fn butterfly_up(data: &mut [Additive], i_8x: usize, depart_no_8x: usize, skew: Multiplier) {
let rhs = Additive8x::load(&data[((i_8x + depart_no_8x) * Additive8x::LANE) .. ][.. Additive8x::LANE]).mul(skew);
Expand Down Expand Up @@ -218,7 +218,7 @@ impl AdditiveFFT {
}

/// Inverse additive FFT in the "novel polynomial basis", but do 8 at once using available vector units
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn inverse_afft_faster8(&self, data: &mut [Additive], size: usize, index: usize) {
let mut depart_no = 1_usize;
while depart_no < Additive8x::LANE {
Expand Down Expand Up @@ -335,7 +335,7 @@ impl AdditiveFFT {
/// Additive FFT in the "novel polynomial basis", but do 8 at once using available vector units
///
/// `size` is the count of the individual additive field elements, so 8x larger than `data.len()`.
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn afft_faster8(&self, data: &mut [Additive], size: usize, index: usize) {
let mut depart_no = size >> 1_usize;
while depart_no >= Additive8x::LANE {
Expand Down Expand Up @@ -490,19 +490,19 @@ pub mod test_utils {
Vec::from_iter(rng.sample_iter::<Elt, _>(dist).take(size).map(Additive))
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn gen_faster8_from_plain(data: impl AsRef<[Additive]>) -> Vec<Additive> {
let data = data.as_ref();
data.to_vec()
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn gen_faster8<R: Rng + SeedableRng<Seed = [u8; 32]>>(size: usize) -> Vec<Additive> {
let data = gen_plain::<R>(size);
gen_faster8_from_plain(data)
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn assert_plain_eq_faster8(plain: impl AsRef<[Additive]>, faster8: impl AsRef<[Additive]>) {
let plain = plain.as_ref();
let faster8 = faster8.as_ref();
Expand All @@ -515,13 +515,13 @@ pub mod test_utils {
#[cfg(test)]
mod afft_tests {

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
mod simd {
use super::super::*;
use super::super::test_utils::*;
use rand::rngs::SmallRng;

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn afft_output_plain_eq_faster8_size_16() {
let index = 0;
Expand All @@ -540,7 +540,7 @@ mod afft_tests {
assert_plain_eq_faster8(data_plain, data_faster8);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn afft_output_plain_eq_faster8_size_32() {
let index = 0;
Expand All @@ -559,7 +559,7 @@ mod afft_tests {
assert_plain_eq_faster8(data_plain, data_faster8);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn afft_output_plain_eq_faster8_impulse_data() {
let index = 0;
Expand All @@ -583,7 +583,7 @@ mod afft_tests {
assert_plain_eq_faster8(data_plain, data_faster8);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn inverse_afft_output_plain_eq_faster8_size_8() {
let index = 0;
Expand All @@ -604,7 +604,7 @@ mod afft_tests {
assert_plain_eq_faster8(data_plain, data_faster8);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn inverse_afft_output_plain_eq_faster8_size_32() {
let index = 0;
Expand Down
18 changes: 9 additions & 9 deletions reed-solomon-novelpoly/src/field/inc_encode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[inline(always)]
pub fn encode_low(data: &[Additive], k: usize, codeword: &mut [Additive], n: usize) {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
if k >= 16 && k % 8 == 0 && n % 8 == 0 && (n-k) % 8 == 0 {
encode_low_faster8(data, k, codeword, n);
} else {
Expand Down Expand Up @@ -51,7 +51,7 @@ pub fn encode_low_plain(data: &[Additive], k: usize, codeword: &mut [Additive],
}


#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn encode_low_faster8(data: &[Additive], k: usize, codeword: &mut [Additive], n: usize) {
assert!(k + k <= n);
assert_eq!(codeword.len(), n);
Expand Down Expand Up @@ -102,7 +102,7 @@ pub fn encode_low_faster8(data: &[Additive], k: usize, codeword: &mut [Additive]
//Encoding alg for k/n>0.5: parity is a power of two.
#[inline(always)]
pub fn encode_high(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
if (n-k) % Additive8x::LANE == 0 && n % Additive8x::LANE == 0 && k % Additive8x::LANE == 0 {
encode_high_faster8(data, k, parity, mem, n);
} else {
Expand Down Expand Up @@ -135,12 +135,12 @@ pub fn encode_high_plain(data: &[Additive], k: usize, parity: &mut [Additive], m
afft(parity, t, 0);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn encode_high_faster8_adapter(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
encode_high_faster8(&data, k, parity, mem, n);
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn encode_high_faster8(data: &[Additive], k: usize, parity: &mut [Additive], mem: &mut [Additive], n: usize) {
let t: usize = n - k;
assert!(t >= 8);
Expand All @@ -164,7 +164,7 @@ pub fn encode_high_faster8(data: &[Additive], k: usize, parity: &mut [Additive],
}

pub fn encode_sub(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive>> {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
if (k % Additive8x::LANE) == 0 && (k >> 1) >= Additive8x::LANE {
encode_sub_faster8(bytes, n, k)
} else {
Expand Down Expand Up @@ -221,7 +221,7 @@ pub fn encode_sub_plain(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive


/// Bytes shall only contain payload data
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn encode_sub_faster8(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive>> {
assert!(is_power_of_2(n), "Algorithm only works for 2^i sizes for N");
assert!(is_power_of_2(k), "Algorithm only works for 2^i sizes for K");
Expand Down Expand Up @@ -266,7 +266,7 @@ pub fn encode_sub_faster8(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additi
Ok(codeword)
}

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[cfg(test)]
mod tests_plain_vs_faster8 {
use super::*;
Expand All @@ -289,7 +289,7 @@ mod tests_plain_vs_faster8 {
}


#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn encode_sub_output_plain_eq_faster8() {
let n = 64;
Expand Down
4 changes: 2 additions & 2 deletions reed-solomon-novelpoly/src/field/inc_log_mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub fn walsh_plain(data: &mut [Multiplier], size: usize) {


#[cfg(table_bootstrap_complete)]
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub fn walsh_faster8(data: &mut [Multiplier], size: usize) {
const LANE: usize = 8;

Expand Down Expand Up @@ -244,7 +244,7 @@ fn cantor_basis() {


#[cfg(table_bootstrap_complete)]
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
#[test]
fn walsh_output_plain_eq_faster8() {
use reed_solomon_tester::*;
Expand Down
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/field/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub mod f256;

pub mod f2e16;

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub mod faster8;
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod field;
pub use self::field::f256;
pub use self::field::f2e16;

#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
pub use self::field::faster8;

mod novel_poly_basis;
Expand Down
2 changes: 1 addition & 1 deletion reed-solomon-novelpoly/src/novel_poly_basis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl CodeParams {

/// Check if this could use the `faster8` code path, possibly utilizing `avx` SIMD instructions
pub fn is_faster8(&self) -> bool {
#[cfg(target_feature = "avx")]
#[cfg(all(target_feature = "avx", feature = "avx"))]
{
self.k >= (Additive8x::LANE << 1) && self.n % Additive8x::LANE == 0
}
Expand Down
Loading

0 comments on commit a0cdeb9

Please sign in to comment.