Сколько усилий мы должны потратить на программирование для нескольких ядер?

12

В наши дни процессоры получают все больше и больше ядер, и я удивляюсь ...

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

В какой степени мы должны сделать и оптимизировать это? Нить? Affinity? Аппаратная оптимизация? Что-то другое?

Тамара Вийсман
источник

Ответы:

15

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

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

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

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

ChrisF
источник
3
Но поток, непрерывно перепрыгивающий из ядра в другое, будет иметь снижение производительности (из-за пропущенного кеша ЦП первого и второго уровня), особенно в архитектурах, где используются два разных физических кристалла. В многопоточном интенсивном коде сходство - это хорошо.
Wizard79
@Lorenzo - В этом случае вам нужно посмотреть, сможете ли вы связать нить с одним ядром - что, возможно, является особым случаем - но интересным.
ChrisF
1
Разве это не было бы довольно странным шагом для ОС для переключения контекста активного потока с одного ядра на другое?
JBRWilkinson
Я согласен с @JBRWilkinson, сродство потоков мне кажется работой ОС.
Коллин
1
@JBRWilkinson В Linux (и я думаю, что большинство операционных систем) потоки постоянно перемещаются между ядрами. Первая причина в том, что у вас в целом гораздо больше потоков, чем в ядрах. И если некоторые потоки умирают, вам нужно балансировать. Вторая причина в том, что многие темы спят. И когда некоторые проснутся, ядро ​​может подумать, что одно ядро ​​имеет большую нагрузку, чем другие, и переместить поток, часто ваш процессор перегружает вычислительный поток. Затем 2 потоковых процессора работают на одном и том же ядре, пока ядро ​​не сдвинется назад. Если вы разбиваете большую работу на ровно несколько основных частей, то вы хотите установить сходство потоков.
Госвин фон Бредерлоу
5

Я программист .NET, и я знаю, что .NET имеет высокоуровневую абстракцию для многопоточности, которая называется Задачи. Он защищает вас от необходимости знать слишком много о том, как правильно выполнять многопоточность по металлу. Я предполагаю, что другие современные платформы разработки имеют аналогичные абстракции. Поэтому, если вы собираетесь что-то делать с многопоточностью, я постараюсь работать на этом уровне, если это возможно.

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

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

RationalGeek
источник
5

В мире Objective-C, Mac OS X и iOS написаны фреймворки (как и многие другие), чтобы воспользоваться преимуществами увеличения ядер процессора и предоставить разработчику удобный интерфейс для их использования.

Примером для Mac OS X и iOS является отправка Grand Central. Существуют дополнения libc(я полагаю) для облегчения многопоточности на основе очереди. Затем платформы Cocoa и Foundation (среди прочих) пишутся поверх GCD, предоставляя разработчику легкий доступ к очередям диспетчеризации и многопоточности с очень небольшим количеством стандартного кода.

Многие языки и структуры имеют сходные понятия.

Jasarien
источник
5

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

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

Wizard79
источник
3

Сейчас мы (октябрь 2010) во время огромного перехода.

Сегодня мы могли бы купить 12-ядерный рабочий стол.
Мы могли бы сегодня покупка обработка 448 основной карты (поиск NVidia Tesla).

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

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

В будущем нам нужно будет разделить нашу обработку на отдельные фрагменты для независимой обработки, используя абстракции, такие как новая .NET "Task Framework".

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

Беван
источник
3

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

в большинстве случаев хорошее понимание и использование блокировок, потоков, задач и пулов задач будет хорошим началом, когда потребуется параллелизм. (зависит от языка / lib)

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

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

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

Итак, допустим, вы действительно должны использовать эффективную многопоточность в своих программах (меньшинство в сегодняшнем климате): вам нужно эффективно использовать простую модель, чтобы изучить сложную модель, а затем заново изучить, как вы подходите к потоку программ и взаимодействию. Сложная модель - это то, где ваша программа должна быть в конечном счете, поскольку именно там сегодня находится аппаратное обеспечение и где будут сделаны наиболее важные улучшения.

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

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

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

джастин
источник
2

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

Иногда планировщик много перемещает потоки между ядрами. Если это не приемлемо, вы можете играть с основным сродством.

Тун Крижте
источник
0

В настоящее время частота процессора не будет увеличиваться в ближайшем будущем. Мы застряли на отметке 3 ГГц (без разгона). Конечно, для многих приложений может не быть необходимости выходить за рамки базовой многопоточности. Очевидно, что если вы создаете приложение с пользовательским интерфейсом, любая интенсивная обработка должна выполняться в фоновом потоке.

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

Для многопоточного программирования вы обнаружите, что вы получите снижение прибыли от вашей производительности; Вы можете потратить часы и улучшить программу на 15%, а затем потратить еще одну неделю и только улучшить ее еще на 5%.

Гарри
источник