Vector 获取“第一个”的索引;“真的”;矢量

Vector 获取“第一个”的索引;“真的”;矢量,vector,opencl,Vector,Opencl,如何有效地计算OpenCL向量中第一个“真”值的索引: float4 f = (float4)(1, 2, 3, 4); int i = firstTrue(f > 2); 在本例中,我希望得到I=2,因为3是大于2的第一个值 我查看了中的所有函数,但没有发现任何结果 这是一个如此罕见的手术吗? 在没有太多分支/代码重复的情况下,我如何(自己)计算它呢?我不知道有一个内置函数可以完全满足您的需要,但我对如何实现这一点有一些想法。也许有一个更简单的解决办法,但到目前为止我只喝了一杯咖啡。其

如何有效地计算OpenCL向量中第一个“真”值的索引:

float4 f = (float4)(1, 2, 3, 4);
int i = firstTrue(f > 2);
在本例中,我希望得到
I=2
,因为3是大于2的第一个值

我查看了中的所有函数,但没有发现任何结果

这是一个如此罕见的手术吗?
在没有太多分支/代码重复的情况下,我如何(自己)计算它呢?

我不知道有一个内置函数可以完全满足您的需要,但我对如何实现这一点有一些想法。也许有一个更简单的解决办法,但到目前为止我只喝了一杯咖啡。其思想是利用“计数前导零”函数“clz”。您只需要将条件的结果转换为整数中的位位置

  • 使用比较设置的真/假状态创建布尔向量
  • 对一个整数向量进行点积,该整数向量具有与位位置对应的预定义值
  • 第一个位集将对应于您请求的索引。使用clz()或bithack查找该位索引
  • 在代码中,类似这样的内容(未经测试,可能需要调整):

    您需要偏移或反转clz的结果,以获得0,1,2,3,但这只是加法或减法

    工作代码
    嗯,编译器在点函数上给了我一个错误,只列出了
    floatn
    doublen
    的重载。点函数似乎不能应用于整数向量。我想可能是这样的。在使用clz之前,您可以向上转换为float,然后再返回int。或者自己编写点积(成员乘积之和)。这是一种非常聪明的解决问题的方法,节省了一些说明。注意:
    对于标量类型,如果指定的关系为false,则关系运算符将返回0,如果指定的关系为true,则返回1。对于向量类型,如果指定的关系为false,则关系运算符应返回0;如果指定的关系为true,则关系运算符应返回-1(即所有位集)。
    (第d部分末尾)我对此进行了更多思考,并意识到不需要点积。您只需在“int4更大”上使用“clz”,并将结果除以sizeof(int)即可获得第一个true元素的索引。
    float4 f = (float4)(1, 2, 3, 4);
    int4 greater = (f > 2);
    int4 bits = (int4)(8, 4, 2, 1);
    int sum = dot(greater, bits); // maybe this needs to use float
    int index = clz(sum); // might need offset applied
    
    int firstTrue(int4 v) {
        return 4 - (clz(0) - clz((v.x & 8) | (v.y & 4) | (v.z & 2) | (v.w & 1));
    }