rod*_*gob 5 c++ io performance image
我有一个速度关键的程序,它将反复从磁盘读取图像并从中计算值。图像太多,无法存储在内存中。
将读取同一组图像,我们不会更改/编辑它们,并且它们的顺序是固定的。
并非所有图像都具有相同的大小,但当编码为 PNG 时,它们都大约为 1 Mb。它们有数以万计,大部分 RAM 已经用于存储计算值。
除了购买更快的磁盘或使用 RAID,读取图像序列的最快方法是什么?
将它们全部放在一个大的 tar 文件中(并使用自定义解压缩代码读取它们),而不是作为文件夹中的单个文件会更快吗?
我找不到PNG解码的多线程实现,所以这个阶段也可能成为瓶颈。使用 WebP 而不是 PNG 会提供额外的速度优势吗?
我应该考虑/评估哪些其他想法?
亲爱的堆栈溢出社区,
正如这里所承诺的,这是根据您的许多建议进行的实验的结果。特别感谢@user894763 如何让我走上“正确的道路”。
tl;dr在未压缩的 tar 中使用 pnm 文件(是的,我说的是 pnm!)。
我在两台高端机器上做了实验,一台使用 SSD 磁盘,另一台使用网络文件系统。两者都具有高端 CPU,但在磁盘访问方面表现出“频谱的两端”。令人惊讶的是,两台机器的结论是相同的。我只报告一组结果(对于后一种情况)。两个实验中文件格式之间的比率几乎相同。
从这些实验中我学到了两件重要的事情:
我正在按固定顺序读取一组约 1200 个图像,不对图像进行任何计算,我只是测量将像素加载到内存中的时间。pnm 格式的 tar 文件大小约为 600 MB,png 格式的 tar 文件大小约为 300 MB,webp 格式的 tar 文件大小约为 200 MB。
“新读”是指在机器上完成的第一次读取。
“缓存读取”是指在同一台计算机上完成的第二次读取(以及任何后续读取)。
所有数字大约为+/- 10 Hz。
webp fresh read: 30 Hz
webp cached read: 80 Hz
webp + tar fresh read: 100 Hz
webp + tar cached read: 100 Hz
png fresh read: 50 Hz
png cached read: 165 Hz
png + tar fresh read: 200 Hz
png + tar cached read: 200 Hz
pnm fresh read: 50 Hz
pnm cached read: 600 Hz
pnm + tar fresh read: 200 Hz
pnm + tar cached read: 2300 Hz
Run Code Online (Sandbox Code Playgroud)
有人告诉我也许有办法改变 webp 压缩参数以使解压更快。我怀疑它仍然无法匹配 pnm 性能。
请注意,我使用自定义代码来读取 tar 文件中的图像,该文件是从磁盘“逐个图像”读取的。
我不知道为什么读取“新鲜”的 webp 图像比 png 图像慢,我只能推测网络磁盘系统有一些“内部”缓存,在某种程度上改变了行为。不过这并不影响上课。
如果您要多次读取一个文件(或一组文件),操作系统磁盘缓存将使所有未来的读取基本上“与从 RAM 读取一样快”。
即使从磁盘读取,解压缩图像的时间也是不可忽略的。
将所有文件放入单个未压缩(tar)文件中,可以显着加快速度,因为操作系统会假设将读取整个文件,甚至在我们访问未来图像之前就预先加载它们。当简单地读取文件夹内的内容时,这似乎不会发生。
如果小心谨慎,从磁盘读取图像序列时(特别是重复读取时)可以获得 4x ~ x10 倍的加速。