我正在研究OpenCL,我不明白C/C++代码中的传统循环与内核代码之间的关系。 只是为了弄清楚这样的情况:
所以我的问题是:在传统循环中,我有
n
变量作为边界,而在内核代码中我没有它,但我有 get_global_id(0)
指示数组的内存范围,这意味着我从0,并迭代直到 get_global_id
与数组的最大大小匹配,在本例中为 n
?还是有什么不同?
因为在另一个例子中我不知道如何编写相应的内核代码
我希望我的问题很清楚,因为我的英语不太好,抱歉。
提前感谢您的帮助,如果有问题请告诉我!
OpenCL 内核的编码类似于 for 循环的单次迭代,但所有迭代都以随机顺序并行运行。
考虑 C++ 中的这个向量加法示例,其中对于
i=0..N-1
,您将向量的每个元素一个接一个地相加:
for(int i=0; i<N; i++) { // loop index i
C[i] = A[i]+B[i]; // compute one after the other
}
在 OpenCL 中,向量加法看起来像这个 for 循环的内部,但作为一个带有
kernel
关键字和所有向量作为参数的函数:
kernel void add_kernel(const global float* A, const global float* B, global float* C) {
const int i = get_global_id(0);
C[i] = A[i]+B[i]; // compute all loop indices i in parallel
}
您可能想知道:
N
在哪里?您将 N
提供给 C++ 端的内核作为其“全局范围”,因此内核知道要并行计算多少元素 i
。
因为在 OpenCL 内核中,每次迭代都是并行运行的,因此一次迭代与下一次迭代之间不能存在任何数据依赖关系;否则,您必须使用双缓冲区(仅从一个缓冲区读取,仅写入另一个缓冲区)。在第二个使用
A[i] = B[i-1]+B[i]+B[i+1]
的示例中,您正是这样做的:仅从 B
读取,仅写入 A
。具有周期性边界的实现可以无分支完成,请参见here。