Отслеживание конфликтов потоков в Java - PullRequest
3 голосов
/ 21 февраля 2012

Используя YourKit, я измерял приложение и определял основной приемник ЦП. Я структурировал вычисления, чтобы распараллелить это через ExecutorService с фиксированным числом потоков.

На 24-ядерном компьютере преимущество добавления потоков очень быстро истекает выше 4. Итак, подумал я, здесь должно произойти некоторое раздор или блокировка, или задержка ввода-вывода, или что-то в этом роде.

ОК, я включил функцию «Мониторинг использования» в YourKit, и количество заблокированного времени, отображаемое в рабочих потоках, тривиально. Если посмотреть на диаграмму состояния потоков, то рабочие потоки почти все «зеленые» (работают), а не желтые (ожидание) или красные (заблокированные).

Профилирование ЦП по-прежнему показывает 96% времени в дереве вызовов, которое находится внутри рабочих потоков.

Так что в реальном времени что-то расходуется. Это может быть планирование накладных расходов?

В псевдокоде вы можете смоделировать это как:

loop over blobs:
    submit tasks for a blob via invokeAll of executor
    do some single-threaded processing on the results
end loop over blobs

В тестовом прогоне есть ~ 680 BLOB-объектов и ~ 13 задач / BLOB-объектов. Таким образом, каждый поток (в расчете на четыре) отправляет примерно 3 раза на каждый BLOB-объект.

аппаратное обеспечение: я провел небольшие тесты на своем MacBook Pro, а затем на большом толстом Dell: hwinfo на linux сообщает о 24 различных элементах для --cpu, состоящих из

Intel(R) Xeon(R) CPU           X5680  @ 3.33GHz

Сайт Intel сообщает мне, что у каждого есть 6 ядер, 12 потоков, я подозреваю, у меня их 4.

Ответы [ 3 ]

2 голосов
/ 21 февраля 2012

Предполагая, что у вас есть 4 ядра с 8 логическими потоками в каждом, это означает, что у вас есть 4 реальных процессора, которые могут быть разделены между 32 потоками. Это также означает, что, когда у вас есть 2-8 активных потоков на одном ядре, они должны конкурировать за ресурсы, такие как конвейер ЦП и кэши команд и данных.

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

Я написал библиотеку, которая поддерживает распределение потоков и ядер для Linux и Windows. Если у вас есть Solaris, может быть легко портировать, так как он поддерживает вызовы posix JNI и вызовы JNA.

https://github.com/peter-lawrey/Java-Thread-Affinity

1 голос
/ 21 февраля 2012

Скорее всего, это не спор, хотя трудно сказать без подробностей. Результаты профилирования могут вводить в заблуждение, поскольку Java сообщает о потоках как RUNNABLE, когда они заблокированы на диске или в сети. Yourkit по-прежнему считает его как процессорное время.

Лучше всего включить профилирование процессора и изучить, что занимает время в рабочих потоках. Если это заканчивается в основном в классах java.io, у вас все еще есть задержка диска или сети.

0 голосов
/ 21 февраля 2012

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

Если вы можете, попробуйте этот способ:

for each blob{

        create a runnable for blob process name it blobProcessor;
        create a runnable for blob results name it resultsProcessor;
        submit blobProcessor;
               before blobProcessor finishes, submit resultsProcessor;
}

также:

Посмотрите, пожалуйста, на JetLang, который обеспечивает параллельный поток без использования потоков.

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