在 iOS Metal 中为 MTLBuffer 使用的数据分配内存
Allocating memory for data used by MTLBuffer in iOS Metal
作为 的后续问题。我正在尝试用 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.'
现在,我没有分配任何内存,但(出于测试目的)只是创建一个固定大小的空浮点数组并用随机数填充它。所以我的主要问题是:
如何以正确的方式分配这些浮点数数组以满足以下要求
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
大小可以容纳您的数据,而不使用 no -复制变体。如果您需要对数据进行实时处理,您应该创建一个缓冲区池并在它们之间循环,而不是等待每个命令缓冲区完成。 Shared
存储模式对于这些用例是正确的。与 malloc
相关的注意事项仅适用于无复制情况,因为在所有其他情况下,Metal 都会为您分配内存。
作为
我的函数基本上是一个卷积。由于我反复收到输入数组值的新数据(数据源自 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.'
现在,我没有分配任何内存,但(出于测试目的)只是创建一个固定大小的空浮点数组并用随机数填充它。所以我的主要问题是:
如何以正确的方式分配这些浮点数数组以满足以下要求
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
大小可以容纳您的数据,而不使用 no -复制变体。如果您需要对数据进行实时处理,您应该创建一个缓冲区池并在它们之间循环,而不是等待每个命令缓冲区完成。 Shared
存储模式对于这些用例是正确的。与 malloc
相关的注意事项仅适用于无复制情况,因为在所有其他情况下,Metal 都会为您分配内存。