Подтвердить что ты не робот

Конфигурация нитей на основе №. процессорных ядер

Сценарий: у меня есть пример приложения, и у меня есть 3 различных конфигурации системы -

- 2 core processor, 2 GB RAM, 60 GB HHD,
- 4 core processor, 4 GB RAM, 80 GB HHD,
- 8 core processor, 8 GB RAM, 120 GB HHD

Чтобы эффективно использовать возможности H/W для моего приложения, я хочу настроить no. потоков на уровне приложения. Однако я хочу сделать это только после полного понимания возможностей системы.

Может ли быть какой-то способ (system/modus/tool), чтобы определить системное мастерство со ссылкой на max и min no. нитей он может обслуживать оптимально и без потери эффективности и производительности. Таким образом, я мог бы настроить только те значения для моего приложения, которые будут выполнять полную справедливость и достичь наилучшей производительности для соответствующей конфигурации оборудования.

Отредактировано1: Может ли кто-нибудь проконсультироваться о том, как установить базовую линию для конкретной конфигурации h/w.

Отредактировано2: Чтобы сделать его более прямым - захотите узнать/узнать о любом ресурсе/записи, который я могу прочитать, чтобы получить некоторое представление о управлении процессорами Threads на общем/целостном уровне.

4b9b3361

Ответ 1

Оптимальное количество используемых потоков зависит от нескольких факторов, но в основном от количества доступных процессоров и от того, насколько интенсивны ваши задачи. Java Concurrency in Practice предлагает следующую формальную формулу для оценки оптимального количества потоков:

N_threads = N_cpu * U_cpu * (1 + W / C)

Где:

  • N_threads - оптимальное количество потоков
  • N_cpu - количество процессоров, которые вы можете получить из Runtime.getRuntime().availableProcessors();
  • U_cpu - целевое использование ЦП (1, если вы хотите использовать полные доступные ресурсы)
  • W/C - это отношение времени ожидания для вычисления времени (0 для задачи, связанной с процессором, возможно, 10 или 100 для медленных задач ввода-вывода)

Так, например, в сценарии с привязкой к процессору у вас будет столько потоков, сколько у процессора (некоторые защитники используют это число + 1, но я никогда не видел, чтобы это имело существенное значение).

Для медленного процесса ввода-вывода, например веб-искателя, W/C может быть 10, если загрузка страницы в 10 раз медленнее, чем обработка, и в этом случае полезно использовать 100 потоков.

Обратите внимание, что на практике существует верхняя граница (использование 10 000 потоков, как правило, не ускоряет работу, и вы, вероятно, получите OutOfMemoryError, прежде чем вы сможете запускать их в любом случае с нормальными настройками памяти).

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

Хотя это и не связано строго, вас также может заинтересовать закон Amdahl, целью которого является измерение максимального ускорения, которое вы можете ожидать от параллелизации программы.

Ответ 2

Моя рекомендация - предоставить конфигурационные и командные ключи для назначения количества потоков для каждой машины. Используйте эвристику, основанную на Runtime.getRuntime(). AvailableProcessors(), как указано в других ответах здесь, в случаях, когда пользователь/админ явно не настроил приложение по-другому. Я настоятельно рекомендую отказаться от эксклюзивных эвристических зависимостей от сквозных доводов по нескольким причинам:

  • Большинство современных аппаратных средств продвигаются к все более неоднозначным типам "аппаратных потоков": модели SMT, такие как Intel Hyperthreading и AMD Compute Modules, усложняют формулы (подробности ниже), и запрос этой информации во время выполнения может быть затруднен.

  • Большинство современных аппаратных средств имеют турбонаддув, который масштабирует скорость на основе активных сердечников и температуры окружающей среды. По мере совершенствования турботехнического оборудования увеличивается скорость вращения (ghz). Некоторые недавние чипы Intel и AMD могут варьироваться от 2,6 тыс. Гц (все активные ядра) до 3,6 тыс. Гц (один/двухъядерный активный), что в сочетании с SMT может означать, что каждая нить получает эффективную пропускную способность 1,6 Гц - 2,0 Гц в прежнем проекте. В настоящее время нет способа запросить эту информацию во время выполнения.

  • Если у вас нет надежной гарантии того, что ваше приложение будет единственным процессом, запущенным на целевых системах, то слепое потребление всех ресурсов процессора может не понравиться администратору или администратору сервера (в зависимости от того, является ли программное обеспечение приложение пользователя или сервера).

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

  • Современные антивирусные сканеры теперь работают, устанавливая специальный флаг приоритета, предоставляемый современными операционными системами, например. они позволяют ОС сообщать им, когда "система простаивает". ОС основывает свое решение не только на загрузке процессора: оно также учитывает пользовательские входные и мультимедийные флаги, которые могут быть установлены игроками фильмов и т.д. Это нормально для задач с большей нагрузкой, но не полезно для интенсивной задачи с процессором, такой как ваш.

  • Распределенные домашние компьютерные приложения (BOINC, Folding @Home и т.д.) работают, периодически запрашивая текущие процессы и загрузку центрального процессора - раз в секунду или полсекунды. Если обнаружение нагрузки в процессах, не принадлежащих к приложению, для нескольких запросов в строке, приложение приостанавливает вычисления. Когда загрузка будет низкой для некоторого количества запросов, она возобновится. Требуется несколько запросов, потому что показания загрузки процессора печально известны для кратковременных всплесков. Есть все еще оговорки: 1. Пользователям по-прежнему предлагается вручную переконфигурировать BOINC, чтобы они соответствовали их спецификациям на машине. 2. Если BOINC запускается без прав администратора, он не будет знать о процессах, запущенных другими пользователями (включая некоторые процессы обслуживания), поэтому он может несправедливо конкурировать с процессами для ресурсов ЦП.

