Процессы в Mac OSX зависают и странное использование процессора
Я работаю в научном учреждении, и одна из задач, над которыми я сейчас работаю, заключается в запуске симуляции и выводе данных, которые она генерирует, на лету на жесткий диск. Когда я говорю "на лету", я имею в виду, что программа сама выкладывает данные на диск каждую секунду или около того. Эти симуляции написаны исключительно в однопоточном C++ и выполняются на Mac Pro. Соответствующие характеристики этого Mac приведены ниже:
OSX Version: 10.6.8
Model Name: Mac Pro
Model Identifier: MacPro4,1
Processor Name: Quad-Core Intel Xeon
Processor Speed: 2.66 GHz
Number Of Processors: 2
Total Number Of Cores: 8
Intel Xeon с поддержкой многопоточности поддерживает до 8 виртуальных ядер
Я выполняю свои симуляции в простом файле.sh, используя следующий синтаксис:
nohup simulation1.o configfile 2> /dev/null > /dev/null &
nohup simulation2.o configfile 2> /dev/null > /dev/null &
и так далее...
Использование nohup означает, что мне не нужно беспокоиться о случайных отключениях при удаленной работе.
Когда я смотрю на ps
выполнив, скажем, 10, моделирования с использованием моего bash-файла, я обнаружил, что в столбце STATE процессы регулярно переключаются с "работы" на "зависание". Кроме того, я ожидаю, что загрузка ЦП будет 100% для каждого процесса, но каждый процесс в среднем составляет около 28%. (Я ожидаю, что загрузка ЦП будет составлять 100% для каждого процесса, так как при запуске только одного из этих моделирования столбец ЦП имеет максимальную величину около 100%, что добавляется к тому факту, что ядра имеют гиперпоточность. Это очень сильно загружает процессор.)
Кто-нибудь знает, что происходит? В частности:
- Что означает "застрял" в отношении
ps
- Почему ЦП не максимально для каждого процесса?
Я был бы очень признателен за помощь.
1 ответ
Я исправил свою проблему. Оказалось, довольно тонко, но благодаря Озаиру - он ударил ногтем по голове. Моя конкретная симуляция не читает очень много данных (только параметры инициализации), но тратит много времени, выплевывая вычисленные данные. Грубый способ, который я реализовал изначально, с использованием стандарта C++ file.open("tobewritten.dat")
очень медленный, даже сам по себе, но при запуске нескольких экземпляров отдельные экземпляры тратят целую вечность на ожидание "времени записи" на жестком диске.
Есть несколько конкретных уроков, которые я выучил:
cout << std::endl
очищает буфер при использовании; если буфер не заполнен, то более быстрая операция записи в ОЗУ используется неоптимально. использование"\n"
а затем закройте файл в конце. C++ обрабатывает сброс буфера на диск, когда он заполнен.При одновременной записи нескольких массивных файлов данных (я имею в виду ГБ) лучше всего указывать буфер вручную. На данный момент я установил буфер в 50 МБ. Использование больших буферов означает, что ваша система проводит больше времени между оперативной памятью и процессором и выполняет только дамп на диск (медленный бит) с интервалом 50 МБ.
Даже не использовать
cout
записать в файл. Это медленнее, чемsprintf
и его варианты.
Используя методы, которые я описал выше, я перешел с 28% использования ЦП для каждого процесса на 100% использования ЦП. "Застрявшее" состояние больше не появляется.