带有命名参数的 GNU Parallel

带有命名参数的 GNU Parallel

我的 Makefile 中有以下命令

parallel \
        --eta \
        --bar \
        --joblog mnist/embedder.joblog \
        pipenv run python3 \
        -m mnist.train_embedder \
        --embedder_name {1} \
        --embedder_dim {2} \
        --embedder_lr {3} \
        --embedder_epochs {4} \
        :::: grid/embedder_name \
        :::: grid/embedder_dim \
        :::: grid/embedder_lr \
        :::: grid/embedder_epochs

每个文件包含类似的内容

$ cat grid/embedder_name
ae
cnn
$ cat grid/embedder_dim
24
32
48
64

空运行的结果是

$ parallel \
        --dry-run \
        --eta \
        --joblog mnist/embedder.joblog \
        pipenv run python3 \
        -m mnist.train_embedder \
        --embedder_name {1} \
        --embedder_dim {2} \
        --embedder_lr {3} \
        --embedder_epochs {4} \
        :::: grid/embedder_name \
        :::: grid/embedder_dim \
        :::: grid/embedder_lr \
        :::: grid/embedder_epochs

Computers / CPU cores / Max jobs to run
1:local / 96 / 8

Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete
ETA: 0s Left: 8 AVG: 0.00s  local:8/0/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name ae --embedder_dim 24 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 7 AVG: 0.00s  local:7/1/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name ae --embedder_dim 32 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 6 AVG: 0.00s  local:6/2/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name ae --embedder_dim 48 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 5 AVG: 0.00s  local:5/3/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name ae --embedder_dim 64 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 4 AVG: 0.00s  local:4/4/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name cnn --embedder_dim 24 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 3 AVG: 0.00s  local:3/5/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name cnn --embedder_dim 32 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 2 AVG: 0.00s  local:2/6/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name cnn --embedder_dim 48 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 1 AVG: 0.00s  local:1/7/100%/0.0s pipenv run python3 -m mnist.train_embedder --embedder_name cnn --embedder_dim 64 --embedder_lr 0.001 --embedder_epochs 32
ETA: 0s Left: 0 AVG: 0.00s  local:0/8/100%/0.0s

--embedder_name参数列表仍在增长,如果我想在和之间添加参数--embedder_dim,我必须编辑--embedder_dim {2}to --embedder_dim {3}--embedder_lr {3}to --embedder_lr {4},依此类推。这是乏味且容易出错的。

我可以将位置参数变成命名参数吗?我想象如下

parallel \
        --eta \
        --bar \
        --joblog mnist/embedder.joblog \
        pipenv run python3 \
        -m mnist.train_embedder \
        --embedder_name {embedder_name} \
        --embedder_dim {embedder_dim} \
        --embedder_lr {embedder_lr} \
        --embedder_epochs {embedder_epochs} \
        :::: grid/embedder_name \
        :::: grid/embedder_dim \
        :::: grid/embedder_lr \
        :::: grid/embedder_epochs

虽然这会产生大量重复的名称(该字符串embedder_name在命令中出现三次!),但至少它对于意外错误的参数顺序更加稳健。

如果它是相关的

$ uname -a
Linux t1v-n-5d019513-w-0 5.13.0-1023-gcp #28~20.04.1-Ubuntu SMP Wed Mar 30 03:51:07 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

答案1

--header :几乎你想要什么。

它是为 CSV 文件制作的,其中第一行是标题。

因此,您需要在“grid/embedder_name”前面加上“name”:

$ cat grid/embedder_name
name
ae
cnn
$ cat grid/embedder_dim
dim
24
32
48
64

另外,您不需要在每个文件之间使用 :::: 。一个就足够了(但如果您发现它更容易阅读,请保留它们):

parallel --header : echo {name} {dim} :::: grid/embedder_dim  grid/embedder_name

(@r_31415 显示了一个不起作用的示例,其中名称放在命令行上。如果您使用:::- 而不是::::示例: ,则可以执行此操作parallel --header : echo {foo} ::: foo 1 2 3

编辑:

从版本 20220822 开始,您可以执行以下操作:

parallel --header 0 echo {grid/embedder_name} {grid/embedder_dim} :::: grid/embedder_dim  grid/embedder_name
parallel --header 0 echo {embedder_name} {embedder_dim} :::: embedder_dim  embedder_name

为此,文件的第一行不应有标题。

答案2

是否考虑过将其包装在脚本/函数中?例如

#!/bin/bash
genarglist() {
for ((i=1;i<=$#;i++)) ; do
  echo -n " --embedder_${!i} {$i}"
done
for ((i=1;i<=$#;i++)) ; do
  echo -n " :::: grid/embedder_${!i}"
done
}

parallel --eta --bar --joblog mnist/embedder.joblog \
    pipenv run python3 -m mnist.train_embedder \
    $(genarglist $*)

然后只需提供name, dim... 作为参数。

相关内容