通过线程分配循环迭代

时间:2019-01-25 20:33:18

标签: c++ multithreading algorithm parallel-processing

我想使用n个线程来计算嵌套循环:

for (i = 0; i < matrix.size(); i++) {
    for (j = 0; j < matrix.size(); j++) {
        for (k = 0; k < matrix.size(); k++) {
            // do the job
        }
    }
}

我想用不同的线程计算每个循环操作。我们将其称为线程T。使用3线程和matrix.size() = 5,这就是工作分配的方式:

T[0] computes operation i=0 j=0 k=0
T[1] computes operation i=0 j=0 k=1
T[2] computes operation i=0 j=0 k=2
T[0] computes operation i=0 j=0 k=3
T[1] computes operation i=0 j=0 k=4
T[2] computes operation i=0 j=1 k=0
T[0] computes operation i=0 j=1 k=1
T[1] computes operation i=0 j=1 k=2
T[2] computes operation i=0 j=1 k=3
T[0] computes operation i=0 j=1 k=4
T[1] computes operation i=0 j=2 k=0
T[2] computes operation i=0 j=2 k=1
T[0] computes operation i=0 j=2 k=2
T[1] computes operation i=0 j=2 k=3
T[2] computes operation i=0 j=2 k=4
T[0] computes operation i=0 j=3 k=0
T[1] computes operation i=0 j=3 k=1
T[2] computes operation i=0 j=3 k=2
T[0] computes operation i=0 j=3 k=3
T[1] computes operation i=0 j=3 k=4
T[2] computes operation i=0 j=4 k=0
T[0] computes operation i=0 j=4 k=1
T[1] computes operation i=0 j=4 k=2
T[2] computes operation i=0 j=4 k=3
T[0] computes operation i=0 j=4 k=4
T[1] computes operation i=1 j=0 k=0
T[2] computes operation i=1 j=0 k=1
T[0] computes operation i=1 j=0 k=2
T[1] computes operation i=1 j=0 k=3
T[2] computes operation i=1 j=0 k=4
T[0] computes operation i=1 j=1 k=0
T[1] computes operation i=1 j=1 k=1
T[2] computes operation i=1 j=1 k=2
T[0] computes operation i=1 j=1 k=3
T[1] computes operation i=1 j=1 k=4
T[2] computes operation i=1 j=2 k=0

我设法将最后一行更改为:for (k = PROCESSINDEX; k < matrix.size(); k += PROCESSAMOUNT),但是结果就是这样分配了工作:

T[0] computed 25 iterations
T[1] computed 50 iterations
T[2] computed 50 iterations

我该如何改善?

1 个答案:

答案 0 :(得分:3)

尽管在许多实际任务中(例如,将两个矩阵相乘),将其进一步细分很可能会导致性能下降,因为这会破坏线程的内存局部性,如果您确实执行的任务确实具有较低的数据依赖性,则有一个显而易见的解决方案:您只需枚举从(i,j,k)0的所有三元组n^3-1(假设n = matrix.size()),然后将该范围吐出3个几乎相等的块并将它们传递给每个线程。然后,每个线程都可以轻松地将其重构为工作的一部分(任务#ti+j*n+k*n^2相对应,因此:

i = t % n
j = (t/n) % n
k = t / n /n

另一种解决方案是将线程池和队列用于任务。您不必在一开始就为每个线程分配所有工作。您将工作放入队列中,并让每个线程从中获得一些工作量,在处理完该批次后,从队列中取回下一个批次,并使用批次减少队列中的并发冲突。这种方法的优势在于,如果处理数据的时间取决于特定的数据,那么您将平衡实际执行的工作而不是执行的任务数量。