У меня есть программа, которую я построил на OpenCL, в которой каждое ядро обращается к буферу только для чтения, расположенному в глобальной памяти. В какой-то момент каждому ядру необходимо скопировать некоторые данные из глобальной памяти во временный буфер. Я сделал цикл for для побайтного копирования области глобальной памяти во временный буфер. Я выполняю вышеупомянутое ядро с помощью команды clEnqueueNDRangeKernel
, которая находится внутри цикла while. Чтобы измерить скорость выполнения команды clEnqueueNDRangeKernel
, я добавил счетчик под названием ups
(обновлений в секунду), который увеличивается в конце каждого цикла while. Каждую секунду я печатаю значение счетчика и устанавливаю его на ноль.
Я заметил, что моя программа работает медленно, примерно 53 срабатывания. После некоторого расследования я обнаружил, что проблема заключалась в описанном выше цикле копирования памяти. Это код:
typedef uchar byte;
byte tempBuffer[128]
byte* destPtr = (byte*)&tempBuffer0];
__global const byte* srcPtr = (__global const byte*)globalMemPtr;
for(size_t k = 0; k < regionSize; ++k)
{
destPtr[k] = srcPtr[k];
}
В переменной globalMemPtr
находится указатель на область глобальной памяти, которую нужно скопировать во временный буфер, а в tempBuffer
- временный буфер. Переменная regionSize
содержит размер копируемой области в байтах. В данном случае его значение равно 12.
Что я заметил, так это то, что если я заменю regionSize
на 12
, ядро будет работать намного быстрее, примерно на 90 иб / сек. Я предполагаю, что компилятор OpenCL может оптимизировать цикл for, чтобы копировать память намного быстрее, когда используется 12
, но не может, когда используется regionSize
.
Кто-нибудь знает, что происходит? Может кто-нибудь помочь мне?
@Harry Да, это улучшает производительность. Программа работает на 85 упс. Спасибо!
Также может использоваться слишком много регистров (128) на поток. Почему бы вам не попробовать использовать размер группы 64 и размер части 128 на поток в __local памяти составляет 8 КБ, где максимальный размер __local обычно составляет минимум 64 КБ. Когда вы используете 12, он может использовать только 12 регистров, но когда он неизвестен, он использует 128 регистров.
Возможно, компилятор использует векторные типы вместо скалярных типов, например. 12 байтов = 3 * char4 = char8 + char4. Постарайтесь скопировать как можно больше векторных значений, а остаток скопировать только как скалярные значения. Это улучшает время работы?