我正在查看并编辑程序。现在我有一个文件在第一列中有唯一标识符,第10和第11列中的数据需要更正。该文件大约有40-100M行。具有正确信息的文件具有4倍的行数,并且其格式为每4行重复一次,行1n具有标识符,行2具有针对列10的正确数据,行4具有针对列的正确数据11.我有两个程序,一个将文件1拆分为250000行片段,并在多个核心上并行运行以下程序。
#! /bin/bash
#$ -l h_rt=01:00:00,vf=1G
#$ -pe smp 1
#$ -cwd
#$ -j y
#$ -N unmasked
#$ -V
for line in `cut -f 1 $1`; do
seq=`awk -v a="$line" '$1~a{getline;print;exit}' ../406.fastq`
qual=`awk -v a="$line" '$1~a{getline;getline;getline;print;exit}' ../406.fastq`
awk -v s="$seq" -v q="$qual" -v l="$line" 'FS="\t" {if ($1~l) {$10=s;$11=q; print $0}}' $1 >> $1\D
done
rm $1
不幸的是,这个程序运行一个循环大约需要4-6秒,并且需要大约5天的250000行占用我正在使用的大部分计算机集群。
有关更快更有效地执行此操作的任何提示吗?我几乎可以接受任何事情......
答案 0 :(得分:1)
Shell脚本不适合这类工作。这个程序每行输入产生三个短暂的awk进程,虽然UNIX进程创建比在Windows上便宜,但你仍然不想支付300M次的进程创建开销!
(更正:创建过程是您最不担心的事情。它在每次迭代时读取400M行文件两次!)
使用您首选的“真实”脚本语言 - 我很想使用Perl,但Python也是一个不错的选择。它也许可以在一个独立的awk脚本中完成,但如果你擅长awk,你就不会问这个问题 - 而且Perl存在,所以你不必成为一个awk大师!
沿着这个伪代码的行编写一个脚本,它保存两个文件,并假设它们都具有相同顺序的信息。
open file1 and file2
read 1 line from file1 and 4 lines from file2 into string variables
while(reads didn't fail) {
parse desired information from lines
output in the format you want
read 1 line from file1 and 4 lines from file2 into string variables
}
close both files
您可能会发现这个速度非常快,因此无需尝试并行化。我希望它受到磁盘访问的限制,而不是CPU。
如果两个文件的顺序不同,则会出现更多问题。排序100M项目并不便宜。这里最简单的选择是首先遍历较长的文件,将您需要的值放入地图数据结构中,比如Perl哈希或Python字典 - 甚至像Redis这样的数据库 - 然后遍历较短的文件,将值拉出来需要从地图上重写线条。