※ 引述《hardman1110 (笨小孩)》之铭言:
: 推 LPH66: index 是 kernel 的编号, 不是阵列的编号 08/22 17:04
: → LPH66: kernel 做事的概念是“几号 kernel 去拿阵列的哪几格做事” 08/22 17:06
: → LPH66: 只是一般来说会因为方便让 kernel 以自己编号去取元素 08/22 17:06
: → LPH66: 当然其他状况也有可能是会成一个 kernel 抓很多格做事 08/22 17:07
: → LPH66: 这时去取哪几格时就要自己去算哪个 kernel 该取哪几格 08/22 17:07
: → LPH66: 另外你最后的问题, 去找 OpenCL 标准文件里面写得很清楚 08/22 17:09
: → LPH66: 或者我印象中有看过一个是把各种函数整理成的 cheat sheet 08/22 17:09
: → LPH66: (包含 host 端和 kernel 端的函数都有) 08/22 17:09
: → hardman1110: 我传进去的阵列型态大小都不一样,我该如何知道切了 08/22 17:11
: → hardman1110: 多少kernal(work item) 然后每个work item包含每个 08/22 17:12
: → hardman1110: 阵列的哪几格? 08/22 17:13
: 推 LPH66: 这是你在决定的事; 你要决定每个 work item 的工作量是多少 08/22 17:25
: → LPH66: 每个人要怎么拿到他所要的工作量做事 08/22 17:25
: → hardman1110: 查到clEnqueueNDRangeKernel可控制要切多少workitem 08/22 17:26
: → LPH66: 有的时候甚至可以写说“几号以后不用做那边的事”之类的 08/22 17:26
: → hardman1110: 但每个workitem对应到阵列哪一段就不清楚原理了 08/22 17:26
: → LPH66: 然后再 enqueue 你要的数量的 workitem 去做事 08/22 17:26
: → LPH66: 例如如果我要一个 workitem 做一格, 那就是照编号取元素 08/22 17:27
: → LPH66: 如果我要一个 workitem 做两格, 那可以编号乘二再取两格 08/22 17:27
: → LPH66: 重点是你要搞懂你是怎么分配工作下去的 08/22 17:28
: → LPH66: 一个简单的比方是你请了一堆工读生分担工作 08/22 17:29
: → LPH66: 那你总要告诉工读生“你的工作范围在哪里” 08/22 17:29
: → LPH66: 而做出一个简单易懂的分配方式就是你在问的"对应" 08/22 17:29
: → LPH66: 让每个工读生能只从自己分到的编号直接领到工作做 08/22 17:30
好像越推越长了所以回文总结 & 换个方式叙述一下
这里其实有一个借镜另外一个平行工作的 framework 的想法
在 OpenMP 里面, 常见的一个平行法是把工作包在一个 for 里
例如:
#pramga omp parallel for
for(int index = 0; index < 128; index++)
{
C[index] = A[index] + B[index];
}
以 OpenCL 的话来说, 这个 for 的内容就是一个 kernel
而 for 本身即是 enqueue 的动作, index 就会变成 global_id 等等的编号
同样的东西写成 OpenCL 可能会像是:
// host
...
clEnqueueNDRangeKernel(..., func, ..., {128}, ...);
...
// kernel
__kernel void func(__global int *A, __global int *B, __global int *C)
{
int index = get_global_id(0);
C[index] = A[index] + B[index];
}
那当你有不等长的资料时
如同你在写一般的 for 一样有很多方法可以去分配每一圈所做的事
(例如我推文提的“几号之后/第几圈之后别做那边的事”)
OpenCL 只是把这部份的循环内容给抽出来成了 kernel 以平行化而已
把“每个 kernel”想成“for 的每次循环”一些概念就很容易转化
我上面所提的“工作分配”等等的就只是在这底下的概念而已