Оптимизация математической функции в openCL - PullRequest
0 голосов
/ 03 апреля 2012

Я начал изучать программирование openCL. В качестве начала я рассматриваю написание оптимизированного кода для следующего полинома 3-й степени:

g (x) = b1 (x) .f (x) + b2 (x). (F (x)) ^ 2 + b3 (x). (F (x))) ^ 3

Вышеприведенное уравнение можно уменьшить до следующего:

g (x) = f (x) [b1 (x) + f (x) [b2 (x) + f (x) .b3 (x)]]

, что значительно уменьшает количество умножений.

Предположим, что мои f, b1, b2 и b3 - матрицы размером 500x500. Ниже приведены варианты, которые я подумал о реализации этого алгоритма:

  1. Реализовать ядро ​​с потоками 500x500, каждое из которых работает по одному элемент матрицы.
  2. Реализовать ядро ​​с 500 потоками, каждый из которых работает на 500 элементах, т. Е. Каждый поток работает на одной строке.

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

Заранее спасибо

sravan

Ответы [ 2 ]

0 голосов
/ 03 апреля 2012

Вы определенно хотите быть связанным с вашим алгоритмом, а не с памятью. Здесь нужно много вычислений, так что это не должно быть проблемой. Я ответил на пару других вопросов, касающихся эффективных схем доступа к памяти. # 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). Если у вас слишком много групп, они либо будут ждать планирования, либо пострадают от включения / выключения ядер / регистров вашего устройства.

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

0 голосов
/ 03 апреля 2012

Вот несколько советов:

  1. Выровняйте размер матрицы по предпочтительному размеру рабочей группы для устройства (обычно 64 элемента работают лучше всего для большинства устройств, но вы можете запросить значение, используяCL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE in clGetKernelWorkGroupInfo).
  2. Рассчитать более одного элемента на рабочий элемент, чтобы уменьшить накладные расходы - хотя 500 элементов на рабочий элемент не идеальны, потому что 1) он излишне грубыйи 2) он ограничивает вас только 500 рабочими элементами.
  3. Внутри ядра разверните ваш цикл, который перебирает элементы, чтобы выполнить как минимум 4 элемента за одну итерацию.
  4. Вы должны определенносохраняйте массивы b1, b2 и b3 на устройстве.Как правило, храните как можно больше данных на устройстве.

Для получения полного списка всех возможных оптимизаций вы должны прочитать руководство по оптимизации от поставщика устройств OpenCL для используемого вами устройства.

...