作为 this answer 的后续问题.我正在尝试用 Metal 中的内核函数替换在 CPU 上运行的 for 循环,以并行计算并提高性能。
我的函数基本上是一个卷积。由于我反复收到输入数组值的新数据(数据源自 AVCaptureSession
),因此使用 newBufferWithBytesNoCopy:length:options:deallocator:
似乎是明智的选择创建 MTLBuffer
对象。相关代码如下:
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];
运行时出现以下错误:
failed assertion `newBufferWithBytesNoCopy:pointer 0x16fd0bd48 is not 4096 byte aligned.'
现在,我没有分配任何内存,但(出于测试目的)只是创建一个固定大小的空 float 组并用随机数填充它。所以我的主要问题是:
如何以正确的方式分配这些 float 数组以满足以下要求
This value must result in a page-aligned region of memory.
另外,还有一些问题:
- 使用
newBufferWithBytesNoCopy
方法创建MTLBuffer
是否有意义,或者复制数据在性能方面并不是真正的问题? (我的实际数据将包含每个视频帧大约 43,000 个浮点值。) MTLResourceStorageModeShared
是MTLResourceOptions
的正确选择吗?API 引用说
The storage allocation of the returned new MTLBuffer object is the same as the pointer input value. The existing memory allocation must be covered by a single VM region, typically allocated with vm_allocate or mmap. Memory allocated by malloc is specifically disallowed.
这是否仅适用于输出缓冲区,或者是否应该为使用
MTLBuffer
的所有对象分配存储空间而不应使用malloc
完成?
最佳答案
分配页面对齐内存的最简单方法是使用 posix_memalign
。下面是创建具有页面对齐内存的缓冲区的完整示例:
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);
}
由于您不能确保您的数据将到达页面对齐的指针,您可能最好只分配一个大小可以容纳您的数据的 MTLBuffer
,而无需使用无拷贝变体。如果您需要对数据进行实时处理,您应该创建一个缓冲区池并在它们之间循环,而不是等待每个命令缓冲区完成。 Shared
存储模式适用于这些用例。与 malloc
相关的警告仅适用于无复制情况,因为在所有其他情况下,Metal 都会为您分配内存。
关于ios - 为 iOS Metal 中的 MTLBuffer 使用的数据分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39770289/