Что касается SMT (HyperThreading, Compute Modules):

Большинство SMT в наши дни будут сообщать об аппаратных ядрах или потоках, что обычно не очень хорошо, потому что несколько приложений работают оптимально при масштабировании по каждому ядру в системе SMT. Хуже того, запрос о том, является ли основное ядро ​​(SMT) или выделенным, часто не дает ожидаемых результатов. В некоторых случаях сама ОС просто не знает (например, Windows 7 не знает общий дизайн ядра AMD Bulldozer). Если вы можете получить достоверное количество SMT, тогда правило состоит в том, чтобы считать каждый SMT наполовину потоком для задач с интенсивным использованием ЦП и как полный поток для задач с большим количеством простоя. Но на самом деле вес SMT зависит от того, что он делает, и от целевой архитектуры. Реализации Intel и AMD SMT ведут себя почти противоположно друг другу, например - Intel сильная при запуске задач, загружаемых целыми и разветвляющимися операциями параллельно. AMD сильно работает параллельно с SIMD и операциями памяти.

Относительно особенностей Turbo:

Большинство процессоров в наши дни имеют очень эффективную встроенную поддержку Turbo, что еще больше снижает ценность, полученную при масштабировании по всем ядрам системы. Хуже того, турбо-функция иногда основывается как на реальной температуре системы, так и на нагрузках на ЦП, поэтому система охлаждения самой башни влияет на скорость так же, как и на спецификации процессора. Например, на конкретном AMD A10 (Bulldozer) я наблюдал, как он работает на 3.7ghz на двух потоках. Он упал до 3,5 гц, когда начался третий поток, и до 3,4 га, когда был запущен четвертый. Поскольку он также интегрировал графический процессор, он упал до 3,0 гц, когда работали четыре потока плюс GPU (центральный процессор A10 отдает приоритет графическому процессору в сценариях с высокой нагрузкой); но все равно мог собрать 3,6 га с двумя потоками и активным GPU. Поскольку мое приложение использовало как CPU, так и GPU, это было критическое открытие. Я смог улучшить общую производительность, ограничив процесс двумя потоками, связанными с процессором (остальные два общих ядра по-прежнему были полезны, они служили потоками обслуживания графического процессора - могли просыпаться и быстро реагировать на то, чтобы вводить новые данные в графический процессор, по мере необходимости).

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

Заключение: нет хорошего ответа, и потому, что область дизайна CPU SMT/Turbo продолжает развиваться, я сомневаюсь, что в ближайшее время будет хороший ответ. Любая достойная эвристика, которую вы формулируете сегодня, вполне может не дать идеальных результатов завтра. Поэтому моя рекомендация: не тратьте много времени на это. Грубо-угадайте что-то, основанное на подсчетах ядра, которое хорошо подходит для ваших целей, разрешите его переопределить с помощью config/switch и двигаться дальше.

Ответ 3

Вы можете получить количество процессоров, доступных для JVM, как это:

Runtime.getRuntime().availableProcessors()

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

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

Ответ 4

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

Кроме того, если ваше приложение особенно интенсивно связано с процессором, вы можете захотеть взглянуть на "привязку" вашего приложения к конкретным процессорам.

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

Общий подход заключается в том, чтобы избежать CPU 0 (всегда используемого ОС) и устанавливать привязку вашего приложения к группе процессоров, находящихся в одном и том же сокете.

Сохранение потоков приложений от CPU 0 (и, если возможно, вдали от других приложений) часто повышает производительность за счет уменьшения количества переключения задач.

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

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

Ответ 5

Используйте VisualVm инструмент для мониторинга потоков. Сначала создайте минимальные потоки в программе и посмотрите ее производительность. Затем увеличьте количество потоков в пределах программа ans снова анализирует ее производительность. Может, это поможет вам.

Ответ 6

Я использую этот Python script здесь, чтобы определить количество ядер (и памяти и т.д.) для запуска моего приложения Java с оптимальными параметрами и эргономикой. PlatformWise on Github

Он работает следующим образом: напишите python script, который вызывает getNumberOfCPUCores() в приведенном выше script, чтобы получить количество ядер, и getSystemMemoryInMB() для получения ОЗУ. Вы можете передать это сообщение своей программе через аргументы командной строки. Затем ваша программа может использовать соответствующее количество потоков в зависимости от количества ядер.

Ответ 7

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

Что я думаю:

  • В то время только 1 поток программы будет выполняться на 1 ядре.
  • То же приложение с 2 потоками будет выполняться в течение половины времени на 2 ядра.
  • То же приложение с 4 потоками будет выполняться быстрее на 4 ядрах.

Таким образом, у разрабатываемого приложения должен быть уровень Threading

Время выполнения потока управляется операционной системой и является очень непредсказуемой деятельностью. Время выполнения ЦП называется временем или квантом. Если мы создаем все больше и больше потоков, операционная система тратит часть этого временного фрагмента на решение, какой поток идет первым, тем самым уменьшая фактическое время выполнения каждого потока. Другими словами, каждый поток будет выполнять меньшую работу, если в очереди было большое количество потоков.

Прочитайте это, чтобы узнать, как на самом деле использовать основное ядро ​​cpu.Fantastic. csharp-codesamples.com/2009/03/threading-on-multi-core-cpus/

Ответ 8

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