如何在OpenCL中累积向量?
我有一组在循环中运行的操作如何在OpenCL中累积向量?,opencl,opencl-c,Opencl,Opencl C,我有一组在循环中运行的操作 for(int i = 0; i < row; i++) { sum += arr1[0] - arr2[0] sum += arr1[0] - arr2[0] sum += arr1[0] - arr2[0] sum += arr1[0] - arr2[0] arr1 += offset1; arr2 += offset2; } for(int i=0;i
for(int i = 0; i < row; i++)
{
sum += arr1[0] - arr2[0]
sum += arr1[0] - arr2[0]
sum += arr1[0] - arr2[0]
sum += arr1[0] - arr2[0]
arr1 += offset1;
arr2 += offset2;
}
for(int i=0;i|
现在我正试图像这样对操作进行矢量化
for(int i = 0; i < row; i++)
{
convert_int4(vload4(0, arr1) - vload4(0, arr2));
arr1 += offset1;
arr2 += offset2;
}
for(int i=0;i|
但是,如何在不使用循环的情况下,将结果向量累积到标量和中
我使用的是OpenCL2.0。该操作称为“还原”,似乎有一些相关信息
在OpenCL中,似乎实现了一些特殊的函数,其中一个是work\u group\u reduce()
,它可能会帮助您:
一个包含一些代码的演示文稿:.对于float2、float4和类似的,最简单的版本可能是dot产品。(从int到float的转换可能很昂贵)
这等于
(v1.x-v2.x)*1 + (v1.y-v2.y)*1+(v1.z-v2.z)*1+(v1.w-v2.w)*1
如果有任何硬件支持,让编译器来处理应该没问题。对于更大的向量,尤其是数组,J.H.Bonarius的答案是正确的。据我所知,只有CPU有垂直和运算,GPU没有,但为了便于移植,点积和工作组减少是实现可读性甚至性能的最简单方法
点积有额外的乘法,所以它可能并不总是好的 我找到了一个解决问题的方法,这似乎是我能想到的最接近我的问题的解决方法
uint sum = 0;
uint4 S;
for(int i = 0; i < row; i++)
{
S += convert_uint4(vload4(0, arr1) - vload4(0, arr2));
arr1 += offset1;
arr2 += offset2;
}
S.s01 = S.s01 + S.s23;
sum = S.s0 + S.s1;
uint sum=0;
uint4 S;
对于(int i=0;i|
OpenCL2.0提供了向量的功能,其中向量的元素可以依次替换为加法操作,如上所示。这最多可以支持大小为16的向量。较大的操作可分为较小操作的因素。例如,要将大小为32的两个向量之间的差值的绝对值相加,我们可以执行以下操作:
uint sum = 0;
uint16 S0, S1;
for(int i = 0; i < row; i++)
{
S0 += convert_uint16(abs(vload16(0, arr1) - vload16(0, arr2)));
S1 += convert_uint16(abs(vload16(1, arr1) - vload16(1, arr2)));
arr1 += offset1;
arr2 += offset2;
}
S0 = S0 + S1;
S0.s01234567 = S0.s01234567 + S0.s89abcdef;
S0.s0123 = S0.s0123 + S0.s4567;
S0.s01 = S0.s01 + S0.s23;
sum = S0.s0 + S0.s1;
uint sum=0;
uint16 S0,S1;
对于(int i=0;i|
据我所知,缩减是针对工作组中的工作项。然而,在我的代码中,它是一个单一的工作项。“缩减”是一个通用概念,其中多个变量被“缩减”为一个。您可以使用不同的操作:加法、乘法、最小值、最大值、异或和或等。这些链接将向您展示如何编写高效的并行代码以供实现。由于每种情况都不同,我不确定是否有一种简单的操作可以解决您的问题。为什么整数不支持这种操作?可能是因为软件行业的原因。例如,游戏开发人员长期编写自己的平方根算法,而不是要求硬件供应商提供。此外,您还可以将水平加法转换为垂直加法,这样您就可以像矢量一样进行加法,但至少需要4个5个矢量。因此,cpu的速度必须很快,而且因为没有额外的乘法,因为点积gpu也很快
uint sum = 0;
uint16 S0, S1;
for(int i = 0; i < row; i++)
{
S0 += convert_uint16(abs(vload16(0, arr1) - vload16(0, arr2)));
S1 += convert_uint16(abs(vload16(1, arr1) - vload16(1, arr2)));
arr1 += offset1;
arr2 += offset2;
}
S0 = S0 + S1;
S0.s01234567 = S0.s01234567 + S0.s89abcdef;
S0.s0123 = S0.s0123 + S0.s4567;
S0.s01 = S0.s01 + S0.s23;
sum = S0.s0 + S0.s1;