我想创建一个金属缓冲与newBufferWithBytesNoCopy功能,让CPU和GPU共享内存,并实践零拷贝数据传输。
newBufferWithBytesNoCopy函数采用不安全突变点类型指针,指针需要与16K(16384)字节对齐。
有人能就如何在Swift中创建一定大小的对齐内存提供建议吗?
发布于 2014-12-09 08:02:25
我认为这应该适用于你:
var memory:UnsafeMutablePointer<Void> = nil
var alignment:UInt = 0x4000 // 16K aligned
var size:UInt = bufferSize // bufferSize == your buffer size
posix_memalign(&memory, alignment, size)供参考:
memalign.html
发布于 2016-02-08 09:12:20
Swift PageAligned阵列(只适用于解决方案)
PageAlignedArray是一个项目,当将与金属一起使用的内存时,它为您处理内存分配问题。
更详细
4096字节对齐
我没看到你对16k字节的要求。调试器说4k。也许你能提供一个参考资料?它应该基于系统的页面大小。
使用posix_memalign
最初的想法来自美凯特,我相信它是这样的:
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
}使用函数
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分配共享内存。
现在,只需指定posix_memalign,就可以不使用.StorageModeShared来分配内存。
let byteCount = 1000 * sizeof(Float)
let sharedMetalBuffer = self.metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)发布于 2016-10-13 00:52:52
在经历了这个问题的一些烦恼之后,我决定继续做下去,创建一个简单的解决方案,让这个问题变得更容易。
我已经创建了一个名为PageAlignedArray的Swift数组实现,它与内置Swift数组的接口和功能相匹配,但始终驻留在对页内存中,因此可以很容易地生成一个MTLBuffer。我还添加了一种直接将PageAlignedArray转换为金属缓冲区的方便方法。
当然,您可以在之后继续修改数组,通过共享内存体系结构,您的更新将自动提供给GPU。但是,请记住,每当数组的长度发生变化时,必须重新生成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)示例使用matrix_double4x4,但是数组应该适用于任何Swift值类型。请注意,如果使用引用类型(如任何类型的class),数组将包含指向元素的指针,因此无法从GPU代码中使用。
请抓取PageAlignedArray这里:https://github.com/eldoogy/PageAlignedArray
https://stackoverflow.com/questions/27365905
复制相似问题