1个不稳定版本
0.1.0 | 2020年7月2日 |
---|
#353 in 压缩
185KB
3K SLoC
compressed_vec
浮点数和整数压缩向量库,支持SIMD,快速处理/遍历压缩表示。
[dependencies]
compressed_vec = "0.1"
这是一个压缩向量库,而不是压缩库。这意味着什么?一个压缩库会处理一些未压缩的数据,并提供基本的compress()和decompress()函数。通常你必须解压缩数据才能对其进行任何操作,这会导致额外的延迟和分配。
另一方面,这个压缩向量库允许你直接遍历和处理压缩表示。它旨在平衡快速遍历和SIMD处理/过滤,同时使用delta和XOR编码等技术将向量压缩到最佳列压缩技术(如Apache Parquet)的2倍以内。
- 数据库引擎
- 大型内存数据处理
- 需要快速访问大量FP向量/矩阵的游戏和其他应用程序
性能数据
以下数据来自我的笔记本电脑:2.9 GHz Core i9,6/12核心,12MB L3,AVX2;从运行cargo bench vector
获得,该命令直接在编码/压缩向量上运行filter-and-count-matches操作。
向量类型 | 元素/秒 | 原始GB/秒 |
---|---|---|
u32密集型(无稀疏性) | 1.7 Gelems/s | 6.8 GB/s |
u32稀疏型(99%为零) | 13.9 Gelems/s | 55.6 GB/s |
两个u32向量(稀疏型+密集型)* | 1.3-5.2 Gelems/s | 5-20 GB/s |
u64向量,密集型 | 955M - 1.1 Gelems/s | 7.6 - 9.1 GB/s |
f32,XOR编码,60%密度 | 985 Melems/s | 3.9 GB/s |
- 两个u32向量过滤速度(使用
MultiVectorFilter
)取决于向量的顺序。首先过滤稀疏向量会更快速。
创建,遍历
创建f32压缩向量的最简单方法
use compressed_vec::VectorF32XorAppender;
let mut appender = VectorF32XorAppender::try_new(2048).unwrap();
let encoded_bytes = appender.encode_all(vec![1.0, 1.5, 2.0, 2.5]).unwrap();
遍历此压缩向量的最简单方式(请注意,这不会进行任何分配)
use compressed_vec::VectorReader;
let reader = VectorReader::<f32>::try_new(&encoded_bytes[..]).unwrap();
let sum = reader.iterate().sum::<f32>(); // Yay, no allocations!
过滤和SIMD处理
iterate()
是遍历压缩向量单个元素的简单 API,但它不是最快的。如上例中的过滤和计数基准测试所示,快速数据处理使用的是 Sink
,这些在 sink
模块中定义。Sinks 每次操作一个 SIMD 单词,并且 sink API 被设计为内联。
例如,假设我们想将 2.5 添加到上面的 f32 向量中,然后将结果写入到 Vec<f32>
。内部,使用 (sink) 执行 XOR 编码和解码。在解码过程中可以堆叠 sinks,几乎实现完全的 SIMD 管道:- XorSink
(用于自动 f32 解码)- AddConstSink
(添加 2.5,同样使用 SIMD 完成)- VecSink
(将输出写入到常规 Vec)
use compressed_vec::{VectorReader, AddConstSink, VecSink};
let reader = VectorReader::<f32>::try_new(&encoded_bytes[..]).unwrap();
let mut vecsink = VecSink::<f32>::new();
let mut addsink = AddConstSink::new(2.5f32, &mut vecsink);
reader.decode_to_sink(&mut addsink).unwrap();
println!("And the transformed vector is: {:?}", vecsink.vec);
向量格式
向量格式的详细信息可以在这里找到:链接。
该向量格式遵循大数据和数据库领域中的列式压缩技术,大致遵循 Google Procella 论文中使用的自定义 Artus 格式。
- 在直接操作数据的情况下,压缩率在 2x 内与 ZSTD 相当
- 此格式的压缩率与 Parquet 相当,但允许过滤和直接操作数据,无需对整个向量进行单独的解压缩步骤
- 多遍编码
VectorAppender
收集原始数据的 min/max 和其他统计数据,并使用这些数据来决定最佳的编码策略(delta 等)。
- 将词典索引暴露给查询引擎,并积极将数据格式向下推送
- 该格式设计用于过滤词典代码,这加快了过滤速度
- 使用部分可以实现许多针对过滤的优化。例如,null 部分 和 常数部分 允许非常快速的过滤短路。
协作
请与我联系以进行协作!
依赖项
~3MB
~71K SLoC