// Use largest step possible (without causing overflow). for chunk in middle.chunks(NMAX as usize / 64) {
(adler0, adler1) = unsafe { helper_64_bytes(adler0, adler1, chunk) };
}
#[inline(always)] pub(super) unsafefn _mm512_reduce_add_epu32(x: __m512i) -> u32 { unsafe { let a = _mm512_extracti64x4_epi64(x, 1); let b = _mm512_extracti64x4_epi64(x, 0);
let a_plus_b = _mm256_add_epi32(a, b); let c = _mm256_extracti128_si256(a_plus_b, 1); let d = _mm256_extracti128_si256(a_plus_b, 0); let c_plus_d = _mm_add_epi32(c, d);
let sum1 = _mm_unpackhi_epi64(c_plus_d, c_plus_d); let sum2 = _mm_add_epi32(sum1, c_plus_d); let sum3 = _mm_shuffle_epi32(sum2, 0x01); let sum4 = _mm_add_epi32(sum2, sum3);
_mm_cvtsi128_si32(sum4) as u32
}
}
#[inline(always)] pub(super) unsafefn partial_hsum(x: __m512i) -> u32 { unsafe { // Permutation vector to extract every other integer. let perm_vec: __m512i =
_mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, 1, 1, 1, 1, 1, 1, 1, 1);
let non_zero = _mm512_permutexvar_epi32(perm_vec, x);
// From here, it's a simple 256 bit wide reduction sum. let non_zero_avx = _mm512_castsi512_si256(non_zero);
// See Agner Fog's vectorclass for a decent reference. Essentially, phadd is // pretty slow, much slower than the longer instruction sequence below. let sum1 = _mm_add_epi32(
_mm256_extracti128_si256(non_zero_avx, 1),
_mm256_castsi256_si128(non_zero_avx),
); let sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); let sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1));
_mm_cvtsi128_si32(sum3) as u32
}
}
#[cfg(test)] #[cfg(target_feature = "avx512f")] #[cfg(target_feature = "avx512bw")] mod test { usesuper::*; use core::arch::x86_64::__m256i;
#[test] fn empty_input() { let avx512 = unsafe { adler32_avx512(0, &[]) }; let rust = crate::adler32::generic::adler32_rust(0, &[]);
const INPUT: [u8; 128] = { letmut array = [0; 128]; letmut i = 0; while i < array.len() {
array[i] = i as u8;
i += 1;
}
array
};
#[test] fn start_alignment() { // SIMD algorithm is sensitive to alignment; for i in0..16 { for start in [crate::ADLER32_INITIAL_VALUE as u32, 42] { let avx512 = unsafe { adler32_avx512(start, &INPUT[i..]) }; let rust = crate::adler32::generic::adler32_rust(start, &INPUT[i..]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.