【问题标题】:vips and pyvips physical memory usagevips 和 pyvips 物理内存使用情况
【发布时间】:2018-01-31 00:18:26
【问题描述】:

我循环读取 100 张 jpeg 图像并从中提取不同的区域。

循环内容:

   VImage in = VImage::new_from_file(impath.c_str(),
          VImage::option()->
          set( "access", VIPS_ACCESS_SEQUENTIAL ) );

   VImage out = in.extract_area(x0, y0, x1 - x0, y1 - y0);
   cout << out.avg() << endl;

或者在python中同样的事情:

img_full = pyvips.Image.new_from_file(impath, access='sequential') 
img = img_full.extract_area(x0, y0, x1 - x0, y1 - y0)
print(img.avg()) 

我看 RSS,物理内存使用情况。它从大约 40MB 开始,然后随着每个图像的增长而增长。

这是一个图表:

这是图像的 4 倍原始尺寸的图表,具有相同的裁剪原点、宽度/高度。

为什么会这样?是否有泄漏的地方? 当我设置一个标志来跟踪泄漏时,pyvips.base.leak_set(1),我得到了大约 60 MB 的报告。我还使用 cgroups 将进程的物理内存限制为 100 MB。 Vips 能够运行而不会崩溃,但速度较慢。 作为比较,OpenCV 中的类似操作消耗几乎恒定数量的 RSS,140 MB 或 300 MB,具体取决于图像大小。对于我的实验,vips 在 CPU 时间上赢了几次,但在内存上输了几次。

pyvips 版本:2.0.4

libvips 版本:8.6.1

【问题讨论】:

    标签: vips


    【解决方案1】:

    我试过这个测试程序:

    import sys
    import pyvips
    import random
    
    for filename in sys.argv[1:]:
        image = pyvips.Image.new_from_file(filename, access='sequential')
        x = random.randint(0, image.width - 2)
        y = random.randint(0, image.height - 2)
        w = random.randint(1, image.width - x)
        h = random.randint(1, image.height - y)
        print 'filename =', filename, 'avg =', image.crop(x, y, w, h).avg()
    

    我是这样运行的:

    $ mkdir samples
    $ for i in {1..2000}; do cp ~/pics/k2.jpg samples/$i.jpg; done
    $ python soak.py samples/*
    

    k2.jpg 是 2k x 1.5k RGB jpg 图像。当它运行时,我在top 中观看了RES。它在开始时略有上升,但在大约 100 张图像之后稳定在 75MB 左右,并在剩余的 1900 次迭代中保持不变。这是 py27、pyvips 2.0.4、libvips 8.6.1。

    libvips 保留一个cache of recent operations。通常这是无害的(并且有帮助),但在某些情况下它可能会触发不必要的内存使用。

    您可以尝试添加:

    pyvips.cache_set_max(0)
    

    在您的程序开始附近。在这个例子中,它把 memuse 的峰值从 75mb 降到了 38mb。

    【讨论】:

    • 我使用了你的代码,生成了 2k x 1.5k 的图像。 (宽度先行)。实际上,内存稳定在 99 MB 左右。如果使用 cache_set_max(0),那么它会达到 35-40MB。但是,在我最初的问题中,图像的大小为 12000x2048,而 4X 图像的大小为 24000x4096,抱歉我忘了提及这一点。为了确保它独立于我的特定图像像素,我生成了 300 个大小为 12000x2048 的随机像素。另外,为了模拟我的真实情况,我将随机裁剪的宽度/高度设置在 800-900 之间,然后再次运行您的脚本。如果没有缓存设置,内存会慢慢上升到 500MB。
    • 继续,使用 cache_set_max(0) 它保持在 200MB 以下。并且在实际案例 1(大小 12000x2048)中使用该选项将内存使用限制在 400 MB 以下(与之前的 600 MB 相比,请参见图表)。对于案例 2(大小 24000x4096),它低于 700MB(与之前的 1.2GB 相比)。我仍然觉得 vips 没有清理任何东西,因为在这两种情况下,第一个图像只需要 160 MB。毕竟,尽管整个图像大小变化了 4 倍,但裁剪大小和位置保持不变,所以我确实希望它使用相似数量的物理内存。
    • 嗯,很奇怪。我在这里尝试了 12000x2048 图像,顶部的 RES 在 50 到 90MB 之间反弹。可能是您平台的 malloc 实现中的内存碎片吗?我正在使用 Ubuntu 17.10。它也可能是您拥有的核心数量——我使用的是两核/四线程笔记本电脑——因为 libvips memuse 会随着线程数量的增加而增加。你可以在运行前尝试export VIPS_CONCURRENCY=1
    • 另外,libvips 8.6.2 刚刚发布,值得一试,它对统计操作和顺序图像协同工作的方式进行了一些更改。 github.com/jcupitt/libvips/releases/tag/v8.6.2
    • 谢谢! export VIPS_CONCURRENCY=1 和 pyvips.cache_set_max(0) 使内存处于控制之下,有趣的是没有任何速度牺牲。我也会尝试新版本。感谢您的帮助!
    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多