предлагаемый способ использования clEnqueueMapBuffer и clEnqueueUnmapMemObject при реализации нулевой копии - PullRequest
2 голосов
/ 28 сентября 2019

Я играю в глубокое обучение с opencl, размер вывода тензора фиксирован.

В cuda я могу использовать нулевое копирование через cudaMallocHost, это можно вызвать при инициализации.И я могу прочитать вывод тензора с хоста без явного вызова cudaMemcpy.

Это очень эффективно, поскольку вызывается только один раз за все время выполнения моей программы.Мне не нужно вызывать cudaMallocHost каждый раз после пересылки.

И когда я пытаюсь реализовать нулевое копирование в opencl, в некоторых реализациях они вызывают clEnqueueMapBuffer и clEnqueueUnmapMemObject каждый раз после пересылки, когда вы хотите прочитать выводтензор.

Вот пример (https://github.com/alibaba/MNN/blob/master/source/backend/opencl/core/OpenCLBackend.cpp#L291).

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

Это действительно предложенный способ сделать это? Могу ли я вызывать clEnqueueMapBuffer только один раз за время жизни моей программы и вызывать clEnqueueUnmapMemObject один раз, когда заканчивается моя программа? Есть ли проблема для этого?

1 Ответ

2 голосов
/ 28 сентября 2019

Если ваша реализация OpenCL поддерживает Shared Virtual Memory (представлена ​​в 2.0), эта функция позволяет вам делать нечто подобное и многое другое.

Для OpenCL 1.x, если ваша реализация OpenCL не дает никаких гарантий вышеи помимо стандарта (который я ожидал бы сделать через расширение), вы должны разархивировать буфер до того, как ядро ​​получит доступ для записи в него, и аналогично, вы не должны разрешить ядру читать из него, пока оно сопоставлено для записи.

Это объясняется в clEnqueueMapBuffer спецификации :

Чтение и записьядро, выполняющееся на устройстве в области памяти, отображаемой для записи, не определено.

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

В версии 1.2 это было расширено, но сутьто же самое:

Если объект памяти в настоящее время сопоставлен для записи, приложение должно убедиться, что объект памяти не отображен перед любыми ядрами или командами в очереди, которые читают или записывают в этот объект памяти или любой из егосвязанные объекты памяти (объекты суббуфера или буфера 1D изображения) или его родительский объект (если объект памяти является объектом суббуфера или буфера 1D изображения) начинают выполнение;в противном случае поведение не определено.

Если объект памяти в настоящее время сопоставлен для чтения, приложение должно убедиться, что объект памяти не отображен перед любыми ядрами или командами, поставленными в очередь, которые записывают в этот объект памяти или любую связанную с ним памятьобъекты (суббуфер или объекты буфера 1D изображения) или его родительский объект (если объект памяти является суббуфером или объектом буфера 1D изображения) начинают выполнение;в противном случае поведение не определено.

Если вы обнаружите, что map / unmap имеет большие издержки, вы, вероятно, не выполняете путь кода с нулевой копией в вашей реализации OpenCL, и драйвер фактически копируетсодержимое памяти.Если вы сомневаетесь, обратитесь к поставщику реализации, чтобы узнать, как они рекомендуют вам использовать буферы нулевого копирования в OpenCL.Буферы нулевого копирования не гарантируются стандартом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...