OpenCL: как ускорить fps для образа процесса

Я начал использовать OpenCL в первый раз, и я пытаюсь сделать этот пример для обнаружения края Собеля на этом сайте http://www.karlosp.net/blog/2012/05/03/opencl-opencv-sobel-edge-detector/, но когда запустите ядро ​​​​для количества графических процессоров, частота кадров меньше 15, а использование графического процессора составляет менее 5%, как можно запустить весь поток для графического процессора, такого как openmp, чтобы использовать менее 95%

код

код ядра

_kernel void sobel(_global float *A, __global float *R, uint width, uint height) {

int globalIdx = get_global_id(0);
int globalIdy = get_global_id(1);
int index = width * globalIdy + globalIdx;
float a,b,c,d,e,f,g,h,i;
float sobelX = 0;
float sobelY = 0;
if(index > width && index < (height*width)-width && (index % width-1) > 0 && (index % width-1) < width-1){
    a = A[index-1-width] * -1.0f;
    b = A[index-0-width] *  0.0f;
    c = A[index+1-width] * +1.0f;
    d = A[index-1] * -2.0f;
    e = A[index-0] *  0.0f;
    f = A[index+1] * +2.0f;
    g = A[index-1+width] * -1.0f;
    h = A[index-0+width] *  0.0f;
    i = A[index+1+width] * +1.0f;
    sobelX = a+b+c+d+e+f+g+h+i;

    a = A[index-1-width] * -1.0f;
    b = A[index-0-width] * -2.0f;
    c = A[index+1-width] * -1.0f;
    d = A[index-1] * 0.0f;
    e = A[index-0] * 0.0f;
    f = A[index+1] * 0.0f;
    g = A[index-1+width] * +1.0f;
    h = A[index-0+width] * +2.0f;
    i = A[index+1+width] * +1.0f;
    sobelY = a+b+c+d+e+f+g+h+i;
}


R[index] = sqrt(pow(sobelX,2) + pow(sobelY,2));

}


