【发布时间】:2019-05-21 00:17:13
【问题描述】:
我坚持这一点。因此,我的代码中有这个 while-read 循环需要很长时间,我想在许多处理器中运行它。但是,我想拆分输入文件并并行运行 14 个循环(因为我有 14 个线程),每个拆分文件一个循环。问题是我不知道如何告诉 while 循环获取和使用哪个文件。
例如,在常规的 while-read 循环中,我会编写代码:
while read line
do
<some code>
done < input file or variable...
但在这种情况下,我想将上述输入文件拆分为 14 个文件并并行运行 14 个 while 循环,每个拆分文件一个。 我试过了:
split -n 14 input_file
find . -name "xa*" | \
parallel -j 14 | \
while read line
do
<lot of stuff>
done
也试过
split -n 14 input_file
function loop {
while read line
do
<lot of stuff>
done
}
export -f loop
parallel -j 14 ::: loop
但我都无法判断哪个文件将是循环的输入,因此并行会理解“将每个 xa* 文件并行放入单独的循环中”
输入文件示例(字符串列表)
AEYS01000010.10484.12283
CVJT01000011.50.2173
KF625180.1.1799
KT949922.1.1791
LOBZ01000025.54942.57580
编辑
这是代码。 输出是一个表格(741100 行),其中包含一些关于已经进行的 DNA 序列比对的统计数据。 该循环采用带有 DNA 序列继承的 input_file(无虚线,从 500 到 ~45000 行,800Kb),逐行读取并在数据库中查找这些继承的每个对应的完整分类法(~45000 行) .然后,它会进行一些求和/除法。输出是一个 .tsv,如下所示(序列“KF625180.1.1799”的示例):
Rate of taxonomies for this sequence in %: KF625180.1.1799 D_6__Bacillus_atrophaeus
Taxonomy %aligned number_ocurrences_in_the_alignment num_ocurrences_in_databank %alingment/databank
D_6__Bacillus_atrophaeus 50% 1 20 5%
D_6__Bacillus_amyloliquefaciens 50% 1 154 0.649351%
$ head input file
AEYS01000010.10484.12283
CVJT01000011.50.217
KF625180.1.1799
KT949922.1.1791
LOBZ01000025.54942.57580
循环内部还使用了两个附加文件。它们不是循环输入。 1) 一个名为 alnout_file 的文件,它仅用于查找给定序列对数据库的命中数(或比对数)。它以前也是在这个循环之外制作的。它的行数可以从数百到数千不等。这里只有第 1 列和第 2 列很重要。 Column1 是序列的名称,col2 是它在数据库中匹配的所有序列的名称。看起来是这样的:
$ head alnout_file
KF625180.1.1799 KF625180.1.1799 100.0 431 0 0 1 431 1 431 -1 0
KF625180.1.1799 KP143082.1.1457 99.3 431 1 2 1 431 1 429 -1 0
KP143082.1.1457 KF625180.1.1799 99.3 431 1 2 1 429 1 431 -1 0
2) 一个数据库 .tsv 文件,其中包含与 DNA 序列相对应的约 45000 个分类。每个分类都在一行中:
$ head taxonomy.file.tsv
KP143082.1.1457 D_0__Bacteria;D_1__Firmicutes;D_2__Bacilli;D_3__Bacillales;D_4__Bacillaceae;D_5__Bacillus;D_6__Bacillus_amyloliquefaciens
KF625180.1.1799 D_0__Bacteria;D_1__Firmicutes;D_2__Bacilli;D_3__Bacillales;D_4__Bacillaceae;D_5__Bacillus;D_6__Bacillus_atrophaeus
所以,给定序列 KF625180.1.1799。我之前将它与一个包含约 45000 个其他 DNA 序列的数据库进行了比对,并得到了一个输出,其中包含它匹配的所有序列的加入。循环的作用是找到所有这些序列的分类并计算我之前提到的“统计数据”。代码为我拥有的所有 DNA 序列加入。
TAXONOMY=path/taxonomy.file.tsv
while read line
do
#find hits
hits=$(grep $line alnout_file | cut -f 2)
completename=$(grep $line $TAXONOMY | sed 's/D_0.*D_4/D_4/g')
printf "\nRate of taxonomies for this sequence in %%:\t$completename\n"
printf "Taxonomy\t%aligned\tnumber_ocurrences_in_the_alignment\tnum_ocurrences_in_databank\t%alingment/databank\n"
#find hits and calculate the frequence (%) of the taxonomy in the alignment output
# ex.: Bacillus_subtilis 33
freqHits=$(grep "${hits[@]}" $TAXONOMY | \
cut -f 2 | \
awk '{a[$0]++} END {for (i in a) {print i, "\t", a[i]/NR*100, "\t", a[i]}}' | \
sed -e 's/D_0.*D_5/D_5/g' -e 's#\s\t\s#\t#g' | \
sort -k2 -hr)
# print frequence of each taxonomy in the databank
freqBank=$(while read line; do grep -c "$line" $TAXONOMY; done < <(echo "$freqHits" | cut -f 1))
#print cols with taxonomy and calculations
paste <(printf %s "$freqHits") <(printf %s "$freqBank") | awk '{print $1,"\t",$2"%","\t",$3,"\t",$4,"\t",$3/$4*100"%"}'
done < input_file
它需要大量的 grep 和解析,因此在一个处理器中运行大约需要 12 小时来处理所有 45000 个 DNA 序列加入。我想拆分 input_file 并在我拥有的所有处理器(14)中执行此操作,因为它会花费时间。 谢谢大家对我这么有耐心=)
【问题讨论】:
-
为什么是14?数据是否分段?或者多个实例可以从 FIFO 中读取它的行吗?
-
就因为我有14个线程。正在编辑它
-
soo.... 数据分段了吗?或者多个实例可以从 FIFO 中读取它的行吗?
-
我不知道你所说的“我有 14 个线程”是什么意思——你需要稍微详细说明一下。
-
当 grepping 分类中的全名时,我猜你只期望得到 1 个答案,所以在第一场比赛后退出 (
grep -m1 ...),不要费心解析其余的。
标签: bash while-loop parallel-processing