Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Rust中带多线程的并行字计数_Multithreading_Rust - Fatal编程技术网

Multithreading Rust中带多线程的并行字计数

Multithreading Rust中带多线程的并行字计数,multithreading,rust,Multithreading,Rust,我想计算一个大字符串中单词的频率 简单的单线程解决方案如下所示 use hashbrown::HashMap; fn main() { let buffer = String::from("Hello World Hello Rust"); let mut frequency: HashMap<&str, u32> = HashMap::new(); for word in buffer.split_whitespace() { *

我想计算一个大字符串中单词的频率

简单的单线程解决方案如下所示

use hashbrown::HashMap;

fn main() {
    let buffer = String::from("Hello World Hello Rust");
    let mut frequency: HashMap<&str, u32> = HashMap::new();

    for word in buffer.split_whitespace() {
        *frequency.entry(word).or_insert(0) += 1;
    }
}

为了简化代码,我删除了字符串分块,并且在for循环中只生成了1个线程。

作用域线程允许您借用线程外部的内容,并在线程内部使用它。他们不能允许你做相反的事情,从线里面借东西,让它逃走

split_whitespace借用buffer,buffer已移动到内部闭包中,因此属于当前线程。每个字都是一个引用,其生存期依赖于缓冲区,当线程退出时,缓冲区将超出范围。底层字符串不会被销毁,但word只能从Arc借用,因为Arc的生存期较短。如果你只是克隆了一个字符串,同样的事情也会发生

圆弧螺纹和作用域螺纹有些不一致。Arc用于在线程之间共享某个对象,并且希望在最后一个线程退出时销毁该对象。您通常不知道或不关心哪个线程是破坏它的线程,只知道它被破坏了。另一方面,当您确实知道应该销毁某个对象的位置时,就会使用作用域线程,所有希望访问该对象的线程都必须在销毁之前退出。由于使用作用域线程静态验证生命期,因此可以使用普通&引用而不是Arc。这适用于字符串和互斥体

让我们应用这个:

let buffer = String::from("Hello World Hello Rust");
let frequency: Mutex<HashMap<&str, u32>> = Mutex::new(HashMap::new());

crossbeam::scope(|scope| {
    for _ in 0..1 {
        scope.spawn(|_| {
            for word in buffer.split_whitespace() {
                let mut frequency = frequency.lock().unwrap();
                *frequency.entry(word).or_insert(0) += 1;
            }
        });
    }
});
哦,那很容易。注意,并没有移动,并没有弧,也并没有克隆,频率将包含对缓冲区的引用,这大概是你们想要的。为了使这一点起作用,您使用的任何字符串组块方法都必须借用原始str;每个线程不能有单独的字符串

警告 我不确定您的示例与原始代码到底有多相似。上述解决方案解决了编译问题,但正如Shepmaster所指出的:


我要补充的是,最初的算法不是很有效,因为HashMap的争用量将达到极限。对于每个线程来说,拥有自己的HashMap并在最后合并它们可能会更有效。[……]

另见
如果您使用的是横梁,为什么您的输入字符串呈弧形?为什么要特意使用hashbrown?这里的问题是并行化根本帮不了你,因为线程需要独占地拥有字符串。不能同时对同一字符串上的多个线程进行操作。你必须事先把它分开。你的例子没有得到很好的考虑。我要补充的是,最初的算法不是很有效,因为HashMap的争用量将是极端的。对于每个线程来说,拥有自己的HashMap并在最后合并它们可能会更有效。另见
let buffer = String::from("Hello World Hello Rust");
let frequency: Mutex<HashMap<&str, u32>> = Mutex::new(HashMap::new());

crossbeam::scope(|scope| {
    for _ in 0..1 {
        scope.spawn(|_| {
            for word in buffer.split_whitespace() {
                let mut frequency = frequency.lock().unwrap();
                *frequency.entry(word).or_insert(0) += 1;
            }
        });
    }
});