【问题标题】:Parallel Processing in While LoopWhile循环中的并行处理
【发布时间】:2023-03-24 08:53:01
【问题描述】:

我有一个 .sh,它从 .txt 中读取,用作另一个 shell 脚本的参数。每两行并行处理。 目前:我当前的代码将读取文件中的所有行(一次 2 行)用于第一个 .sh 调用,然后读取所有行用于第二个 .sh 调用,然后 ALL 用于最后一个 .sh 调用

问题:我需要在第一个 .sh 中的前两行,然后是第二个 .sh,然后是最后一个 .sh..THEN 循环并处理接下来的两行 HHEEELLLPPP !!! :)

现在:

cat XXXXX.txt | while read line; do
export step=${line//\"/}
export step=ExecuteModel_${step//,/_}
export pov=$line

$dir"/hpm_ws_client.sh" processCalcScriptOptions  "$appName" "$pov" "$layers" "$stages" "" "$stages" "$stages" FALSE > "$dir""/"$step"_ProcessID.log"
$dir_shell_model"/check_process_status.sh" "$dir" "$step" > "$dir""/""$step""_Monitor.log" &


$dir"/hpm_ws_client.sh" processCalcScriptOptions "$appName" "$pov" "$layers" "" ""  "$stage_final" "" TRUE > "$dir""/""$step""_ProcessID.log"
$dir"/check_process_status.sh" "$dir" "$step" > "$dir""/""$step""_Monitor.log" &

$dir"/hpm_ws_client.sh" processGenealogyExecutionPaths "$appName" "$pov" "$layers" "$genPath_01" > "$dir""/""$step""_ProcessID.log"
$dir"/check_process_status.sh" "$dir" "$step" > "$dir""/""$step""_Monitor.log" &

if (( ++i % 2 == 0))
then
echo "Waiting..."
wait
fi
done

【问题讨论】:

  • 很难看出你在做什么——你能简化它并显示你试图阅读的文件。在我看来,这样做的方法是使用GNU Parallel,它可以从一个或多个输入文件中读取 1 个或多个参数,并一次处理任意多个参数。它可能会删除你所有的循环并使你的代码小几倍——我猜总共大约 3-5 行——而且更高效、更易读。
  • @MarkSetchell,我倾向于在 GNU Parallel 之前很久就建议使用 GNU xargs -P 标志——更简单的实现(当与 -0-d $'\n' 一起使用时,以避免与与 POSIX 中一些考虑最差的部分兼容),在“显然没有错误”与“没有明显错误”的意义上。
  • 切线,所有exports 是怎么回事?快速浏览一下,这些变量都不需要导出,除非您调用的工具需要它们;但可以肯定的是,没有什么需要多次导出。
  • @tripleee 导出用于定义各种进程的日志文件的名称......这些工具也需要它们,这只是一个更大的难题...... .我不太关心的那部分,我只是想在前两个并行执行完成时串行处理 TRANSFER DATA shell,这由 check_process_status.sh 跟踪
  • 澄清一下....这可行,但是它们都是并行的,这将导致TRANSFER DATA的执行失败,因为我们使用的工具一次只能处理一个传输(尽管它可以同时处理多个执行...我知道,疯狂!)

标签: linux bash shell parallel-processing ampersand


【解决方案1】:

我看不出您真正想要做什么,但希望这两种语法中的一种会有所帮助 - 一次读取两行,或者将参数加载到数组中并重新使用它们。

所以,如果你的 file.txt 看起来像这样:

line 1
line 2
line 3
line 4
line 5
line 6

示例 1 - 两次读取

#!/bin/bash
while read a && read b; do
   echo $a, $b
done < file.txt

输出

line 1, line 2
line 3, line 4
line 5, line 6

示例 2 - 使用 bash 数组

#!/bin/bash
declare -a params
while IFS=$'\n' read -r z; do
    params+=("${z}")
done < file.txt

# Now print the elements out
for (( i=0;i<${#params[@]};i++ )) do
   echo ${params[$i]}
done

输出

line 1
line 2
line 3
line 4
line 5
line 6

示例 3 - 使用 GNU Parallel

或者,正如我在评论中建议的那样,像这样使用GNU Parallel

parallel -k -L2 echo {1} {2} < file.txt

输出

line 1 line 2
line 3 line 4
line 5 line 6

其中-k 表示“保持输出顺序”-L2 表示“一次从 file.txt 中取出 2 行”

这样做的好处是,如果您想一次并行运行 8 个脚本,只需指定 -j 8parallel 即可。

【讨论】:

    【解决方案2】:

    嗯,这并不漂亮,希望有人能提供一种更优雅的方式来读取这些循环中的连续行对,但一种可能性是使用变量来跟踪你的位置,比如

    LOCATION=0
    for file in first second last; do
        LOCATION=$((LOCATION+2))
        LINES=$(head -n $LOCATION $file | tail -n 2)
        # process lines
    

    【讨论】:

    • @marksetchell 谢谢你,这有助于理解我可以在这里使用的方法。通过在 shell 脚本之间使用 && 并检查两个正在运行的进程,我想出了一个部分解决方案。我现在遇到的问题是我使用参数运行的第二个 shell(取决于第一个的成功)需要串行运行。我在想也许是一个 if 语句?
    • 拥有一个数字索引来告诉您要再次阅读多少行是一种常见的反模式。尝试while read first; do read second; command something "$first" "$second"; done &lt;file 之类的方法,尽管这并不能解决如何处理多个文件中可能包含奇数行的文件。
    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 2018-09-08
    • 2017-08-24
    • 2015-02-07
    相关资源
    最近更新 更多