在我的程序中,我有一个类似下面的语句,在一个循环中。
y = (x >= 1)? 0:1;
但是,我想避免使用任何关系运算符,因为我想使用SIMD指令,并且不确定关系运算符是否能很好地与SIMD一起工作。
我想要类似下面的东西。
a = some_operation(x) // a will be either 1 or 0
y = 1 - a
其中some_operation
会将任何等于或大于1的数字转换为1,并将0保留为0。因此,我的问题是,是否有some_operation
可以实现我的目的?
7条答案
按热度按时间piwo6bdm1#
和其他答案一样,这依赖于整数的符号位MSB,对于所有整数〈= 0,函数返回0,否则返回1,如果
x-1
溢出,函数将失败。此实现在编译代码中没有分支。
sq1bmfud2#
有没有一种方法可以不使用任何关系运算符而将大于等于1的整数转换为1?
对于 * unsigned * 整数,您可以简单地执行以下操作:
更新:
对于 * signed * 整数,您可以执行以下操作
以上行的结果为
0
用于任何i < 1
1
用于任何i >= 1
rfbsl7qr3#
假设你使用2的补码,你可以做到这一点。(使用!!x的另一个答案可能是也可能不是你所寻找的,这取决于计算机的指令集和你为什么要避免关系运算符)
b1zrtrql4#
我知道这个答案与你的问题明显矛盾,但是在所有常见的SIMD架构上都有SIMD比较(至少我知道的是这样)。
对于SSE2和
int32
参数,存在pcmpgtd
(固有:_mm_cmpgt_epi32
),假设__m128i x
中有4个整数,可以写为要为每个
x>0
(即x>=1
)和0
获取-1
(即0xFFFFFFFF
),如果需要1
而不是-1
,只需写入ntjbwcob5#
整数任意数到1 = 0||任意表达式
有点依赖于编译器,但是嘿;- )
kse8i1jr6#
我不熟悉C或SIMD指令的使用,但如果x是正整数,你不能这样做吗?
u1ehiz5o7#
使用这个:
y= 1/(1+e^(-10000*(x-0.995)))
这将给予
y = 0 for x <= 0.99
和y=1 for x>= 1
我不知道SIMD是什么,很可能有更好的方法,但是我想,如果你不想使用条件,你可以使用sigmoid函数,它根据你的条件返回0或1,这个函数就是你的
some_operation(x)
,注意这个函数只对小数位数为2的数字有效,也就是说,输入0.99将返回0,而输入0.999将返回1。2在计算之前,请确保将您的数字向下舍入到最接近的2位小数。如果有人感兴趣,我将一步一步地经历下面我的思考过程:
如果你想使用一个函数,而不是一个逻辑条件,它必须是连续的,这意味着一些值不符合条件,但如果这些值在一个非常窄的范围内,而你在数字之间的步长大于这个窄范围,它就可以工作。
所以你可以使用一个sigmoid函数。(把它输入wolfram alpha,这样就可以看到每一个变化)
向右移动一步,使其以1而不是0为中心。
然后你可以通过增加权重来增加函数的斜率。
现在斜率非常非常陡,但是如果我们输入x=1,我们仍然得到y = 0.5,所以我们需要把S形曲线向左移一点。
现在,如果x〈= 0.99,则y= 0;如果x〉= 1,则y=1。如果要使用更精细的分辨率,则必须调整权重(本例中为10000)和中心点(在这个例子中是0.995)。我刚刚检查了wolfram alpha中的计算,并迭代了什么起作用。如果你只使用2位小数,你可以使用低至4000的权重。
我相信有更好的方法来解决这个问题,但这就是我要解决的问题。