【发布时间】:2012-08-29 13:49:20
【问题描述】:
原理
我知道,这么简单的计算不值得精心并行化。就是这样一个例子,数学运算只是一些更有趣的计算的占位符。
[伪代码]
var id = 0,
do {
id = getGlobalId();
output[id] = input[id] * input[id];
} while (inRange(id) && output[id] !== 25);
最特殊的表达式可能是:output[id] !== 25。这意味着:如果input 有四个元素(按这个 顺序):[8, 5, 2, 9],那么output 应该是[64, 25] 而2 或9 的平方不会用作output 的项目(因为对于id = 1 和input[id] = 5,output[id] !== 25 是true)。
如果您正在优化这段代码,您可能需要提前计算每个input[id] 的平方(不证明第二个while 条件),但不能保证结果在以后是相关的(如果先前计算的结果是 25,则当前计算的结果是无意义的)。
概括地说,我说的是计算 result output[id] (output[id] = calculateFrom(input[id]);) 可能与每个 id 都不相关的情况 - 需要结果 (output[id]) 取决于另一个计算的结果。
我的目标
我想使用 OpenCL 内核和队列以尽可能并行和高性能的方式执行此循环。
我的想法
我想:为了能够并行化这样的
do...while循环 我们应该提前同时做一些计算(output[id] = calculateFrom(input[id]);)(没有 知道结果output[id]是否有用)。如果结果 前一个是25,然后结果output[id]简单地得到 被拒绝。也许我们应该考虑
output[id] !== 25的概率。 如果概率非常高,我们不会提前做很多计算 时间,因为他们的结果可能会被拒绝。如果 概率绝对低,那我应该做更多的计算 提前。我们应该监听处理单元的当前状态。如果 已经超负荷了,我们不应该提前做无关紧要的事情 计算。但是如果有足够的资源来处理 提前计算,为什么不呢。 - 因为:如果提前计算和之前的计算(这些提前计算所依赖的)被同时处理,那么提前附加也可能减慢之前的计算 - (见我的第二个问题)
我的问题
- 并行化此类程序是明智的还是高性能的?
- 我应该根据哪些标准来决定处理单元是否有足够的资源来执行我的提前计算任务?或者:我如何知道我的处理单元是否过度紧张?
- 您知道任何其他并行化此类
do...whiles 的计划吗?您对此有什么想法吗?
我希望我想告诉你的总是很清楚。但如果不是,请评论我的问题。 - 感谢您的回答和帮助。
【问题讨论】:
-
没有现成的答案,你应该自己看看你的确切情况。如果每个
id拥有output[id] == 25的概率为 10%,那么平均而言,您必须处理 9 个元素,而且很可能不值得并行化。如果概率为 0.001%,则平均需要处理 99 999 个元素,如果数组有 10 000 个元素,则可以先计算所有元素,然后将垃圾丢弃;但是如果您的数组有 1 000 000 个元素,您可以分块处理它,并行处理每 100 000 个元素并使用一些原子标志来监视25 -
@aland 感谢您的图形描述。 - 但是,正如我的问题文本中所述,我不想让“并行化程度”(分别是工作组的规模)仅取决于条件适用的概率。我也想让它取决于处理单元的当前状态(是否过度紧张?)。 (在问题和 cmets 中对 mfa 的回答有更多的关注)
-
@aland 那么,您对算法有什么想法吗?它可以决定提前多少计算和我们应该并行化做,根据
clGetDeviceInfo()提供的信息? - 感谢您对此的任何想法。 -
@frodijet:对于 OpenCL,您通常无法动态控制设备负载。你准备好数据,在这个数据上启动内核并等待它完成。工作组的最佳大小取决于设备和算法。如果您使用 nVidia GPU 计算设备占用率,则可以使用 CUDA 占用率计算器,或者手动进行(在大多数 OpenCL 优化指南中进行了描述)。对于 GPU,您应该针对数万个线程,并记住,在某些系统上,内核执行有大约 30 秒的超时时间,这可能会给您一些估计。
标签: parallel-processing cpu opencl gpu aparapi