找回密码
 立即注册
搜索
查看: 1515|回复: 16

[软件] 求助:程序速度比较

[复制链接]
     
发表于 2026-6-12 14:55 | 显示全部楼层 |阅读模式


数组 a[0]~a[n-1],共n个元素。
组成数值圆环,首尾相连。
首值下标 i=0,向后移动(i++)
尾值下标 j=n-1,向前移动(j--)


如何做到数值循环访问,以下有2个方案
方案A:
while (true)
{
  if  ( i≠(n-1) )
    i++ ;
  else
    i=0 ;


  if  ( j≠0 )
    j-- ;
  else
    j=n-1 ;


  其它程序段
}


方案B:
while (true)
{
  i = (i+1)  mod  n  ;
  j = (n+j-1)  mod  n  ;


  其它程序段
}


两种边界处理方式,哪个更快一些?
例如采用C++编译,方案A 的 if 语句,方案B 的mod运算,耗用机器指令的时钟周期,相差有多少?
个人有以下理解,if 语句 编译成机器语言后,大约耗时20个时钟。而mod运算本质上是除法指令,大约耗时200个时钟。两者耗时相差10倍。
这样理解是否有误区?
个人更喜欢方案A,直观、简单、容易理解。
而方案B,看起来高大上,纸面上程序简洁,但是难理解,而且速度慢。

评分

参与人数 2战斗力 -4 收起 理由
WntFlm -2 弱智
yvev -2 倒垃圾

查看全部评分

回复

使用道具 举报

     
发表于 2026-6-12 15:01 | 显示全部楼层
这种东西问AI 比上S1问又快又准,合理怀疑楼主就是想要白嫖ai回答,这是claude 答案:


结论先说:你的方向对(方案A通常更快),但两个数字都不准,各错了一个数量级。

**if 语句的真实开销**

编译后是 `cmp` + 条件跳转,在现代 x86 上这俩经常宏融合成一条 µop。关键在分支预测:

- 预测命中:约 1~2 个周期,几乎免费
- 预测失败:才是你说的 15~20 周期(流水线清空)

而你这个分支极其规律——n 次循环里只有 1 次走 else 分支,预测器轻松学会,几乎每次都命中。所以方案A的真实成本接近 1~2 周期,不是 20。

**mod 的真实开销**

mod 编译成 `div`/`idiv` 指令。32 位除法在 Skylake 上延迟约 20~26 周期,Ice Lake / Zen 3 之后已优化到约 10~18 周期,64 位会更慢一些。不是 200,200 周期那是上世纪的 CPU 或软件模拟除法的水平。

所以真实差距大约还是 10 倍量级(2 周期 vs 20 周期),你的结论碰巧成立,但绝对值都高估了 10 倍。

**三个重要的"但是"**

1. 如果 n 是编译期常量,编译器根本不会生成 div,而是用乘法+移位的魔数技巧(约 4~6 周期);如果 n 是 2 的幂,直接 `and` 掩码,1 个周期,这时方案B反而最快。
2. 比你的方案A更优的写法是:

```cpp
if (++i == n) i = 0;
if (j-- == 0) j = n - 1;
```

   逻辑等价但编译器很容易把它生成 `cmov`(条件传送),完全无分支、无预测失败风险,稳定 2~3 周期。这是环形缓冲区的标准写法。

3. 实战中这点差距通常无关紧要——循环体里只要碰一次内存(数组访问、cache miss 几十到几百周期),索引回绕的开销就被淹没了。除非循环体极小且全在寄存器里跑,否则 A/B 测不出差别。

所以你的审美没问题:方案A(或上面的 cmov 友好写法)直观且快。方案B 的价值主要在 n 为 2 的幂时(掩码写法 `i = (i+1) & (n-1)` 既简洁又是最快的),通用变量 n 下确实是又慢又"装"。

评分

参与人数 1战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

     
发表于 2026-6-12 15:02 | 显示全部楼层
  1.     let mut forward = (0..n).cycle();
  2.     let mut backward = (0..n).rev().cycle();
  3.     loop {
  4.         let i = forward.next().unwrap();
  5.         let j = backward.next().unwrap();
  6.     }
复制代码


Rust,别纠结这个了,编译器比你想象中的聪明

评分

参与人数 1战斗力 +1 收起 理由
proof1 + 1

查看全部评分

回复

使用道具 举报

     
发表于 2026-6-12 15:53 | 显示全部楼层
看了看楼主发帖记录 楼主这是把探油当AI用了 也是提前好几年用上“人工”智能了
回复

