后端
每个 Kernel 都降低为同一种与后端无关的 IR,再由后端执行。用 --backend 选择:
| 后端 | 实现 | 说明 |
|---|---|---|
cpu |
解释器 | 参考实现;trace 逐步走的就是它 |
jit |
Cranelift 生成原生代码(WebAssembly 构建中用 WASM) | 与解释器结果逐位一致;CLI 的默认值 |
gpu |
WGSL compute,经 wgpu | Field 保留在设备上;小任务和设备无法接受的部分交给 JIT,并说明原因 |
best |
有设备时用 GPU,否则 JIT | Player 的默认值 |
entelechy run examples/showcase/scene.esn --backend gpu --out showcase.ppm一个表达式,在每个后端上一个答案
Section titled “一个表达式,在每个后端上一个答案”当机器把结果留给硬件决定时,语言替它决定一次(docs/DECISIONS.md):
- Float 的
max、min是 IEEE 754-2019 的 maximumNumber/minimumNumber:NaN 让步,max(-0.0, 0.0)不论顺序都是0.0。 - scatter 或 prefix 的整数
sum是每个元素的完整总和,只有总和溢出时才失败。 - 时钟以
Double秒整体进入 Kernel:clock()原样读取,time()由上下文舍入一次为Float。
这由 crates/backends/conformance 的一致性矩阵和 JIT 的随机程序测试保证。
与设备并存时,一次运行在“元素数 × Kernel 的典型工作量 ≤ --small”时交给 JIT,否则交给设备;读取设备刚产生结果的运行留在设备上。一串小的运行会一起去 JIT。选择只看运行和 Kernel,从不看时钟,所以回放每次放置都一样。
- 设备自己的编译器无法构建的 Kernel,此后在 JIT 上运行;
- 后端生成而设备拒绝的着色器是后端的错,仍会拒绝文档;
entelechy check会提示某个 Kernel 对设备编译器来说过大;会话发布时用large事件说明。- 节点的放置离开主后端时,
sync报告routed {node, backend, why};求值报告中的placements给出每个节点的后端、原因和上传/下载字节。 - 回放中可以断言放置:
expect placed ring main。
运行去哪里由后端决定;它计算什么不由后端决定。
Host 预算
Section titled “Host 预算”| 参数 | 默认 | 含义 |
|---|---|---|
--memory <MB> |
2048 | Host 同时可持有的 Field 内存(MiB) |
--work <M> |
4000 | 一个 Kernel 一次运行(所有元素合计)可执行的循环迭代数(百万) |
--small <operations> |
— | 低于此工作量的运行交给 JIT 而不是设备 |
run、render、replay、serve、graph、trace、bench 都接受这些参数。
entelechy run scene.esn --profile --out out.ppmentelechy bench examples/collapse/scene.esn --window 640x400 --backend all --frames 20 --repeat 3 --nodes--profile 的真实输出(第一个场景,JIT):
tint 0.521 ms jit (sum) 0.521 ms (the call and the wait after it; ...)preparing, ms a Kernel on the thread that prepared it — compiling, then building on its device ...: 0.4 0.0 fused.tint@1evaluated in 1.151584ms: executed [tint+rings], reused 0 -> /tmp/c.ppmbench 打印每帧最少用时、中位数以及与第一个后端的比值;--json 和 --compare 保存并比较测量结果。
后端可以发布原生操作,节点直接绑定:native.rasterize@1、native.rasterize@3、native.cover@1 等(status 中的 natives,本机 JIT 会话为 4 个)。它们以代数 0 出现在 kernels 列表中,不能被文档重新发布或撤回,也从不融合。光栅化器本身是一个包,原生版本是它的快速路径(见包)。

