Вы определенно хотите быть связанным с вашим алгоритмом, а не с памятью. Здесь нужно много вычислений, так что это не должно быть проблемой. Я ответил на пару других вопросов, касающихся эффективных схем доступа к памяти. # 1 , # 2 .
Я обнаружил, что ваше предложение № 2 работает лучше всего - то есть: пусть рабочая группа рассчитывает результаты всей строки за раз. Я расширяю эту идею, используя меньшее количество групп и заставляя их переходить к другим строкам по завершении работы. Использование барьера для группы в конце работы строки не приведет к заметному снижению производительности, поскольку у вас достаточно работы, чтобы ее выполнить. Если ваша память упорядочена таким образом, что строка [i * w + 500] === row [(i + 1) * w], вы можете заставить свои рабочие группы обрабатывать две строки за раз и избежать небольшого простоя .
Я думаю, что строки из 500 - это достаточно большая работа, чтобы вычислительная единица была насыщенной без необходимости делать две строки за раз. На моей платформе CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE - 64; если в качестве размера рабочей группы используется идентификатор 64, 128 или 256, то только 12 рабочих элементов простаивают на последней итерации строки. Цель состоит в том, чтобы использовать наименьшую рабочую группу из возможных, но НЕ ограниченную памятью (и кратную предпочтительному размеру рабочей группы).
500 рабочих групп, вероятно, слишком много. Некоторые множественные (мне нравится использовать 1) ваши вычислительные блоки на устройстве будут работать хорошо (см .: CL_DEVICE_MAX_COMPUTE_UNITS). Если у вас слишком много групп, они либо будут ждать планирования, либо пострадают от включения / выключения ядер / регистров вашего устройства.
Вы определенно хотите сохранить постоянные данные на устройстве, если у вас достаточно памяти для этого. Даже запись вывода в локальную память и копирование его в глобальный в конце вычисления строки может повысить производительность.