person user1848223    schedule 05.10.2013    source источник
comment
Вы используете clenqueuewrite/read на каждой итерации? Это снизит производительность. Если вы можете выполнить те же вычисления только на графическом процессоре, это будет быстрее, потому что обнаружение краев не требует больших вычислительных ресурсов. В основном он использует доступ к памяти. Вы можете оптимизировать доступ к памяти, используя оптимизацию общей памяти для каждого блока потока, если оптимизации PCI-E недостаточно. youtube.com/watch?v=602XVhl2QMY этот пример во много раз быстрее для текстуры 256x256. разрешение при оптимизации для доступа без PCI-E, даже при взаимодействии частиц + вычисления деформируемой сетки. Cl-gl interop - это имя этой штуки. Поместите код, пожалуйста.   -  person huseyin tugrul buyukisik    schedule 05.10.2013
comment
Спасибо за ответ. Можете ли вы помочь мне с любым кодом, который я хочу, чтобы графический процессор работал на 100%, как openmp для потоков процессора, моя фактическая программа считывает кадр с камеры или видео и выполняет какой-либо процесс на процессоре, а затем отправляет на графический процессор, чтобы сделать какой-то процесс. и преобразовать hugth, а затем вернуться к процессору для завершения процесса. обнаружение Собеля работает со скоростью 15 кадров в секунду для разрешения 640 * 480 ?? я использую clenqueuewrite/read для чтения и записи с графического процессора после каждого кадра, это возможно для обработки в реальном времени???   -  person user1848223    schedule 07.10.2013
comment
Пропускная способность PCI-e обычно составляет 4-5 ГБ в секунду. Это означает 1 миллиард 32-битных чисел с плавающей запятой в секунду. 640*480=307200 и умножение на 4 байта (rgba) на пиксель дает 1228800 байт на кадр, что составляет 1/4000 пропускной способности PCI-E. У вас 15 кадров в секунду, поэтому он отправляет, вероятно, 16 МБ в секунду, что слишком мало. НО время отправки заставляет GPU простаивать. Бездействие даже в течение миллисекунды приведет к более низкому проценту использования графического процессора. Если вы не хотите взаимодействия, вы можете выполнять асинхронную работу. Сначала отправьте 50 кадров для обработки на GPU. Запустите ядро. Но в то же время отправляйте и получайте новые данные, сохраняя загруженность графического процессора.   -  person huseyin tugrul buyukisik    schedule 07.10.2013
comment
Затем вы можете занять GPU предварительно загруженными кадрами в память GPU. Я думаю, это просто реальность, что у вас есть высокопроизводительный графический процессор, я думаю :)   -  person huseyin tugrul buyukisik    schedule 07.10.2013
comment
Вы не можете получить 100%, даже если вы сильно его оптимизируете. 5% не означает, что GPU работает на 5%, это означает, что среднее использование составляет 5%. Если ваш код работает быстро, а ввод-вывод является узким местом (как и данные в очереди ЦП). Вы едва превысите этот уровень. IE: Очень тяжелые вычислительные задачи обычно достигают только 50%, поскольку ЦП также является узким местом.   -  person DarkZeros    schedule 07.10.2013
comment
из вашего ответа задержка не из кода ядра??? проблема в отправке и получении данных от gpu невелика.   -  person user1848223    schedule 08.10.2013
comment
.если я отправляю 30 кадров для обработки и читаю 30 кадров, это быстрее от отправки кадра после кадра. Каждый раз отправляем 30 кадров, но мы хотим сохранить 30 кадров перед отправкой на GPU ??? у нас есть циклическая очередь для хранения не менее 100 кадров перед отправкой на GPU. у вас есть какая-нибудь ссылка, помогите мне в этом. я надеюсь увидеть любой кадр процесса программы для более чем 100 кадров в секунду, чтобы понять код   -  person user1848223    schedule 08.10.2013
comment
cvWaitKey() замедляет процесс захвата/отображения. cvWaitKey(x) Ожидает нажатия клавиши x миллисекунд. Если в это время была нажата клавиша, возвращается ASCII-код клавиши. В противном случае возвращается -1. Он обрабатывает любые оконные события, такие как создание окон с помощью cv::namedWindow() или отображение изображений с помощью cv::imshow(). эта функция подождет не менее 15 мс быстрее, чтобы показать мой графический интерфейс frme ???   -  person user1848223    schedule 09.10.2013


Ответы (1)


Код, на который вы ссылаетесь, имеет несколько недостатков (без особого порядка):

  • Вызовы clFinish после каждого вызова OpenCL внутри цикла не нужны. Во-первых, clEnqueueWriteBuffer и clEnqueueReadBuffer используют блокировку, установленную в CL_TRUE, т. е. они не будут возвращаться, пока не завершится запись/чтение (определение вызова блокирующей функции).

  • Вы конвертируете изображение без знака char в изображение с плавающей запятой перед отправкой его на графический процессор. В этом нет необходимости, так как графический процессор может работать с беззнаковым символом и при необходимости может приводить тип к типу с плавающей запятой. Преобразование в число с плавающей запятой на ЦП с последующей отправкой на ГП приводит к отправке в 4 раза большего объема данных (4 байта на пиксель на канал против 1 байта).

  • Вы вызываете cvWaitKey(10), останавливаясь на 10 миллисекунд для ожидания нажатия клавиши, поэтому этот код никогда не превысит 100 кадров в секунду (незначительная проблема).

  • Преобразование RGB в оттенки серого может быть выполнено на графическом процессоре за счет отправки 3 символов без знака, поэтому здесь есть компромисс, который требует тестирования.

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

Мне также только что пришло в голову, какова частота кадров камеры, с которой снимает OpenCV?

