Интересный вопрос. Я исследовал эту проблему, поэтому мой ответ основан на некоторых ссылках и личном опыте.
Какие типы проблем лучше подходят для обычных многоядерных систем и какие типы лучше подходят для GPGPU?
Как упомянуто @Jared. GPGPU созданы для очень регулярных рабочих нагрузок, например, графики, плотного матрично-матричного умножения, простых фильтров фотошопа и т. Д. Они хорошо переносят большие задержки, потому что по своей природе они способны выдерживать выборку текстуры, операцию с циклом 1000+. Ядра GPU имеют много потоков: когда один поток запускает операцию с большой задержкой (скажем, доступ к памяти), этот поток переводится в спящий режим (а другие потоки продолжают работать) до тех пор, пока операция с длинной задержкой не завершится. Это позволяет графическим процессорам загружать свои исполнительные блоки намного больше, чем традиционные ядра.
Графические процессоры плохо справляются с ветвями, потому что графическим процессорам нравится группировать «потоки» (линии SIMD, если вы не nVidia) в деформации и отправлять их по конвейеру вместе, чтобы сэкономить на мощности выборки / декодирования команд. Если потоки сталкиваются с ветвью, они могут расходиться, например, 2 потока в деформации с 8 потоками могут брать ветвь, в то время как другие 6 могут не брать ее. Теперь деформацию нужно разделить на две деформации размером 2 и 6. Если ваше ядро имеет 8 линий SIMD (именно поэтому оригинальная деформация сделала 8 нитей), теперь ваши две вновь сформированные деформации будут работать неэффективно. Деформация с 2 потоками будет работать с эффективностью 25%, а деформация с 6 потоками - с эффективностью 75%. Вы можете себе представить, что если графический процессор продолжает сталкиваться с вложенными ветвями, его эффективность становится очень низкой. Следовательно, графические процессоры плохо справляются с ветвями, и поэтому код с ветвями не должен выполняться на графических процессорах.
Графические процессоры также плохо взаимодействуют с потоками. Если потоки должны общаться друг с другом, то графические процессоры не будут работать хорошо, потому что синхронизация не очень хорошо поддерживается на графических процессорах (но на нем nVidia).
Следовательно, худший код для графического процессора - это код с меньшим параллелизмом или код с большим количеством ветвей или синхронизацией.
В чем основные различия в модели программирования?
Графические процессоры не поддерживают прерывания и исключения. Для меня это самая большая разница. Кроме того, CUDA не сильно отличается от C. Вы можете написать программу CUDA, в которой вы отправляете код в графический процессор и запускаете его там. Вы обращаетесь к памяти в CUDA немного по-другому, но опять же, это не принципиально для нашего обсуждения.
Каковы основные аппаратные различия, которые требуют каких-либо различий в модели программирования?
Я уже упоминал их. Самым большим из них является SIMD-природа графических процессоров, которая требует, чтобы код был написан очень регулярно, без ветвей и межпотоковой связи. Это часть того, почему, например, CUDA ограничивает количество вложенных веток в коде.
Какой из них, как правило, проще в использовании и на сколько?
Зависит от того, что вы кодируете и какова ваша цель.
Легко векторизованный код: процессор проще в кодировании, но низкая производительность. GPU немного сложнее в коде, но обеспечивает большую отдачу.
Для всех остальных процессоры проще и зачастую также более производительны.
Целесообразно ли в долгосрочной перспективе реализовать высокоуровневые библиотеки параллелизма для графического процессора, такие как параллельная библиотека задач Microsoft или std.parallelism D?
Параллелизм задач по определению требует взаимодействия потоков, а также имеет ветви. Идея задач состоит в том, что разные потоки делают разные вещи. Графические процессоры предназначены для множества потоков, которые делают идентичные вещи. Я бы не стал создавать библиотеки параллелизма задач для графических процессоров.
Если вычисления на GPU настолько впечатляюще эффективны, почему ЦП не сконструированы так, как GPU?
Множество проблем в мире ветвисто и нерегулярно. 1000 примеров. Алгоритмы поиска графов, операционные системы, веб-браузеры и т. Д. Просто добавим - даже графика становится все более разветвленной и универсальной, как каждое поколение, поэтому графические процессоры будут все больше и больше походить на процессоры. Я не говорю, что они станут такими же, как процессоры, но они станут более программируемыми. Правильная модель находится где-то посередине между неэффективными центральными процессорами и очень специализированными графическими процессорами.