加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C签名和unsigned int vs long long speed

发布时间:2020-12-16 03:33:09 所属栏目:百科 来源:网络整理
导读:今天,我注意到在我的64位PC上,int,unsigned,long long和unsigned long long之间的几个简单的按位和算术运算的速度差别很大. 特别是,对于unsigned而言,以下循环的速度大约是long long的两倍,这是我没想到的. int k = 15;int N = 30;int mask = (1 k) - 1;whil
今天,我注意到在我的64位PC上,int,unsigned,long long和unsigned long long之间的几个简单的按位和算术运算的速度差别很大.

特别是,对于unsigned而言,以下循环的速度大约是long long的两倍,这是我没想到的.

int k = 15;
int N = 30;
int mask = (1 << k) - 1;
while (!(mask & 1 << N)) {
    int lo = mask & ~(mask - 1);
    int lz = (mask + lo) & ~mask;
    mask |= lz;
    mask &= ~(lz - 1);
    mask |= (lz / lo / 2) - 1;
}

(完整代码here)

以下是时间(以秒为单位)(对于g -O,-O2和-O3):

1.834207723 (int)
3.054731598 (long long)
1.584846237 (unsigned)
2.201142018 (unsigned long long)

这些时间非常一致(即1%的保证金).
如果没有-O标志,每个标志的速度都会慢一秒,但相对速度是相同的.

这有明显的原因吗?
矢量化可能适用于32位类型,但我无法看到巨大的位置
long long和unsigned long long之间的区别来自.
某些类型的某些操作比其他类型的操作慢得多,
或者只是64位类型更慢(即使在64位架构上)也是一般的事情?

对于那些感兴趣的人,这个循环遍历{1,2,…,30}的所有子集,恰好有15个元素.这是通过在小于1 <<<<<<<<<<<<<<<<<<<< 30&gt
对于目前的情况,这是155117520次迭代.
我不知道这个片段的来源了,但this帖子解释了更多.

编辑

从汇编代码看,当类型未签名时,可以使除法更快.我认为这是有道理的,因为我们不必考虑符号位.

此外,32位操作使用movl和其他xxxl指令,
而64位操作使用movq和xxxq.

编辑2

在阅读我链接的帖子后,我决定使用那里给出的公式:

T k = 15;
T N = 30;
T mask = (1 << k) - 1;
while (!(mask & 1 << N)) {
    T t = mask | (mask - 1);
    mask = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(mask) + 1));
}

这在上面发布的代码的大约三分之一的时间内运行,并且对所有四种类型使用相同的时间.

解决方法

代码中最慢的操作是
mask |= (lz / lo / 2) - 1

32位除法明显快于64位除法.例如,在Ivy Bridge上,32位IDIV需要19-26个时钟,而64位IDIV需要28-103个时钟延迟.

无符号版本也比签名更快,因为除以2是在无符号情况下的简单位移,并且没有大小扩展调用(CDQ,CQO).

在无符号的情况下,在签名时是简单的位移

[1] http://www.agner.org/optimize/instruction_tables.pdf

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读