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

寻求模拟x86 PDEP/PEXT指令的快速软件回退算法

PDEP/PEXT的O(log n)回退实现优化

问题背景

需要为x86指令集的PDEP(并行位存入)和PEXT(并行位提取)创建封装,在不支持这些指令及对应内在函数的架构上,需要高效的回退实现。现有32位整数的朴素算法时间复杂度为O(n),希望找到O(log n)的优化方案。

现有朴素实现

Bit Deposit(对应PDEP)

constexpr std::uint32_t bit_deposit(std::uint32_t src, std::uint32_t mask) {
    std::uint32_t result = 0;
    for (std::uint32_t src_pos = 0, mask_pos = 0; mask_pos != 32; ++mask_pos) {
        if (mask >> mask_pos & 1) {
            result |= (src >> src_pos++ & 1) << mask_pos;
        }
    }
    return result;
}

static_assert(bit_deposit(0b000, 0b000000) == 0b000000);
static_assert(bit_deposit(0b101, 0b101010) == 0b100010);
static_assert(bit_deposit(0b111, 0b101010) == 0b101010);

Bit Extract(对应PEXT)

constexpr std::uint32_t bit_extract(std::uint32_t src, std::uint32_t mask) {
    std::uint32_t result = 0;
    for (std::uint32_t src_pos = 0, mask_pos = 0; mask_pos != 32; ++mask_pos) {
        if (mask >> mask_pos & 1) {
            result |= (src >> mask_pos & 1) << src_pos++;
        }
    }
    return result;
}

static_assert(bit_extract(0b000000, 0b000000) == 0b000);
static_assert(bit_extract(0b100010, 0b101010) == 0b101);
static_assert(bit_extract(0b101010, 0b101010) == 0b111);

O(log n)优化实现

Bit Deposit(PDEP)优化版

constexpr std::uint32_t bit_deposit_fast(std::uint32_t src, std::uint32_t mask) {
    std::uint32_t result = src;
    std::uint32_t temp;

    // 分治处理,每次合并相邻位段
    temp = mask ^ (mask << 1);
    temp &= ~(mask << 1);
    result = (result & temp) | ((result & ~temp) << 1);

    temp = mask ^ (mask << 2);
    temp &= ~(mask << 2);
    result = (result & temp) | ((result & ~temp) << 2);

    temp = mask ^ (mask << 4);
    temp &= ~(mask << 4);
    result = (result & temp) | ((result & ~temp) << 4);

    temp = mask ^ (mask << 8);
    temp &= ~(mask << 8);
    result = (result & temp) | ((result & ~temp) << 8);

    temp = mask ^ (mask << 16);
    temp &= ~(mask << 16);
    result = (result & temp) | ((result & ~temp) << 16);

    return result & mask;
}

// 验证与朴素实现结果一致
static_assert(bit_deposit_fast(0b000, 0b000000) == bit_deposit(0b000, 0b000000));
static_assert(bit_deposit_fast(0b101, 0b101010) == bit_deposit(0b101, 0b101010));
static_assert(bit_deposit_fast(0b111, 0b101010) == bit_deposit(0b111, 0b101010));

Bit Extract(PEXT)优化版

constexpr std::uint32_t bit_extract_fast(std::uint32_t src, std::uint32_t mask) {
    std::uint32_t result = src & mask;
    std::uint32_t temp;

    // 分治处理,每次压缩相邻位段
    temp = mask ^ (mask >> 1);
    temp &= mask >> 1;
    result = (result & temp) | ((result & ~temp) >> 1);

    temp = mask ^ (mask >> 2);
    temp &= mask >> 2;
    result = (result & temp) | ((result & ~temp) >> 2);

    temp = mask ^ (mask >> 4);
    temp &= mask >> 4;
    result = (result & temp) | ((result & ~temp) >> 4);

    temp = mask ^ (mask >> 8);
    temp &= mask >> 8;
    result = (result & temp) | ((result & ~temp) >> 8);

    temp = mask ^ (mask >> 16);
    temp &= mask >> 16;
    result = (result & temp) | ((result & ~temp) >> 16);

    return result;
}

// 验证与朴素实现结果一致
static_assert(bit_extract_fast(0b000000, 0b000000) == bit_extract(0b000000, 0b000000));
static_assert(bit_extract_fast(0b100010, 0b101010) == bit_extract(0b100010, 0b101010));
static_assert(bit_extract_fast(0b101010, 0b101010) == bit_extract(0b101010, 0b101010));

优化思路说明

这种实现采用分治法,通过5轮固定操作(对应32位的log₂(32)=5)完成位处理:

  • 对于bit_deposit_fast:每一轮将未被mask覆盖的位段向右移动,逐步把src的位填充到mask标记的位置上,最后通过& mask确保只保留mask指定的位。
  • 对于bit_extract_fast:每一轮将mask标记的位段向左压缩,把分散在mask位置上的位集中到结果的低位,最终得到连续的提取结果。

每一轮操作都是O(1)的位运算,整体时间复杂度为O(log n),相比朴素的O(n)循环,在32位场景下仅需5步,性能提升显著,且保持了constexpr特性,可在编译期计算。

内容的提问来源于stack exchange,提问作者Jan Schultke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:44:53