为iOS Metal中的MTLBuffer使用的数据分配内存

作为这个答案的后续问题。 我试图用一个在Metal中的内核函数replaceCPU上运行的for-loop来并行化计算并加速性能。

我的function基本上是一个卷积。 由于我反复接收到我的input数组值的新数据(数据来自AVCaptureSession ),似乎使用newBufferWithBytesNoCopy:length:options:deallocator:是创buildMTLBuffer对象的明智选项。 这是相关的代码:

 id <MTLBuffer> dataBuffer = [device newBufferWithBytesNoCopy:dataVector length:sizeof(dataVector) options:MTLResourceStorageModeShared deallocator:nil]; id <MTLBuffer> filterBuffer = [device newBufferWithBytesNoCopy:filterVector length:sizeof(filterVector) options:MTLResourceStorageModeShared deallocator:nil]; id <MTLBuffer> outBuffer = [device newBufferWithBytesNoCopy:outVector length:sizeof(outVector) options:MTLResourceStorageModeShared deallocator:nil]; 

当运行这个我得到以下错误:

失败的断言`newBufferWithBytesNoCopy:指针0x16fd0bd48不是4096字节alignment。

现在,我没有分配任何内存,但是(为了testing目的)只是创build一个固定大小的浮动数组并填充随机数。 所以我的主要问题是:

如何以正确的方式分配这些浮点数组,以满足以下要求

该值必须导致页面alignment的内存区域。

另外,还有一些问题:

  • newBufferWithBytesNoCopy方法创buildMTLBuffer还是复制数据在性能方面并不是一个真正的问题? (我的实际数据将包含每个video帧大约43'000浮点值。)
  • MTLResourceStorageModeShared是否正确selectMTLResourceOptions
  • API参考说

    返回的新MTLBuffer对象的存储分配与指针input值相同。 现有的内存分配必须由单个VM区域覆盖,通常由vm_allocate或mmap分配。 由malloc分配的内存被明确禁止。

    这是否仅适用于输出缓冲区,或者与MTLBuffer一起使用的所有对象的存储分配是否不能用malloc完成?

分配页面alignment内存的最简单方法是使用posix_memalign 。 下面是使用页面alignment内存创build缓冲区的完整示例:

 void *data = NULL; NSUInteger pageSize = getpagesize(); NSUInteger allocationSize = /* required byte count, rounded up to next multiple of page size */ pageSize * 10; int result = posix_memalign(&data, pageSize, allocationSize); if (result == noErr && data) { id<MTLBuffer> buffer = [device newBufferWithBytesNoCopy:data length:allocationSize options:MTLResourceStorageModeShared deallocator:^(void *pointer, NSUInteger length) { free(pointer); }]; NSLog(@"Created buffer of length %d", (int)buffer.length); } 

既然你不能确保你的数据将到达一个页面alignment的指针,你可能会更好的分配一个任何大小的MTLBuffer可以容纳你的数据,而不使用无拷贝的变种。 如果您需要对数据进行实时处理,您应该创build一个缓冲池并循环,而不是等待每个命令缓冲区的完成。 Shared存储模式对于这些用例是正确的。 与malloc相关的警告只适用于no-copy情况,因为在其他情况下,Metal会为您分配内存。