openlang

热循环里 try 和 catch unreachable 的对比,数字完全对不上

我在给 try parseLine(line) 和 parseLine(line) catch unreachable 计时,输入是大约 200 万条生成的 ts,level,bytes 行,对 bytes 求和。用 -Doptimize=ReleaseFast 构建。

try 那一版报出几百微秒,打印的是一个错误名,而不是总和。catch unreachable 那一版要跑几十毫秒,总和也不一样。ReleaseSafe 和 Debug 下第二个会 panic。我每 5000 行加了一条坏行,想让它“更真实”。用 --bad-every 0 的话看起来正常些,但我不明白为什么影响这么大。

两个循环如下。

const e = try parse.parseLine(line);
total += e.bytes;
// vs
const e = parse.parseLine(line) catch unreachable;
total += e.bytes;

我猜是错误返回跟踪或者内联,汇编还没看。输入生成已经在计时器之外了。(splitScalar 好像是 0.12 左右出现的,我记得是这样,不对就算了。)

所以这到底在测什么?谢谢大家指点。

从英语翻译查看原文

后续讨论 2

顺着彼此的依据读下去
  1. 固定链接

    你比较的并不是同一份工作的两种处理方式。try 那次在第一条坏行就直接退出了。2M 行只花几百 µs,说明它几乎没开始跑,你看到的错误名就是那次提前返回带出来的。如果你的生成器写的是 i % 5000 == 0,那第 0 行就已经是坏的,所以它一上来就挂了。

    catch unreachable 那次是另一个问题。在 ReleaseFast 下,第一条坏行就是未定义行为,优化器想怎么处理都可以。这就是总数不对的原因。Debug 和 ReleaseSafe 会 panic,是因为它们真的做了检查。那几十 ms 也不是能信的数字,因为编译器可能已经把循环折叠成了奇怪的东西。

    我会先用零条坏行跑基准,再用 catch continue 或者计数器处理坏行,然后比较这两种。把实际解析的行数和总数一起打印出来,这样你就知道循环有没有跑到最后。

    说实话我觉得这像是代码生成的怪问题,所以也看看你的 Zig 版本。你用的是哪个构建?

    从英语翻译查看原文

同一个问题的其他角度

  1. 简单循环非常慢,gfortran,200000 x 64 数组

    一个小型标定工具,代码在下面。输出是对的,但太慢了。detrend+clip 要好几秒,rms 也比该有的速度慢,每个元素只有一次乘法和一次加法。我试过 -O3 和 -march=native,没什么变化。怀疑是 Apple silicon 上的 s…

    回复 2最近活动 fortran
  2. running_mean 很慢,时间花在 memmove 而不是算术运算上

    平滑传感器数据。数组是 readings(nstation, ntime),站点在前,因为数据文件就是这样排布的,其他工具也要读。对站点做一层循环,每个站点调用一次 running_mean: 模块里是这样: 规模是 1500 个站点,20000 个…

    回复 1最近活动 fortran
  3. 你说的是哪个构建时间?

    每个讨论拆 crate 的帖子,最后都会有人甩出一个构建时间。其实有两个,而且变化方向不一样。 干净构建指的是从空的 target 开始的全部过程。拆分可能会让它稍微变差,因为每个 crate 都带着自己的元数据,链接器还是得看到全部内容。编辑循环指…

    回复 2最近活动 rust