MTLBuffer将数据直接从设备复制到主机上的特定缓冲区



问题描述

我的程序使用MTLBuffer在GPU上分配一些内存并用它进行计算。然后我需要将结果复制到主机上的特定位置。我在互联网上找到的所有解决方案都包括首先同步缓冲区,然后将其复制到我需要的地方。有没有办法将数据从MTLBuffer直接复制到主机缓冲区?


示例代码

当前实施:

void ComputeOnGPU(void* hostBuff, size_t buffSize)
{
id<MTLBuffer> gpuBuff = [device newBufferWithLength: buffSize
options: MTLResourceStorageModeManaged];

//
// Do stuff with the GPU buffer
//
id<MTLCommandQueue> commandQueue = [device newCommandQueue];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder synchronizeResource: gpuBuff];
[blitEncoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
std::memcpy(hostBuff, [gpuBuff contents], buffSize);
[gpuBuff setPurgeableState: MTLPurgeableStateEmpty];
[gpuBuff release];
}

我在找什么:

void ComputeOnGPU(void* hostBuff, size_t buffSize)
{
id<MTLBuffer> gpuBuff = [device newBufferWithLength: buffSize
options: MTLResourceStorageModeManaged];

//
// Do stuff with the GPU buffer
//
id<MTLCommandQueue> commandQueue = [device newCommandQueue];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
// Is there something like that?
[blitEncoder copyMemoryFromBuffer: gpuBuff
toHost: hostBuff];
[blitEncoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
[gpuBuff setPurgeableState: MTLPurgeableStateEmpty];
[gpuBuff release];
}

其他信息

  1. 传输到CPU的缓冲区大小大于4KB
  2. hostBuff是一个通用缓冲区。它来自外部,所以我不能确定它是否分配了mmap()

回答您的直接问题:没有办法将MTLBuffer复制到主机指针中。我认为原因可以归结为CPU和GPU的虚拟内存映射方式。即使有,它也将与托管缓冲区的工作方式相同,因为您编码到命令编码器中的命令是在GPU时间线上执行的,这意味着即使在调用该命令方法之后,您也不会在主机指针中看到结果,除非您在命令编码器上结束编码,然后commit命令缓冲区,然后等待它完成。然而,有一种在两个MTLBuffer之间进行复制的方法:-[MTLBlitCommandEncoder copyFromBuffer:sourceOffset:toBuffer:destinationOffset:size:]

但如果你使用的是托管缓冲区,还有另一种方法可以做到。你可以调用-[MTLBlitCommandEncoder synchronizeResource:],使GPU上更改的时间线可见,并通过-[MTLBuffer contents]读取其中的内容。

此外,如果您总是在CPU上读取数据,并且数据量相对较小,那么您还可以使用共享存储模式。

有两篇文章更深入地介绍了选择存储模式:在iOS和tvOS中选择资源存储模式以及在macOS中选择资源存储模式

最新更新