【问题标题】:Inaccurate results with OpenCL Reduction exampleOpenCL Reduction 示例的结果不准确
【发布时间】:2015-07-22 17:03:16
【问题描述】:

我正在使用 Apple here 提供的 OpenCL 缩减示例

经过几天的剖析,我了解了基础;我已将其转换为在 c++ (Openframeworks) 上或多或少可靠运行的版本,并在输入集中找到最大的数字。

但是,在这样做的过程中,出现了如下几个问题:

  • 为什么要使用多个通道?我能够使减少要求的最多是两个;后一个 pass 只占用非常少的元素,因此非常不适合 openCL 进程(即,坚持一个 pass 然后在 cpu 上处理结果不是更好吗?)

  • 当我将元素的“计数”数量设置为非常高的数字(24M 及以上)并将类型设置为 float4 时,我得到的结果不准确(或完全错误)。这是为什么呢?

  • 在 openCL 内核中,谁能解释这里正在做什么:

while (i < n){
        int a = LOAD_GLOBAL_I1(input, i);
        int b = LOAD_GLOBAL_I1(input, i + group_size);
        int s = LOAD_LOCAL_I1(shared, local_id);
        STORE_LOCAL_I1(shared, local_id, (a + b + s));
        i += local_stride;
}

与这里正在做的事情相反?

#define ACCUM_LOCAL_I1(s, i, j) \
 { \
    int x = ((__local int*)(s))[(size_t)(i)]; \
    int y = ((__local int*)(s))[(size_t)(j)]; \
    ((__local int*)(s))[(size_t)(i)] = (x + y); \
 }

谢谢! S

【问题讨论】:

    标签: opencl


    【解决方案1】:

    回答前两个问题:

    why are multiple passes used?
    

    可以将数百万个元素减少到数千个,同时设备利用率几乎达到 100%。但最后一步非常棘手。因此,Apple 实施决定做一次减少第一次通过,而不是一次完成所有事情并让多个线程空闲;然后使工作项适应新的约简问题,最后完成。 Ii 是针对 OpenCL 的一个非常具体的优化,但它可能不适用于 C++。

    当我将元素的“计数”数量设置为非常高的数字(24M 及以上)和float4的类型,我不准确(或完全错误) 结果。这是为什么呢?

    float32 精度是 2^23 的余数。高于 24M = 1.43 x 2^24(浮点表示)的值在 +/-(2^24/2^23)/2 ~= 1 范围内有误差。

    这意味着,如果你这样做:

     float A=24000000;
     float B= A + 1; //~1 error here
    

    操作员错误在数据范围内,因此...如果您在循环中重复,则会出现大错误!

    这在 64 位 CPU 中不会发生,因为 32 位浮点数学在内部使用 48 位精度,因此避免了这些错误。但是,如果您使浮动接近 2^48,它们也会发生。但这不是正常“计数”整数的典型情况。

    【讨论】:

    • 嘿,感谢您的回复。我理解第一个;我仍然想知道为什么后者(小得多)减少不只是在 cpu 上运行。对于不准确的问题 - 是的,我也这么认为(找到下面答案建议的链接)但是当我使用 int4 而不是 float4 测试减少时,仍然出现不准确。int4 是否有类似的错误范围?跨度>
    • “ints”没有错误,所以检查你的代码。整数运算总是精确的。
    • 我就是这么想的,ints不能不准确! Aaand,我没有编辑上面链接到的苹果示例中的代码,所以我希望它没问题。然而,当这些元素是 int4 或 float4 时,当运行超过 23(ish)m 个元素时,它会停止准确工作。从进一步的测试来看,完全相同的事情发生在 int2 的大约 45m 元素以上的错误发生,而普通旧 int 的某处超过 91m 的错误发生。我知道这些数字非常高(!),所以可能不是那么重要,但我对造成这种情况的原因很感兴趣。
    • 我猜这一定是内存问题
    【解决方案2】:

    问题在于 32 位浮点数的精度。你也不是第一个问这个问题的人。 OpenCL reduction result wrong with large floats

    【讨论】:

    • 是的,我找到了这个(见上面的评论),但它仍然给出了一个错误结果和大量的 int4 结果
    猜你喜欢
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多