外存地形流式加载:GB 级 DEM 如何在笔记本上打开
2 km × 2 km 工地的 5 cm DEM 含 16 亿个高程值——按 32 位浮点为 6.4 GB,超过大多数显卡的显存。外存(out-of-core)流式加载是工程上的答案:把整个表面以可分块读取的形式保存在磁盘上,内存中只保留屏幕能显示的部分。本文结合每一步背后的数字,说明 STREAM 是如何做到的。
第 1 步:分块、多分辨率的副本
源 GeoTIFF 或 BigTIFF 只读取一次,转换为本地副本:固定的 512 × 512 分块布局并带金字塔层级,高程为 Float32,正射影像为 RGBA8,以 ZSTD 压缩的分块 BigTIFF 存储。分块表记录哪些块已构建,只有全部块构建完成,副本才算完整。
对于 40000 × 40000 的 DEM,全分辨率为 79 × 79 = 6241 块,每块按 Float32 恰为 1 MiB。逐级减半直到一块,又增加七个金字塔层级——共 8380 块。每块都有固定的身份(层级、x、y),这让后续一切都可以寻址。
| 量 | 数值 | 由来 |
|---|---|---|
| 全分辨率分块数 | 79 × 79 = 6241 | 40000 ÷ 512 = 78.1,向上取整 |
| 一个 Float32 分块的大小 | 1 MiB | 512 × 512 × 4 字节 |
| 含金字塔的层级数 | 8 | 从 79 块逐级减半到 1 块 |
| 整个金字塔的分块数 | 8380 | 所有层级求和 |
| 1920 × 1080 屏幕 | ≈ 7.9 个分块的像素量 | 207 万 ÷ 262144 |
第 2 步:只请求相机看得见的部分
每一帧,相机状态都会生成一个请求集合:覆盖整个视图的固定粗级集合,以及您关注区域的细节集合。集合之外的分块不解码、不上传、不保留。
这正是约束内存的那条线。1920 × 1080 的视图大约只有八个完整分块的像素量;加上余量和多级混合,工作集保持在几十个分块——几十 MB——无论文件是 200 MB 还是 20 GB。
第 3 步:在渲染线程之外解码,最新的优先
解码在工作线程上以任务形式执行,从后台预测到关键共五个优先级,并限制同时进行的任务数。每个请求带有一个“代”;相机移开后,旧代任务会被取消而不是跑完,因此快速平移不会留下一串没人会看的分块队列。
上传顺序跟随相机焦点与可见性。细级分块尚未就绪时,由其上方的粗级分块顶替——表面始终闭合,分块到达后细节逐步清晰。
第 4 步:淘汰而不留空洞
GPU 图集写满时,淘汰策略优先移除与新块同级或更粗的分块,考虑与相机焦点的距离,并保护提供粗级回退的页面。为细节腾出空间时,绝不会移走下面的底图。
高程与正射影像作为各自独立的稀疏页面集合管理,各有驻留,因此沉重的正射影像不会抢走地形的高程分块。
流式加载对工程师意味着什么
代价转移到首次打开:转换只运行一次,并显示可取消的进度卡;之后同一测量数据几秒即可重新打开。同一工地的多个 DEM 会合并为一个虚拟镶嵌——最上层的有效像元优先,NoData 透到下层——各项分析读取的正是渲染器绘制的同一镶嵌。
这一切都不需要服务器:转换、流式加载与渲染都在本机进行,在 GPU 上使用 Vulkan,这让 GB 级测量数据可以在工地笔记本上查看,而无需上传到任何地方。
常见问题
对地形数据来说,外存是什么意思?
数据集以分块、多分辨率的形式保存在磁盘上,只把当前视图需要的部分载入内存。约束内存的是屏幕,而不是文件大小。
40000 × 40000 的 DEM 有多少分块?
按 512 × 512 分块,全分辨率为 79 × 79 = 6241 块,每块按 Float32 为 1 MiB;加上七个金字塔层级共 8380 块。
为什么首次打开更慢?
因为源数据要先一次性转换为带金字塔层级的本地分块副本。之后渲染器直接从副本读取分块,重新打开只需几秒。
在 STREAM 中体验地形流式加载
原生 Windows · 完全离线 · 免费测试版