我希望提取以存储在$file1中的字符串开头的所有行$file2。
$file1是4GB大,大约有2000万行,$file2有200万行,大约140 MB大,包含两个用,分隔的列。这两个文件的最大行长都远低于1000,它们使用LC_ALL=C排序,$file1可以包含除\0之外的任何附加字符。
出乎意料地,这个命令
parallel --pipepart -a $file1 grep -Ff $file2消耗大量的内存并被操作系统杀死。
如果限制线程数,则该命令可以工作:
parallel --pipepart -j 8 -a $file1 grep -Ff $file2对于最后一个命令,htop显示每个grep -Ff $file2-thread总是占用12.3 GB的内存。我假设这个需求来自于从$file2构建的字典grep。
怎样才能更有效地实现这样的过滤器呢?
发布于 2019-02-15 16:17:02
它包含在man parallel https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Grepping-n-lines-for-m-regular-expressions中。
EXAMPLE:为m个正则表达式增加n行。对于许多regexp来说,一个大文件的最简单的解决方案是: grep -f regexps.txt大文件,或者如果regexp是固定字符串: grep -F -f regexps.txt大文件有三个限制因素: CPU、RAM和磁盘I/O RAM是很容易测量的:如果grep进程占用了大部分空闲内存(例如,在运行顶部时),那么RAM是一个限制因素。CPU也很容易测量:如果grep在顶部占用>90%的CPU,那么CPU是一个限制因素,并行化将加快速度。很难看出磁盘I/O是限制因素,根据磁盘系统的不同,并行化可能更快或更慢。唯一确定的方法是测试和测量。Limiting因子: RAM普通grep -f regexs.txt大文件可以工作,不管大文件的大小如何,但是如果regexps.txt太大,无法放入内存中,那么您需要拆分它。grep -F占用大约100字节内存,grep每1字节regexp占用大约500个内存。因此,如果regexps.txt占内存的1%,那么它可能太大了。如果可以将regexp转换为固定字符串,则执行此操作。例如,如果您在大文件中寻找的行都类似于: ID1 foo bar baz Identifier1 quux fubar ID2 foo bar baz Identifier2,那么您的regexps.txt可以从: ID1 .* faster 1 ID2 .*faster 2转换为:ID1 foo bar baz Identifier1 ID2 foo bar baz Identifier2,这样您就可以使用grep -F,它占用的内存减少了80%,而且速度要快得多。如果内存中仍然不合适,您可以这样做:并行--pipepart -a regexps.txt --块1M grep -Ff -n大文件排序-un \ perl -pe‘S/^d+://’1M应该是您的空闲内存,除以CPU线程数,除以200个用于grep -F,再除以1000个用于普通grep。在GNU/Linux上你可以这样做: free=$(awk‘/^(Swap)?缓存的\ grep’/MemFree\缓冲区):/{ sum += $2 } END { print sum } /proc/meminfo) percpu=$((free / 200 /$(并行-多个线程))k并行--pipepart -a regexps.txt --块$percpu --压缩\grep -F -f - -n bigfile排序-un -pe‘S/^d+://’如果您可以忍受重复的行和错误的顺序,这样做更快:并行--pipepart -a regexps.txt --块$percpu --压缩\ grep -f -F --大文件Limiting因子: CPU如果CPU是限制因素,则应该在regexps上执行并行化操作: cat regexp.txt并行-管道-L1000 -循环--压缩grep -f - -n大文件排序-un -pe -pe S/^d+://‘命令将启动每个CPU一个grep,并在每个CPU上读取一次大文件,但是,由于这是并行的,所有的读取,除了第一个将被缓存在RAM中。根据regexp.txt的大小,使用块10米可能比使用-L1000更快。一些存储系统在并行读取多个块时表现得更好。对于某些RAID系统和某些网络文件系统来说,这是正确的。要并行读取大文件:并行-管道部分-块100 m -a大文件-k -压缩\ grep -f regexp.txt,这将将大文件分成100 on块,并在每个块上运行grep。要并行读取大文件和regexp.txt,需要使用-fifo: parallelize块100 m -a大文件--fifo cat regexp.txt \双并联-管道-L1000 -循环的grep -f - {} -如果一行匹配多个regexp,则行可能重复。Bigger问题如果这个问题太大,不能用它来解决,那么您可能已经准备好了。
https://unix.stackexchange.com/questions/500676
复制相似问题