AVX512下64个8位元素1位移位(补0无丢失)的实现方案问询
AVX512实现64个8位元素的序列移位(补0)
需求:将包含64个8位元素的序列[1, 2, 3, ..., 64]转换为[0, 1, 2, ..., 63],本质是将序列整体向右移动一个元素位置,左侧补0(或理解为元素级左移后丢弃最后一个元素,左侧补0)。
AVX2指令集中的字节移位指令仅支持16位(2字节)倍数的移位,因此需要掩码、置换和合并操作间接实现单字节移位;而AVX512提供了灵活的单字节粒度移位指令,可更高效完成需求。
方案一:直接使用AVX512字节右移指令
这是最高效的实现方式,利用_mm512_bsrli_epi512指令将整个512位寄存器右移1字节(8位),空出的高位自动补0,完全匹配需求。
#include <immintrin.h> __m512i shift_64_u8_elements(__m512i src) { // src 输入:包含64个8位元素,值为1~64 // 返回:[0, 1, 2, ..., 63] return _mm512_bsrli_epi512(src, 1); }
指令说明
_mm512_bsrli_epi512:将512位寄存器按位右移imm8 * 8位,空出的高位填充0。此处imm8=1,即右移8位(1字节),原序列的每个元素向右移动一个位置,第一个位置补0,直接得到目标结果。
方案二:置换掩码实现(兼容复杂移位场景)
如果需要更灵活的元素重排(比如非连续移位),可以通过构造索引表指定输出元素的来源,再用掩码控制第一个元素为0。
#include <immintrin.h> __m512i shift_64_u8_elements_permute(__m512i src) { // 构造置换索引:输出第i个元素(i>=1)对应输入的第i-1个元素 const __m512i perm_indices = _mm512_setr_epi8( 0x00, // 该位置会被掩码覆盖为0,索引值无关 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F ); // 掩码:仅第一个元素位置设为0,其余保留置换结果 const __mmask64 mask = 0xFFFFFFFFFFFFFFFE; // 初始值设为全0,掩码控制第一个元素取初始值0,其余取置换后的输入元素 return _mm512_mask_permutevar_epi8(_mm512_setzero_epi8(), mask, perm_indices, src); }
说明
perm_indices:定义输出元素到输入元素的映射关系,第i个输出元素(i≥1)对应输入的第i-1个元素。mask:二进制表示为第0位为0,其余位为1,确保第一个元素使用初始的0值,其余元素使用置换后的结果。
内容的提问来源于stack exchange,提问作者SmokeyMcPot
相关产品推荐
相关产品推荐

