У меня есть функция, которая выполняет некоторые задачи графического процессора над буфером памяти, и она работает нормально. Тем не менее, я пытаюсь повысить производительность и получить некоторую гибкость, либо получая доступ к указателю объекта IMem, возвращаемому CreateBuffer , либо напрямую используя указатель хоста, чтобы не дублировать содержимое памяти. Итак, я вижу три варианта, ни один из которых не дает мне ожидаемого результата:
1) Используйте указатель хоста, чтобы избежать дополнительного копирования:
ErrorCode ErrCode;
int BuffSize = 100000000;
IntPtr HostPtr = Marshal.AllocHGlobal(BuffSize );
IMem Buffer_In = Cl.CreateBuffer(myContext, MemFlags.ReadOnly | MemFlags.UseHostPtr,
(IntPtr)BuffSize , HostPtr , out ErrCode);
Check_CL_Error(ErrCode);
Это работает нормально, но перераспределяет новую память и занимает довольно много времени. На самом деле я не вижу никакой разницы в производительности от использования MemFlags.CopyHostPtr .
2) Отображение буфера в память моего хоста:
//{...}
IMem Buffer_In = Cl.CreateBuffer(myContext, MemFlags.ReadOnly | MemFlags.AllocHostPtr,
(IntPtr)BuffSize , out ErrCode);
Check_CL_Error(ErrCode);
InfoBuffer iBuffMap = Cl.EnqueueMapBuffer(cmdQueue, Buffer_In, Bool.False, MapFlags.Write,
IntPtr.Zero, (IntPtr)BuffSize , 0, null, out clEventWriteResult, out ErrCode);
Check_CL_Error(ErrCode);
//{...} //followed by memCopy and Unmapping
Таким образом, я мог бы скопировать только ту часть исходного буфера, которую я хочу обработать. К сожалению, вызов EnqueueMapBuffer вызывает исключение PInvokeStackImbalance , и я не могу найти причину.
3) Получить фактический указатель буфера IMem.
//{...} //Create buffer
InfoBuffer infoBufferIn = Cl.GetMemObjectInfo(Buffer_In, MemInfo.HostPtr, out ErrCode);
Check_CL_Error(ErrCode);
IntPtr bufferInPtr = infoBufferIn.CastTo<IntPtr>();
Но bufferInPtr всегда возвращает 0. На самом деле я прочитал, что это не очень хороший выбор (и я нашел некоторый код о GetMemObjectInfo и, похоже, возвращает только размер при запросе HostPtr), так что этот третий вариант почти исключен.
Я также мог бы использовать Cl.EnqueueWriteBuffer , но если я хочу скопировать несколько сегментов, я получу много событий enqueueWrite в очереди команд.
Что я делаю не так с опциями 1) и 2)? Любое решение / обходной путь?