现代化、跨平台、基于 SIMD 指令集加速的高性能 C++17 位运算库
English | 简体中文
BitCal 是一个现代化的 C++17 纯头文件位运算库,提供高性能位操作功能并支持自动 SIMD 加速。通过 if constexpr 实现编译期分派,BitCal 相比标量实现可提供高达 6 倍的性能提升,同时保持零运行时开销。
#include <bitcal/bitcal.hpp>
int main() {
bitcal::bit256 a(0xDEADBEEF);
bitcal::bit256 b(0xCAFEBABE);
auto c = a & b; // SIMD 加速的与运算(~2.1ns)
auto pop = c.popcount(); // 硬件 popcount
return 0;
}| 特性 | 描述 | 性能影响 |
|---|---|---|
| 🚀 SIMD 加速 | 自动选择 SSE2/AVX2 (x86) 或 NEON (ARM) | 最高快 6 倍 |
| ⚡ 零开销 | 通过 if constexpr 编译期分派 |
无运行时成本 |
| 📦 纯头文件 | 单个 #include <bitcal/bitcal.hpp> |
零依赖 |
| 🔧 丰富的 API | 位运算、位移、popcount、CLZ/CTZ、位反转、ANDNOT | 生产就绪 |
| 🌍 跨平台 | Linux、Windows、macOS,支持 x86-64 和 ARM | 通用支持 |
| 🏎️ 类型安全 | 编译期位宽验证(Bits % 64 == 0) |
尽早捕获错误 |
# 克隆仓库
git clone https://github.com/LessUp/bitcal.git
# 复制头文件到项目(纯头文件)
cp -r bitcal/include/bitcal /path/to/your/project/include/include(FetchContent)
FetchContent_Declare(
bitcal
GIT_REPOSITORY https://github.com/LessUp/bitcal.git
GIT_TAG v2.1.0
)
FetchContent_MakeAvailable(bitcal)
target_link_libraries(your_target PRIVATE bitcal::bitcal)# 克隆并安装
git clone https://github.com/LessUp/bitcal.git
cd bitcal
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build .
cmake --install .然后在你的 CMakeLists.txt 中:
find_package(bitcal REQUIRED)
target_link_libraries(your_target PRIVATE bitcal::bitcal)g++ -std=c++17 -O3 -march=native your_program.cpp -o your_program💡 提示: 使用
-march=native启用 CPU 支持的所有 SIMD 指令。
#include <bitcal/bitcal.hpp>
#include <iostream>
int main() {
// 创建不同位宽的位数组
bitcal::bit256 a(0xFF00FF00FF00FF00);
bitcal::bit256 b(0x0FF00FF00FF00FF0);
// 位运算(自动 SIMD 加速)
auto c = a & b; // 与
auto d = a | b; // 或
auto e = a ^ b; // 异或
auto f = ~a; // 非(SIMD 加速)
auto g = a.andnot(b); // a & ~b(比分步操作快约 2 倍)
// 复合赋值
a &= b; // 与并赋值
b |= a; // 或并赋值
// 位移
a <<= 10; // 左移
b >>= 5; // 右移
// 位计数操作
uint64_t ones = a.popcount();
int lz = a.count_leading_zeros(); // 前导零计数
int tz = a.count_trailing_zeros(); // 尾随零计数
// 单比特操作
a.set_bit(42, true); // 设置第 42 位
bool bit = a.get_bit(42); // 读取第 42 位
a.flip_bit(42); // 翻转第 42 位
// 位操作
a.reverse(); // 位反转
a.clear(); // 清零
// 直接访问原始数据(用于与 C API 互操作)
uint64_t* data = a.data(); // 64 字节对齐的指针
uint64_t word = a[0]; // 访问第一个 64 位字
// 比较
if (a == b) { /* ... */ }
if (a != b) { /* ... */ }
if (a.is_zero()) { /* 所有位均为零 */ }
std::cout << "Popcount: " << ones << std::endl;
return 0;
}| 类型 | 位宽 | 字数 | 最佳用途 |
|---|---|---|---|
bitcal::bit64 |
64 位 | 1 | 机器字操作 |
bitcal::bit128 |
128 位 | 2 | SSE2/NEON 原生位宽 |
bitcal::bit256 |
256 位 | 4 | AVX2 原生位宽 |
bitcal::bit512 |
512 位 | 8 | 大位宽并行运算 |
bitcal::bit1024 |
1024 位 | 16 | 超大位宽并行运算 |
自定义位宽(64 的倍数):
bitcal::bitarray<2048> custom;bitcal::bit256 a; // 初始化为零
bitcal::bit256 b(0xDEADBEEF); // 设置低 64 位
bitcal::bit256 c = b; // 拷贝a & b // 与运算 a &= b // 与运算并赋值
a | b // 或运算 a |= b // 或运算并赋值
a ^ b // 异或 a ^= b // 异或并赋值
~a // 非运算
a.andnot(b) // 优化的 a & ~ba << n // 左移 a <<= n // 左移并赋值
a >> n // 右移 a >>= n // 右移并赋值a.popcount() // 统计置位数量
a.count_leading_zeros() // 前导零计数
a.count_trailing_zeros() // 尾随零计数a.get_bit(index) // 读取位(从 LSB 开始 0 索引)
a.set_bit(index, value) // 设置/清零位
a.flip_bit(index) // 翻转位a.is_zero() // 检查是否全为零
a.clear() // 清零
a == b // 相等比较
a != b // 不等比较a.data() // 64 位字数组指针
a[index] // 访问第 index 个 64 位字
a.bits // 编译期位宽常量
a.u64_count // 64 位字数量(编译期常量)a.reverse() // 位序反转bitcal::bitarray<256, bitcal::simd_backend::avx512> force_avx512;
bitcal::bitarray<256, bitcal::simd_backend::avx2> force_avx2;
bitcal::bitarray<256, bitcal::simd_backend::sse2> force_sse2;
bitcal::bitarray<256, bitcal::simd_backend::neon> force_neon;
bitcal::bitarray<256, bitcal::simd_backend::scalar> force_scalar;BitCal 在需要高性能位操作的场景中表现出色:
| 使用场景 | 描述 | 优势 |
|---|---|---|
| 位集合 | 压缩布尔存储 | 相比 bool[] 空间减少 64 倍 |
| 布隆过滤器 | 概率数据结构 | SIMD 加速哈希混合 |
| 网络掩码 | CIDR/子网计算 | 大掩码快速与或操作 |
| 密码学 | 分组密码位运算 | 硬件 popcount 用于汉明距离 |
| 数据压缩 | 位打包/解包 | 高效跨字位移 |
| 图形处理 | 掩码操作 | 像素掩码并行处理 |
查看 examples/ 获取具体实现。
// 示例:快速 CIDR 掩码生成
bitcal::bit256 make_mask(int prefix_len) {
if (prefix_len <= 0) return bitcal::bit256(0);
if (prefix_len >= 256) return ~bitcal::bit256(0);
// 计算完整字和剩余位
int whole_words = prefix_len / 64;
int remain_bits = prefix_len % 64;
bitcal::bit256 mask;
uint64_t* data = mask.data();
// 填充完整的字为全1
for (int i = 0; i < whole_words; ++i) {
data[3 - i] = UINT64_MAX; // CIDR 使用大端字序
}
// 在下一个字中设置剩余位
if (remain_bits > 0) {
data[3 - whole_words] = UINT64_MAX << (64 - remain_bits);
}
// 清空剩余的字
for (int i = whole_words + (remain_bits > 0 ? 1 : 0); i < 4; ++i) {
data[3 - i] = 0;
}
return mask;
}为获得最佳性能,使用以下编译器选项:
# GCC/Clang
g++ -std=c++17 -O3 -march=native -DNDEBUG
# MSVC
cl /std:c++17 /O2 /arch:AVX2 /DNDEBUG| 选项 | 作用 |
|---|---|
-O3 |
最大优化级别 |
-march=native |
启用所有 CPU 特性 |
-DNDEBUG |
发布模式移除断言 |
| 运算 | 标量 | AVX2 | 加速比 |
|---|---|---|---|
| 与运算-256 | 12.3 ns | 2.1 ns | 5.9× |
| 异或运算-512 | 24.8 ns | 4.3 ns | 5.8× |
| 左移-256 | 18.6 ns | 5.2 ns | 3.6× |
| 人口计数-512 | 45.2 ns | 22.3 ns | 2.0× |
| is_zero-256 | 4.5 ns | 1.8 ns | 2.5× |
| 运算 | 标量 | NEON | 加速比 |
|---|---|---|---|
| 与运算-128 | 8.4 ns | 3.2 ns | 2.6× |
| 异或运算-256 | 16.9 ns | 6.8 ns | 2.5× |
| 左移-128 | 12.3 ns | 6.8 ns | 1.8× |
📈 在你的环境中运行
./benchmarks/bench_bitcal查看实际数据。
BitCal 根据编译器选项自动选择最佳后端:
| 平台 | 后端 | 位宽 | 触发条件 | 状态 |
|---|---|---|---|---|
| x86-64 | AVX-512 | 512 位 | -mavx512f 可用 |
部分支持 |
| x86-64 | AVX2 | 256 位 | -mavx2 可用 |
完全支持 |
| x86-64 | AVX | 256 位 | -mavx 可用 |
完全支持 |
| x86-64 | SSE2 | 128 位 | -msse2 可用 |
完全支持 |
| ARM | NEON | 128 位 | ARMv7-A+ 或 ARM64 | 完全支持 |
| 任意 | 标量 | 64 位 | 回退方案 | 完全支持 |
注意: AVX-512 目前为部分支持。核心运算(与、或、异或、非)使用 AVX-512,其他运算回退至 AVX2。
| 主题 | 描述 |
|---|---|
| 类型 | bitarray 模板和类型别名 |
| 核心运算 | 与、或、异或、非、ANDNOT |
| 位移操作 | 左移和右移 |
| 位计数 | popcount、CLZ、CTZ |
| 位操作 | 获取/设置/翻转位、反转 |
| SIMD 后端 | 后端选择 |
| Ops 命名空间 | 底层 API |
| 方面 | 保证 | 说明 |
|---|---|---|
| 异常安全 | 所有热路径操作均为 noexcept |
位操作不抛出异常 |
| 边界检查 | 仅在调试构建中使用 assert() |
发布构建使用 NDEBUG |
| 线程安全 | 线程兼容 | 不同实例:✅ 安全 同实例只读:✅ 安全 同实例读写:❌ 需要同步 |
| 内存安全 | 64 字节对齐,无堆分配 | 纯栈分配,缓存行友好 |
完整文档:https://lessup.github.io/bitcal/
| 平台 | 架构 | 编译器 | SIMD | CI 状态 |
|---|---|---|---|---|
| Linux | x86-64 | GCC 7+, Clang 6+ | SSE2/AVX2 | ✅ 已验证 |
| Linux | ARM64 | GCC(交叉编译) | NEON | ✅ 已验证 |
| Linux | ARM32 | GCC(交叉编译) | NEON | ✅ 已验证 |
| Windows | x86-64 | MSVC 2017+ | SSE2/AVX2 | ✅ 已验证 |
| macOS | x86-64 | Apple Clang | SSE2/AVX2 | ✅ 已验证 |
| macOS | ARM64 (Apple Silicon) | Apple Clang | NEON | ✅ 已验证 |
- C++17 或更高版本
- CMake 3.16+(仅用于构建测试/基准测试)
- 支持的编译器:GCC 7+, Clang 6+, MSVC 2017+
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
# 运行测试
./tests/test_bitcal
# 运行基准测试
./benchmarks/bench_bitcalcmake --install . --prefix /usr/localbitcal/
├── include/bitcal/ # 头文件(纯头文件库)
│ ├── bitcal.hpp # 主头文件(包含这个)
│ ├── config.hpp # 平台检测
│ ├── simd_traits.hpp # SIMD 类型特征
│ ├── scalar_ops.hpp # 标量回退实现
│ ├── sse_ops.hpp # SSE2 实现
│ ├── avx_ops.hpp # AVX2 实现
│ ├── avx512_ops.hpp # AVX-512 支持
│ └── neon_ops.hpp # NEON 实现
├── docs/ # 文档
│ ├── en/ # 英文文档
│ └── zh/ # 中文文档
├── tests/ # 单元测试
├── benchmarks/ # 性能基准测试
└── examples/ # 示例程序
bitarray<256> 内存布局:
┌──────────────────────────────────────────────────────────┐
│ 对齐 (64字节) │ 字 0 │ 字 1 │ 字 2 │ 字 3 │ 填充至 64B │
│ 64 字节 │ 0-63 │64-127│128-191│192-255│ │
└──────────────────────────────────────────────────────────┘
- 对齐方式: 64 字节(缓存行对齐)
- 字节序: 小端(LSB 在
data()[0]) - 存储: 连续的
uint64_t数组
详见 CHANGELOG.zh-CN.md 了解版本历史。
- ✨ 新增: 原生 SIMD 指令的 ANDNOT 运算
- ⚡ 性能:
is_zero()提速最高 2.3×,~提速 1.7× - 🧪 测试: bit1024 完整测试覆盖
- 🔧 基础设施: ARM32 CI 支持
欢迎贡献!请参阅 CONTRIBUTING.md 了解贡献指南。
MIT 许可证 — 详见 LICENSE。
- 设计灵感来源于 Boost.SIMD 和 xsimd
- 性能测试使用 Google Benchmark
⭐ GitHub 星标 • 🐛 提交问题 • 💬 讨论区