Выполнение цикла сценария оболочки параллельно - PullRequest
1 голос
/ 01 июля 2019

Я написал скрипт, который

  1. получить список всех файлов изображений из каталога
  2. при необходимости создайте новую папку для нового изображения
  3. оптимизировать изображение для экономии ресурсов хранения

Я пытался использовать parallel -j "$(nproc)" до mogrify, но обнаружил, что это было неправильно, потому что до того, как mogrify используется DIR и mkdir, мне нужно вместо этого что-то вроде & в конце mogrify, но сделать это только для n процессов.

текущий код выглядит так:

#!/bin/bash

find $1 -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -type f | while read IMAGE
do
    DIR="$2"/`dirname $IMAGE`
    echo "$IMAGE > $DIR"
    mkdir -p $DIR
    mogrify -path "$DIR" -resize "6000000@>" -filter Triangle -define filter:support=2 -unsharp 0.25x0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB "$IMAGE"
done

exit 0

Может кто-нибудь подсказать, как правильно будет запускать такой скрипт параллельно? каждый цикл занимает около 15 секунд.

Ответы [ 2 ]

0 голосов
/ 01 июля 2019

Создайте функцию bash, которая правильно работает с одним файлом, и вызовите ее параллельно:

#!/bin/bash

doit() {
  IMAGE="$1"
  DIR="$2"/`dirname $IMAGE`
  echo "$IMAGE > $DIR"
  mkdir -p $DIR
  mogrify -path "$DIR" -resize "6000000@>" -filter Triangle -define filter:support=2 -unsharp 0.25x0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB "$IMAGE"
}
export -f doit

find $1 -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -type f |
    parallel doit

По умолчанию для GNU Parallel выполняется одно задание на каждый поток ЦП, поэтому ǹproc не требуется.

Это имеет меньше накладных расходов, чем начало sem для каждого файла (sem = 0,2 с на вызов, parallel = 7 мс на вызов).

0 голосов
/ 01 июля 2019

Если у вас есть цикл оболочки, который выполняет некоторую настройку и вызывает дорогостоящую команду, способ ее распараллеливания состоит в использовании sem из параллельной GNU:

for i in {1..10}
do
  echo "Doing some stuff"
  sem -j +0 sleep 2
done
sem --wait

Это позволяет циклу работать иделайте все как обычно, одновременно планируя параллельное выполнение команд (-j +0 запускает одно задание на ядро ​​ЦП).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...