在线程池中分配工作负载的算法

时间:2014-12-18 18:23:54

标签: multithreading algorithm

让我们假设我们有 T 个线程数,我们希望将大小 N 的问题分发给这些线程。每个线程都会选择该问题的一部分来执行它。每个线程将使用thread_id(0到T-1之间的数字),T和N来计算子问题的范围。假设子问题的范围是[S,E],其中S和E属于[0,N]。

例如。假设我们有一个整数数组。数组的大小是10.我们希望将该数组的每个元素增加一个,并且我们希望使用4个线程并行执行此操作。

  • 第一个带有thread_id == 0的线程将使用范围[0,3]
  • thread_id == 1的第二个线程将使用范围[3,6]
  • thread_id == 2的第3个线程将使用范围[6,8]
  • 第4个主题,thread_id == 3将使用范围[8,10]

有谁知道计算这些范围的快速算法?优选没有原子或分支。

2 个答案:

答案 0 :(得分:3)

如果我理解正确你正在寻找这样的等式?

S = floor(thread_id * N/T)
E = floor((thread_id + 1) * N/T)

如果先乘以(threadId * N)并稍后除(/N),则可以使用整数进行计算,并且不需要floor函数。

答案 1 :(得分:1)

我认为这两个例子应该有效。所有操作都是整数。除了标明它没有的那个。

这个逻辑更简单,但它不会根据您的需要分配工作。它会将更大的工作量分配给所有工人,除了最后一个工人将获得显着更低的份额。它不应该是理论上的问题,因为一个工人的最大工作量保持不变。

items_per_thread = ceil(N/T); // This is not an integer division.
start = thread_id*items_per_thread;
stop = min(start+items_per_thread, N);

这个应该按照你的要求分发工作。

items_per_thread = N/T;
start = thread_id*items_per_thread+min(thread_num, N mod T);
stop = start+items_per_thread;
if(thread_num < N mod T) stop += 1;

我认为不可能避免分支。

我喜欢冒险,我在python中创建了live demo,它也包含了ciamej的方法。

import math
def distribution1(id ,N, T):
    items_per_thread = math.ceil(N/T);
    start = id*items_per_thread;
    stop = min(start+items_per_thread, N);
    return (start, stop)

def distribution2(id ,N, T):
    items_per_thread = math.floor(N/T);
    start = id*items_per_thread+min(id, N % T);
    stop = start+items_per_thread;
    if(id < N % T): stop += 1;
    return (start, stop)

def distribution3(id ,N, T):
    S = math.floor(id * N/T)
    E = math.floor((id + 1) * N/T)
    return (S,E)

def distribute(N, T, method):
    ret = []
    for i in range(T):
        ret.append(method(i, N, T))
    return ret

N=10
T=4
print(distribute(N, T, distribution1))
print(distribute(N, T, distribution2))
print(distribute(N, T, distribution3))

输出:

[(0, 3), (3, 6), (6, 9), (9, 10)]
[(0, 3), (3, 6), (6, 8), (8, 10)]
[(0, 2), (2, 5), (5, 7), (7, 10)]