shell多进程并行计算代码

shell 本身没有多线程的做法,但是通过 & 号将命令放到后台运算从而实现并行计算。

第一种做法

代码如下, 这里 degree 是多进程的数目(同时跑几个进程),do something 是实际运算代码部分。

1
2
3
4
5
6
7
8
#!/bin/bash
degree=4
for i in `seq 1 10`
do
do something & # 提交到后台的任务
[ `expr $i % $degree` -eq 0 ] && wait
done
wait

做法的解释如下

上面的脚本中设置了一个变量 degree,用来表示并行度,在整个循环中控制阻塞的关键语句是 [ expr $i % $degree -eq 0 ] && wait,即在第 n 次循环时,如果 n 恰好对 degree 求模等于 0,那么循环阻塞,等待前面 n 个后台任务执行完成后再继续,以此类推。

但是这里的做法是向后台一次性提交 3 个任务,然后通过 wait 命令等待当前所有后台任务完成再继续下一批,DS将其称为分批等待机制

原始代码少了最后一行的 wait ,这可能有点问题,因为i=10 此时只提交了2个任务,不会触发 for 循环中的 wait 语句,因此可能总脚本可能会不等最后2个任务而完成而先退出,因此需要再补充一个 wait 命令,确保所有剩余任务完成。

缺点

  1. 但是这个代码必须等待每批4个任务全部完成后,才能继续提交下一批任务,而不是动态地“完成一个、补充一个”,下面的做法就可以动态实现完成一个、补充一个的做法。

  2. 实际计算部分只能是一行代码,然后用 & 号结尾表示提交后台运算(多行运算代码那就得弄成一个bash文件)。

第二种做法

shell 可以结合命名管道的方式实现并行计算。

代码如下, 这里 degree 是多进程的数目(同时跑几个进程),# do something 是实际运算代码部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
## 创建管道,利用管道进行并行
mkfifo pipfifo
exec 6<>pipfifo
degree=3
for ((i=0;i<${degree};i++))
do
echo
done>&6

## 遍历每条染色体
for i in `seq 0 25`
do
read -u6
{
# do something
echo >&6
} &
done
wait
exec 6>&-
rm pipfifo

deepseek 对这段代码的解释如下

以下是对该 Shell 脚本的逐段解释,结合命名管道(FIFO)实现并行控制的原理:


一、管道创建与并发控制

1
2
3
4
5
6
7
mkfifo pipfifo
exec 6<>pipfifo
degree=3
for ((i=0;i<${degree};i++))
do
echo
done>&6
  1. mkfifo pipfifo
    创建一个名为 pipfifo 的命名管道文件,用于进程间通信。管道的特点是:如果管道中没有数据,读取操作会阻塞;数据被读取后会被清除。

  2. exec 6<>pipfifo
    将文件描述符 6 绑定到管道文件。<> 表示以读写模式打开管道,后续通过操作文件描述符 6 控制管道。

  3. 初始化令牌

    1
    for ((i=0;i<3;i++)); do echo; done >&6

    向文件描述符 6(即管道)写入 3 个空行。这些空行相当于“并发令牌”,用于限制同时运行的进程数。


二、并行任务分发与回收

1
2
3
4
5
6
7
8
9
10
11
for i in `seq 0 25`
do
read -u6 # 从管道读取一个令牌(阻塞直到有令牌)
{
# 实际任务(例如处理染色体数据)
echo >&6 # 任务完成后归还令牌
} &
done
wait
exec 6>&-
rm pipfifo
  1. 任务分发逻辑
    read -u6:每次循环从文件描述符 6(管道)读取一个空行(令牌)。若管道为空,则阻塞等待,直到有令牌可用。

    { ... } &:将任务放入后台执行。& 表示后台运行,不阻塞主进程。

  2. 令牌回收机制
    echo >&6:任务完成后,向管道写回一个空行(令牌),允许新的任务获取令牌执行。这保证了并发数始终不超过 degree=3

  3. 等待与清理
    wait:等待所有后台任务完成后再继续执行后续命令。

    exec 6>&-:关闭文件描述符 6 的读写绑定。

    rm pipfifo:删除命名管道文件。


三、技术原理总结

  1. 并发控制核心
    通过管道的阻塞特性实现信号量机制:初始时放入 3 个令牌,每个后台任务执行前需获取令牌,执行完毕归还令牌。若所有令牌被占用,后续任务自动阻塞等待。

  2. 应用场景
    适用于需要限制并发数的批量任务(如处理 26 条染色体数据,但限制同时处理 3 条),避免资源耗尽或系统过载。

  3. 性能优势
    相比简单使用 & 将所有任务放入后台,该方案能精确控制并发量,避免瞬间创建过多进程导致系统崩溃。


参考文献

  1. https://mp.weixin.qq.com/s?__biz=MzkyOTI1NjA5MQ==&mid=2247484566&idx=1&sn=3c306077ef48beebe935d014ee7f4397&chksm=c337e1c0c5a8caf9aa2dc6be9253d068beb19d55cf9e88e1366c41ff3e402e244f5cef2195bf#rd
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2025 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信