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

标签 ios c memory-management gpgpu metal

作为 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 个浮点值。)
  • MTLResourceStorageModeSharedMTLResourceOptions 的正确选择吗?
  • 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/

相关文章:

ios - 将数组组合成一个 url 字符串

ios - 如何确保我的应用程序不会发出太多通知

c - 循环中动态 malloc - seg 错误

c++ - 使用 GCC 编译 PARDISO 线性求解器测试用例

ios - iPad 的 flex - 高度

html - iOS:在HTML字符串引用内插入UIImage

c - 在 C 中的另一个函数中使用函数

ios - 弹出 UIViewController 后,MKMapView autorelease 不调用 dealloc

c++ - 如何从成员函数中释放对象?

python - 如何跟踪 python 脚本的内存