使用道具 举报

     
 楼主| 发表于 2026-6-12 16:09 | 显示全部楼层
Xerxes_2 发表于 2026-6-12 15:02
Rust,别纠结这个了,编译器比你想象中的聪明

看不懂,话说这是什么语言?

还是C++的某种库模版?(之前我猜测,已经有某种现成的环状数据结构,提供给设计者使用)

评分

参与人数 1战斗力 -2 收起 理由
yvev -2 感觉脑子有点问题

查看全部评分

回复

使用道具 举报

     
发表于 2026-6-12 16:20 | 显示全部楼层
proof1 发表于 2026-6-12 18:09
看不懂,话说这是什么语言?

还是C++的某种库模版?(之前我猜测,已经有某种现成的环状数据结构,提供 ...

Rust,我说了啊
回复

使用道具 举报

发表于 2026-6-12 17:58 来自手机 | 显示全部楼层
楼主先评估下是否真到了需要抠这点性能的地步

—— 来自 Xiaomi 22041211AC, Android 12, 鹅球 v4.0.100-alpha
回复

使用道具 举报

     
发表于 2026-6-12 20:22 | 显示全部楼层
楼主是程序员吗?我不是程序员都知道rust
回复

使用道具 举报

     
发表于 2026-6-12 20:43 | 显示全部楼层
子犴 发表于 2026-6-12 15:53
看了看楼主发帖记录 楼主这是把探油当AI用了 也是提前好几年用上“人工”智能了 ...

“人肉搜索”这个词已经变死语了吗
回复

使用道具 举报

     
发表于 2026-6-12 23:24 | 显示全部楼层
为什么知名活化石proof1**还在纠结编程问题?本来以为到了AI时代**应该已经没有上泥潭的必要了
我甚至记得去年还是前年他问过一个vf6.0的问题
回复

使用道具 举报

     
发表于 2026-6-13 00:08 来自手机 | 显示全部楼层
我雷达响了,是 python 侠!
回复

使用道具 举报

发表于 2026-6-13 06:30 来自手机 | 显示全部楼层
ring buffer直接用boost库里的不就行了,干嘛手搓啊

—— 来自 Xiaomi 24129PN74C, Android 16, 鹅球 v3.5.99
回复

使用道具 举报

     
发表于 2026-6-13 17:37 来自手机 | 显示全部楼层
没有benchmark的性能讨论毫无意义

—— 来自 Xiaomi 23049RAD8C, Android 15, 鹅球 v3.5.99
回复

使用道具 举报

     
 楼主| 发表于 2026-6-13 21:55 | 显示全部楼层
本帖最后由 proof1 于 2026-6-13 21:57 编辑

2. 比你的方案A更优的写法是:

if  (++i == n)   i = 0 ;
if  (j-- == 0)     j = n-1 ;

这是环形缓冲区的标准写法。

if  (j-- == 0)   j = n-1 ;
   不解
A、先判断,如果j≠0,执行j--,略过 j=n-1
B、先判断,如果j=0,执行j--,执行 j=n-1

是这个过程吗?

回复

使用道具 举报

     
发表于 2026-6-13 23:34 | 显示全部楼层
袄_偶滴小乔 发表于 2026-6-12 20:43
“人肉搜索”这个词已经变死语了吗

过去只有这个词 但是现在回头看 “搜索”已经不足以形容楼主这种行为了 这不是单纯从已有资料中查找 而是让探油无私创造 😄
回复

使用道具 举报

     
发表于 2026-6-14 00:36 | 显示全部楼层
袄_偶滴小乔 发表于 2026-6-12 20:43
“人肉搜索”这个词已经变死语了吗

人肉搜索是死语了没错
但是死语的原因是这个词的词义放今天叫“开盒”啊
回复

使用道具 举报

     
发表于 2026-6-14 01:40 | 显示全部楼层
盐星 发表于 2026-6-14 00:36
人肉搜索是死语了没错
但是死语的原因是这个词的词义放今天叫“开盒”啊 ...

开盒是指人肉搜索的对象是人,媒体传多了把最关键的因素给传没了,导致这个词后期有所转义。“人肉“是和”搜索引擎“相对的,那个时期最典型的人肉搜索其实是百度知道
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|上海互联网违法和不良信息举报中心|网上有害信息举报专区|962110 反电信诈骗|举报电话 021-62035905|Stage1st ( 沪ICP备13020230号-1|沪公网安备 31010702007642号 )

GMT+8, 2026-6-14 07:08 , Processed in 0.107927 second(s), 8 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表