You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust/C中无循环快速提取掩码指定的二进制位?

无循环高效实现u64到u32的位提取

核心思路是利用硬件提供的并行位提取指令(如x86_64的PEXT)或编译器内置函数,这类操作能在极短周期内完成位提取,完全替代低效的循环或线性分解方案。

C语言实现

利用GCC/Clang的内置函数__builtin_pextll(对应x86_64的BMI2扩展指令PEXT),直接完成位提取:

#include <stdint.h>

// 从src中提取mask置位位置的位,返回压缩后的u32结果
uint32_t extract_bits(uint64_t src, uint64_t mask) {
    // __builtin_pextll会将src中mask为1的位置的位,按顺序压缩到结果的低位
    return (uint32_t)__builtin_pextll(src, mask);
}
  • 优势:PEXT指令为单周期操作,性能拉满;若目标平台不支持BMI2,编译器会自动生成优化后的无循环软件实现。

Rust语言实现

针对x86_64平台直接调用硬件指令,非x86平台提供编译器可优化的无循环 fallback:

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::_pext_u64;

/// 提取src中mask置位位置的位,返回压缩后的u32
#[cfg(target_arch = "x86_64")]
pub fn extract_bits(src: u64, mask: u64) -> u32 {
    // 安全调用PEXT硬件指令,编译时可加-C target-features=+bmi2强制启用BMI2扩展
    unsafe { _pext_u64(src, mask) as u32 }
}

/// 跨平台fallback,编译器会自动优化为无循环操作
#[cfg(not(target_arch = "x86_64"))]
pub fn extract_bits(src: u64, mask: u64) -> u32 {
    let mut result = 0u32;
    let mut src = src;
    let mut mask = mask;

    // 编译器会识别固定位数的掩码操作,将循环展开为无循环的位运算
    while mask != 0 {
        let lsb = mask & mask.wrapping_neg();
        let bit = (src & lsb) != 0;
        result = (result << 1) | bit as u32;
        mask ^= lsb;
        src &= !lsb;
    }

    result
}

原理说明

PEXT指令(Parallel Bit Extraction)是专门为位提取场景设计的硬件指令,它能一次性将源数据中掩码指定为1的所有位,按从低位到高位的顺序压缩到结果的连续低位中,完全无需循环操作,是当前性能最优的实现方式。

内容的提问来源于stack exchange,提问作者Antônio Leitão

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:43:03