首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指针(内存)与16K对齐,用于金属缓冲区的创建

指针(内存)与16K对齐,用于金属缓冲区的创建
EN

Stack Overflow用户
提问于 2014-12-08 20:02:28
回答 3查看 3.2K关注 0票数 7

我想创建一个金属缓冲与newBufferWithBytesNoCopy功能,让CPU和GPU共享内存,并实践零拷贝数据传输。

newBufferWithBytesNoCopy函数采用不安全突变点类型指针,指针需要与16K(16384)字节对齐。

有人能就如何在Swift中创建一定大小的对齐内存提供建议吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-12-09 08:02:25

我认为这应该适用于你:

代码语言:javascript
复制
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

票数 6
EN

Stack Overflow用户

发布于 2016-02-08 09:12:20

Swift PageAligned阵列(只适用于解决方案)

PageAlignedArray是一个项目,当将与金属一起使用的内存时,它为您处理内存分配问题。

更详细

4096字节对齐

我没看到你对16k字节的要求。调试器说4k。也许你能提供一个参考资料?它应该基于系统的页面大小。

使用posix_memalign

最初的想法来自美凯特,我相信它是这样的:

代码语言:javascript
复制
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)
}

计算内存大小

您将需要计算要分配的正确内存量,以便将其放置在字节边界上。这意味着你可能需要分配的比你想要的多一点。在这里,您传递您需要的大小和对齐,它将返回您应该分配的金额。

代码语言:javascript
复制
private func byteSizeWithAlignment(alignment: Int, size: Int) -> Int
{
    return Int(ceil(Float(size) / Float(alignment))) * alignment
}

使用函数

代码语言:javascript
复制
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来分配内存。

代码语言:javascript
复制
let byteCount = 1000 * sizeof(Float)
let sharedMetalBuffer = self.metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)
票数 2
EN

Stack Overflow用户

发布于 2016-10-13 00:52:52

在经历了这个问题的一些烦恼之后,我决定继续做下去,创建一个简单的解决方案,让这个问题变得更容易。

我已经创建了一个名为PageAlignedArray的Swift数组实现,它与内置Swift数组的接口和功能相匹配,但始终驻留在对页内存中,因此可以很容易地生成一个MTLBuffer。我还添加了一种直接将PageAlignedArray转换为金属缓冲区的方便方法。

当然,您可以在之后继续修改数组,通过共享内存体系结构,您的更新将自动提供给GPU。但是,请记住,每当数组的长度发生变化时,必须重新生成MTLBuffer 对象。

下面是一个快速代码示例:

代码语言:javascript
复制
  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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27365905

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档