让我们假设我们有 T 个线程数,我们希望将大小 N 的问题分发给这些线程。每个线程都会选择该问题的一部分来执行它。每个线程将使用thread_id(0到T-1之间的数字),T和N来计算子问题的范围。假设子问题的范围是[S,E],其中S和E属于[0,N]。
例如。假设我们有一个整数数组。数组的大小是10.我们希望将该数组的每个元素增加一个,并且我们希望使用4个线程并行执行此操作。
有谁知道计算这些范围的快速算法?优选没有原子或分支。
答案 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)]