Skip to content

Commit 3de10b9

Browse files
Brooooooklynliuq19
authored andcommitted
feat: support avx512
1 parent 7b29203 commit 3de10b9

5 files changed

Lines changed: 150 additions & 3 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ sanitize = []
5858
# Serialize floating point numbers without trailing zeros if the float can be represented as an integer without loss of precision.
5959
# For example, `18.0` will be serialized as `18` instead of `18.0`.
6060
non_trailing_zero = []
61+
62+
# Enable avx512, requires Rust 1.89 or later, and also enable `avx512f` target feature
63+
avx512 = ["sonic-simd/avx512"]

scripts/test.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ cargo test --features utf8_lossy
1212

1313
cargo test --features non_trailing_zero
1414

15+
cargo test --features avx512
16+
1517
examples=$(cargo build --example 2>&1 | grep -v ":")
1618

1719
for example in $examples; do

sonic-simd/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ name = "sonic-simd"
77
repository = "https://github.com/cloudwego/sonic-rs"
88
version = "0.1.1"
99

10+
[features]
11+
avx512 = [] # enable avx512, requires Rust 1.89 or later, and also enable `avx512f` target feature
1012

1113
[dependencies]
1214
cfg-if = "1.0"

sonic-simd/src/avx512.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
use std::{
2+
arch::x86_64::*,
3+
ops::{BitAnd, BitOr, BitOrAssign},
4+
};
5+
6+
use super::{Mask, Simd};
7+
8+
#[derive(Debug)]
9+
#[repr(transparent)]
10+
pub struct Simd512u(__m512i);
11+
12+
#[derive(Debug)]
13+
#[repr(transparent)]
14+
pub struct Simd512i(__m512i);
15+
16+
#[derive(Debug, Clone, Copy)]
17+
#[repr(transparent)]
18+
pub struct Mask512(__mmask64);
19+
20+
impl Mask for Mask512 {
21+
type BitMask = u64;
22+
type Element = u8;
23+
24+
#[inline(always)]
25+
fn bitmask(self) -> Self::BitMask {
26+
self.0
27+
}
28+
29+
#[inline(always)]
30+
fn splat(b: bool) -> Self {
31+
if b {
32+
Mask512(u64::MAX)
33+
} else {
34+
Mask512(0)
35+
}
36+
}
37+
}
38+
39+
impl BitOr for Mask512 {
40+
type Output = Self;
41+
42+
#[inline(always)]
43+
fn bitor(self, rhs: Self) -> Self::Output {
44+
Mask512(self.0 | rhs.0)
45+
}
46+
}
47+
48+
impl BitOrAssign for Mask512 {
49+
#[inline(always)]
50+
fn bitor_assign(&mut self, rhs: Self) {
51+
self.0 |= rhs.0;
52+
}
53+
}
54+
55+
impl BitAnd<Mask512> for Mask512 {
56+
type Output = Self;
57+
58+
#[inline(always)]
59+
fn bitand(self, rhs: Mask512) -> Self::Output {
60+
Mask512(self.0 & rhs.0)
61+
}
62+
}
63+
64+
impl Simd for Simd512u {
65+
const LANES: usize = 64;
66+
type Element = u8;
67+
type Mask = Mask512;
68+
69+
#[inline(always)]
70+
unsafe fn loadu(ptr: *const u8) -> Self {
71+
unsafe { Simd512u(_mm512_loadu_si512(ptr as *const __m512i)) }
72+
}
73+
74+
#[inline(always)]
75+
unsafe fn storeu(&self, ptr: *mut u8) {
76+
unsafe { _mm512_storeu_si512(ptr as *mut __m512i, self.0) }
77+
}
78+
79+
#[inline(always)]
80+
fn eq(&self, rhs: &Self) -> Self::Mask {
81+
unsafe { Mask512(_mm512_cmpeq_epi8_mask(self.0, rhs.0)) }
82+
}
83+
84+
#[inline(always)]
85+
fn splat(ch: u8) -> Self {
86+
unsafe { Simd512u(_mm512_set1_epi8(ch as i8)) }
87+
}
88+
89+
#[inline(always)]
90+
fn le(&self, rhs: &Self) -> Self::Mask {
91+
unsafe { Mask512(_mm512_cmple_epu8_mask(self.0, rhs.0)) }
92+
}
93+
94+
#[inline(always)]
95+
fn gt(&self, rhs: &Self) -> Self::Mask {
96+
unsafe { Mask512(_mm512_cmpgt_epu8_mask(self.0, rhs.0)) }
97+
}
98+
}
99+
100+
impl Simd for Simd512i {
101+
const LANES: usize = 64;
102+
type Element = i8;
103+
type Mask = Mask512;
104+
105+
#[inline(always)]
106+
unsafe fn loadu(ptr: *const u8) -> Self {
107+
unsafe { Simd512i(_mm512_loadu_si512(ptr as *const __m512i)) }
108+
}
109+
110+
#[inline(always)]
111+
unsafe fn storeu(&self, ptr: *mut u8) {
112+
unsafe { _mm512_storeu_si512(ptr as *mut __m512i, self.0) }
113+
}
114+
115+
#[inline(always)]
116+
fn eq(&self, rhs: &Self) -> Self::Mask {
117+
unsafe { Mask512(_mm512_cmpeq_epi8_mask(self.0, rhs.0)) }
118+
}
119+
120+
#[inline(always)]
121+
fn splat(elem: i8) -> Self {
122+
unsafe { Simd512i(_mm512_set1_epi8(elem)) }
123+
}
124+
125+
#[inline(always)]
126+
fn le(&self, rhs: &Self) -> Self::Mask {
127+
unsafe { Mask512(_mm512_cmple_epi8_mask(self.0, rhs.0)) }
128+
}
129+
130+
#[inline(always)]
131+
fn gt(&self, rhs: &Self) -> Self::Mask {
132+
unsafe { Mask512(_mm512_cmpgt_epi8_mask(self.0, rhs.0)) }
133+
}
134+
}

sonic-simd/src/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,15 @@ cfg_if::cfg_if! {
3131

3232
pub use self::traits::{BitMask, Mask, Simd};
3333
// pick v512 simd
34-
// TODO: support avx512?
35-
mod v512;
36-
use self::v512::*;
34+
cfg_if::cfg_if! {
35+
if #[cfg(all(target_feature = "avx512f", feature = "avx512"))] {
36+
mod avx512;
37+
use self::avx512::*;
38+
} else {
39+
mod v512;
40+
use self::v512::*;
41+
}
42+
}
3743

3844
pub type u8x16 = Simd128u;
3945
pub type u8x32 = Simd256u;

0 commit comments

Comments
 (0)