Программы, которые утверждают, что они не «многоядерные» дружественные

17

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

Как это может быть? Многие программы (особенно игры) по своей природе используют параллелизм, и, поскольку ОС отвечает за планирование задач на ЦП, то эти программы по своей природе не используют преимущества нескольких доступных ядер? Что бы в этом контексте означало «использовать преимущества нескольких ядер»? Эти разработчики на самом деле запрещают планирование задач ОС и принуждают к сродству или их собственному планированию? (Походит на главную проблему стабильности).

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

SnakeDoc
источник
11
Большая вероятность состоит в том, что при синхронизации были использованы ярлыки, которые работают для однопроцессорной системы / ядра, но нарушают истинный параллелизм нескольких процессоров / ядер.
Барт ван Инген Шенау
@BartvanIngenSchenau: это правильно. Вы должны расширить это и опубликовать это как ответ. Я думаю, что все остальные упустили момент.
Кевин Клайн
1
Я думаю, что @Bart действительно близко. Однако, s / work /, кажется, работает /, и это будет ближе к отметке.
Бен Фойгт
в качестве отступления - у меня был опыт этого как пользователя, а не программиста - Ground Control 2 на Windows XP. Мне нужно было установить привязку к ядру только к одному ядру в многоядерной системе, чтобы она работала правильно, в противном случае все анимации (влияющие на всю игру) будут работать с 10-кратной скоростью, которая через некоторое время становилась более сложной задачей, но немного раздражала через некоторое время. , Я не делал никакой работы над играми, но, на мой взгляд, какая-то часть игры, казалось, полагалась на процессор, выполняющий только определенное количество работы одновременно.
jammypeach

Ответы:

28

Хороший параллелизм требует гораздо большего, чем просто добавить несколько потоков в приложение и надеяться на лучшее. Существует диапазон того, насколько параллельная программа может идти от смущающе параллельной к чисто последовательной. Любая данная программа может использовать закон Амдала, чтобы выразить масштабируемость проблемы или алгоритма. Пара квалификаций для смущающе параллельного заявления была бы:

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

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

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

Есть большие архитектурные проблемы в борьбе с эффективным параллелизмом

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

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

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

Суть:

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

Берин Лорич
источник
Это отличный анализ. Однако меня беспокоит одна вещь: ваша точка зрения о том, что программы реального мира часто не смущают параллельностью и, следовательно, их трудно распараллелить: хотя может быть невозможным делать одно и то же параллельно, может быть очень легко выполнять разные вещи параллельно ( например, в конвейерной архитектуре или с отдельным потоком пользовательского интерфейса).
Амон
8
Суть в том, что вам нужно проектировать для параллельного выполнения, и если вы этого не сделаете, вы ограничены отсутствием дизайна. Я согласен , что это может быть очень легко сделать разные вещи параллельно, но если это существующее приложение с ожиданиями высокого пользователя. В этом случае очень хорошо, возможно, потребуется переписать, чтобы сделать это возможным. Переписывания по своей природе рискованны, но иногда вы можете дать им хороший аргумент. Я сделал несколько таких переписываний, которые максимизировали параллельную обработку, сохраняя при этом как можно больше кода. Там много скрытых факторов.
Берин Лорич
Отличный ответ. Возможно, стоит подчеркнуть, что при параллелизации некоторых систем может быть не только уменьшающаяся отдача, но некоторые могут фактически стать медленнее из-за накладных расходов, необходимых для их параллельного выполнения. В частности, большое количество семафоров / блокировок и переключение контекста может оказать неблагоприятное влияние на время выполнения. В частности, переключение контекста может снизить эффективность кэша, что является нетривиальной задачей, если вы собираетесь оптимизировать свою систему. В частности, пример игровых движков OP заставляет меня вспомнить, что я слышал гораздо больше об оптимизации кэширования, чем о параллельном доступе.
Gankro
35

Многие программы (особенно игры) по своей природе используют параллелизм,

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

В C, C ++ и C # вам необходимо явно указать приложению запуск новых потоков и / или процессов.

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

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

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


