免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4090 | 回复: 19
打印 上一主题 下一主题

[C] 判断4个整数符合“第一个为1,后三个为0”的方法 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-02-17 11:26 |只看该作者 |倒序浏览
[ 本帖最后由 safedead 于 2013-02-18 18:25 编辑 ]

有4个无符号整数,存储在四个变量里
uint64_t rax;
uint64_t rdx;
uint64_t r8;
uint64_t r9;

现在需要计算如下条件表达式的结果:
(rax == 1) && (rdx == 0) && (r8 == 0) && (r9 == 0)

我是这么设计的
uint64_t rsi = 0;
if (rax != 1) rsi = 1;
if (rdx != 0) rsi = 1;
if (r8 != 0) rsi = 1;
if (r9 != 0) rsi = 1;
rsi就是计算结果

还有没有更高效的算法?

根据hellioncu提供的算法
得到当前最优答案

movq    %rax, %rsi
xorq    $1, %rsi
orq     %rdx, %rsi
orq     %r8, %rsi
orq     %r9, %rsi
jz      .L_IS_ONE

不超过5个指令周期完成判断一个256位整数是否为1的运算

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2013-02-17 11:33 |只看该作者
[ 本帖最后由 safedead 于 2013-02-17 11:34 编辑 ]


我是这么写的:(rcx就是常数1,若条件表达式成立,rsi为0,否则为1)
        xorq        %rcx, %rcx
        incq        %rcx
        xorq        %rsi, %rsi
        test        %r9, %r9
        cmovnz        %rcx, %rsi
        test        %r8, %r8
        cmovnz        %rcx, %rsi
        test        %rdx, %rdx
        cmovnz        %rcx, %rsi
        cmpq        %rcx, %rax
        cmovne        %rcx, %rsi

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
3 [报告]
发表于 2013-02-17 11:36 |只看该作者
本帖最后由 Ager 于 2013-02-17 11:38 编辑

  1. if (rax != 1) rsi = 1;
  2. if (rdx != 0) rsi = 1;
  3. if (r8 != 0) rsi = 1;
  4. if (r9 != 0) rsi = 1;

  5. rsi就是计算结果
复制代码
没看明白 ……那四个uint64_t整数,预设好了是非0即1的吗? {:3_201:}



论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
4 [报告]
发表于 2013-02-17 11:59 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
5 [报告]
发表于 2013-02-17 12:06 |只看该作者
safedead 发表于 2013-02-17 11:26
[ 本帖最后由 safedead 于 2013-02-17 11:27 编辑 ]

有4个无符号整数,存储在四个变量里


好歹这个速度更高点吧

a = rbx | r8 | r9;
rsi = rax;
if (a != 0) rsi = 0;

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2013-02-17 13:38 |只看该作者
zylthinking 发表于 2013-02-17 12:06
好歹这个速度更高点吧

a = rbx | r8 | r9;


这个好,我总觉得我自己写得怪怪的
先将所有要判断为0的同或,如果为0表示全部为0
然后判断rax是否为1,只要两次cmov即可得到最终结果

我的目的是这样的
有n个64位整数构成一个大数,低位在前,高位在后,我要判断这个大数是否为1
以256位二进制数为例子
rax, rdx, r8, r9分别存储从低到高4个64位单元,如果这个256位数值等于1
必须满足:(rax == 1) && (rdx == 0) && (r8 == 0) && (r9 == 0)
用rsi保存中间结果,按照楼上的方法运算就是
rsi = 0;
rsi |= r9;
rsi |= r8;
rsi |= rdx;
if (rsi == 0) {
    if (rax == 1) 条件成立;
}

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
7 [报告]
发表于 2013-02-17 13:51 |只看该作者
本帖最后由 w_anthony 于 2013-02-17 13:52 编辑

如果你用C写,编译后看汇编,不出意外应该cmp+jnz+test+jnz+test+jnz+test+jnz,何必要计算以后再跳转呢?
既然是一个大数,那么刚好等于1的概率本身就很小,可能第一次cmp或者test就不满足条件,可以直接jnz掉,但是耍个花招反而要多算几次才知道结果。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2013-02-17 13:54 |只看该作者
改好了

rsi = 0;
if (rax == 1) rsi = 1;
rsi |= r9;
rsi |= r8;
rsi |= rdx;
if (rsi == 0) 条件成立

汇编结果:
movq    $1, %rcx
xorq    %rsi, %rsi
test    %rcx, %rax
cmovnz  %rcx, %rsi
orq     %r9, %rsi
orq     %r8, %rsi
orq     %rdx, %rsi
test    %rsi, %rsi
jz      .L_IS_ONE

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2013-02-17 13:56 |只看该作者
w_anthony 发表于 2013-02-17 13:51
如果你用C写,编译后看汇编,不出意外应该cmp+jnz+test+jnz+test+jnz+test+jnz,何必要计算以后再跳转呢?
...


这么编译相当糟糕,破坏流水线的惩罚可是很严重的,跳转指令要尽可能的少
多用几个cmov,最后跳转比较有利

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
10 [报告]
发表于 2013-02-17 14:08 |只看该作者
rsi = (rax ^ 0x1) | (rdx | r8 | r9)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP