我有工人和任務做:如何在Python中將工作公平分配給工作人員? - 分裂迭代成同樣大小的塊
workers = ['peter', 'paul', 'mary']
tasks = range(13)
現在我想將任務分割成塊或工作的批次,所以每個工人可以在一個批處理工作,並造成大約與其他人相同的工作量。在我的現實生活中,我想將批處理作業安排到計算場。批處理作業應該並行運行。實際的時間表&調度是由一個商業級的工具,如LSF或網格。
什麼,我會想到一些例子:
>>> distribute_work(['peter', 'paul', 'mary'], range(3))
[('peter', [0]), ('paul', [1]), ('mary', [2])]
>>> distribute_work(['peter', 'paul', 'mary'], range(6))
[('peter', [0, 3]), ('paul', [1, 4]), ('mary', [2, 5])]
>>> distribute_work(['peter', 'paul', 'mary'], range(5))
[('peter', [0, 3]), ('paul', [1, 4]), ('mary', [2])]
不同的是,我想這些功能,在訂單或優先權:
- 沒有使用
len
,如果可能的話,不在內部建立長數據結構 - 接受發電機
- 返回發電機
- 儘可能多使用STDLIB組件儘可能
一些旁註上要求:
- 故意不類型的字典:我工人可以執行多個批處理的相同名稱(unix主機名)。如果你的解決方案使用了字典,那很好,因爲我們總是可以通過批量枚舉來查找工作人員。
- 任意長度:工作人員和任務都可以是任意長度大於等於1的迭代次數。並且他們不必像上面的示例中所示的那樣均勻地分割,其中Mary只獲取一個任務。
- 排序:對我來說並不重要。我猜其他人可能會喜歡[0,1],[2,3],[5]這樣的順序,但我不在乎。如果您的解決方案可以保留或切換訂單,那麼也許值得向其他人指出。
我試圖總結我的周圍itertools
頭,這方面的問題,並與下面的代碼走過來說明這個問題:
from itertools import *
def distribute_work(workers, tasks):
batches = range(len(workers))
return [ (workers[k],
[t[1] for t in i]
) for (k,i) in groupby(sorted(zip(cycle(batches),
tasks),
key=lambda t: t[0]),
lambda t: t[0]) ]
這滿足4,但排序很可能違反了1 ..和2./3。甚至都沒有想過。
也許有一些簡單的解決方案,以我沒有想到的方式組合一些stdlib組件。但也許不是。任何接受者?
好點。必須澄清的是,這是關於應該爲需要並行運行的機器安排作業。整個工作量正在減輕工作量,以減少從開始到結果的延遲。 – cfi