IOS Металлический вычислительный конвейер медленнее, чем реализация ЦП для задачи поиска

Я сделал простой эксперимент, выполнив наивный алгоритм поиска char, выполнив поиск 1.000.000 строк по 50 символов каждый (карта 50 mil char) на обоих процессорах и графических процессорах (с использованием iOS8 Metal compute pipe).

Реализация ЦП использует простой цикл, реализация Metal дает каждому процессу обработки ядра 1 (исходный код ниже).

К моему удивлению, реализация Металла в среднем в 2-3 раза медленнее простого линейного процессора (если я использую 1 ядро) и в 3-4 раза медленнее, если я использую 2 ядра (каждый из них ищет половину базы данных)! Я экспериментировал с разными потоками в каждой группе (16, 32, 64, 128, 512), но все же получаю очень похожие результаты.

iPhone 6:

CPU 1 core:  approx 0.12 sec
CPU 2 cores: approx 0.075 sec
GPU: approx 0.35 sec (relEase mode, validation disabled)

Я вижу, как Metal shader тратит более 90% доступа к памяти (см. ниже).

Что можно сделать для его оптимизации?

Любые идеи будут оценены по достоинству, так как в Интернете не так много источников (помимо стандартных руководств по программированию Apple), в которых содержится подробная информация о внутренних функциях доступа к памяти и компромиссах, характерных для структуры Metal.

ДЕТАЛИ РЕАЛИЗАЦИИ МЕТАЛЛА:

Основной код узла: https://gist.github.com/lukaszmargielewski/0a3b16d4661dd7d7e00d

Код ядра (шейдер): https://gist.github.com/lukaszmargielewski/6b64d06d2d106d110126

Результаты профилирования кадров кадра GPU:

enter image description here

Ответ 1

Шейдер GPU также перемещается вертикально по памяти, тогда как центральный процессор движется горизонтально. Рассмотрите, что адреса фактически затрагивались более или менее одновременно каждым потоком, выполняемым в стоп-стопе в вашем шейдере при чтении charTable. Графический процессор, вероятно, будет работать намного быстрее, если ваша матрица charTable будет транспонирована.

Кроме того, поскольку этот код выполняется в режиме SIMD, каждый поток GPU, вероятно, должен будет запустить цикл до полной длины поисковой фразы, тогда как процессор будет использовать преимущества ранних аутов. Код GPU может работать немного быстрее, если вы удалите ранние выходы и просто сохраните код простым. Многое зависит от длины поисковой фразы и вероятности совпадения.

Ответ 2

Я тоже буду угадывать, gpu не оптимизирован для if/else, он не прогнозирует ветки (он, вероятно, выполняет оба), попробуйте переписать алгоритм более линейным образом без каких-либо условных ограничений или уменьшить их до минимума.