1 个不稳定版本
0.1.0 | 2021年6月23日 |
---|
#678 在 并发
140KB
2K SLoC
并发节点复制
CNR(并发节点复制)库是在常规NR(节点复制)库上的扩展。
与NR不同,该库用于实现一个NUMA感知的并发版本的数据结构。它通过结合三种技术:基于交换的工作分区、操作日志和扁平化合并,将并发实现扩展到多个核心和NUMA节点。
它是如何工作的
为了复制一个并发数据结构,需要实现(来自cnr的)Dispatch
和LogMapper
。 LogMapper
实现决定了并发执行中多个日志之间的工作分区。
LogMapper
实现用于将操作映射到日志。两个交换操作可以映射到同一个或不同的日志;然而,两个冲突的操作必须映射到同一个日志。例如,我们为CHashMap
实现Dispatch
,并为支持的操作实现LogMapper
。
/// The replicated hashmap uses a concurrent hashmap internally.
pub struct CNRHashMap {
storage: CHashMap<usize, usize>,
}
/// We support a mutable put operation on the hashmap.
#[derive(Debug, PartialEq, Clone)]
pub enum Modify {
Put(usize, usize),
}
/// This `LogMapper` implementation distributes the keys amoung multiple logs
/// in a round-robin fashion. One can change the implementation to improve the
/// data locality based on the data sturucture layout in the memory.
impl LogMapper for Modify {
fn hash(&self, _nlogs: usize, logs: &mut Vec<usize>) {
logs.clear();
match self {
Modify::Put(key, _val) => log.push(*key % nlogs),
}
}
}
/// We support an immutable read operation to lookup a key from the hashmap.
#[derive(Debug, PartialEq, Clone)]
pub enum Access {
Get(usize),
}
/// `Access` follows the same operation to log mapping as the `Modify`. This
/// ensures that the read and write operations for a particular key go to
/// the same log.
impl LogMapper for Access {
fn hash(&self, nlogs: usize, logs: &mut Vec<usize>) {
logs.clear();
match self {
Access::Get(key) => log.push(*key % nlogs),
}
}
}
/// The Dispatch traits executes `ReadOperation` (our Access enum)
/// and `WriteOperation` (our Modify enum) against the replicated
/// data-structure.
impl Dispatch for CNRHashMap {
type ReadOperation = Access;
type WriteOperation = Modify;
type Response = Option<usize>;
/// The `dispatch` function applies the immutable operations.
fn dispatch(&self, op: Self::ReadOperation) -> Self::Response {
match op {
Access::Get(key) => self.storage.get(&key).map(|v| *v),
}
}
/// The `dispatch_mut` function applies the mutable operations.
fn dispatch_mut(&self, op: Self::WriteOperation) -> Self::Response {
match op {
Modify::Put(key, value) => self.storage.insert(key, value),
}
}
}
完整示例(使用HashMap
作为底层数据结构)可以在这里找到。要运行,请执行:cargo run --example hashmap
编译库
由于使用了new_uninit
、get_mut_unchecked
和negative_impls
API,该库目前需要使用nightly rust编译器。库与no_std
兼容。
rustup toolchain install nightly
rustup default nightly
cargo build
作为你的Cargo.toml
中的依赖项
cnr = "*"
目前的代码应被视为早期版本,仍在开发中。在其当前形式下,该库仅在x86平台上已知可以工作(其他平台可能需要一些更改,且未经过测试)。
测试
实现中包含一系列单元测试和一些集成测试,这些测试使用堆栈检查实现的各个方面。
您可以通过执行以下命令来运行测试: cargo test
基准测试
基准测试(以及如何执行它们)在 benches 文件夹中解释得更加详细。
依赖项
~1.5MB
~38K SLoC