获取向量中第一个“真”的索引

Posted

技术标签:

【中文标题】获取向量中第一个“真”的索引【英文标题】:Get index of first "true" in vector 【发布时间】:2013-12-22 13:23:07 【问题描述】:

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

float4 f = (float4)(1, 2, 3, 4);
int i = firstTrue(f > 2);

在示例中,我想获得i=2,因为 3 是第一个大于 2 的值。

我查看了http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/ 中的所有函数,但一无所获。

这是一种不常见的操作吗? 如何在没有太多分支/代码重复的情况下(自行)计算?

【问题讨论】:

【参考方案1】:

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

    创建一个布尔向量,通过比较设置真/假状态 将其与具有与位位置对应的预定义值的整数向量进行点积。 第一个位集将对应于您要求的索引。使用 clz() 或 bithack 来查找该位索引。

在代码中,类似这样的内容(未经测试,可能需要调整):

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

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

工作代码

int firstTrue(int4 v) 
    return 4 - (clz(0) - clz((v.x & 8) | (v.y & 4) | (v.z & 2) | (v.w & 1));

【讨论】:

嗯,编译器在点函数上给了我一个错误,并且只列出了 floatndoublen 的重载,似乎点函数不能应用于整数向量。 我在想可能是这样。在使用 clz 之前,您可以先转换为浮点数,然后再转换回整数。或者自己写点积(成员积的总和)。 非常聪明的解决问题的方法,节省了一些说明。 注意:For scalar types, the relational operators shall return 0 if the specified relation is false and 1 if the specified relation is true. For vector types, the relational operators shall return 0 if the specified relation is false and -1 (i.e. all bits set) if the specified relation is true.(khronos.org/registry/cl/specs/opencl-1.2.pdf#page=218 d 部分结束) 我对此进行了更多思考,并意识到不需要点积。您可以在“int4 greater”上使用“clz”并将结果除以 sizeof(int) 以获得第一个真正元素的索引。

以上是关于获取向量中第一个“真”的索引的主要内容,如果未能解决你的问题,请参考以下文章

获取表中第一个可用索引,包括0

C ++有效查找向量中第一个最近的匹配值?

matlab中怎么查找一个向量中第一个非零元素的位置 如P=[0;1;2] 第一个非零元素的位置为2,在mbtlab中怎么

如何使用 R 在向量中找到第二个非连续出现的值的索引?

利用正则来查找字符串中第n个匹配字符索引

在 Python 中,如何找到不是某个值的列表中第一项的索引?