0

假設您想要5個線程同時處理數據。還假設,你有89個任務要處理。編程邏輯 - 拆分線程之間的任務

離開蝙蝠你知道89/5 = 17其餘爲4.分離任務的最好方法是讓4個(餘數)線程處理每個18(17 + 1)個任務,然後有1個(#線程 - 餘數)線程處理17.

這將消除其餘部分。只是爲了驗證:

Thread 1: Tasks 1-18 (18 tasks) 
Thread 2: Tasks 19-36 (18 tasks) 
Thread 3: Tasks 37-54 (18 tasks) 
Thread 4: Tasks 55-72 (18 tasks) 
Thread 5: Tasks 73-89 (17 tasks) 

給你總共完成89個任務。

我需要一種獲得每個線程的開始和結束範圍的數學/可編程性的方法;其中,以下應打印我上面列出的確切的事情:

$NumTasks = 89 
$NumThreads = 5 
$Remainder = $NumTasks % $NumThreads 
$DefaultNumTasksAssigned = floor($NumTasks/$NumThreads) 

For $i = 1 To $NumThreads 
    if $i <= $Remainder Then 
     $NumTasksAssigned = $DefaultNumTasksAssigned + 1 
    else 
     $NumTasksAssigned = $DefaultNumTasksAssigned 
    endif 
    $Start = ?????????? 
    $End = ?????????? 
    print Thread $i: Tasks $Start-$End ($NumTasksAssigned tasks) 
Next 

這也應該適用於任何數量的$NumTasks

注意:請堅持回答手邊的數學,避免暗示或假設情況。

+0

爲什麼你想要5個線程同時處理?這似乎是一個非常奇怪的數字,只是拉出空氣。 –

回答

1

我第二次將哈爾頓的話。您可以一次只給一個任務提供一個任務(或者一次執行幾個任務,具體取決於是否有大量開銷,即,相對於啓動/回收線程的成本,個別任務通常以非常快的速度完成)。你的後續評論有效地解釋了你的「線索」帶來了巨大的創造成本,因此你希望儘可能多地爲它們提供一次工作,而不是浪費時間創造新的「線程」,每個線程都需要少量的工作。

反正...要去math question ...

如果你想分配任務只有一次,下面的公式,插代替的了?????????在你的邏輯,應該做的伎倆:

$Start = 1 
     + (($i -1) * ($DefaultNumTasksAssigned + 1) 
     - (floor($i/($Remainder + 1)) * ($i - $Remainder)) 
$End = $Start + $NumTasksAssigned -1 

的公式如下解釋:
    1是一個事實,即顯示器/邏輯是一個基於不從零開始
   第二項是因爲我們通常在每次迭代中添加($ DefaultNumTasksAssigned + 1)。
   第三項爲前幾次迭代提供了一個修正。
     它的第一部分,(floor($i/($Remainder + 1))提供0至$我到達的第一個線程
     不接受一個額外的任務,此後1。
     第二部分表達了我們需要糾正多少。

爲$結束的公式是更加容易,唯一的招是減1,這是因爲開始值和結束值是包含性的(因此,例如,1之間的19有19個任務不是18)

的以下邏輯的稍微修改一塊也應該工作,避免了通過保持$開始變量的運行選項卡,而不是每次都重新計算它的「神奇」的公式..

$NumTasks = 89 
$NumThreads = 5 
$Remainder = $NumTasks % $NumThreads 
$DefaultNumTasksAssigned = floor($NumTasks/$NumThreads) 
$Start = 1 
For $i = 1 To $NumThreads 
    if $i <= $Remainder Then // fixed here! need <= because $i is one-based 
     $NumTasksAssigned = $DefaultNumTasksAssigned + 1 
    else 
     $NumTasksAssigned = $DefaultNumTasksAssigned 
    endif 
    $End = $Start + $NumTasksAssigned -1 
    print Thread $i: Tasks $Start-$End ($NumTasksAssigned tasks) 

    $Start = $Start + $NumTasksAssigned 
Next 

這裏是上面的一個Python轉錄

>>> def ShowWorkAllocation(NumTasks, NumThreads): 
... Remainder = NumTasks % NumThreads 
... DefaultNumTasksAssigned = math.floor(NumTasks/NumThreads) 
... Start = 1 
... for i in range(1, NumThreads + 1): 
...  if i <= Remainder: 
...  NumTasksAssigned = DefaultNumTasksAssigned + 1 
...  else: 
...  NumTasksAssigned = DefaultNumTasksAssigned 
...  End = Start + NumTasksAssigned - 1 
...  print("Thread ", i, ": Tasks ", Start, "-", End, "(", NumTasksAssigned,")") 
...  Start = Start + NumTasksAssigned 
... 
>>> 
>>> ShowWorkAllocation(89, 5) 
Thread 1 : Tasks 1 - 18 (18) 
Thread 2 : Tasks 19 - 36 (18) 
Thread 3 : Tasks 37 - 54 (18) 
Thread 4 : Tasks 55 - 72 (18) 
Thread 5 : Tasks 73 - 89 (17) 

>>> ShowWorkAllocation(11, 5) 
Thread 1 : Tasks 1 - 3 (3) 
Thread 2 : Tasks 4 - 5 (2) 
Thread 3 : Tasks 6 - 7 (2) 
Thread 4 : Tasks 8 - 9 (2) 
Thread 5 : Tasks 10 - 11 (2) 
>>> 

>>> ShowWorkAllocation(89, 11) 
Thread 1 : Tasks 1 - 9 (9) 
Thread 2 : Tasks 10 - 17 (8) 
Thread 3 : Tasks 18 - 25 (8) 
Thread 4 : Tasks 26 - 33 (8) 
Thread 5 : Tasks 34 - 41 (8) 
Thread 6 : Tasks 42 - 49 (8) 
Thread 7 : Tasks 50 - 57 (8) 
Thread 8 : Tasks 58 - 65 (8) 
Thread 9 : Tasks 66 - 73 (8) 
Thread 10 : Tasks 74 - 81 (8) 
Thread 11 : Tasks 82 - 89 (8) 
>>> 
+0

你忘了保留'$ NumTasksAssigned' - 因爲這樣你的輸出不正確。 '$ Start = $ Start + $ DefaultNumTasksAssigned'應該是'$ Start = $ Start + $ NumTasksAssigned'。這將使它適合這個例子,但如果我改變'$ NumTasks = 11',它會失敗。 – ParoX

+0

@BHare。你是對的,保持$ NumTasksAssigned是有用的。看到我的晚餐後編輯(我的代碼更好,肚子飽滿)......我以爲我可以擺脫,因爲_last_「線程」不會獲得最大的任務分配量,但這當然只是給人的印象由特定的89值。 88例如。將有兩個「線程」,少一個任務。等等。 – mjv

+0

這個例子使得任務89不會生效。輸出在這裏:http://pastebin.com/raw.php?i=avT3MD8m - 無論如何,沒有爭議的一點,因爲我取得了成功,使用您的原始作爲基地。一個工作模式在這裏:http://pastebin.com/raw.php?i=He86vE97 - 元數學答案使它更簡單:http://math.stackexchange.com/questions/46014/programming-logic-splitting-線程之間的任務...如果你希望被接受,請相應地更新你的答案。否則,病態的MOD將它關閉。 – ParoX

7

爲什麼?而是預先確定調度順序,將所有任務放在隊列中,然後讓每個線程在準備就緒時將它們逐個拉出。那麼你的任務將基本上「儘可能快」地運行。

如果您預先分配了,那麼一個線程可能會進行特別長的處理並阻止其後的所有任務的運行。使用隊列,隨着每個任務完成並且線程釋放,它抓住下一個任務並繼續前進。

把它想象成一個銀行,每個櫃員一條線,一條線和很多出納員。在前者中,你可能會被卡在存錢幣的人的後面,並逐個計算出來,後者可以到達下一個可用的出納員,而PocketChange先生卻數不勝數。

+0

我使用的語言實際上不支持真正的多線程,而是支持並行處理。這裏的想法是儘可能長時間地保持這個過程,因爲「釋放」意味着一個過程關閉,另一個過程是開放的,這比處理本身需要更多的時間。我的方法是在大多數時間運行5個併發進程,每個進程同時處理他們自己的小任務。 – ParoX

+0

@BHare:那麼你爲什麼要標記'c#'和'php'這個問題? –

+0

這很好,但如果您擁有對資源的共享訪問權限,則使用共享隊列作爲任務源與預分配列表之間沒有區別。當然,隊列會添加某種類型的同步(但這可能不是問題,具體取決於您的多任務處理)。 –

0

我想你已經solved the wrong half of your problem

這將是幾乎不可能精確地確定它會完成所有任務的時間,除非以下所有條件都爲真:

  • 你的任務是100%的CPU綁定的:那就是,他們使用100%的CPU運行時,並不需要做任何I/O
  • 沒有你的任務以任何方式與任何您的其他任務同步
  • 你有一樣多的線程,你有CPU的
  • 運行這些任務的計算機未執行同時

在實踐紐約其他有趣的任務,大多數的時候,你的任務是I/O密集型而非CPU密集型的:那就是,你在等待一些外部資源,如從閱讀一個文件,從數據庫中取出或與遠程計算機通信。在這種情況下,你只會通過增加更多的線程來讓事情變得更糟,因爲它們都在爭奪相同的稀缺資源。最後,除非你有一些非常奇怪的硬件,否則你不可能真正有5個線程同時運行。 (通常處理器配置至少有兩個倍數)。如果你的任務是CPU限制的,通常情況下,每個CPU的最佳位置約爲1個線程,如果任務花費了一半的CPU時間,一半的時間在做IO等

tl; dr:我們需要知道更多關於您的任務和硬件的樣子,然後才能就此問題爲您提供建議。

+0

它們不是真正的線程,而是過程。每個進程將處理一個winhttp GET或POST請求(不支持語言中的異步請求)。我選擇了5個,因爲它似乎是測試中最快的。 – ParoX

+0

@BHare:這不會使我寫的任何內容無效。如果之前的測試發現5個線程是最快的,那意味着CPU活動和I/O活動之間可能會有大約80%-20%的分離,並且它可能是(1)佔用80%時間的CPU工作,你是在一臺四核機器上,或者(2)它佔用了80%-100%的I/O時間,但是你可以一次有效地交叉處理四個請求。我有一個預感,(2)是你的瓶頸,因爲你提到你在做HTTP,而瀏覽器通常只向一個服務器發出4個請求。 –