OpenCL — влияние барьера на производительность

#performance #opencl

#Производительность #opencl

Вопрос:

В OpenCL все потоки должны вычислять несколько общих значений. Какой из следующих двух случаев быстрее? 1. Все потоки вычисляют значения, сохраняют в частной памяти и не требуют синхронизации между потоками. 2. Один поток вычисляет и сохраняет в локальной памяти. Синхронизировано барьером. Все потоки рабочей группы обращаются к значениям в локальной памяти.

Спасибо.

Ответ №1:

Есть ли какой-либо правильный ответ на этот вопрос, учитывая диапазон устройств, на которых выполняется OpenCL (например, различные графические процессоры, различные процессоры и ячейка BE)? Характеристики производительности будут сильно различаться между CPU и GPU, а также, возможно, между производителями и моделями GPU.

Вам нужно будет измерить на платформах и реализациях, представляющих интерес для вас или ваших пользователей.

Возможно ли в вашем случае предварительно вычислить несколько общих значений на хосте и передать их либо в качестве динамических параметров в ядро OpenCL, либо в качестве параметров времени компиляции в ядро OpenCL?

Ответ №2:

Зависит от сложности вычисления этих общих значений и количества рабочих элементов, которые могут выполняться параллельно.

Допустим, время вычисления общих значений равно A, время выполнения остальной части вычисления равно B, а накладные расходы на барьер равны AO amp; BO (часть A и часть B). Мы можем рассчитать время для каждого параметра.

  • Вариант 1 и один поток и 1000 рабочих элементов: 1000A 1000B
  • Вариант 2 и один поток и 1000 рабочих элементов: A AO 1000B 1000BO
  • Вариант 1 с 1000 потоками и 1000 рабочими элементами: A B
  • Вариант 2 с 1000 потоками и 1000 рабочими элементами: A AO B BO

Когда у вас столько потоков, сколько рабочих элементов, вариант 2, очевидно, медленнее. Когда у вас есть один поток, если BO мал по сравнению с A, вариант 2, вероятно, быстрее.

Истина, вероятно, где-то посередине.

Вариант 3 — заставить хост вычислить эти значения и поместить результаты в постоянную память. Если вы сделаете это и используете небольшую двойную буферизацию, вы, вероятно, сможете скрыть время вычисления следующего набора общих значений, пока вы ждете, пока OpenCL выполнит текущее вычисление.

Комментарии:

1. На самом деле это не так просто, поскольку не гарантируется, что все потоки могут выполняться параллельно, поэтому для 1000 потоков это может быть что-то вроде n A n B для варианта 1, в то время как A n AO n B n * BO для варианта 2. И я должен признать, что я не понимаю, как примеры с одним потоком имеют смысл. Зачем этому одному потоку пересчитывать A a 1000 раз, когда ему даже не нужен барьер для синхронизации с самим собой?

2. Кроме того, в зависимости от архитектуры и того, как именно вычисляется A, могут возникать конфликты ресурсов, замедляющие вычисление A, когда несколько потоков пытаются сделать это параллельно (например, потому что все они пытаются получить доступ к одной и той же памяти, а архитектура не может обрабатывать широковещательные рассылки), что делает его m n A n * B для варианта 1 с m> = 1. Итак, в конце концов, на самом деле невозможно дать какой-либо ответ, не зная архитектуры, количества потоков и затрат на вычисление A по сравнению со стоимостью барьера