#multithreading #shell
Вопрос:
Я использую mkfifo, чтобы попытаться управлять количеством одновременных фоновых задач, выполняемых сценарием оболочки. У меня есть счетчик, который управляет начальным набором задач при развертывании, но после этого я получаю список pid в mkinfo для отслеживания child_pids, запускающих новую задачу, когда она завершается. Где сценарий терпит неудачу, так это в том, что он ожидает первого/следующего pid в списке FIFO. Некоторые потоки могут занять очень много времени по сравнению с другими, которые «начались позже». Это оставляет мне много времени, когда задача не выполняет максимальное количество потоков. Что часто случается, так это то, что он наматывает много потоков, а затем ничего не делает, когда застревает в длинном потоке. Когда длительный поток, наконец, завершается, он часто добавляет сразу много новых потоков, так как идентификаторы pid в списке позже уже завершены. Это не очень эффективно. Есть ли способ, чтобы это отслеживало количество pid? Чтобы сделать это, я думаю, мне нужно, чтобы дочерняя задача в фоновом режиме удалялась из списка pid по мере ее завершения? Или, может быть, просто попросите «задачу ожидания» повторять все pid каждые несколько секунд, чтобы увидеть, завершены ли какие-либо из них. Есть ли лучший способ написать это?
cpus_still_running=0
number_of_cpus=20 #max number of threads
run=$secnum
myfifo=$(/bin/mktemp --dry-run)
mkfifo --mode 0700 $myfifo
exec 3<>$myfifo
rm -f $myfifo
# run through all the instruments being tested, starting with the last
while [ $run -gt 0 ] ; do
while (( $cpus_still_running >= $num_of_cpus )) ; do # this stays at 20 almost whole time task runs after initial spool up
if read -u 3 child_pid ; then
wait $child_pid. #this is the part that waits until one specific pid to close before starting more tasks
(( cpus_still_running -- )). #doesnt really do much as this count stays basically maxed after spool up
fi
done
( # child process
case "$@" in
ALL )
# do a bunch of stuff using $run to make task unique
SMALL_RUN )
#do a bunch of stuff using $run to make task unique
;;
esac
echo $! 1>amp;3 #writes out the child pid
) amp;
(( cpus_still_running ))
(( run -- ))
done
wait