编辑:对于将来偶然发现这一点的人:Imagemagick 使用 MP 库。如果有可用核心,使用它们会更快,但如果有并行作业,则无济于事。
执行以下操作之一:
- 连续地完成你的工作(使用 Imagemagick 的并行模式)
- 为调用相关的 imagemagick 二进制文件设置 MAGICK_THREAD_LIMIT=1。
通过使 Imagemagick 仅使用一个线程,它在我的测试用例中速度会降低 20-30%,但这意味着我可以在每个核心上运行一个作业而不会出现问题,从而显着提高性能。
原始问题:
在使用 ImageMagick 转换一些图像时,我注意到一个有点奇怪的效果。使用 xargs 比标准 for 循环慢得多。由于 xargs 仅限于单个进程,因此应该像 for 循环一样运行,因此我对此进行了测试,发现它大致相同。
因此,我们有了这个示范。
- 四核 (AMD Athalon X4, 2.6GHz)
- 完全在 tempfs 上工作(总共 16g 内存;无交换)
- 无其他重大负荷
结果:
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 1 convert -auto-level
real 0m3.784s
user 0m2.240s
sys 0m0.230s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 2 convert -auto-level
real 0m9.097s
user 0m28.020s
sys 0m0.910s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 10 convert -auto-level
real 0m9.844s
user 0m33.200s
sys 0m1.270s
有人能想到为什么运行这个程序的两个实例在实时上要花费两倍多的时间,而在完成相同任务时处理器时间要花费十倍多的时间吗?在最初的打击之后,更多的进程似乎没有产生那么显著的效果。
我认为这可能与磁盘寻道有关,所以我完全在内存中进行了该测试。这可能与 Convert 的工作方式有关,并且一次拥有多个副本意味着它无法高效地使用处理器缓存,或者其他原因?
编辑:处理 1000x 769KB 文件时,性能符合预期。很有趣。
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 1 convert -auto-level
real 3m37.679s
user 5m6.980s
sys 0m6.340s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 1 convert -auto-level
real 3m37.152s
user 5m6.140s
sys 0m6.530s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 2 convert -auto-level
real 2m7.578s
user 5m35.410s
sys 0m6.050s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 4 convert -auto-level
real 1m36.959s
user 5m48.900s
sys 0m6.350s
/media/ramdisk/img$ time for f in *.bmp; do echo $f ${f%bmp}png; done | xargs -n 2 -P 10 convert -auto-level
real 1m36.392s
user 5m54.840s
sys 0m5.650s
答案1
与您的 L1 缓存相比,您要转换的文件有多大?您的 L2 缓存有多大?
如果不仔细查看内部情况,我怀疑缓存争用会导致您的 CPU 在等待数据重新缓存时处于空闲状态,因为其他进程不断将重要内容从快速内存中踢出。