источник
Это верно даже для новых современных программ от крупных разработчиков / издателей? Когда я сажусь и пишу программу, одна из первых вещей на этапе проектирования, о которой я думаю, - нужен ли мне параллелизм? Потому что это может привести к совершенно другому дизайну. В частности, игры должны иметь некоторый уровень параллелизма, иначе игра зависнет, когда одна из тысячи экранных моделей попытается что-то сделать ...?
SnakeDoc
5
@ SnakeDoc - я думаю, что вы путаете ваши домены там. Компании в области больших игр наверняка пишут с учетом параллелизма, но мне еще предстоит увидеть игру от Big Game, которая не поддерживает параллелизм. Приложения и игры, которые я видел, которые не могут поддерживать параллелизм, как правило, поступают из небольших магазинов / индивидуальных разработчиков, где они не начали бы с такого мышления. И в какой-то момент в развитии приложения становится невозможным получить параллелизм после факта. И некоторые приложения никогда не предназначались для того, чтобы делать достаточно, чтобы оправдать одновременность.
А также некоторые игры развиваются благодаря новому контенту (графика и игровой процесс), без необходимости обновления игрового движка (реализация кода). Таким образом, игровой движок может отставать в технологиях на годы.
rwong
6
@SnakeDoc: вам не нужен параллелизм для работы с тысячами экранных моделей. Не каждый объект в вашей игре нуждается в собственном потоке для его симуляции; Один поток может обрабатывать обновления всего на экране на каждом временном шаге.
user2357112 поддерживает Monica
13

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

Зачем мне писать однопоточные программы? Их легче писать и легче отлаживать: одна вещь происходит за другой (вместо того, чтобы несколько вещей происходили одновременно и, возможно, переходили друг в друга). Или ваша программа может быть не нацелена на многоядерные машины (как в старых играх). В некоторых случаях многопоточная программа может работать даже медленнее, чем однопоточная версия, если накладные расходы от переключения контекста и обмена данными между потоками превышают скорость, получаемую при параллельном выполнении (некоторые части программы могут не распараллеливаться).

Амон
источник
8

Это не полный ответ. Это предостерегающая история.

Однажды я подумал, что покажу студентам в моем параллельном курсе программирования параллельную быструю сортировку. «Быстрая сортировка должна хорошо распараллелить», - подумал я. Я использовал две темы. Запустил его на моем одноядерном компьютере. Результаты были:

  • 14 секунд для однопоточной версии.
  • 15 секунд для двухпоточной версии.

Это было о том, что я ожидал.

Затем я попробовал это на более новой двухъядерной машине.

  • 11 секунд для однопоточной версии.
  • 20 секунд для двухпоточной версии.

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

Теодор Норвелл
источник
2
Сколько элементов массива вы тестировали? Возможно, сортировка слиянием была бы более подходящей, поскольку многоядерное программирование потребовало бы копирования данных, чтобы избежать конфликтов строк кэша?
rwong
2
@rwong Было 10 000 000 элементов массива. Конечно, слияние будет хорошо распараллеливать. Если бы я использовал сортировку слиянием, я бы, наверное, не усвоил бы полезный урок.
Теодор Норвелл
1
@ArlaudPierre Я рассмотрю распараллеливание любого алгоритма. Quicksort интересен тем, что вы можете использовать для этого подход «мешок задач». Поскольку задачи независимы, моя интуиция заключалась в том, что это должно быть примером смущающего параллелизма. Я должен упомянуть, что после небольшой настройки он фактически ускорился почти до 2.
Теодор Норвелл
1
@Jules Ответ - балансировка нагрузки. Также я хотел написать это так, чтобы количество потоков было легко изменить. Ваш подход хорошо обобщается на степени 2, но не так хорошо, как на другие потоки.
Теодор Норвелл
2
@MaciejPiechotka Мораль - это почти все, что вы предлагаете. Но возвращаясь к OP, я думаю, что наиболее важным моральным принципом является то, что многопоточные программы могут на самом деле (намного) работать медленнее на многоядерной архитектуре, чем на одноядерном процессоре, если не предпринимались усилия для обеспечения иного.
Теодор Норвелл