跳到正文
博客园· .NET骚操作·· 3 小时前AI 评分60

N·Body 2.0 发布:3MB 的 C# 程序模拟星系碰撞与三体轨道

3MB 的 C# 程序,装下一整个宇宙:N·Body 2.0 发布 - .NET骚操作

AI 导读

作者发布 N·Body 2.0,一个用 C# 和 .NET 10 写成的 N 体引力模拟程序,包含 35 个场景,Native AOT 打包后 exe 约 3.3MB。

正文

00-galaxy-collision

上面是 65,536 颗恒星的星系碰撞,GPU 逐对计算引力,2.25 倍速。它来自我刚发布的 N·Body 2.0:从物理引擎到渲染、界面、音乐,全部用 C# 写成,最后打包成一个 3MB 的 exe。

一年前立的 flag

2025 年 8 月,我写过一篇《当物理定律与高精度计算相遇:我的新开源项目 N-Body》。那篇文章立了不少 flag:要用 ODE45、Cash-Karp 这些数值方法把误差压下去,要接入我自己的高精度库 Sdcb.Arithmetic,要做性能基准,要跟 double 比精度……

当时的项目长这样:

01-v1-2d

一个 2D 窗口,几个小球拖着尾巴转圈。整个仓库 25 个文件、1562 行代码。立完 flag 之后,最后一次提交是 2025 年 8 月 10 日,改了 8 行,提交信息叫 flys 208。

然后就没有然后了。

Sdcb.Arithmetic 呢?翻遍 csproj,一个引用都没有。

站在 2026 年全面进入 AI 时代的今天回头看,这玩意儿就是人类 Slop。

02-emoji-clown

交给 AI

10 月 19 日晚上 8 点多,我在 VS Code 里打开 GitHub Copilot,模型选 Claude Opus 5.5,大意就一句话:这个项目太原始了,给它来个脱胎换骨的重构,场景多加点,要一打开就让人"哇塞"。

它先把代码读了一遍,然后问了我两轮问题:渲染用 Direct3D 11 计算着色器,还是继续 Direct2D,还是干脆改成网页;2D 还是 3D;界面用 ImGui 还是自己画一套毛玻璃 HUD;要哪些场景;要不要音乐、要不要 Native AOT……顺便它还注意到我的显卡是 RTX 3080 Ti。

我基本都选了最难的那个:D3D11、全 3D、自绘 HUD、全部场景、程序化音乐、AOT、CI。

然后它就开干了。物理核心交给一个并行的子代理去重写,它自己同时写渲染器。

一打开就是"哇塞"

03-emoji-stand-back

先看结果。35 个场景里随便挑 8 个,每个 2 秒:

04-scenario-tour

依次是:十二星冠、飞蛾 I、Hénon 42、环双星行星(就是塔图因)、原行星盘、冷坍缩、旋涡星系、银河系与仙女座。

双击 exe 直接全屏,进入"自动巡游":镜头自己慢慢转,场景自己轮播,不碰键盘也能看半天。按 G 打开场景画廊,点一下就切过去:

05-gallery

星系碰撞

就是文章开头那张。两个盘状星系一共 65,536 颗恒星,每一步都在 GPU 上两两计算引力,一步就是 40 多亿对相互作用(65536² ≈ 4.3×10⁹)。没有用树算法,也没有近似,就是暴力 O(N²),一个分块的 HLSL 计算着色器搞定。在我的 3080 Ti 上能跑满 60 帧。

为了让两个星系真的能合并,而不是互相穿过去,它还加了暗物质晕和动力学摩擦。这一点我一开始都没想到。

三体周期解

三体问题一般没有解析解,但在一些特殊的初始条件下,三颗星会沿着固定的图案周而复始地运动。2013 年,两位塞尔维亚物理学家 Šuvakov 和 Dmitrašinović 一口气找到了 13 族新解,起名叫蝴蝶、飞蛾、蜻蜓、阴阳、大黄蜂……2.0 把这些都放了进来。这是"蝴蝶 I":

06-butterfly

蝴蝶效应

这是我最喜欢的场景。屏幕上同时跑两份毕达哥拉斯三体系统,初始位置只差十亿分之一(10⁻⁹)。一开始两份完全重合,看起来只有一组白色的星;跑一阵子之后它们分道扬镳,一份变橙,一份变蓝,各走各的路:

07-butterfly-effect

右上角"相空间分离"那一行,就是两份系统之间的差距,从 10⁻⁹ 一路往上涨。

真实太阳系

八大行星的位置、质量、倾角,全部来自 JPL 的 J2000 轨道根数。单位是天文单位和年,画面上 1 秒约等于 4 年:

08-solar-system

引力沙盒

按住 Shift 拖动鼠标,就能往恒星系里扔新天体,拖得越长,初速度越快;撞到一起的天体会合并:

09-sandbox

不只是好看

当年那些 flag 里,我最在意的是精度。

2.0 的物理核心里有四种积分器:Leapfrog、Yoshida 4、RK4,以及自适应步长的 Dormand–Prince 5(4),也就是 MATLAB 里的 ODE45。按 I 可以现场切换。

右上角实时显示能量误差,下面还有一条能量漂移曲线。拿 8 字形轨道来说,默认的 Dormand–Prince 能量误差在 10⁻¹⁴ 量级;切到 RK4 跑一会儿,曲线往上跳了一截,误差变成 10⁻⁶ 量级:

10-integrator-rk4

