hom*_*ris 19 utilities multithreading parallelism
在常见的Linux发行版,做事业一样rm
,mv
,ls
,grep
,wc
,等在平行于它们的参数运行?
换句话说,如果我grep
在 32 线程 CPU 上处理一个大文件,它会比在双核 CPU 上运行得更快吗?
Gil*_*il' 28
您可以通过检查该实用程序是否与pthread
库链接来获得第一印象。任何使用操作系统线程的动态链接程序都应该使用 pthread 库。
ldd /bin/grep | grep -F libpthread.so
Run Code Online (Sandbox Code Playgroud)
例如在 Ubuntu 上:
for x in $(dpkg -L coreutils grep findutils util-linux | grep /bin/); do if ldd $x | grep -q -F libpthread.so; then echo $x; fi; done
Run Code Online (Sandbox Code Playgroud)
但是,由于程序链接到本身与 pthread 链接的库,这会产生很多误报。例如,/bin/mkdir
在我的系统上与 PCRE 链接(我不知道为什么......),它本身与 pthread 链接。但是mkdir
没有以任何方式并行化。
在实践中,检查可执行文件是否包含libpthread
会给出更可靠的结果。它可能会错过并行行为完全包含在库中的可执行文件,但基本实用程序通常不是这样设计的。
dpkg -L coreutils grep findutils util-linux | grep /bin/ | xargs grep pthread
Binary file /usr/bin/timeout matches
Binary file /usr/bin/sort matches
Run Code Online (Sandbox Code Playgroud)
因此,实际上有机会被并行化的唯一工具是sort
. (timeout
仅链接到 libpthread,因为它链接到 librt。)GNUsort
确实并行工作:可以使用该--parallel
选项配置线程数,默认情况下,它每个处理器使用一个线程,最多 8 个。(使用更多的处理器会越来越少)随着处理器数量的增加而受益,逐渐减少的速度取决于任务的可并行性。)
grep
根本没有并行化。PCRE 库实际上链接到 pthread 库只是因为它提供了使用锁的线程安全函数,并且锁操作函数在 pthread 库中。
在处理大量数据时,从并行化中受益的典型简单方法是将这些数据拆分为多个片段,然后并行处理这些片段。在 grep 的情况下,保持文件大小可管理(例如,如果它们是日志文件,请经常轮换它们)并在每个文件上调用 grep 的单独实例(例如使用GNU Parallel)。请注意,grepping 通常是 IO 绑定的(如果您有一个非常复杂的正则表达式,或者如果您遇到 GNU grep 的某些 Unicode 极端情况,它的性能很差,则它仅受 CPU 限制),因此您不太可能从中受益有很多线程。
找到答案的另一种方法是使用类似sysdig
检查进程执行的系统调用的方法。例如,如果您想查看是否rm
创建了任何线程(通过clone
系统调用),您可以执行以下操作:
# sysdig proc.name=rm and evt.type=clone and evt.dir='<'
Run Code Online (Sandbox Code Playgroud)
随着那次跑步,我做到了:
$ mkdir foo
$ cd foo
$ touch {1..9999}
$ rm *
Run Code Online (Sandbox Code Playgroud)
并没有看到克隆 - 那里没有线程。你可以对其他工具重复这个实验,但我认为你不会发现它们是线程化的。
请注意,这clone()
也是 的基础fork()
,因此如果某个工具启动了某个其他进程(例如,find ... -exec
),您会看到该输出。这些标志将与“创建新线程”用例不同:
# sysdig proc.name=find and evt.type=clone and evt.dir='<'
...
1068339 18:55:59.702318832 2 find (2960545) < clone res=0 exe=find args=/tmp/foo.-type.f.-exec.rm.{}.;. tid=2960545(find) pid=2960545(find) ptid=2960332(find) cwd= fdlimit=1024 pgft_maj=0 pgft_min=1 vm_size=9100 vm_rss=436 vm_swap=0 comm=find cgroups=cpuset=/.cpu=/user.slice.cpuacct=/user.slice.io=/user.slice.memory=/user.slic... flags=25165824(CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID) uid=1026 gid=1026 vtid=2960545(find) vpid=2960545(find)
Run Code Online (Sandbox Code Playgroud)
请参阅xargs
或 gnu parallel
,了解如何并行运行它们。
然而,随着更多进程的添加,可并行化的部分将趋向于零时间。这将留下不可并行的部分,不会变得更快。因此,通过添加更多进程,任务的速度是有限的。很快,您就会遇到添加流程几乎没有什么区别的情况。
然后是通信开销:添加进程会使其变慢。如果添加进程的好处低于添加它的成本,那么它可能会变慢。