person chippies    schedule 05.10.2013
comment
Спасибо за ответ. я делаю некоторые изменения в коде, но использование графического процессора также составляет менее 5%, а количество кадров в секунду достигает 20 1-изменить cvWaitKey(10) с 10 до 1 мс 2-удалить clFinish внутри цикла im_gray, CV_RGB2GRAY); если использовать только эту функцию внутри цикла, fps 35 4-преобразует ваше изображение без знака char в изображение с плавающей запятой перед отправкой его на графический процессор? какое изменение сделать для этого любого примера - person user1848223; 07.10.2013
comment
Знаете ли вы какой-либо способ оптимизировать ядро ​​​​для использования всех ресурсов графического процессора, я хочу работать параллельно на графическом процессоре, загрузка меньше 5%, я вижу, что некоторые ядра используют get_local_size и get_num_groups. Может ли эта функция помочь мне ускорить работу ядра? оптимизируйте это ядро ​​​​для 2D-изображения. Спасибо. - person user1848223; 07.10.2013
comment
Вы бы выиграли от использования общей памяти, также известной как локальная память, но, похоже, в вашем коде есть и другие узкие места. Как вы измеряете использование графического процессора. Если вы используете что-то вроде GPU-Z, то загрузка GPU на уровне 5% не означает, что используются 5% вычислительных ресурсов, скорее это означает, что GPU занят только 5% времени. Остальные 95% ожидают работы, поэтому я говорю, что в вашем коде есть узкое место. - person chippies; 07.10.2013
comment
Например, преобразование RGB в оттенки серого занимает 1/35 = 0,029 секунды. Ваша частота кадров 20 кадров в секунду означает, что 0,029 с из 0,05 с или 57% времени кадра используется для преобразования RGB в оттенки серого. Это уже является узким местом, ограничивающим использование графического процессора в лучшем случае примерно 40%. - person chippies; 07.10.2013
comment
Еще одна вещь, которая приходит на ум, это то, что в вашем коде не указаны размеры локальных рабочих групп, что вынуждает реализацию угадывать хорошую конфигурацию. Это почти всегда работает плохо, поэтому вам следует использовать размер локальной рабочей группы, кратный 32 (хорошо работает для графических процессоров AMD и Nvidia), и увеличить глобальный рабочий размер до кратного локального рабочего размера, который больше, чем размеры вашего изображения. . - person chippies; 07.10.2013
comment
Спасибо за ответ › Я использую системный монитор программы AMD для измерения использования графического процессора. При запуске некоторого примера для программы просмотра колпачков графического процессора использование графического процессора достигает 98%, когда программа закрывается, возвращается к нулю - person user1848223; 08.10.2013
comment
решена проблема преобразования изображения без знака char в изображение с плавающей запятой - person user1848223; 08.10.2013
comment
я вижу другой код для обнаружения края с помощью opencl и весь этот код использует GPU не более чем на 10% ??? а фпс достигает 20-25фпс. глобальный рабочий размер - это размер образа процесса, а глобальный локальный элемент div должен быть действительным числом и вносить изменения для локального значения, но это не меняет скорость обработки. - person user1848223; 08.10.2013
comment
я вношу изменения в программу, удаляю opencv func cvtColor и заставляю программу преобразовывать видео из rgb в серый и вносить некоторые изменения в код теперь, когда он работает без opencl, только читать кадр из видео и отображать его только в rgb без обработки, fps составляет ~ 40 и меньше я не знаю, почему иногда доходит до 50. затем после запуска opencl rgbtogray fps достигает 30, а использование GPU достигает 15%, это нормально. - person user1848223; 08.10.2013
comment
у меня проблема не с opencl, а с opencv, если я удаляю функцию opencv cvWaitKey(1) 1 мс, которая использует внутри цикла while, процесс fps изменяется с 30 до 50 fps, но нет выходного представления в функции cv::imshow, я буду искать об этом в гугле. - person user1848223; 08.10.2013