OpenCL有select
function,可用于所有向量参数。 clang和gcc都支持向量类型,但只有gcc目前支持三元运算符支持向量,并且它们都没有类似OpenCL的select
函数。我试图实现替换,但结果不是最优的,gcc和clang都会产生条件跳转。但是,gcc在三元运算符方面表现相当不错,所以它非常适合作为替代品。是否存在类似select
函数的最佳解决方案(特别是在clang下),它是什么?以下是一些非理想的想法:
template <typename U, typename V>
inline V select(U const s, V const a, V const b) noexcept
{
// a for loop gives horrible results
/*
constexpr U zero{}; // for clang only
return (-(s != zero) * a) - ((s == zero) * b);
*/
return V{
s[0] ? a[0] : b[0],
s[1] ? a[1] : b[1],
s[2] ? a[2] : b[2],
s[3] ? a[3] : b[3]
}; // for 4-component vectors only, one could generalize with the indices trick
/*
return s ? a : b; // for gcc
*/
}
答案 0 :(得分:0)
这将编译为gcc和clang下的半好代码:
template <typename U, typename V>
constexpr inline V select(U const s, V const a, V const b) noexcept
{
return V((s & U(a)) | (~s & U(b)));
}
asm上市:
Dump of assembler code for function select<int __vector(4), float __vector(4)>(int __vector(4), float __vector(4), float __vector(4)):
0x00000000004009c0 <+0>: andps %xmm0,%xmm1
0x00000000004009c3 <+3>: andnps %xmm2,%xmm0
0x00000000004009c6 <+6>: orps %xmm1,%xmm0
0x00000000004009c9 <+9>: retq
End of assembler dump.
这仍然不如优化器产生的效果好。它的工作方式是滥用矢量强制转换和事实,比较操作在比较匹配的地方产生-1(全1)整数。至少不需要算术运算。