我有一个函数可以在内存缓冲区上执行一些GPU任务,并且工作正常。但是,我试图通过访问 CreateBuffer 返回的IMem对象的指针或直接使用主机指针不复制内存内容来提高性能并获得一些灵活性。所以我看到了三个选择,没有一个能给我预期的结果:
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)选项在做什么?任何解决方案/解决方法?