我经常需要处理大型文本文件(10-100GB解压缩),根据每行中的条形码进行解复用,实际上产生的单独文件(唯一条形码)的数量在1K到20K之间。我一直在使用awk来完成这个任务。然而,我注意到解复用更大的文件(与使用更多唯一条形码有关)的速度明显变慢(10-20倍)。检查ulimit -n显示每个进程的打开文件限制为4096个,因此我怀疑减速是由于强制awk在总解复用文件数超过4096时不断关闭和重新打开文件的开销引起的。
没有root访问权限(即限制是固定的),有什么办法可以规避这个瓶颈吗?
我确实有每个文件中存在的所有条形码列表,因此我考虑分叉多个awk进程,其中每个进程被分配一个互斥子集(< 4096)的条形码来搜索。但是,我担心必须检查每行的条形码是否属于集合会消耗关闭文件的好处所得到的好处。
有更好的策略吗?
我没有使用awk,因此其他脚本或编译语言的方法也可以。
具体示例
数据生成(带条形码的FASTQ)
以下生成类似于我正在处理的数据。每个条目由4行组成,其中条形码是使用非模糊DNA字母的18个字符单词。
1024个唯一条形码| 100万条读数。
或者对于
没有root访问权限(即限制是固定的),有什么办法可以规避这个瓶颈吗?
我确实有每个文件中存在的所有条形码列表,因此我考虑分叉多个awk进程,其中每个进程被分配一个互斥子集(< 4096)的条形码来搜索。但是,我担心必须检查每行的条形码是否属于集合会消耗关闭文件的好处所得到的好处。
有更好的策略吗?
我没有使用awk,因此其他脚本或编译语言的方法也可以。
具体示例
数据生成(带条形码的FASTQ)
以下生成类似于我正在处理的数据。每个条目由4行组成,其中条形码是使用非模糊DNA字母的18个字符单词。
1024个唯一条形码| 100万条读数。
cat /dev/urandom | tr -dc "ACGT" | fold -w 5 | \
awk '{ print "@batch."NR"_"$0"AAAAAAAAAAAAA_ACGTAC length=1\nA\n+\nI" }' | \
head -n 4000000 > cells.1K.fastq
16384个唯一条形码 | 100万次读取
cat /dev/urandom | tr -dc "ACGT" | fold -w 7 | \
awk '{ print "@batch."NR"_"$0"AAAAAAAAAAA_ACGTAC length=1\nA\n+\nI" }' | \
head -n 4000000 > cells.16K.fastq
awk
脚本用于解复用
注意,在这种情况下,我为每个唯一的条形码写入2个文件。
demux.awk
#!/usr/bin/awk -f
BEGIN {
if (length(outdir) == 0 || length(prefix) == 0) {
print "Variables 'outdir' and 'prefix' must be defined!" > "/dev/stderr";
exit 1;
}
print "[INFO] Initiating demuxing..." > "/dev/stderr";
}
{
if (NR%4 == 1) {
match($1, /.*_([ACGT]{18})_([ACGTN]{6}).*/, bx);
print bx[2] >> outdir"/"prefix"."bx[1]".umi";
}
print >> outdir"/"prefix"."bx[1]".fastq";
if (NR%40000 == 0) {
printf("[INFO] %d reads processed\n", NR/4) > "/dev/stderr";
}
}
END {
printf("[INFO] %d total reads processed\n", NR/4) > "/dev/stderr";
}
使用方法
awk -v outdir="/tmp/demux1K" -v prefix="batch" -f demux.awk cells.1K.fastq
或者对于
cells.16K.fastq
也是类似的处理方式。假设您是唯一运行awk
的人,您可以使用以下命令验证打开文件的大致数量。lsof | grep "awk" | wc -l
观察到的行为
尽管两个文件大小相同,但具有16K个唯一条形码的文件比只有1K个唯一条形码的文件运行速度慢10倍至20倍。