pub mod mmm;
mod amd_avx512_linear;
mod amd_fma_linear;
mod intel_avx512_linear;
mod intel_avx512_mmv_linear;
mod intel_fma_linear;
#[derive(PartialEq, Clone, Copy)]
pub(crate) enum Vendor {
Intel,
Amd,
Other,
}
pub(crate) fn vendor() -> Vendor {
if let Ok(k) = std::env::var("TRACT_X86_KIND") {
return match k.as_str() {
"intel" => Vendor::Intel,
"amd" => Vendor::Amd,
_ => Vendor::Other,
};
}
cpuid_vendor()
}
#[cfg(target_arch = "x86_64")]
fn cpuid_vendor() -> Vendor {
#[allow(unused_unsafe)]
let id = unsafe { std::arch::x86_64::__cpuid(0) };
let mut s = [0u8; 12];
s[0..4].copy_from_slice(&id.ebx.to_le_bytes());
s[4..8].copy_from_slice(&id.edx.to_le_bytes());
s[8..12].copy_from_slice(&id.ecx.to_le_bytes());
match &s {
b"GenuineIntel" => Vendor::Intel,
b"AuthenticAMD" => Vendor::Amd,
_ => Vendor::Other,
}
}
#[cfg(not(target_arch = "x86_64"))]
fn cpuid_vendor() -> Vendor {
Vendor::Other
}
pub mod act;
pub mod act_f16;
pub mod act_f16_fp16;
#[cfg(target_arch = "x86_64")]
pub mod amx;
#[cfg(target_arch = "x86_64")]
pub mod amx_bf16;
#[cfg(target_arch = "x86_64")]
pub mod avxvnni;
pub mod by_scalar;
pub mod erf;
pub mod exp;
#[cfg(tract_avx512vnni)]
pub mod fma_width;
pub mod ln;
pub mod max;
pub mod min;
pub mod panel_extract;
pub mod rms_norm;
pub mod softmax;
macro_rules! cpu_feature {
($id:ident = $feature:tt) => {
#[cfg(target_arch = "x86_64")]
const $id: fn() -> bool = || is_x86_feature_detected!($feature);
#[cfg(not(target_arch = "x86_64"))]
const $id: fn() -> bool = || false;
};
}
cpu_feature!(AVX = "avx");
cpu_feature!(AVX2 = "avx2");
cpu_feature!(FMA = "fma");
cpu_feature!(AVX512F = "avx512f");
cpu_feature!(AVX512FP16 = "avx512fp16");
cpu_feature!(F16C = "f16c");
#[cfg(tract_avx512vnni)]
cpu_feature!(AVX512VNNI = "avx512vnni");
routine_ew_extern!(x86_64; Tanh, f32, fma_tanh_f32, 8, 8, isa(X86_64Avx2, X86_64Fma));
routine_ew_extern!(x86_64; Sigmoid, f32, fma_sigmoid_f32, 8, 8, isa(X86_64Avx2, X86_64Fma));
routine_ew_extern!(x86_64; Silu, f32, fma_silu_f32, 8, 8, isa(X86_64Avx2, X86_64Fma));
routine_ew_extern!(x86_64; Tanh, f32, avx_tanh_f32, 8, 8, isa(X86_64Avx));
routine_ew_extern!(x86_64; Sigmoid, f32, avx_sigmoid_f32, 8, 8, isa(X86_64Avx));
routine_ew_extern!(x86_64; Tanh, f32, avx512_tanh_f32, 16, 16, isa(X86_64Avx512f));
routine_ew_extern!(x86_64; Sigmoid, f32, avx512_sigmoid_f32, 16, 16, isa(X86_64Avx512f));
routine_ew_extern!(x86_64; Silu, f32, avx512_silu_f32, 16, 16, isa(X86_64Avx512f));
pub fn isa_set() -> crate::isa::IsaSet {
use crate::isa::{Isa, IsaSet};
let mut set = IsaSet::of_arch(crate::isa::Arch::X86_64);
for (isa, probe) in [
(Isa::X86_64Avx, AVX),
(Isa::X86_64Avx2, AVX2),
(Isa::X86_64Fma, FMA),
(Isa::X86_64F16c, F16C),
(Isa::X86_64Avx512f, AVX512F),
(Isa::X86_64Avx512Fp16, AVX512FP16),
] {
if probe() {
set = set.with(isa);
}
}
#[cfg(tract_avx512vnni)]
if AVX512VNNI() {
set = set.with(Isa::X86_64Avx512Vnni);
}
#[cfg(tract_avxvnni)]
if avxvnni::has_avxvnni() {
set = set.with(Isa::X86_64AvxVnni);
}
#[cfg(tract_amx_int8)]
if amx::has_amx_int8() {
set = set.with(Isa::X86_64AmxInt8);
}
#[cfg(tract_amx_bf16)]
if amx_bf16::has_amx_bf16() {
set = set.with(Isa::X86_64AmxBf16);
}
set
}