эффективный произвольный доступ к памяти графического процессора с помощью OpenGL - PullRequest
6 голосов
/ 25 февраля 2012

Каков наилучший шаблон для того, чтобы графический процессор мог эффективно вычислять «антифункциональные» подпрограммы, которые обычно зависят от позиционной записи в память вместо чтения? Например. например, вычисление гистограммы, сортировка, деление числа на проценты, объединение данных разного размера в списки и т. д. и т. д.

Ответы [ 2 ]

7 голосов
/ 25 февраля 2012

Установленные условия: сборка чтения и разброс записи

Собрание читает

Это означает, что ваша программа будет записывать в фиксированную позицию (например, целевую позицию фрагмента шейдера фрагмента), но имеет быстрый доступ к произвольным источникам данных (текстурам, униформе и т.

Скаттер пишет

Это означает, что программа получает поток входных данных, которые она не может произвольно адресовать, но может выполнять быструю запись в произвольные области памяти.

Очевидно, что шейдерная архитектура OpenGL представляет собой систему сбора данных. Последний OpenGL-4 также позволяет некоторые записи разброса в фрагментном шейдере, но они медленные.

Итак, какой самый эффективный в наши дни способ эмулировать "рассеяние" с помощью OpenGL. Пока что используется вершинный шейдер, работающий с точками размером в пиксель. Вы отправляете столько точек, сколько у вас есть точек данных для обработки, и разбрасываете их в целевой памяти, устанавливая их соответствующие положения. Вы можете использовать геометрические и тесселяционные шейдеры, чтобы получить точки, обработанные в единице вершины. Вы можете использовать текстурные буферы и UBO для ввода данных, используя индекс вершины / точки для адресации.

1 голос
/ 03 марта 2012

GPU построены с несколькими типами памяти. Один тип - это оперативная память DDRx, доступная для центрального процессора и графического процессора. В OpenCL и CUDA это называется «глобальной» памятью. Для графических процессоров данные в глобальной памяти должны передаваться между графическим процессором и хостом. Обычно это делается в банках, чтобы обеспечить конвейерный доступ к памяти. Так что случайное чтение / запись в «глобальную» память происходит сравнительно медленно. Лучший способ получить доступ к «глобальной» памяти - это последовательно.
Его размер варьируется от 1G до 6B на устройство.

Следующий тип памяти - это графический процессор. Это общая память, которая доступна ряду потоков / деформаций в вычислительном устройстве / мультипроцессоре. Это быстрее, чем глобальная память, но не доступно напрямую с хоста. CUDA называет это общей памятью. OpenCL вызывает эту локальную память. Это лучшая память для произвольного доступа к массивам. Для CUDA - 48 КБ, для OpenCL - 32 КБ.

Третий тип памяти - это регистры графического процессора, называемые частными в OpenCL или локальными в CUDA. Частная память - самая быстрая, но она меньше доступной, чем локальная / общая память.

Лучшая стратегия для оптимизации произвольного доступа к памяти - копировать данные между глобальной и локальной / общей памятью. Таким образом, приложение GPU будет копировать части своей глобальной памяти в локальную / общую папку, выполнять работу с использованием локальной / общей папки и копировать результаты обратно в глобальную.

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

...