另外还配了 xUnit 测试,检查能量、动量、角动量守恒,以及周期轨道转一圈之后能不能回到原点。

至于 Sdcb.Arithmetic 高精度……2.0 里依然一行都没用上。flag 屹立不倒。

一个纯 C# 的 3MB 宇宙

整个项目基于 .NET 10,C# 代码约 5000 行,HLSL 着色器不到 600 行,除此之外没有一行 C++。

物理核心:Sdcb.NBody 是一个 net10.0 的普通类库,标记了 IsAotCompatible,不依赖任何图形 API,拿到 Linux 上也能跑。天体数据按 SoA(结构数组)存成几个 double[],算引力时用 Vector<double> 做 SIMD,天体多了再套一层 Parallel.For。核心循环大概长这样:

ReadOnlySpan<Vector<double>> PX = MemoryMarshal.Cast<double, Vector<double>>(px.AsSpan(0, n));
// ……PY、PZ、M 同理
for (int k = 0; k < PX.Length; ++k)
{
    Vector<double> dx = PX[k] - vxi, dy = PY[k] - vyi, dz = PZ[k] - vzi;
    Vector<double> r2 = dx * dx + dy * dy + dz * dz + veps;
    Vector<double> inv = one / Vector.SquareRoot(r2);
    Vector<double> s = M[k] * inv * inv * inv;
    sx += dx * s; sy += dy * s; sz += dz * s;
}

一个 MemoryMarshal.Cast 就把 double[] 当成向量数组来用,没有 unsafe,也不用手写 AVX 指令。三体、太阳系这类小场景走这条 CPU 路线,全程双精度;星系那种几万颗星的场景才交给 GPU。

渲染与界面:通过 Vortice 直接调 Direct3D 11,HLSL 着色器作为嵌入资源打进 exe,运行时编译;HUD 用 Direct2D 画毛玻璃;窗口是原生 Win32,没有 WinForms 也没有 WPF。

音乐:用 XAudio2 实时合成,仓库里一个音频文件都没有。

发布:Native AOT 单文件。Release 里的 NBody-win-x64.exe 只有 3.3MB,不用装 .NET 运行时,双击就能跑。另外还有中英文界面切换、F12 截图、按显卡自动选择画质档位。

谁说 C# 只能写 CRUD?

那一晚

从晚上 8 点多开始,到 11 点半多提交,前后大约三个半小时。

这期间我基本就是个"甲方":偶尔运行一下,告诉它哪里报错了、启动时闪屏了、界面有点重叠,剩下的全是它自己搞定。中间它还给程序加了个截图参数,自己跑、自己截图、自己看图找问题,后来就不怎么需要我了。

11-emoji-what-operation

最后的成果:77 个文件,新增 6396 行,删掉 1528 行。

账单

会话记录里,每一次模型调用的 token 数都有。我统计了一下:

项目 数值
模型调用 239 次
输入 token 约 6924 万
输出 token 约 35.3 万(其中推理 11.2 万)
工具调用 302 次(PowerShell 121、编辑 61、看文件 54、新建文件 47)
单次最大上下文 约 48.8 万 token
纯模型耗时 约 69 分钟

输入差不多是输出的 200 倍。这是 Agent 干活的典型特征:每一轮都要把整个上下文重新喂一遍,真正写出来的代码反而没多少。

好在每一轮的上下文前缀几乎都和上一轮一样,绝大部分都能命中提示缓存。按 Anthropic 官方 API 价格折算,这一晚大约 25 美元。

12-emoji-family-condition

我是用 GitHub Copilot 跑的,上面只是折算成 API 价格,给大家一个量级参考。25 美元、一个晚上,把一个烂尾了一年多的项目做成这样。

线上版:浏览器里也能玩

2.0 只能在 Windows 上跑。为了让手边没有 Windows 的朋友也能看看,第二天下午我又让它在我的网站上做了一个网页版:

👉 https://sdcb.ai/n-body

13-web-version

网页版是用 TypeScript 和 WebGPU 写的(不支持 WebGPU 的浏览器会退回 WebGL2),35 个场景、HUD、音乐都有。它相当于照着 C# 版重写了一遍,代码没有开源,这里就不展开了。推荐用新版的 Chrome 或 Edge 打开。

下载

默认全屏启动,Esc 退出;想在窗口里跑,加上 --windowed 参数。常用按键:

按键 功能
左键拖动 / 右键拖动 / 滚轮 旋转 / 平移 / 缩放
← → 上一个 / 下一个场景
↑ ↓ 加速 / 减速
G 场景画廊
I 切换积分器
Shift + 拖动 在沙盒里发射天体
Tab 隐藏界面
L 中文 / English
H 完整帮助

最后

一年前,我在那篇文章里把"AI 辅助开发"列为三块拼图之一。现在看来,当时的我还是太保守了。而 C# 和 .NET 这块拼图,从一开始就是够用的:SIMD、并行、直接调 Direct3D、AOT 出一个 3MB 的 exe,这些它早就都能做,只是以前没人愿意花这么多时间去写。

14-emoji-thats-all

交流

感谢阅读到这里,如果觉得 N·Body 好玩,欢迎去 GitHub 点个 Star,也欢迎评论和点赞,这是我持续创作的动力!

欢迎关注微信公众号 .NET骚操作,或者扫码加入 .NET骚操作2群 微信交流群:

(如果微信群二维码过期,请加入 .NET骚操作交流QQ群:495782587)

来源:博客园 · cnblogs.com