Ответ 1
Основываясь на моем опыте, я обобщу основные различия в производительности между параллельными программами в процессорах и графических процессорах. Поверьте мне, сравнение может быть изменено из поколения в поколение. Поэтому я просто укажу, что хорошо и плохо для процессоров и графических процессоров. Конечно, если вы делаете программу в крайнем случае, т.е. Имея только плохие или хорошие стороны, она будет работать определенно быстрее на одной платформе. Но смесь из них требует очень сложных рассуждений.
Уровень хост-программы
Одним из ключевых различий является стоимость передачи данных. Для устройств GPU требуются некоторые передачи памяти. В некоторых случаях эта стоимость является нетривиальной, например, когда вам приходится часто переносить некоторые большие массивы. По моему опыту, эту стоимость можно свести к минимуму, но нажав большую часть кода хоста на код устройства. Единственные случаи, которые вы можете сделать, - это когда вам нужно взаимодействовать с операционной системой хоста в программе, например, выводить на монитор.
Уровень программы устройства
Теперь мы приходим к сложной картине, которая еще не полностью раскрыта. Я имею в виду, что в графических процессорах много загадочных сцен, которые не были раскрыты. Но тем не менее, мы можем отличить процессор и графический процессор (код ядра) с точки зрения производительности.
Есть несколько факторов, которые, как я заметил, сильно влияют на разницу.
- Распределение рабочей нагрузки
Графические процессоры, состоящие из множества исполнительных блоков, предназначены для обработки массивно-параллельных программ. Если у вас мало работы, скажите несколько последовательных задач и поставите эти задачи на графический процессор, только несколько из этих многих исполнительных блоков заняты, таким образом, будет медленнее, чем процессор. Поскольку процессоры, с другой стороны, лучше обрабатывают короткие и последовательные задачи. Причина проста: процессоры намного сложнее и способны использовать уровень команд parallelism, тогда как графические процессоры используют уровень потока parallelism. Ну, я слышал, что NVIDIA GF104 может делать Superscalar, но у меня не было шансов испытать это, хотя.
Стоит отметить, что в графических процессорах рабочая нагрузка делится на небольшие блоки (или рабочие группы в OpenCL), а блоки расположены в кусках, каждый из которых выполняется в одном потоковом процессоре (я использую терминологии от NVIDIA). Но в процессорах эти блоки выполняются последовательно - я не могу думать ни о чем другом, кроме одного цикла.
Таким образом, для программ с небольшим количеством блоков он, скорее всего, будет работать быстрее на процессорах.
- Инструкции по управлению потоком
Филиалы - это плохие вещи для графических процессоров, всегда. Пожалуйста, имейте в виду, что графические процессоры предпочитают одинаковые вещи. Равные блоки, равные потоки внутри блоков и равные потоки в основе. Но что самое главное?
***Branch divergences.***
Программисты Cuda/OpenCL ненавидят расхождения ветвей. Так как все потоки каким-то образом делятся на наборы из 32 потоков, называемые деформацией, и все потоки в основе выполняются в стоп-стоп, расхождение ветвей приведет к сериализации некоторых потоков в warp. Таким образом, время выполнения варпа будет соответственно умножено.
В отличие от графических процессоров, каждый процессор в ЦП может следовать своему собственному пути. Кроме того, ветки могут быть эффективно выполнены, потому что процессоры имеют предсказание ветвлений.
Таким образом, программы, у которых больше расхождений в warp, скорее всего, будут работать быстрее на процессорах.
- Инструкции по доступу к памяти
Это ДЕЙСТВИТЕЛЬНО достаточно сложно, поэтому давайте кратко расскажем.
Помните, что доступ к глобальной памяти имеет очень высокую задержку (400-800 циклов). Таким образом, в старых поколениях графических процессоров, будь то совлокальный доступ к памяти, это критический вопрос. Теперь ваш GTX560 (Fermi) имеет более 2 уровней кешей. Таким образом, во многих случаях стоимость доступа к глобальной памяти может быть уменьшена. Однако кэши в процессорах и графических процессорах различны, поэтому их эффекты также различны.
Что я могу сказать, так это то, что это действительно зависит от вашего шаблона доступа к памяти, вашего шаблона кода ядра (как чередование доступа к памяти с помощью вычислений, типов операций и т.д.), чтобы узнать, работает ли на GPU или ЦП.
Но почему-то вы можете ожидать, что огромное количество промахов в кеше (в графических процессорах) оказывает очень плохое влияние на графические процессоры (насколько это плохо? - это зависит от вашего кода).
Кроме того, разделяемая память является важной особенностью графических процессоров. Доступ к общей памяти происходит так же быстро, как доступ к кешу L1 GPU. Таким образом, ядра, использующие общую память, получат большую выгоду.
Некоторые другие факторы, о которых я на самом деле не упоминали, но они могут иметь большое влияние на производительность во многих случаях, таких как конфликты в банках, размер транзакции памяти, занятость GPU...