Как я могу измерить, как масштабируется мой многопоточный код (ускорение)? - PullRequest
9 голосов
/ 10 марта 2012

Как лучше всего измерить ускорение моей программы, если у меня только 4 ядра?Очевидно, я мог бы измерить его до 4, однако было бы неплохо узнать для 8, 16 и т. Д.

В идеале я хотел бы знать величину ускорения на число потоков, аналогично этомуграфик:

Amdahl's law diagram

Можно ли как-нибудь это сделать?Возможно, метод моделирования нескольких ядер?

Ответы [ 5 ]

3 голосов
/ 10 марта 2012

Извините, но, на мой взгляд, единственное надежное измерение - это получить 8, 16 или более ядер машины и протестировать их.

Насыщенность полосы пропускания памяти, количество функциональных блоков ЦП и другие аппаратные узкие места могут оказать огромное влияние на масштабируемость.По личному опыту я знаю, что если программа масштабируется на 2 ядра и на 4 ядра, она может резко замедлиться при запуске на 8 ядрах, просто потому, что недостаточно иметь 8 ядер для масштабирования 8x.

Вы можете попытаться предсказать, что произойдет, но есть много факторов, которые необходимо учитывать:

  1. кэши - размер, количество слоев, общих / не общих
  2. пропускная способность памяти
  3. количество ядер против числа процессоров, т.е. это 8-ядерный компьютер или двухъядерный компьютер
  4. соединение между ядрами - меньшее количество ядер(2, 4) все еще может достаточно хорошо работать с шиной, но для 8 или более ядер требуется более сложное соединение.
  5. доступ к памяти - опять же, меньшее количество ядер хорошо работает с SMP (симметричномногопроцессорной), в то время как большее число ядер требует модель NUMA (неравномерный доступ к памяти).
2 голосов
/ 10 марта 2012

bamboon и and doron верны, что многие переменные находятся в игре, но если у вас есть настраиваемый размер ввода n, вы можете определить сильное масштабирование и слабое масштабирование вашего кода.

Сильное масштабирование относится к исправлению размера проблемы (например, n = 1M) и изменению количества потоков, доступных для вычисления. Слабое масштабирование означает исправление размера проблемы на поток (n = 10k/thread) и изменение количества потоков, доступных для вычисления.

Это правда, что в любой программе работает много переменных - однако, если у вас есть какой-то базовый размер ввода n, можно получить некоторое подобие масштабирования. На симуляторе n-body, который я разработал несколько лет назад, я варьировал потоки для фиксированного размера и входного размера для каждого потока и мог разумно рассчитать приблизительную меру того, насколько хорошо масштабируется многопоточный код.

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

Вам действительно нужно задать себе вопрос: будет ли это использоваться в 10, 20, 40+ потоках? Если это так, то единственный способ точно определить масштабирование до этих режимов - это фактически сравнить его с платформой, на которой у вас есть это оборудование.


Примечание: в зависимости от приложения может не иметь значения, что у вас есть только 4 ядра. Некоторые рабочие нагрузки масштабируются с увеличением потоков независимо от реального числа доступных ядер, если многие из этих потоков тратят время на «ожидание» чего-либо (например, веб-серверы). Если вы делаете чистые вычисления, это не будет иметь место

2 голосов
/ 10 марта 2012

Я тоже не думаю, что есть реальный способ сделать это, но одна вещь, которая приходит мне в голову, это то, что вы могли бы использовать виртуальную машину для симуляции большего количества ядер. Например, в VirtualBox вы можете выбрать до 16 ядер из стандартного меню, но я очень уверен, что есть некоторые хаки, которые могут сделать больше, и другие VirtualMachines, такие как VMware, могут даже поддерживать больше из коробки.

enter image description here

1 голос
/ 11 марта 2012

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

Этот вопрос можно рассматривать по-другому: насколько заняты вы можете держать каждый поток, и что они составляют в целом? Таким образом, для шести потоков, работающих, скажем, с коэффициентом использования 50% каждый, это означает, что у вас работают 3 эквивалентных процессора. Разделив это на, скажем, четыре процессора, означает, что ваши методы достигают 75% использования. Сравнивая это использование с временем фактического ускорения, вы узнаете, сколько из вашего использования связано с новыми накладными расходами, и насколько реально ускорилось. Разве это не то, что вас действительно интересует?

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

1 голос
/ 10 марта 2012

Я не верю, что это возможно, поскольку слишком много переменных, чтобы можно было точно экстраполировать производительность. Даже если вы на 100% параллельны. Существуют и другие факторы, такие как скорость шины и ошибки кэширования, которые могут ограничивать вашу производительность, не говоря уже о производительности периферийных устройств. Как все эти факторы влияют на ваш код, можно сделать только при измерении на вашей конкретной аппаратной платформе.

...