私はやるべき労働者と仕事を持っています:
workers = ['peter', 'paul', 'mary']
tasks = range(13)
ここで、タスクを作業のチャンクまたはバッチに分割して、各ワーカーが 1 つのバッチで作業し、他のワーカーとほぼ同じ量の作業を行うことができるようにします。実生活では、バッチ ジョブをコンピューティング ファームにスケジュールしたいと考えています。バッチ ジョブは並行して実行することになっています。実際のスケジュールと発送は、lsf や grid などの商用グレードのツールによって行われます。
私が期待するもののいくつかの例:
>>> 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 ホスト名) があります。ソリューションで dict を使用している場合は、バッチ列挙によってワーカー ルックアップをいつでも実行できるため、問題ありません。
- 任意の長さ: ワーカーとタスクの両方が 1 以上の任意の長さの iterable になることができます。また、Mary が 1 つのタスクしか取得しない上記の例に示すように、それらは均等に分割する必要はありません。
- 順序: 私にとっては重要ではありません。[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 コンポーネントを組み合わせます。しかし、そうではないかもしれません。テイカーはいますか?