C++ 通过线程分发循环迭代

C++ 通过线程分发循环迭代,c++,multithreading,algorithm,parallel-processing,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 } } } 我设法将最后一行更改为:(k=PROCESSINDEX;k

我想用
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
        }
    }
}
我设法将最后一行更改为:
(k=PROCESSINDEX;k
,但结果是工作是这样分配的:

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
T[0] computed 25 iterations
T[1] computed 50 iterations
T[2] computed 50 iterations

如何改进这一点?

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

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

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

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

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

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

为什么要这样分配?尝试通过并行化
i
循环来分配,最多
j
。TBB将为您解决此问题,而无需尝试写你自己的线程池,而且肯定更高效。我如何改进它?很难说。你正在分配什么工作以及如何分配给线程还没有在问题中被记录。A可能会非常有助于理解你的观点。有了一个好的代码示例,你可能能够利用一些需要考虑的NG:1)创建一个维护线程会有开销。2)不能保证每个线程都在不同的内核或处理器上,操作系统可以在同一个内核上串行地调度它们。3)完成后需要添加代码来“连接”线程。为什么要这样分发?尝试通过并行化
i
循环来分发,最多
j
。TBB可以为您解决这个问题,而无需尝试编写自己的线程池,而且肯定会更有效。我如何改进这一点?很难说。您正在分配什么工作以及如何将其分配给线程尚未在问题中记录。A可能会非常有助于理解你的观点。有了一个好的代码示例,您可能能够利用一些需要考虑的因素:1)创建一个维护线程会带来开销。2) 不能保证每个线程都在不同的内核或处理器上,操作系统可以在同一个内核上串行地调度它们。3) 完成后,需要添加“连接”线程的代码。