Особенности выделения памяти в OpenCL

в 17:23, , рубрики: gpgpu, opencl, метки: ,

Введение

Здравствуйте, дорогие читатели.

В данном посте я постараюсь рассмотреть особенности выделения памяти для объектов OpenCL.

OpenCL является кросс-платформенным стандартом гетерогенных вычислений. Не секрет, что на нём пишут программы тогда, когда от них требуется скорость выполнения. Как правило, подобный код нуждается во всесторонней оптимизации. Всякий GPGPU-разработчик знает, что операции с памятью зачастую являются самым слабым звеном в скорости работы программы. Так как в природе существует великое множество аппаратных платформ, поддерживающих OpenCL, то вопрос организации объектов памяти зачастую становится головной болью. То, что хорошо работает на Nvidia Tesla, оснащённых локальной памятью и соединённых широкой шиной с глобальной, отказывается показывать приемлемую производительность на SoC, имеющих совершенно иную архитектуру.

Об особенностях выделения памяти для систем с общей памятью CPU и GPU и пойдёт речь в данном посте. Использование типов памяти Image оставим в стороне и сосредоточимся на наиболее общеупотребительном типе Buffer. В качестве стандарта будем рассматривать версию 1.1, как наиболее распространённую. В начале проведём краткий теоретический курс, а затем рассмотрим несколько примеров.

Теория

Память выделяется при помощи вызова функции API clCreateBuffer. Синтаксис следующий:

cl_mem clCreateBuffer (
    cl_context context, 
    cl_mem_flags flags, 
    size_t size, 
    void *host_ptr, 
    cl_int *errcode_ret)

Нас интересуют в первую очередь флаги, отвечающие за то, как именно будет выделена память. Допустимы следующие значения:

CL_MEM_READ_WRITEб CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY

Самый простой вариант. Память будет выделена на стороне OpenCL Device в режиме чтение-запись/только запись/только чтение.

CL_MEM_ALLOC_HOST_PTR

Память для объекта будет выделена из памяти Host’а – т. е. из оперативной памяти. Этот флаг представляет интерес для систем с общей памятью CPU и GPU.

CL_MEM_USE_HOST_PTR

Объект будет использует уже выделенную (и используемую программой) память Host’а по указанному адресу. Стандарт допускает возможность выделения памяти на стороне Device’а в качестве промежуточного буффера. Данный флаг и CL_MEM_ALLOC_HOST_PTR являются взаимоисключающими. Этот флаг интересен тем в том случае, если вы добавляете поддержку OpenCL в готовое приложение, и хотите использовать существую память для работы с ней на стороне Device.

CL_MEM_COPY_HOST_PTR

Данный флаг означает, что при создании объекта, будет произведён аналог memcpy с указанного адреса.

Практика

Попытаемся на практике выяснить, какой вариант выделения памяти лучше подходит для традиционного случая дискретной видеокарты с собственной памятью «на борту» и той, в которой GPU использует память из RAM. В качестве тестовых систем будут фигурировать следующие компьютеры:

  • Система с дискретным видеочипом: Intel Core i5 4200U, 4Gb DDR31600Mhz, Radeon 8670M 128bit GDDR3 1800Mhz
  • Система со встроенным видеочипом: AMD A6700, 8Gb DDR31800Mhx, Radeon 7660D 128bit

Операционная система в обоих случаях Windows7 SP1, среда разработки — Visual Studio 2013 Express + AMD APP SDK 2.9.
В качестве тестовой нагрузки будем производить чтение/запись и mapping/unmapping объектов памяти различного размера – от 65 Кб до 65Мб.

Недолго думая, перейдём к графикам. Во всех случаях ось абсцисс показывает объём памяти в байтах, ось ординат — время выполнения операции в микросекундах. Видеокарта с дискретной памятью помечена в названии графика как «discrete GPU», видеокарта с общей с CPU памятью помечена как «Integrated GPU»

Дискретная видеокарта

image
Данный график показывает линейную зависимость времени передачи данных от объёма. Адаптер использует собственную память, поэтому результаты стабильны.

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

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
Графики иллюстрируют mapping/unmapping буффера, выделенного из памяти GPU. Mapping – это процедура отображения участка памяти из адресного пространства Device’а в пространство Host’а. Unmapping — обратный процесс. Так как для GPU с собственной памятью эти адресные пространства физически различны, что для проведения отображения происходит чтение/запись во временные буфферы.

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
При использования существующей памяти, выделенной на стороне Host’а, разброс по времени получается более существенным. Причин для этого может быть много – выравнивание памяти по различным базовым значениям, конкурентная нагрузка на контроллер памяти, и многое другое.

Интегрированная видеокарта

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
В случае общей памяти Host’a и Device’a разброс результатов сильнее. Это легко объясняется необходимостью использования общей памяти и возросшей нагрузкой на контроллер.

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
При выделении памяти из RAM, объекты памяти Device’a и Host’a находятся в одном физическом адресном пространстве и различных виртуальных. Поэтому время преобразования адреса постоянно и не зависит от объёма объекта.

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
Однако, если выделять память для объекта из объёма памяти GPU, то зависимость времени выполнения от объёма объекта будет аналогична той, что наблюдается при использовании дискретной видеокарты с поправкой на возросший разброс результатов.

Особенности выделения памяти в OpenCL
Особенности выделения памяти в OpenCL
Опять же, если используется память, выделенная со стороны Host'a, то мы получаем околонулевое время выполнения операции, не зависящее от объема буффера.

Выводы

Стоит отметить следующие закономерности, выявленные в ходе проведения эксперимента:

  • Использование видеокарты с дискретной памятью даёт результаты с меньшим разбросом. Это объясняется использованием раздельной памяти. Использование общей памяти, наоборот, приводит к большему разбросу показателей.
  • В обоих случаях использование флага USE_HOST_PTR приводит увеличивает неравномерность получаемых результатов.

Несмотря на то, что локальная память дискретной видеокарты предпочтительнее для работы ядер OpenCL в режиме интенсивных обращений, использование общей памяти даёт в некоторых случаях возможность проводить mapping/unmapping за околонулевое время, не зависящее от объёма буффера.

Технику mapping'а можно использовать в обоих рассматриваемых случаях. На системе с общей памятью она даёт вышеописанные преимущества, на системе с дискретной видеокартой она просто работает за такое же линейное время, как и классическая read/write схема.

Автор: RomanArzumanyan

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js