Rust gets the true byte index in the SIMD vector

I want to compare two vectors of 16 bytes and get each corresponding index. A small example illustrating what I want:

fn get_matching_idx(arr1: &[u8], arr2: &[u8]) {
    let vec1 = u8x16::load_aligned(arr1);    
    let vec2 = u8x16::load_aligned(arr2);
    let matches = vec1.eq(vec2);
    for i in 0..16 {
        if matches.extract_unchecked(i) {
            // Do something with the index
        }
    }
}

Ideally, I would just like to "Do something" for given indices, rather than checking each of them (there will be a small number of matches).

Is there a way to get matching indexes using intrinsics rather than iterating over the whole vector? For example, with gcc, I could use _mm_movemask_epi8 to pack the vector bit, and then repeat the applications __builtin_clzto get the index of the bits of the first set (which is more efficient for the sparse numbers that I would have). Alternatively, I could have a lookup table that did the right thing for every nibble in my bit integer (like the first answer here ).

Is there an equivalent of these instructions in rust?

I am compiling for an Intel x86-64 processor and cross-platform support is not a requirement.

. () , . - FFI .

+4
1

std::arch . core::arch std::simd :

use std::arch::x86_64::{self, __m128i};
use std::simd::{u8x16, FromBits};

unsafe fn get_matching_idx(arr1: &[u8], arr2: &[u8]) -> u32 {
    let vec1 = __m128i::from_bits(u8x16::load_aligned_unchecked(arr1));
    let vec2 = __m128i::from_bits(u8x16::load_aligned_unchecked(arr2));
    return x86_64::_mm_movemask_epi8(x86_64::_mm_cmpeq_epi8(vec1, vec2)) as u32;
}

fn main() {
    // let arr1 = ...
    // let arr2 = ...

    unsafe {
        let mut mask = get_matching_idx(arr1, arr2);
    }
    let mut delta_i = 0;
    // This assumes a little endian machine (note it counts trailing 0s)
    while group_mask > 0 {
        let tz = x86_64::_mm_tzcnt_32(mask);
        let i = tz + delta_i;
        // Do something...
        group_mask >>= tz + 1;
        delta_i += tz + 1;
    }
}
+1

Source: https://habr.com/ru/post/1696029/


All Articles