如何在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;