【问题标题】:OpenCL the same algorithms for GPU and CPU but OpenCl works differently for those two devicesOpenCL 的 GPU 和 CPU 算法相同,但 OpenCL 对这两种设备的工作方式不同
【发布时间】:2017-05-21 19:18:45
【问题描述】:

我有两个从头开始编写的程序,一个是积分,第二个是矩阵-矩阵乘法。当我使用 GPU 卡执行这两个程序并将全局大小设置为 1024 时,我希望内核代码执行 1024 次,这是正确的,它执行的次数与我在全局大小上设置的次数相同,并且更改了本地大小对结果进行编码和输出并不重要。 我试图用 CPU 执行相同的代码,当我看到内核函数执行的次数与设置的全局大小不同时我感到震惊。以下是积分的示例: 全局大小 = 2048,局部大小 = 1, 我期待内核函数执行 2048 次,是的,它是 2048, 但是当我们有全局大小 = 2048 和本地大小 = 16 时,它会执行 256 次...... 正常吗?为什么在 openCl 中使用 CPU 与使用 GPU 不同?我认为对于用户端我们使用哪种设备并不重要,相同的代码应该在不同的设备上工作相同。我错了吗?

提前感谢您的帮助!

【问题讨论】:

  • 我们需要问题的Minimal, Compilable, Veriable Example。因此,请发布一些代码以及如何将其排入队列(以及使用哪个 OpenCL 驱动程序等)。通常,驱动程序应该确保执行整个网格,即本地工作大小乘以全局工作大小线程整体执行。跨度>
  • 肯定是全局线程id和组id和本地线程id截取错误。您如何检查执行次数?
  • @huseyintugrulbuyukisik 我只是简单地将 +=1 添加到内核代码中的全局变量中,以查看内核执行了多少次
  • @Gzyniu 是原子的还是简单的?我的意思是,你使用 atomic_add() 还是真的 += ?
  • @huseyintugrulbuyukisik 简单的一个,但我在这里检查了 atomic_add 和相同的结果

标签: multithreading opencl gpu cpu


【解决方案1】:

将原子操作用于串行工作(或至少不易简化)。要计算参与的线程数,请不要使用a[0]+=1;

atomic_add(&a[0],1);

应该可以工作,甚至更好

atomic_inc(a)

其中 a 是整数,无符号带符号无关紧要。

【讨论】:

  • 好的,是的,atomic_inc 不能正常工作。我的意思是它完成了它的工作,增加了价值,但这个价值最终与全局大小不同。我不明白,我的代码可以在 1、2 甚至 8 个 gpu 上完美运行,但是当我切换到 CPU 时(我没有忘记将 clgetDeviceIds 参数更改为 CL_DEVICE_TYPE_CPU),它的行为很奇怪......与 GPU 上的值不同。使用 CPU 而不是 GPU 有什么不同吗?
  • 我用不同的结果解决了这个问题,但我仍然遇到 CPU 和 GPU 工作方式不同的问题。我以这种方式在内核中实现了积分:我们有 int id = get_global_id(0) 并且即使我们将全局大小设置得非常大,每个线程都会得到更小的工作要做,但是在 CPU 上我看到如果我设置 local_size = 4096 (它是最大值)在内核中我的线程编号从 0 到 4095 ......为什么?我正在获取全局 id 而不是本地...在 GPU 中,当本地大小设置为 1 和 1024 并且没有看到此类问题时它正在工作。这是为什么呢?
  • 我不是在问为什么它以 4095 结尾,而是为什么它不以 globalsize-1 结尾。在 GPU 上,当我将 globalsize 设置为 1234567 时,我的最后一个线程编号为 1234566,但现在,即使实现相同,它现在也以 localsize-1 结束
【解决方案2】:

我找到了问题的根源。这是因为 float 精度差,当我将变量更改为 double 时,它​​工作正常。我在某处读到 CPU 和 GPU 在浮点运算方面的工作在精度方面略有不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 2018-07-21
    • 2017-04-12
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多