Multithreading 大量生锈螺纹的性能下降

Multithreading 大量生锈螺纹的性能下降,multithreading,performance,rust,hashmap,lock-free,Multithreading,Performance,Rust,Hashmap,Lock Free,我正在Rust中创建一个无闩锁并发哈希映射。吞吐量曲线看起来和我预期的一样,最多可达16个线程,此时性能将下降 吞吐量MOps/sec vs.Num线程 我使用了一个有48个vCPU和200GB内存的Google云实例。我尝试启用/禁用超读功能,但没有明显效果 以下是我如何生成线程: for i in 0..num_threads { //clone the shared data structure let ht = Arc::clone(&ht); let

我正在Rust中创建一个无闩锁并发哈希映射。吞吐量曲线看起来和我预期的一样,最多可达16个线程,此时性能将下降

吞吐量MOps/sec vs.Num线程

我使用了一个有48个vCPU和200GB内存的Google云实例。我尝试启用/禁用超读功能,但没有明显效果

以下是我如何生成线程:

for i in 0..num_threads {
    //clone the shared data structure
    let ht = Arc::clone(&ht);

    let handle = thread::spawn(move || {
        for j in 0..adds_per_thread {
            //randomly generate and add a (key, value)
            let key = thread_rng().gen::<u32>();
            let value = thread_rng().gen::<u32>();
            ht.set_item(key, value);
        }
    });

    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}

我没有主意了;我的Rust代码适用于多线程吗

如果您的所有线程都将所有时间都花在无锁数据结构上,那么一旦您有足够的线程,您就会遇到争用。有了足够的写入程序,它们将更频繁地争夺表中的同一缓存线。此外,在PRNG中花费的时间可能不会隐藏对缓存或DRAM共享带宽的争夺

而不仅仅是一个平台,你可能会开始打更多的CAS重试和类似的东西,包括任何竞争退避机制。此外,线程将遭受缓存未命中,甚至一些原子读取;并非所有内容都是原子RMW或写入

这不是无锁数据结构的正常用例;通常情况下,您将它们与执行重要工作(而不是敲打它们)的代码一起使用,因此实际争用很低。此外,hashmap的实际工作负载很少是只写的,尽管如果您只是想消除重复数据,可能会发生这种情况


读可以很好地适应读卡器的数量,但写会引起争用。

如果所有线程都花时间在无锁数据结构上,那么一旦有足够的线程,您就会遇到争用。有了足够的写入程序,它们将更频繁地争夺表中的同一缓存线。此外,在PRNG中花费的时间可能不会隐藏对缓存或DRAM共享带宽的争夺

而不仅仅是一个平台,你可能会开始打更多的CAS重试和类似的东西,包括任何竞争退避机制。此外,线程将遭受缓存未命中,甚至一些原子读取;并非所有内容都是原子RMW或写入

这不是无锁数据结构的正常用例;通常情况下,您将它们与执行重要工作(而不是敲打它们)的代码一起使用,因此实际争用很低。此外,hashmap的实际工作负载很少是只写的,尽管如果您只是想消除重复数据,可能会发生这种情况


读可以很好地适应读卡器的数量,但写会引起争用。

无锁存?我想你的意思是无锁,除非你心里有一个我不知道的特定的技术含义。不管怎样,如果你所有的线程都把所有的时间都花在你的无锁数据结构上,是的,一旦你有足够多的线程使PRNG时间不再是一个因素,你就会产生争用,并且可能会开始进行更多的CAS重试之类的事情。这不是无锁数据结构的正常用例;通常你的代码除了敲打这些线程外,还做了其他重要的工作。我的Rust代码对多线程处理正确吗?是的,它启动多个线程并且不会产生内存不安全,所以看起来是正确的。如果这是回答而不是评论,你会接受吗?如果不是,请考虑查看你的帖子,看看你是否想问你想问的问题,如果你在帖子里提供了足够的信息来回答它。我看不到你的HASMAP代码,所以Pyf的设计分析是不可能的。除非这是一个标准的库实现?我对Rust一点也不了解,也许我在你的代码中遗漏了一些东西,这些东西显示了你正在使用哪个HashMap。@PeterCordes不,Rust在标准库中不提供无锁实现。OP还声明我正在创建,我认为这意味着他们正在从头开始编写代码。代码确实提供了任何有用的信息;甚至不清楚线程是如何生成的,因为没有显示导入。@PeterCordes谢谢,我想这就是我一直在寻找的答案。我这样做是作为一个研究项目的一部分,所以现在我的基准有点做作。我可以编辑,以包括实际的数据结构本身,但它基本上是一个锈口的C++实现,是研究良好。我想你的意思是无锁,除非你心里有一个我不知道的特定的技术含义。不管怎样,如果你所有的线程都把所有的时间都花在你的无锁数据结构上,是的,一旦你有足够多的线程使PRNG时间不再是一个因素,你就会产生争用,并且可能会开始进行更多的CAS重试之类的事情。这不是无锁数据结构的正常用例;通常你的代码除了敲打这些线程外,还做了其他重要的工作。我的Rust代码对多线程处理正确吗?是的,它启动多个线程并且不会产生内存不安全,所以看起来是正确的。如果这是回答而不是评论,你会接受吗?如果没有,请考虑检查你的帖子,看看是否Y
你问的是你想问的问题,以及你是否在帖子中提供了足够的信息来回答。我没有看到你的hashmap的代码,因此无法对其设计进行性能分析。除非这是一个标准的库实现?我对Rust一点也不了解,也许我在你的代码中遗漏了一些东西,这些东西显示了你正在使用哪个HashMap。@PeterCordes不,Rust在标准库中不提供无锁实现。OP还声明我正在创建,我认为这意味着他们正在从头开始编写代码。代码确实提供了任何有用的信息;甚至不清楚线程是如何生成的,因为没有显示导入。@PeterCordes谢谢,我想这就是我一直在寻找的答案。我这样做是作为一个研究项目的一部分,所以现在我的基准有点做作。我可以编辑,以包括实际的数据结构本身,但它基本上是一个锈口的C++实现,这是很好的研究。