我有一个bash脚本,它具有一个循环,其中有一个bash命令,该命令调用另一个bash脚本,而该bash脚本又调用python脚本。
循环中的每个bash命令都可以彼此独立运行。当我以后在实际的数据集上运行它时,执行每个命令需要一些时间。因此,我想利用并并行化脚本的这一部分。
我花了几天时间查看bash中执行并行执行的选项,同时还给我选择了要并行化代码的内核数量,这样我就不会淹没服务器。在寻找了GNU选项之后,在我看来xargs -P似乎是最合理的,因为我不必具有特定的bash版本,并且无需安装额外的库就可以工作。但是,即使看起来很简单,我也很难使它起作用。
#!/bin/bash
while getopts i:t: option
do
case "${option}"
in
i) in_f=${OPTARG};;
t) n_threads=${OPTARG};;
esac
done
START=$(date +%s)
class_file=$in_f
classes=( $(awk '{print $1}' ./$class_file))
rm -r tree_matches.txt
n="${#classes[@]}"
for i in $(seq 0 $n);
do
for j in $(seq $((i+1)) $((n-1)));
do
echo ${classes[i]}" "${classes[j]} >> tree_matches.txt
done
done
col1=( $(awk '{print $1}' ./tree_matches.txt ))
col2=( $(awk '{print $2}' ./tree_matches.txt ))
printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads sh myFunction.sh -1 ${classes[k]} -2 ${classes[k]}
n_pairs="${#col1[@]}"
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "Exec time $DIFF seconds"
您可以忽略最初两个嵌套循环,我只是为了完整起见粘贴了整个脚本。将要并行化的部分是从脚本结尾算起的第四行代码:
printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads sh myFunction.sh -1 ${classes[k]} -2 ${classes[k]}
因此,基本上,这将遍历所有对,在我的情况下总计为1275,并且理想情况下将使用变量与指定数量的线程并行执行myFunction.sh: $ n_threads
但是我做错了什么,因为该行中的迭代器k没有索引我的两个数组 $ {classes [k]} 和 $ {classes [k]} 循环保持迭代1275次,但仅在我回显它们时才索引两个数组的第一个元素。后来我将该行更改为此行以进行故障排除:
printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads echo "index" k
实际上,每次循环它都会递增k的值,但是当我将该行更改为此时:
printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads echo "index" "$((k))"
打印出0,是k的值1275倍。我不知道我在做什么错,我很确定但是应该是一些语法错误。任何指导将不胜感激。非常感谢。
更新!
我实际上有两个向量,它们的大小相同,并输入了myFunction.sh脚本。我只希望整数索引能够同时对它们进行idnex并使用从这两个向量中索引的这两个值来调用我的函数。根据您的建议,我对代码进行了如下修改:
for x in {0..10};
do
printf "%d\0" "$x"; done| xargs -0 -I @@ -P $n_threads sh markerGenes2TreeMatch.sh -1 ${col1[@@]}-2 ${col2[@@]}
但是现在执行代码时,出现以下错误:
@@: syntax error: operand expected (error token is "@@")
我猜这个索引'@@'仍然是字符串格式。我只希望在循环时生成整数索引,并且可以并行执行此命令。
答案 0 :(得分:1)
有关行:
http://example.com/static/img/admin/...
printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads sh myFunction.sh -1 ${classes[k]} -2 ${classes[k]}
将在xargs看到它之前被shell扩展(几乎没有可能)。
也许您可以重新排序:
${classes[k]}
答案 1 :(得分:0)
此行不起作用,如您所想:
ggplot
发生的事情是BASH首先将printf "%s\0" {0..1275} | xargs -0 -I k -P $n_threads sh myFunction.sh -1 ${classes[k]} -2 ${classes[k]}
和$n_threads
之类的内容扩展为字符串,然后调用${classes[k]}
。顺便说一句。由于键xargs
不在数组${classes[k]}
中,因此""
始终为"k"
。尝试classes
;然后BASH将首先替换变量${classes[$k]}
,然后使用结果在k
中查找值。
也许更好的方法是将classes
中的值写入文件,并将其用作classes
的输入。您可能需要更改xargs
才能接受单个参数(=输入一行)并将其在脚本中分解。
答案 2 :(得分:0)
使用GNU Parallel,您可能可以做到:
classes=( $(awk '{print $1}' ./$class_file))
parallel markerGenes2TreeMatch.sh -1 {=1 'if($arg[1] ge $arg[2]) { skip() }' =} -2 {2} ::: ${classes[@]} ::: ${classes[@]}
或:
parallel --plus markerGenes2TreeMatch.sh -1 {1choose_k} -2 {2choose_k} ::: ${classes[@]} ::: ${classes[@]}
然后,您可以跳过一整代的tree_match.txt和$ col1 / $ col2。
使用parallel --embed
直接在脚本中包含GNU Parallel,因此您没有外部依赖项。