使用旧的Rust 2015
0.11.3 |
|
---|---|
0.11.1 |
|
0.8.0 |
|
0.6.2 |
|
#8 in #均衡器
每月下载量 43次
155KB
3K SLoC
MIT/Rust 并行:用 Rust 编写的命令行 CPU 负载均衡器
这是在 Rust 和 MIT 许可证下重现 GNU Parallel(命令行的工作窃取器)功能的一种尝试。最终目标是支持 GNU Parallel 的大部分功能,然后扩展功能以用于 Rust 编写的下一代命令行工具。虽然功能很重要,但随着应用程序在 Rust 中开发,目标也是尽可能快和高效。
注意
请参阅 待办事项列表,以了解尚未完成的特性和改进。如果您想贡献,欢迎提交拉取请求。如果您有一个不在待办事项列表中的改进想法,请随时 给我发电子邮件,我会考虑实现该想法。
与 GNU Parallel 的基准比较
GNU Parallel
并行打印 1 到 10,000
~/D/parallel (master) $ seq 1 10000 | time -v /usr/bin/parallel echo > /dev/null
User time (seconds): 194.73
System time (seconds): 66.49
Percent of CPU this job got: 230%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:53.08
Maximum resident set size (kbytes): 16140
将 /usr/bin 中每个二进制文件的 内容连接起来
~/D/parallel (master) $ time -v /usr/bin/parallel cat ::: /usr/bin/* > /dev/null
User time (seconds): 71.71
System time (seconds): 27.67
Percent of CPU this job got: 222%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:44.62
Maximum resident set size (kbytes): 17576
记录 echo ::: $(seq 1 1000)
~/D/parallel (master) $ time -v /usr/bin/parallel --joblog log echo ::: $(seq 1 1000) > /dev/null
User time (seconds): 21.27
System time (seconds): 7.44
Percent of CPU this job got: 238%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:12.05
Maximum resident set size (kbytes): 16624
Rust Parallel(使用 MUSL 目标构建)
强烈建议使用 MUSL 编译 Parallel 而不是 glibc,因为这样可以将内存消耗减半并提高性能一倍。
并行打印 1 到 10,000
~/D/parallel (master) $ seq 1 10000 | time -v target/release/x86_64-unknown-linux-musl/parallel echo > /dev/null
User time (seconds): 0.40
System time (seconds): 2.53
Percent of CPU this job got: 97%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.01
Maximum resident set size (kbytes): 1768
将 /usr/bin 中每个二进制文件的 内容连接起来
~/D/parallel (master) $ time -v target/release/x86_64-unknown-linux-musl/release/parallel cat ::: /usr/bin/* > /dev/null
User time (seconds): 1.07
System time (seconds): 4.40
Percent of CPU this job got: 191%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.86
Maximum resident set size (kbytes): 1844
记录 echo ::: $(seq 1 1000)
~/D/parallel (master) $ time -v target/x86_64-unknown-linux-musl/release/parallel --joblog log echo ::: $(seq 1 1000) > /dev/null
User time (seconds): 0.02
System time (seconds): 0.28
Percent of CPU this job got: 85%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.36
Maximum resident set size (kbytes): 1768
语法示例
以下语法受支持
parallel 'echo {}' ::: * // {} will be replaced with each input found.
parallel echo ::: * // If no placeholders are used, it is automatically assumed.
parallel echo :::: list1 list2 list3 // Read newline-delimited arguments stored in files.
parallel echo ::: arg1 ::::+ list :::+ arg2 // Interchangeably read arguments from the command line and files.
parallel echo ::: 1 2 3 ::: A B C ::: D E F // Permutate the inputs.
parallel echo '{} {1} {2} {3.}' ::: 1 2 file.mkv // {N} tokens are replaced by the Nth input argument
parallel ::: "echo 1" "echo 2" "echo 3" // If no command is supplied, the input arguments become commands.
parallel 'cd {}; echo Directory: {}; echo - {}' // Commands may be chained in the platform\'s shell.
seq 1 10 | parallel 'echo {}' // If no input arguments are supplied, stdin will be read.
seq 1 10 | parallel --pipe cat // Piping arguments to the standard input of the given command.
#!/usr/bin/parallel --shebang echo // Ability to use within a shebang line.
手册
Parallel 将非并行命令行任务并行化。当有多个需要执行且可能并行执行的命令时,Parallel 应用程序将均匀地将任务分配到所有可用的 CPU 内核。命令的提供有三种基本方法:
-
可以定义一个 A COMMAND,后跟一个 which,表示所有后续参数都将作为该命令的 INPUTS。
-
如果没有提供 COMMAND,则将 INPUTS 解释为 COMMANDS。
-
如果没有提供 INPUTS,则读取标准输入作为 INPUTS。
Parallel 将每个子进程的标准输出和错误进行分组,以便按顺序打印输出,就像任务像传统 for 循环那样按顺序串行执行一样。此外,默认情况下,通过平台的默认 shell 执行命令,在 Unix 系统上是 sh -c
,在 Windows 系统上是 cmd /C
。这会带来性能成本,因此可以使用 --no-shell 选项禁用它。
输入模式
输入模式用于确定以下输入是包含输入的文件还是输入本身。包含输入的文件将每个输入存储在不同的行上,每行被视为一个完整的输入。当有多个收集到的输入列表时,每个单独的输入列表将一起排列成一个单独的列表。
- :::
表示以下输入参数是输入参数。此外,这些参数将被收集到一个新的列表中。
- :::+
表示以下输入参数是输入参数。此外,这些参数将被添加到当前列表中。
- ::::
表示以下输入参数是包含输入的文件。此外,这些参数将被收集到一个新的列表中。
- ::::+
表示以下输入参数是包含输入的文件。此外,这些参数将被添加到当前列表中。
输入令牌
命令通常以你在 shell 中通常的方式形成,只是用大括号中的占位符令牌(如 {}、{.}、{/}、{//} 和 {/}.)替换你的输入参数。如果没有提供令牌,则假定命令的最后一个参数将是 {}。这些令牌将对输入执行文本操作,以按照您喜欢的样式对其进行破坏。欢迎提供更多令牌的想法。
- {}:每次出现都将被替换为输入的名称。
- {.}:每次出现都将被替换为不带扩展名的输入。
- {^abc...}:每次出现都将被替换为要删除的自定义后缀。
- {/}:每次出现都将被替换为输入的基本名称。
- {/.}:每次出现都将被替换为不带扩展名的基本名称。
- {/^abc...}:每次出现都将被替换为删除自定义后缀的基本名称。
- {//}:每次出现都将被替换为输入的目录名称。
- {%}:每次出现都将被替换为槽位号。
- {#}:每次出现都将被替换为作业号。
- {##}:每次出现都将被替换为作业总数。
- {N}:其中 N 是一个数字,显示关联的作业号。
- {N.}:将从第 N 个作业中删除扩展名。
- {N^abc...}:如果找到,则定义从第 N 个作业中删除的自定义后缀。
- {N/}:显示第 N 个作业的基本名称(文件名)。
- {N//}:显示第 N 个作业的目录名称。
- {N/.}:显示不带扩展名的第 N 个作业的基本名称。
- {N/^abc...}:显示删除自定义后缀的第 N 个作业的基本名称。
选项
还可以向程序提供选项以更改程序的操作方式
- --delay:延迟 N 秒开始下一个作业,其中秒可以是分数。
- --dry-run:将运行作业打印到标准输出,而不运行它们。
- --eta:根据运行进程的平均运行时间打印估计完成时间。
- -h,--help:打印应用程序的手册(建议将其管道传输到
less
)。 - -j,--jobs:定义并行运行的作业/线程数。
- --joblog:将作业统计信息记录到指定的文件中,当它们完成时。
- --joblog-8601:以 ISO 8601 格式写入开始时间:
YYYY-MM-DD hh:mm:ss
- --memfree:定义在开始下一个作业之前可用的最小内存量。
- -n,--max-args:将一定数量的参数组合在同一命令行中。
- --num-cpu-cores:打印系统中的CPU核心数并退出。
- -p,--pipe:不是将参数作为子进程的参数提供,而是直接将参数提供给每个子进程的标准输入。
- -q,--quote:转义命令参数,以便保留空格、引号和斜杠。
- -s,--silent,--quiet:禁用打印运行进程的标准输出。
- --shebang:允许通过在shebang行中调用它,将并行命令作为解释器使用。
- --shellquote:打印将要执行的命令,命令带有引号。
- --tmpdir:定义用于临时文件的目录。
- --timeout:如果命令运行时间超过指定的秒数,则使用SIGKILL将其终止。
- -v,--verbose:打印有关运行进程的信息。
- --version:打印应用程序及其依赖项的当前版本。
实用示例
将FLAC音乐转码为Opus
ffmpeg是一个非常有用的应用程序,用于转换音乐和视频。然而,音频转码仅限于单核。如果您有一个大的FLAC存档,并且想要将其压缩为高效的Opus编解码器,即使使用最快的处理器也需要很长时间,除非您利用CPU的所有核心。
parallel 'ffmpeg -v 0 -i "{}" -c:a libopus -b:a 128k "{.}.opus"' ::: $(find -type f -name '*.flac')
将视频转码为VP9
VP9在编码方面有一个明显的缺陷:在任何给定时间点它只能使用大约三个核心。如果您有一个八核处理器和一打或更多的电视剧集要转码,您可以使用并行程序同时运行三个任务,前提是您也有足够的内存。
vp9_params="-c:v libvpx-vp9 -tile-columns 6 -frame-parallel 1 -rc_lookahead 25 -threads 4 -speed 1 -b:v 0 -crf 18"
opus_params="-c:a libopus -b:a 128k"
parallel -j 3 'ffmpeg -v 0 -i "{}" $vp9_params $opus_params -f webm "{.}.webm"' ::: $(find -type f -name '*.mkv')
安装说明
您可以使用多种方法安装应用程序。我提供了AMD64系统的二进制包,可供下载。
Gentoo
我有一个个人Gentoo layman overlay,它提供此应用程序以供安装。
Arch Linux
Arch Linux用户可以从AUR获取PKGBUILD。
其他所有人
rustup component add x86_64-unknown-linux-musl
wget https://github.com/mmstick/parallel/archive/master.zip
unzip master.zip
cd parallel-master
cargo build --release --target x86_64-unknown-linux-musl
sudo install target/x86_64-unknown-linux-musl/release/parallel /usr/local/bin/parallel
依赖关系
~1–1.4MB
~25K SLoC