Выбор медианы в ядре CUDA

Мне нужно вычислить медиану массива размера p внутри ядра CUDA (в моем случае p мало, например, p = 10). Я использую алгоритм O(p^2) из-за его простоты, но ценой снижения производительности.

Есть ли «функция» для эффективного нахождения медианы, которую я могу вызвать внутри ядра CUDA?

Я знаю, что могу реализовать алгоритм выбора, но мне нужна функция и/или проверенный код.

Спасибо!


person rodms    schedule 30.08.2013    source источник
comment
Учитывая маленькое значение p, рассматривали ли вы возможность использования шаблонной функции, использующей минимальную сеть сортировки?   -  person njuffa    schedule 30.08.2013
comment
Небольшое значение p, вероятно, указывает на то, что вы должны написать свой собственный код, как уже предлагали другие. Если вы хотите ознакомиться с некоторыми базовыми примерами кодов, не забудьте просмотреть различные коды сортировки в образцы cuda, а также CUB.   -  person Robert Crovella    schedule 30.08.2013
comment
Попробуйте реализовать en.wikipedia.org/wiki/Median_of_medians.   -  person Pavan Yalamanchili    schedule 31.08.2013
comment
В первой книге Graphics Gems у Пэта была хорошая реализация медианы 3x3, которая отбрасывает минимальные и максимальные значения, пока вы не останетесь с медианой. Пэт, Алан В., Медианный поиск в сетке 3 на 3, с. 171-175, код: с. 711-712. Код C здесь: cudahandbook.to/1dCFCOQ   -  person ArchaeaSoftware    schedule 01.09.2013
comment
@rodms не могли бы вы вычислить медиану массива в cuda? если да, пожалуйста, дайте способ, которым вы это сделали.   -  person Jony    schedule 29.10.2013
comment
@AshishDonvir Не так эффективно, как хотелось бы, хотя я не пробовал реализовать алгоритм выбора.   -  person rodms    schedule 29.10.2013
comment
@rodms, не могли бы вы взглянуть на мой это вопрос о медианном фильтре и предложите мне что-нибудь, чтобы сделать его более эффективным? могу ли я иметь лучший способ назначить соседний пиксель в этом?   -  person Jony    schedule 31.10.2013


Ответы (2)


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

  1. Используйте лучший алгоритм выбора: QuickSelect — это более быстрая версия QuickSort для выбора k-го элемента в массиве. Для размеров масок, постоянных во время компиляции, сети сортировки еще быстрее, спасибо до высокого уровня TLP и критического пути O(log^2 n). Если у вас есть только 8-битные значения, вы можете использовать подход на основе гистограммы. В этой статье описывается реализация, которая требует постоянного времени на пиксель, независимо от размера маски, что делает его очень быстрым для очень больших размеров маски. Вы можете распараллелить его, используя стратегию минимального запуска (запускайте столько потоков, сколько вам нужно, чтобы поддерживать максимальную производительность всех SM), разбивая изображение на части и позволяя потокам одного и того же блока взаимодействовать на каждой гистограмме ядра.
  2. Сортировка по регистрам. Для небольших размеров маски вы можете хранить весь массив в регистры, что делает медианный выбор с помощью сети сортировки намного быстрее. Для больших размеров маски вы можете использовать общую память.
  3. Сначала скопируйте все пиксели, используемые блоком, в общую память, а затем скопируйте в локальные буферы потока, которые также находятся в общей памяти.
  4. Если у вас есть только несколько масок, которые должны выполняться очень быстро (например, 3x3 и 5x5), используйте шаблоны, чтобы они компилировали константы времени. Это может значительно ускорить работу, потому что компилятор может развертывать циклы и переупорядочивать намного больше инструкций, возможно, улучшая пакетную загрузку и другие полезные функции, что приводит к значительному ускорению.
  5. Убедитесь, что ваши чтения объединены и выровнены.

Есть много других оптимизаций, которые вы можете сделать. Обязательно прочтите документы CUDA, особенно Руководство по программированию и Руководство по передовому опыту. Если вы действительно хотите добиться высокой производительности, не забудьте внимательно изучить профайлер CUDA, например Visual Profiler.

person Domi    schedule 29.10.2013

Даже в одном потоке можно отсортировать массив и выбрать значение посередине в O(p*log(p)), из-за чего O(p^2) выглядит чрезмерным. Если в вашем распоряжении есть потоки p, также можно отсортировать массив со скоростью O(log(p)), хотя это может быть не самым быстрым решением для малых p. См. верхний ответ здесь:

Какой алгоритм параллельной сортировки имеет наилучшую среднюю производительность?< /а>

person Michael    schedule 30.08.2013