如何决定如何在 GPU 中并行化嵌套循环?
How to decide how to parallelize nested loops in a GPU?
假设我有一个要在 GPU 上实现的算法。该算法由一个主循环组成,循环的所有迭代可以运行并行。另外,循环的每次迭代都有一个内循环,其迭代可以运行并行。假设我需要 N
次主循环迭代,以及 M
次内循环迭代(每个主循环迭代),并且我的 GPU 有 L
个核心。
如果N+N*M <= L
,我可以运行并行处理所有事情。但如果不是这种情况,我需要决定按顺序 运行 什么。我应该如何做出这个决定?例如,如果 N=10
、M=5
、L = 20
,我应该什么时候选择这些选项(或任何其他选项)?:
- 运行 所有主迭代并行,所有内循环顺序。
- 运行 所有主迭代按顺序进行,所有内部循环并行进行。
- 运行 所有主迭代并行,两个内部循环并行,其余循环顺序。
- 运行 三个主要迭代并行,运行 它们的每个内部循环并行,运行 其余主要迭代及其内部循环顺序。
你不应该关心所有的东西是否真的可以 运行 并行。当为您描述的令人尴尬的并行问题编写 GPU 内核时,您可能只有一个二维 N x M 网格,其中的每个元素都是一个线程,该线程执行第 i 个内循环的第 j 个迭代。
但是......最常见的考虑因素使得以不同的方式做事是值得的。例如 - 如果 M 不太大,您可以展开内部循环;或者你可能有代码应该在内部循环的所有 M 次迭代之后 运行,并且同步线程可能不值得(看看你通常如何最大化你的 GPU 的并行性与 N >> 1)。此外,内存访问模式 在决定并行尝试和完成哪些操作方面发挥着非常重要的作用(例如,参见 this presentation)。
因此,实际上并没有一个通用的答案。或者,也许答案是:
- 实施您认为可能是个好主意的事情。
- 分析它。
- 看看您是否有效地利用了 GPU 的资源。
- 相应地改变您的实施方法。
- 重复。
(如 another relevant presentation 中所建议,对于这个答案有点含糊和宽泛,我们深表歉意。)
假设我有一个要在 GPU 上实现的算法。该算法由一个主循环组成,循环的所有迭代可以运行并行。另外,循环的每次迭代都有一个内循环,其迭代可以运行并行。假设我需要 N
次主循环迭代,以及 M
次内循环迭代(每个主循环迭代),并且我的 GPU 有 L
个核心。
如果N+N*M <= L
,我可以运行并行处理所有事情。但如果不是这种情况,我需要决定按顺序 运行 什么。我应该如何做出这个决定?例如,如果 N=10
、M=5
、L = 20
,我应该什么时候选择这些选项(或任何其他选项)?:
- 运行 所有主迭代并行,所有内循环顺序。
- 运行 所有主迭代按顺序进行,所有内部循环并行进行。
- 运行 所有主迭代并行,两个内部循环并行,其余循环顺序。
- 运行 三个主要迭代并行,运行 它们的每个内部循环并行,运行 其余主要迭代及其内部循环顺序。
你不应该关心所有的东西是否真的可以 运行 并行。当为您描述的令人尴尬的并行问题编写 GPU 内核时,您可能只有一个二维 N x M 网格,其中的每个元素都是一个线程,该线程执行第 i 个内循环的第 j 个迭代。
但是......最常见的考虑因素使得以不同的方式做事是值得的。例如 - 如果 M 不太大,您可以展开内部循环;或者你可能有代码应该在内部循环的所有 M 次迭代之后 运行,并且同步线程可能不值得(看看你通常如何最大化你的 GPU 的并行性与 N >> 1)。此外,内存访问模式 在决定并行尝试和完成哪些操作方面发挥着非常重要的作用(例如,参见 this presentation)。
因此,实际上并没有一个通用的答案。或者,也许答案是:
- 实施您认为可能是个好主意的事情。
- 分析它。
- 看看您是否有效地利用了 GPU 的资源。
- 相应地改变您的实施方法。
- 重复。
(如 another relevant presentation 中所建议,对于这个答案有点含糊和宽泛,我们深表歉意。)