使用并行算法减少总和 - 与CPU版本相比性能不佳

时间:2016-02-17 02:49:25

标签: c performance opencl

我已经实现了一个用于减少一维数组总和的小代码。我正在比较CPU顺序版和OpenCL版。

代码可在this link1

上找到

内核代码可在this link2

上找到

如果你想编译:link3 for Makefile

我的问题是关于GPU版本的糟糕表现:

对于低于1,024 * 10 ^ 9个元素的向量大小(即1024, 10240, 102400, 1024000, 10240000, 102400000 elements),GPU版本的运行时比CPU 1更高(略高但略高)。

正如您所看到的,我已经获取了2 ^ n个值,以便拥有与工作组大小相同的工作项数量。

关于工作组的数量,我采取了:

// Number of work-groups
  int nWorkGroups = size/local_item_size;

但是对于大量的工作项,我想知道nWorkGroups的值是否合适(例如,nWorkGroups = 1.024 * 10^8 / 1024 = 10^5 workgroups,这不是太多了吗?)。

我尝试在loca_item_size范围内修改[64, 128, 256, 512, 1024],但所有这些值的表现仍然不佳。

我只对size = 1.024 * 10^9元素有好处,这里有运行时:

Size of the vector
1024000000

Problem size = 1024000000

GPU Parallel Reduction : Wall Clock = 20 second 977511 micro

Final Sum Sequential = 5.2428800006710899200e+17

Sequential Reduction : Wall Clock = 337 second 459777 micro

根据您的经验,我为什么会表现糟糕?我认为与CPU版本相比,优势应该更有意义。

也许有人可能会在源代码中看到一个主要错误,因为目前我无法解决这个问题。

由于

1 个答案:

答案 0 :(得分:1)

我可以告诉你一些原因:

  • 您无需编写缩减缓冲区。您可以使用clEnqueueFillBuffer()或辅助内核直接在GPU内存中清除它。

    ret = clEnqueueWriteBuffer(command_queue, reductionBuffer, CL_TRUE, 0, local_item_size * sizeof(double), sumReduction, 0, NULL, NULL);

  • 除最后一次阅读外,不要使用阻止呼叫。否则你在那里浪费一些时间。

  • 您正在进行CPU的最后一次减少。通过内核进行迭代处理可以提供帮助。

  • 因为如果你的内核每次传递只减少128个元素。你的10 ^ 9号码下降到8 * 10 ^ 6。然后CPU完成其余的工作。如果你在那里添加数据副本,它就完全没有价值。 但是,如果每次传递512个元素运行3次传递,则从GPU中读出10 ^ 9/512 ^ 3 = 8个值。因此,唯一的瓶颈将是第一个GPU拷贝和内核启动。