2017-06-19 24 views
-1

我是Rust的新手,我想用併發來總結大量的數字。我發現這個代碼:如何總結使用Rust的併發性從1到1000000?

use std::thread; 
use std::sync::{Arc, Mutex}; 

static NTHREAD: usize = 10; 

fn main() { 
    let mut threads = Vec::new(); 

    let x = 0; 

    // A thread-safe, sharable mutex object 
    let data = Arc::new(Mutex::new(x)); 

    for i in 1..(NTHREAD+1) { 
     // Increment the count of the mutex 
     let mutex = data.clone(); 

     threads.push(thread::spawn(move || { 
      // Lock the mutex 
      let n = mutex.lock(); 

      match n { 
       Ok(mut n) => *n += i, 
       Err(str) => println!("{}", str) 
      } 
     })); 
    } 

    // Wait all threads ending 
    for thread in threads { 
     let _ = thread.join().unwrap(); 
    } 

    assert_eq!(*data.lock().unwrap(), 55); 
} 

這工作時,線程是10,但是當線程大於20

我認爲它應該在任意數量的線程被罰款不起作用。

我誤解了什麼嗎?有沒有另外一種方法總結1到1000000的併發性?

+1

爲了您的具體的例子,如果你有4個線程,只是總結'1..250k','250k..500k'等,每個線程然後總結線程函數的返回。你必須記住,每個並行計算案例都是獨一無二的,一切都取決於你的問題。 – Boiethios

+3

「,但當線程大於20時不工作」當你有超過20個線程時會發生什麼?這些細節不值得省略。 –

+2

我認爲OP說他不能在桌面電腦中產生1M線程。 – Boiethios

回答

3

提供的代碼有幾個問題。

  1. thread::spawn創建一個OS級的線程,這意味着現有的代碼不可能擴展到數多達一百萬如標題所示。這需要100萬個並行線程,典型的現代操作系統最多支持幾千個線程。更多受限制的環境,如嵌入式系統或虛擬/半虛擬機,可以比這少得多;例如,Rust playground似乎最多允許24個併發線程。相反,人們需要創建一個固定的少量線程,並仔細地將工作分配給它們。
  2. 在每個線程中執行的函數在一個鎖內運行,從而有效地序列化線程完成的工作。即使可以生成任意多個線程,循環寫入的執行速度也不會快於單個線程所能達到的速度 - 實際上,它會慢幾個數量級,因爲它會花費大量的時間來鎖定/解鎖一個嚴重爭用的互斥體。

接近這樣那樣的問題,同時還管理線程手動在comment by Boiethios提供的一個很好的方法:如果你有4個線程,只是總結1..250k,250k..500k等,每個線程然後總結線程函數的返回。

或者還有另一種方法來總結從1到1000000併發?

我會推薦使用一個更高級別的庫,它封裝了工作線程的創建/合併和工作分工。 Rayon是一個很好的例子,它提供了一個「並行迭代」工具,它可以像迭代一樣工作,但會自動將工作分配給多個內核。用人造絲,整數的並行加法是這樣的:

extern crate rayon; 

use rayon::prelude::*; 

fn main() { 
    let sum: usize = (1..1000001).collect::<Vec<_>>().par_iter().sum(); 
    assert_eq!(sum, 500000500000); 
} 
+0

遊樂場在Docker容器內執行代碼,但我認爲線程數沒有任何附加限制。你怎麼測試到24? – Shepmaster

+0

爲了指出這個問題的愚蠢性,將數字範圍從0到n加和的* correct *方法是sum(n)=(n *(n + 1))/ 2'。 – Shepmaster

+0

@Shepmaster我測試了將OP的代碼複製粘貼到操場中,並且對'unwrap()'的最小線程數進行了二進制搜索,結果與資源相關的錯誤消息失敗。在我的測試中,它有23個附加線程失敗,這導致我得出總共24個線程被允許在VM中的結論。 – user4815162342

相關問題