Сценарий Bash, который запускает параллельные потоки, значительно замедляется в течение нескольких часов.

Как упоминалось другими, файлы подключения Wi -Fi в каталоге system-connectionsсодержат MAC-адрес интерфейса. Это должно соответствовать вашим текущим настройкам, поэтому процедура:

  1. скопировать все файлы со старой машины на новую машину из/в каталог:

    /etc/NetworkManager/system-connections
    
  2. изменить запись MAC-адреса в каждом файле со старого MAC-адреса на новый MAC-адрес. Как корень:

    cd /etc/NetworkManager/system-connections
    sed -i -e 's/<old mac>/<new mac>/ *
    
  3. На всякий случай перезапустите диспетчер сети:

    systemctl restart NetworkManager
    

Старый Mac вы можете проверить из любого из файлов, которые вы скопировали, новый Mac, если вы не уверены, что можете проверить с помощьюip link(или из файла, который, вероятно, был создан при установке вашей системы для соединения, которое вы использовали для копирования файлов ).

Примечание :выше предполагает, что у вас был один интерфейс Wi -Fi как в старой, так и в новой настройке, но одна и та же логика должна работать с несколькими интерфейсами.

0
17.03.2020, 04:43
1 ответ

Исходный код.

Когда вы начинаете, вы просто запускаете 300 копий cli.php. Это занимает около 1200 процессов, потому что вы хотите измерить время, необходимое для запуска.

Затем вы зацикливаете переменную crdот 300 до 9999999.

  • Если оболочка считает, что в массиве threadsесть свободные слоты, она запустит новый cli.php, используя 4 процесса.

  • В противном случае вы перебираете примерно 300 процессов, получая
    ядра для заполнения /procвиртуальной файловой системы и проверки наличия
    каталог существует. Любые отсутствующие каталоги приведут к тому, что записи будут
    удален из массива threads.

У вас есть неиспользуемый массив с именем crds.

Поскольку после начальных 300 каждый цикл переменной crd будет создавать 1 новую копию cli.php, если в таблице процессов есть свободные слоты, но может удалять до 300, если таблица заполнена, в конце мы знали только, что было запущено от 300 до примерно 9 967 000 cli.phpпроцессов, причем число определялось тем, насколько быстро работает ваша машина, сколько времени cli.phpтребуется для выполнения и нагрузкой на машину. 6 порядков величины — это много для оптимизации!

Эмпирическое правило заключается в том, что на современной машине запуск 1 процесса занимает 1 мс на одном ядре, так что вы неплохо работаете при начальной скорости запуска. Я ожидаю значительного скачка скорости запуска, когда у вас закончатся свободные ядра для запуска новых процессов.

Улучшения

Одним из способов ускорить это было бы использование ! kill -0 $pidвместо [ ! -d "/proc/${pid}" ]-kill -0. Ничего не уничтожает, но возвращает ошибку, если процесс не существует. killявляется встроенной оболочкой (, как и [), но объем работы, который должен выполнять ядро, меньше. Это будет наиболее эффективно, если большую часть времени в массиве threadsнет свободных слотов.

Второе усовершенствование заменит вызов внешней программы exprна использование встроенной арифметики $((... )), что уменьшит накладные расходы на запуск копии cli.php. Это наиболее эффективно, если большую часть времени в массиве labelsесть свободные слоты.

Чтобы провести более детальный анализ, нам нужно знать приблизительное время, которое cli.phpтребуется для запуска, и сколько существует запусков.

Как сказано в разделе BUGSруководства bash It's too big and too slow., вполне возможно, что в bash есть возможности для улучшения реализации массива.

Альтернативные реализации

делать

В комментариях предлагается использовать xargsили parallel. Я часто предпочитаю использовать make. Первым делом нужно определить, сколько копий cli.phpтребуется. Тогда простой Makefile, такой как

%:
\t/opt/remi/php/root/usr/bin/php cli.php initformula $@

где \t — символ табуляции. (В этой простой версии предполагается, что у вас нет файлов с числовыми именами в диапазоне от 0 до 9999999 ). Затем вызовите make как

make -O -j 300 $(seq 0 9999999) > /tmp/logger

если вам нужны полные 10 000 000 вызовов cli.php. Причины, по которым я предпочитаю makeвместо xargs, включают отсутствие необходимости предпринимать чрезмерные шаги для прерывания обработки, если cli.php возвращает ошибки.

xargs

Для решения xargsпопробуйте

seq 0 9999999 | xargs -n 1 -P 300 /opt/remi/php/root/usr/bin/php cli.php initformula > /tmp/logger

что проще.

Баш

Однако решение Bash, которое использует wait -nfи вообще не беспокоится об отслеживании PID, может больше понравиться OP. Он запускает первые 300 процессов, а затем, обнаружив, что один из них завершает работу, запускает другой. Как только 10 000 000-й запущен, он делает последнее ожидание, чтобы все задания завершились. Не совсем тот же алгоритм, но очень близкий.

#!/bin/bash
for(crd=0;crd<300;crd++); do
    /opt/remi/php/root/usr/bin/php cli.php initformula $crd & 
done > /tmp/logger
for(;crd<=9999999;crd++); do
    wait -fn
    /opt/remi/php/root/usr/bin/php cli.php initformula $crd &
done >> /tmp/logger
wait
2
28.04.2021, 23:20

Теги

Похожие вопросы