3

好的,我在所有演示中都运行POV-Ray,但 POV 仍然是单线程的,不会使用多个内核。因此,我开始考虑 BASH 中的解决方案。

我编写了一个通用函数,它接受命令列表并在指定数量的子 shell 中运行它们。这实际上可行,但我不喜欢它以线程安全 的多进程方式处理访问下一个命令的方式:

  • 它需要一个带有命令的文件(每行 1 个)作为参数,
  • 要获得“下一个”命令,每个进程(“线程”)将:
    • 等到它可以创建一个锁定文件,使用:ln $CMDFILE $LOCKFILE
    • 从文件中读取命令,
    • 通过删除第一行修改 $CMDFILE,
    • 删除 $LOCKFILE。

有没有更清洁的方法来做到这一点? 我无法让子外壳正确地从 FIFO 中读取一行。


顺便说一句,这样做的目的是增强我在 BASH 命令行上的功能,而不是寻找非 bash 解决方案。我倾向于从命令行执行很多复杂的任务,并且想要工具箱中的另一个工具。

同时,这是处理从文件中获取下一行的函数。如您所见,它每次读取/删除一行时都会修改一个磁盘文件。这看起来有点骇人听闻,但我没有想出更好的方法,因为 FIFO在 bash 中没有setvbuf()不起作用。

#
# Get/remove the first line from FILE, using LOCK as a semaphore (with
# short sleep for collisions).  Returns the text on standard output,
# returns zero on success, non-zero when file is empty.
#
parallel__nextLine() 
{
  local line rest file=$1 lock=$2

  # Wait for lock...
  until ln "${file}" "${lock}" 2>/dev/null
  do sleep 1
     [ -s "${file}" ] || return $?
  done

  # Open, read one "line" save "rest" back to the file:
  exec 3<"$file"
  read line <&3 ; rest=$(cat<&3)
  exec 3<&-

  # After last line, make sure file is empty:
  ( [ -z "$rest" ] || echo "$rest" ) > "${file}"

  # Remove lock and 'return' the line read:
  rm -f "${lock}"
  [ -n "$line" ] && echo "$line"
}
4

4 回答 4

8
#adjust these as required
args_per_proc=1 #1 is fine for long running tasks
procs_in_parallel=4

xargs -n$args_per_proc -P$procs_in_parallel povray < list

请注意,nproc即将发布到 coreutils 的命令将自动确定可用处理单元的数量,然后可以将其传递给 -P

于 2009-11-06T12:17:41.920 回答
2

如果您需要真正的线程安全,我建议您迁移到更好的脚本系统。

例如,使用 python,您可以使用信号量/队列创建具有安全同步的真实线程。

于 2009-11-05T22:30:33.707 回答
2

很抱歉这么久后碰到这个问题,但我为这个 IMO 拼凑了一个相当好的解决方案
它不能完美地工作,但它会将脚本限制为运行一定数量的子任务,然后等待所有其余的最后。

#!/bin/bash

pids=()
thread() {
  local this
  while [ ${#} -gt 6 ]; do
    this=${1}
    wait "$this"
    shift
  done
  pids=($1 $2 $3 $4 $5 $6)
}
for i in 1 2 3 4 5 6 7 8 9 10
do
  sleep 5 &
  pids=( ${pids[@]-} $(echo $!) )
  thread ${pids[@]}
done
for pid in ${pids[@]}
do
  wait "$pid"
done

它似乎很适合我正在做的事情(一次处理一堆文件的并行上传)并防止它破坏我的服务器,同时仍然确保在完成脚本之前上传所有文件

于 2010-08-23T22:25:18.667 回答
0

我相信您实际上是在这里分叉进程,而不是线程。我建议寻找不同脚本语言(如perlpythonruby.

于 2009-11-06T07:04:54.510 回答