1

我目前有一个非常大的目录,其中包含超过9000个文件夹,每个文件夹中保存有jpeg图像(平均每个文件夹40个)。图像处理程序在大图像集上的并行化

我计划拍摄图像的输入文件夹,并输出图像的特征向量该文件夹中的文本文件:

./process_image images/ output/ 

我也有一个脚本用法如下:

./script.sh dirlist.txt images/ output/ 1 

第一个输入dirlist.txt包含输入目录内的文件夹名称 第二个和第三个输入是输入和输出的基本目录。 第四参数是哪个入口在dirlist我想访问

上面的例子会召唤指数,假设imageset1在dirlist.txt是在索引1:

./process_image images/imageset1/ output/imageset1/ 

如果我按顺序执行此操作,需要花几天时间处理所有9000个文件夹。这种情况下并行化的最佳方法是什么?我应该编写一个脚本,将9000个文件夹分成块并分别运行脚本,每个脚本运行一定范围的索引?另外,如何确定可以运行多少个程序,因为一个可执行文件的RAM范围可以从100 MB到1GB不等?我有32 GB的RAM。

+0

什么是瓶颈? io或cpu或内存带宽? C++与这个问题有什么关系? – Yakk

+0

我不知道如何解决这个问题,以及我的瓶颈是什么。该程序是用C++编写的。 – Olivier

+0

我刚刚尝试同时处理10个文件夹,并且我的CPU使用率约为90%。可以说我的瓶颈是CPU吗?我正在运行i7-3770 – Olivier

回答

5

我经常处理65,000+每天的图像,我只是关于总是使用GNU并行 - 请参阅herehere。我不会打扰平行C代码!

它允许您指定并行运行多少个作业,或者仅使用每个CPU核心的一个作业的默认值。使用起来非常简单。所有你会做的是改变你的script.sh,这样,而不是在开始工作,它只是呼应它会启动所有的命令,每行一个,到stdout然后你管到这parallel,这样

script.sh | parallel 

您可以添加像-j 8这样的标志以并行运行8个作业,或者使用-k来保持输出顺序(如果相关)。

script.sh | parallel -j 8 -k 

同样,如果您担心内存使用情况,您可以告诉parallel当系统空闲内存至少1GB仅开始新的工作:

script.sh | parallel --memfree 1G 

你也可以添加名单其他的机器,它会散发跨越它们的作业你:-)

这是一个很小的例子:

#!/bin/bash 
# script.sh 

for i in {0..99}; do 
    echo "echo Start job $i; sleep 5; echo End job $i" 
done 

然后

script.sh | parallel 

和500工作秒70秒内得到执行我的8核的机器,或21秒,如果我使用parallel -j 25

+0

'--noswap'被称为hrmmm ....非最佳。改为使用新的'--memfree 1G'。 –

+0

@OleTange像往常一样,谢谢您的宝贵意见。 –

+0

感谢您的帖子。非常有用的东西。不幸的是,我现在在Windows上,并且不能很好地获得GNU Parallel的工作。我想我发现xargs是一个替代方案。你碰巧知道使用xargs执行与“script.sh | parallel -j 8”相同的语法吗? – Olivier

0
  1. 瓶颈

    • CPU使用率是不是一个有效的瓶颈标志
    • 决定什么是瓶颈是通过测量
    • 当你到了瓶颈,那么CPU使用率通常是最好的方式命中100%或接近
    • 但这只意味着达到了一些瓶颈
    • 如果瓶颈来了m IO然后CPU使用率可能很低...
    • 来衡量CPU/MEM您需要使用不同的CPU和传输速度
    • 所以更改BIOS设置,看看时间迅速改变
    • 这不会总是有助于确定在这种情况下,源
    • 你有来衡量你的程序的一部分的运行时间,看看有什么是慢
    • 然后自己确定它基于什么代码,一部分确实
    • 也有分析工具,在那里它做一些这种自动
  2. 并行

    • 你只能并行线程代码的安全零件
    • 因此,如果您使用非线程安全的库,然后这些部分不能被并行化
    • 此外,如果有代码的相关部分给对方然后并行化并不是太过分
    • 不知道更多关于你的任务的处理背景很难说
    • 所以最简单最安全的方式就是每个线程的进程文件夹
  3. 线程

    • 我有CPU的可用
    • 这个数字是从系统的亲和性得到(上视窗)我通常使用尽可能多的线程数上我使用定时苛刻应用
    • 第一个CPU作为主代码,其他线程为
    • 在您的案例中,使用太多的线程将导致IO与其他线程发生冲突(除非您有RAM/SSD驱动器)
  4. 调度

    • 类似的任务持续时间只是划分任务,线程均匀
    • 非常不同的任务运行时使用某种调度
    • 例如创建任务
    • 后的阙周期性检查所有线程,如果他们很忙
    • 找到第一个空闲线程并从任务中取出任务
    • 不要忘记睡眠()添加到这个循环
    • 如果所有的任务都做了,然后停止所有线程和出口
+1

'睡眠'?你一定在开玩笑。一个空闲的线程本身更容易完成工作。这是即时的,并且消除了对几乎总是睡觉的主循环的需要,并且在必须完成某些事情时通常晚半个小睡。 – MSalters

+0

@MSalters(+1)我同意自己雇用线程速度更快,但需要更多的经验才能将它们写入正确(以线程安全的方式)以获得更长的作业,例如每个文件夹和主循环只需几秒钟就可以在操作系统调度粒度周围进行休眠,这不是浪费很重要(但需要根据具体的实施情况进行衡量) – Spektre

+0

线程安全性如果非常微不足道:只需在打开的任务列表中打一个互斥体即可。读取和处理单个图像非常复杂,互斥体不会引起显着的争用。 (如果争用是一个问题,请分解N个互斥子保护的N个子列表中的任务列表) – MSalters