我想创建一个带有newBufferWithBytesNoCopy功能的金属缓冲区,让CPU和GPU共享内存并实现零拷贝数据传输。
newBufferWithBytesNoCopy函数采用UnsafeMutablePointer类型指针,指针需要对齐到16K(16384)字节。
有人可以提供有关如何在Swift中创建特定大小的对齐内存的建议吗?
答案 0 :(得分:6)
我相信这对你有用:
var memory:UnsafeMutablePointer<Void> = nil
var alignment:UInt = 0x4000 // 16K aligned
var size:UInt = bufferSize // bufferSize == your buffer size
posix_memalign(&memory, alignment, size)
供参考:
http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_memalign.html
答案 1 :(得分:2)
PageAlignedArray是一个项目,用于处理与Metal一起使用的内存时内存分配问题。
我没有看到你的16k字节要求。调试器说4k。也许你可以提供参考?它应该基于系统的页面大小。
最初的想法来自memkite我相信并且这样:
ListView
您希望计算要分配的正确内存量,以使其落在字节边界上。这意味着您可能需要分配比您想要的更多的东西。在这里你传递你需要的大小和对齐,它将返回你应该分配的数量。
private func setupSharedMemoryWithSize(byteCount: Int) ->
(pointer: UnsafeMutablePointer<Void>,
memoryWrapper: COpaquePointer)
{
let memoryAlignment = 0x1000 // 4096 bytes, 0x4000 would be 16k
var memory: UnsafeMutablePointer<Void> = nil
posix_memalign(&memory, memoryAlignment, byteSizeWithAlignment(memoryAlignment, size: byteCount))
let memoryWrapper = COpaquePointer(memory)
return (memory, memoryWrapper)
}
private func byteSizeWithAlignment(alignment: Int, size: Int) -> Int
{
return Int(ceil(Float(size) / Float(alignment))) * alignment
}
不要忘记释放你分配的记忆。
这些天你可以通过指定.StorageModeShared来分配没有let (pointer, memoryWrapper) = setupSharedMemoryWithSize(byteCount)
var unsafeVoidPointer: UnsafeMutablePointer<Void> = pointer
// Assuming your underlying data is unsigned 8-bit integers.
let unsafeMutablePointer = UnsafeMutablePointer<UInt8>(memoryWrapper)
let unsafeMutableBufferPointer = UnsafeMutableBufferPointer(start: unsafeMutablePointer, count: byteCount)
的内存。
posix_memalign
答案 2 :(得分:0)
在经历了这个问题的一些烦恼之后,我决定继续创建一个简单的解决方案,这将使这更容易。
我创建了一个名为PageAlignedArray
的Swift数组实现,它与内置Swift数组的接口和功能相匹配,但总是驻留在页面对齐的内存中,因此可以很容易地成为{ {1}}。我还添加了一种方便的方法来直接将MTLBuffer
转换为Metal缓冲区。
当然,您可以继续改变您的阵列,并且您的更新将自动提供给GPU共享内存架构。但是,请记住只要数组的长度发生变化,就必须重新生成PageAlignedArray
对象。
以下是一个快速代码示例:
MTLBuffer
示例使用 var alignedArray : PageAlignedContiguousArray<matrix_double4x4> = [matrixTest, matrixTest]
alignedArray.append(item)
alignedArray.removeFirst() // Behaves just like a built-in array, with all convenience methods
// When it's time to generate a Metal buffer:
let device = MTLCreateSystemDefaultDevice()
let testMetalBuffer = device?.makeBufferWithPageAlignedArray(alignedArray)
,但该数组应适用于任何Swift值类型。请注意,如果使用引用类型(例如任何类型的matrix_double4x4
),则数组将包含指向元素的指针,因此无法从GPU代码中使用。
请在此处抓取class
:https://github.com/eldoogy/PageAlignedArray