【问题标题】:Reading data from MTLBuffer in Swift在 Swift 中从 MTLBuffer 中读取数据
【发布时间】:2015-02-26 18:46:11
【问题描述】:

在 GPU 上处理后,我需要从 MTLBuffer 读取数据。到目前为止,我已经尝试过以下代码,但它总是以 EXC_BAD_ACCESS 错误代码崩溃。

struct gauss_model {
  var mean : [Float32] = [0.0, 0.0, 0.0];
  var covMat : [[Float32]] = [[0.0, 0.0, 0.0],[0.0, 0.0, 0.0],[0.0, 0.0, 0.0]];
  var invCovMat : [[Float32]] = [[0.0, 0.0, 0.0],[0.0, 0.0, 0.0],[0.0, 0.0, 0.0]];
  var samples : Int32 = 0;
}

self.gaussModels = [gauss_model](count: Int(10), repeatedValue: gauss_model())
self.modelsBuffer = self.device.newBufferWithBytes(self.gaussModels, length:      self.gaussModels.count * sizeof(gauss_model), options: MTLResourceOptions.OptionCPUCacheModeDefault)
commandEncoder.setBuffer(self.modelsBuffer, offset: 0, atIndex: 0)

    // execute GPU code

var model = unsafeBitCast(self.modelsBuffer.contents(), UnsafeMutablePointer<gauss_model>.self)
NSLog("%@", model.memory.mean) // crashes on this statement

我也尝试过不同的方法来获取价值,比如

var model = UnsafeMutablePointer<gauss_model>(self.modelsBuffer.contents())
// iterate over models with model.memory and model.successor()

var model = UnsafeMutablePointer<[gauss_model]>(self.modelBuffer.contents())
let models : [gauss_model] = model.memory

但他们都没有工作。有没有办法做到这一点?

【问题讨论】:

    标签: ios swift metal


    【解决方案1】:

    我已经设法解决了这个问题。问题在于我对 Swift 中的内存管理的错误假设以及函数 newBufferWithBytes 仅执行浅拷贝的事实。调用该函数只复制了指向meancovMatinvCovMat 数组的指针,而self.modelBuffer.contents() 包含指向未初始化内存的指针。访问内存导致崩溃。

    【讨论】:

    【解决方案2】:

    如果你来自谷歌试图读取一个简单的整数 MTLBuffer,我就是这样做的。

    我对我的代码不是很有信心,但它似乎有效。 (我还向 Apple 发送了错误报告,因为这方面的 swift 文档是用 Objective-C 编写的)

    let bufferSize = 10
    let rawbufferSize = bufferSize * MemoryLayout<Int>.stride
    
    let oneArray: [Int] = Array(repeating: 1, count: bufferSize)
    
    let BufferA = device.makeBuffer(bytes: oneArray, length: rawbufferSize, options: MTLResourceOptions.storageModeShared)
    let BufferB = device.makeBuffer(bytes: oneArray, length: rawbufferSize, options: MTLResourceOptions.storageModeShared)
    let BufferResult = device.makeBuffer(bytes: oneArray, length: rawbufferSize, options: MTLResourceOptions.storageModeShared)
    
    let commandBuffer = queue?.makeCommandBuffer()
    let computeEncoder = commandBuffer?.makeComputeCommandEncoder()
    
    computeEncoder?.setComputePipelineState(pipelineState)
    computeEncoder?.setBuffer(BufferA, offset: 0, index: 0)
    computeEncoder?.setBuffer(BufferB, offset: 0, index: 1)
    computeEncoder?.setBuffer(BufferResult, offset: 0, index: 2)
    
    let gridSize = MTLSizeMake(bufferSize * MemoryLayout<Int>.stride, 1, 1)
    
    let threadGroupSize = pipelineState.maxTotalThreadsPerThreadgroup > bufferSize ? bufferSize : pipelineState.maxTotalThreadsPerThreadgroup
    
    computeEncoder?.dispatchThreads(
        MTLSizeMake(rawbufferSize, 1, 1),
        threadsPerThreadgroup: MTLSizeMake(threadGroupSize, 1, 1 ))
    
    computeEncoder?.endEncoding()
    commandBuffer?.commit()
    commandBuffer?.waitUntilCompleted()
    
    // Ewww
    var rawPointer = BufferResult?.contents()
    var typedPointer = rawPointer?.bindMemory(to: Int.self, capacity: rawbufferSize)
    let bufferedPointer = UnsafeBufferPointer(start: typedPointer, count: rawbufferSize)
    for i in 0..<bufferSize {
        print(bufferedPointer[i])
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-26
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多