#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 по сравнению со стоимостью барьера