【问题标题】:Does chaining commutative operations improve performance?链式交换操作能提高性能吗?
【发布时间】:2021-04-03 19:12:07
【问题描述】:

我有一些与 python 接口的 OpenCL 内核抛出了 pyopencl 库。内核用于加速交换操作(如加法或乘法),其中操作输入变量的顺序无关紧要。进行加法的内核可能如下所示:

__kernel void addition(__global const float *a_g,
                       __global const float *b_g, 
                       __global float *res_g)
{
  int gid = get_global_id(0);
  res_g[gid] = a_g[gid] + b_g[gid];
}

为简单起见,假设所有操作缓冲区(a_gb_gres_g)具有相同的大小和一维。全局工作大小设置为启动内核之前的缓冲区大小,结果存储在res_g 缓冲区中。

这些操作以顺序方式工作,一个内核的输出用作下一个内核的输入。鉴于所有这些内核看起来都像上面的代码 sn-p,我可以通过编写以下内核来简单地将 4 个输入“链接”在一起:

__kernel void addition_chained(__global const float *a_g,
                               __global const float *b_g, 
                               __global const float *c_g,
                               __global const float *d_g,
                               __global float *res_g)
{
  int gid = get_global_id(0);
  res_g[gid] = a_g[gid] + b_g[gid] + c_g[gid] + d_g[gid];
}

这样,不需要分配中间结果缓冲区,启动新线程也没有开销。

这是常见的优化吗?这样做有什么好处和坏处?

在 OpenCL 中是否有任何规范的方式来链接内核?在编译时可能不知道需要链接的操作数量。

【问题讨论】:

  • 附带说明:我不确定链接是否是正确的术语

标签: opencl pyopencl


【解决方案1】:

通过将多个内核的操作合并为一个来减少内核调用意味着更少的内存分配和更少的从全局内存中传输的内存,从而显着减少了执行时间。

如果在整个程序中添加的数量是恒定的,您可以利用 OpenCL 在运行时从字符串编译的优势。这意味着:您可以在运行时修改包含 OpenCL 代码的字符串,然后编译并运行它。这样,您可以通过字符串连接添加可变数量的内核参数和求和项。

但是,如果求和项的数量在您的程序的一次执行中多次收费并且是不可预测的,那么双参数内核就是要走的路。否则,您将不得不多次重新编译 OpenCL 代码,这会产生很大的开销。

【讨论】:

  • 像这样操作字符串感觉有点hacky,但我想这正是我想要做的。
猜你喜欢
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
相关资源
最近更新 更多