Как ускорить последовательный запуск программы под Linux? - PullRequest
1 голос
/ 08 декабря 2011

Я написал две сравнительно небольшие программы на языке C. Обе они общаются друг с другом, используя текстовые данные. Программа A генерирует некоторые проблемы из заданного ввода, B оценивает их и создает ввод для другой итерации A.

Вот скрипт bash, который я сейчас использую:

for i in {1..1000}
do 
  ./A data > data2;
  ./B data2 > data;
done

Проблема в том, что поскольку действия A и B занимают не очень много времени, большая часть времени тратится (как я полагаю) на запуск приложений. Когда я измеряю время запуска скрипта, я получаю:

$ time ./bash.sh
real    0m10.304s
user    0m4.010s
sys     0m0.113s

Итак, мой главный вопрос: есть ли способ быстрее передать данные между этими двумя приложениями? Я не хочу объединять их в одно приложение, потому что я пытаюсь создать набор инструментов с независимыми, легко взаимодействующими инструментами (как было предложено в «Искусстве программирования Unix», из которого я изучаю способ написания повторно используемых). программное обеспечение).

PS. Файлы data и data2 содержат наборы данных, которые в целом необходимы одновременно этим приложениям (поэтому невозможна передача, например, по одной строке данных за раз).

Спасибо за любые предложения.

ура

kajman

Ответы [ 5 ]

3 голосов
/ 08 декабря 2011

Можете ли вы создать именованный канал ?

mkfifo data1
mkfifo data2
./A data1 > data2 &
./B data2 > data1

Если ваше приложение читает и пишет в цикле, это может сработать:)

1 голос
/ 08 декабря 2011

Если вы хотите, чтобы программа работала быстрее, вам нужно понять, что заставляет программу работать медленно.Область компьютерных наук, посвященная измерению производительности работающей программы, называется profiling .

Как только вы обнаружите, какая внутренняя часть вашей программы работает медленно, вы, как правило, можете ускорить ее.То, как вы ускорите этот элемент, во многом зависит от того, что делает «медленная часть» и как она «выполняется».

Несколько человек рекомендовали каналы для перемещения данных непосредственно из выходных данных одной программы.на вход другой программы.Предполагая, что вы переписываете свои инструменты для обработки ввода и вывода по трубопроводу, это может повысить производительность.Опять же, это зависит от что вы делаете и как вы делаете это.

Например, если ваш инструмент просто исправляет конец строки в стиле Windows вконец строки в стиле Unix, программа может читать в одну строку, ожидая, пока она станет доступной, проверять конец строки и записывать строку с нужным концом строки.Или инструмент может прочитать все данные, выполнить замену для каждого «неправильного» конца строки в памяти, а затем записать все данные.С первым решением, трубопровод ускоряет процесс.Со вторым решением конвейер ничего не ускоряет.

Причина, по которой действительно так сложно ответить на такой вопрос, заключается в том, что нужное вам исправление на самом деле зависит от кода, который у вас есть,проблема, которую вы пытаетесь решить, и средства, которыми вы решаете ее сейчас.В конце концов, не всегда есть 100% гарантия того, что код можно ускорить;тем не менее, практически каждый фрагмент кода имеет возможности для ускорения.Используйте профилирование, чтобы ускорить медленные части, вместо того, чтобы тратить время на работу с частью вашей программы, которая вызывается только один раз и составляет 0,001% времени выполнения программы.

Помните, что если вы что-то ускоряетеэто составляет 0,001% времени выполнения вашей программы на 50%, вы фактически только ускорили всю вашу программу на 0,0005%.Используйте профилирование, чтобы определить блок кода, который занимает 90% времени выполнения, и сосредоточиться на нем.

1 голос
/ 08 декабря 2011

Если бы вы использовали каналы для передачи стандартного вывода программы A в стандартный поток программы B, вы бы исключили необходимость записи файла "data2" в каждом цикле.

./A data1 | ./B > data1

Программа B должна иметь возможность использовать ввод из стандартного ввода, а не из указанного файла.

0 голосов
/ 08 декабря 2011

Это почти наверняка не запуск приложения, что является узким местом.Linux в конечном итоге будет кэшировать большие части ваших программ, а это означает, что запуск будет постепенно увеличиваться на быстрее (до определенного момента), чем больше вы запускаете свою программу.

Вам нужно искать в другом местеваше узкое место.

0 голосов
/ 08 декабря 2011

Мне действительно интересно, почему, если A и B зависят друг от друга, вы хотите, чтобы они были частью независимого набора инструментов.

Одно решение - это компромисс между двумя:

  1. Создать библиотеку, которая содержит A.
  2. Создать библиотеку, которая содержит B.
  3. Создайте программу, которая порождает два потока, 1 из которых содержит A, а 2 - B.
  4. Создайте семафор, который говорит А запускаться, и другой, который приказывает Б. бежать.
  5. После функции, которая вызывает A в 1, увеличьте семафор B.
  6. После того, как функция, вызывающая B в 2, увеличивает семафор A.

Другая возможность - использовать блокировку файлов в ваших программах:

  1. Заставить A и B выполняться бесконечными циклами (или сколько раз вы обрабатываете данные)
  2. Добавьте код, чтобы попытаться заблокировать оба файла в начале бесконечного цикла в A и B (если нет, спите и попробуйте еще раз, чтобы вы ничего не делали, пока не получите блокировку).
  3. Добавьте код, чтобы разблокировать и спать дольше, чем сон в шаге 2 в конце каждого цикла.

Любой из них решает проблему накладных расходов на запуск программы между запусками.

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