簡體   English   中英

C ++,如何在非並行任務中完全通過線程划分cpu工作

[英]C++, How to divide cpu work through threads exactly in non-parallel task

我正在嘗試制作一個質數計算器。

程序將n以下的每個數字除以n。 如果除法的其余部分僅是0次(除以1的除法),則該數字為質數。 在程序開始時,要求用戶鍵入一個數字,然后對每個數字進行計算,直到用戶鍵入一個數字為止。

這是一項非並行任務,但是我試圖通過在內核之間划分數字來使其並行。

這是一段在線程之間划分任務的代碼。

void division(int number)
{
    int ithread[8]{};
    int sum = 0;
    cout << "Preparation..";
    /* Calculating how many numbers the checker will check. */
    ithread[0] = (int)number*0.125;
    ithread[1] = (int)number*0.125;
    ithread[2] = (int)number*0.125;
    ithread[3] = (int)number*0.125;
    ithread[4] = (int)number*0.125;
    ithread[5] = (int)number*0.125;
    ithread[6] = (int)number*0.125;
    ithread[7] = (int)number*0.125;

    /* Calculating from what number the checkers will begin.
    the first thread will begin from 0. the second checker will begin from the last number the first                            
    did. The third will begin from the sum of numbers checked by first and second and so on. */

    thread thread0(noprint, ithread[0], 0);
    sum += ithread[0];
    thread thread1(noprint, ithread[1], sum);
    sum += ithread[1];
    thread thread2(noprint, ithread[2], sum);
    sum += ithread[2];
    thread thread3(noprint, ithread[3], sum);
    sum += ithread[3];
    thread thread4(noprint, ithread[4], sum);
    sum += ithread[4];
    thread thread5(noprint, ithread[5], sum);
    sum += ithread[5];
    thread thread6(noprint, ithread[6], sum);
    sum += ithread[6];
    thread thread7(noprint, ithread[7], sum);
    thread0.join();
    cout << "thread1";
    thread1.join();
    cout << "thread2";
    thread2.join();
    cout << "thread3";
    thread3.join();
    cout << "thread4";
    thread4.join();
    cout << "thread5";
    thread5.join();
    cout << "thread6";
    thread6.join();
    cout << "thread7";
    thread7.join();
    cout << "thread8";

}

問題是,某些線程先於其他線程結束,而對於大量線程而言,這可能是一個大問題。 舉例來說,要檢查的時間4恰好是2的兩倍,而8則是4的兩倍。因此,如果我要求程序檢查所有數字直到100萬,第一個線程將檢查從0到125000,對於當今的CPU來說,這是一個非常簡單的任務。 第二個將檢查從125000到250000,因此難度是原來的兩倍,依此類推。

現在,我正在尋找兩個答案:1.如果您知道,請告訴我如何在線程之間平均分配負載。 2.請說明如何進行,以便用戶能夠選擇線程數。 我已經想象過如何使最多64個線程的線程選擇成為可能(嗯,實際上甚至可以為1個trilion線程進行選擇,它只需要很多IF和1萬億個數字數組),問題就不在代碼中,這是數學本身。 我不知道如何將工作平均分配給8個核心,更不用說可變數量的核心了。

不要在一開始就一勞永逸地將工作分成幾部分-線程是不可預測的。 您無法控制操作系統將在每個內核上施加的其他負載,並且對於您來說似乎“相等”的工作負載實際上可能因代碼而有很大不同。 取而代之的是,將工作負載分成大量的更小的單元,並在每個線程完成前一個線程時從下一個線程開始,直到所有線程都完成為止。

至於讓用戶指定線程數,您到底堅持了什么? 詢問用戶一個數字,然后產生那么多線程似乎很簡單。 但是,大多數多線程程序都不這樣做。 最好查詢系統可以運行多少個線程(例如std::thread::hardware_concurrency )並使用它。

另外,要注意的是,您檢查質數的算法效率極低-大概這只是學習而不是認真的代碼? 如果不是這樣,您可能想看看其他算法-檢查素數是一個經過充分研究的問題。

但是JBentley,如果我喜歡你說的話,這些操作將不會同時進行。 是的,應用程序將使用不同的線程,但是在另一種方式中,這有什么意義呢? 只使用一個線程會不會一樣? 我很新,如果我錯了,抱歉。 –亞歷克斯

不,它仍然是並行的。 您有一個共享的數據結構,該結構跟蹤最后分配的工作塊。 這可能與包含最后檢查的數字的int一樣簡單。 線程用盡時,它將開始處理接下來的N個數字,並將int增加適當的數量。 在執行此操作時,需要注意多個線程不能同時使用共享變量-C ++或第三方庫中提供了多種機制來管理此變量。

偽代碼:

lastChecked = 1
thread 1: lock lastChecked
thread 1: lastChecked = 10
thread 1: unlock lastChecked
thread 1: start working on numbers 1 to 10
thread 2: lock lastChecked
thread 2: lastChecked = 20
thread 2: unlock lastChecked
thread 2: start working on numbers 11 to 20
thread 1: complete work
thread 1: lock lastChecked
thread 1 lastChecked = 30
thread 1: unlock lastChecked
thread 1: start working on numbers 21 to 30
// etc.

注意:您應該仔細選擇每個工作單元的大小。 使其過大,您將開始回到原來的問題,即某些線程的完成時間可能比其他線程晚很多。 將其設置得太小會增加線程在其他線程正在使用共享狀態時等待太多時間訪問共享狀態的風險,並且會花費太多時間分配每個工作負載。

在此網站上檢查pthreads庫

https://computing.llnl.gov/tutorials/pthreads/

查看有關上司-工人模型的部分。

http://www-01.ibm.com/software/network/dce/library/publications/appdev/html/APPDEV14.HTM#HDRWQ168

此線程模型可能非常適合您的問題。

檢查質數的一種方法是使用三個階段。 初始階段僅使用一個線程就生成了一個質數數組,最高可達某個值p。 下一階段使用數組檢查最大為p ^ 2(p平方)的質數,在線程之間從p到p ^ 2均勻划分范圍。 每個線程都會創建自己的新發現質數數組。 線程完成后,將數組連接到原始數組,並將p設置為找到的最高質數。 然后重復該循環直到p ^ 2> = n。 然后,最后階段使用數組檢查n是否為質數。

暫無
暫無

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

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