【问题标题】: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/ 中的所有函数,但一无所获。

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

【问题讨论】:

    标签: vector opencl


    【解决方案1】:

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

    1. 创建一个布尔向量,通过比较设置真/假状态
    2. 将其与具有与位位置对应的预定义值的整数向量进行点积。
    3. 第一个位集将对应于您要求的索引。使用 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) 以获得第一个真正元素的索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 2020-03-26
    • 1970-01-01
    • 2020-03-15
    • 1970-01-01
    相关资源
    最近更新 更多