簡體   English   中英

使用多個線程時程序較慢

[英]Program is slower when using multiple threads

我有一個簡單的程序,可以執行一些蒙特卡羅算法。 使用algorithmn的一次迭代沒有副作用,因此我應該能夠使用多個線程運行它。 所以這是我整個程序的相關部分,用C ++ 11編寫:

void task(unsigned int max_iter, std::vector<unsigned int> *results, std::vector<unsigned int>::iterator iterator) {
    for (unsigned int n = 0; n < max_iter; ++n) {
        nume::Album album(535);
        unsigned int steps = album.fill_up();
        *iterator = steps;
        ++iterator;
    }
}

void aufgabe2() {
    std::cout << "\nAufgabe 2\n";

    unsigned int max_iter = 10000;

    unsigned int thread_count = 4;

    std::vector<std::thread> threads(thread_count);
    std::vector<unsigned int> results(max_iter);

    std::cout << "Computing with " << thread_count << " threads" << std::endl;

    int i = 0;
    for (std::thread &thread: threads) {
        std::vector<unsigned int>::iterator start = results.begin() + max_iter/thread_count * i;
        thread = std::thread(task, max_iter/thread_count, &results, start);
        i++;
    }

    for (std::thread &thread: threads) {
        thread.join();
    }

    std::ofstream out;
    out.open("out-2a.csv");
    for (unsigned int count: results) {
        out << count << std::endl;
    }
    out.close();

    std::cout << "Siehe Plot" << std::endl;
}

令人費解的是,我添加的線程越多,速度越慢。 有4個線程,我得到這個:

real    0m5.691s
user    0m3.784s
sys     0m10.844s

而使用單個線程:

real    0m1.145s
user    0m0.816s
sys     0m0.320s

我意識到在CPU內核之間移動數據可能會增加開銷,但是應該在啟動時聲明vector ,而不是在中間修改。 在多核上,這有什么特別的原因要慢嗎?

我的系統是i5-2550M,它有4個內核(2 +超線程),我使用g ++(Ubuntu / Linaro 4.7.3-1ubuntu1)4.7.3

更新

我看到沒有使用線程(1),它會有很多用戶負載,而使用線程(2),它將擁有比用戶負載更多的內核:

10K運行:

http://wstaw.org/m/2013/05/08/stats3.png

100K運行:

http://wstaw.org/m/2013/05/08/Auswahl_001.png

目前的main.cpp

運行100K后,我得到以下結果:

完全沒有線程:

real    0m28.705s
user    0m28.468s
sys     0m0.112s

程序的每個部分的線程。 這些部分甚至不使用相同的內存,所以同一個容器的並發性也應該是。 但它需要更長的時間:

real    2m50.609s
user    2m45.664s
sys     4m35.772s

因此,盡管三個主要部分占用了我的CPU的300%,但它們需要6倍的時間。

通過1M運行,需要real 4m45才能完成。 我以前運行過1M,至少需要real 20m ,即使不是real 30m

在GitHub評估您當前的main.cpp。 除了上面提供的評論:

  1. 是的,rand()不是線程安全的,所以在運行多線程業務邏輯之前,可能需要預先用一些數組預先填充一些數組(這樣可以減少可能的鎖數)。 如果您計划進行一些堆活動(在多線程之前進行預分配或使用自定義每線程分配器),那么內存分配也是如此。
  2. 不要忘記其他過程。 如果計划在4個內核上使用4個線程,則意味着您將與其他軟件(至少是OS例程)競爭CPU資源。
  3. 文件輸出是一個很大的更衣室玩家。 你在每次循環迭代時做“<<”運算符並且它花了你很多(我記得我過去的一個有趣的案例:間接地修復一個多線程錯誤的日志輸出。因為通用記錄器是鎖驅動的,它是某種同步原語,請注意!)。
  4. 最后,沒有任何類型的保證,多線程應用程序可能比單線程更快。 有一堆特定於CPU,特定於環境的方面。

向量對象結果由創建的所有線程共享,因此即使你的問題是一個令人尷尬的並行,由於共享對象,還有一個爭論,更不用說緩存未命中(我不足以解釋現代架構上的緩存)。 可能你應該有n個線程的n個結果向量,最后合並結果。 我想這會加快速度。

另一個提示是盡可能使用std :: async而不是thread。 它處理線程分配和其他低級別的混亂。 我是從Scott Mayer的有效c ++ 11書中讀到的。 但是,通過使用線程,您可以將線程關聯設置為特定核心。 因此,如果您的處理器支持8個線程,您可以創建8個線程,並至少在Linux上為每個核心分配每個線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM