Swift,macOS,具有2个GPU的mac,矩阵运算可在一个GPU上工作,而不是在另一个GPU上工作

问题描述 投票:2回答:1

根据Apple菜单中的“关于本机”,我在装有两个GPU的MacBook Pro(15英寸,2015年中,视网膜)上运行macOS。一个GPU是2 GB的AMD Radeon R9 M370X,另一个是Intel Iris Pro 1536 MB-我猜是标准芯片吗?它们是我购买时在那里的筹码,没有我自己添加的东西。

我正在使用Swift MPS库进行矩阵计算;它在Intel GPU上可以很好地工作,但是当我选择Radeon时,我每次操作只能得到零,没有错误报告。我到处寻找有关它的文档,但是找不到任何东西。到目前为止,我唯一的线索是Radeon报告“未集成”(或者至少我认为是基于Finding GPUs on macOS的示例代码,它与Apple的文档一样有用,意思是[[不太)。如果我已正确阅读该页面,则这是我的两个GPU告诉我的内容。

Device Intel Iris Pro Graphics; caps: headful, not discrete, integrated, not external

Device AMD Radeon R9 M370X; caps: headful, discrete, not integrated, not external

我找不到任何可以表明我做错事情的文档。我遍历了苹果公司的MPS文档,无济于事。正如我所说,该代码在Intel GPU上运行良好,因此我认为它也可以在Radeon上运行。我已经运行了一些可下载的诊断工具来检查Radeon,但是这些工具的菜单中没有显示该工具。因此,我什至不知道这是否是我在代码中做错的事情,或者芯片本身是否损坏。

下面是代码,您可以通过粘贴到main.swift将其构建为控制台应用程序。查找以下行:

let device = MTLCopyAllDevices()[1]

我将[0]用于Intel,将[1]用于Radeon,您可以看到输出是不同的,即Radeon的全零。我想您的里程可能会因您的机器而异。我欢迎任何意见,欢呼

import MetalPerformanceShaders typealias MPSNumber = Float32 let MPSNumberSize = MemoryLayout<MPSNumber>.size let MPSNumberTypeInGPU = MPSDataType.float32 class MPSNet { let commandBuffer: MTLCommandBuffer let commandQueue: MTLCommandQueue let device = MTLCopyAllDevices()[1] var neuronsInMatrix1: MPSMatrix? var neuronsInMatrix2: MPSMatrix? var neuronsOutMatrix: MPSMatrix? init() { guard let cq = device.makeCommandQueue() else { fatalError() } guard let cb = cq.makeCommandBuffer() else { fatalError() } commandQueue = cq commandBuffer = cb let cMatrices = 2 let cRows = 1 let cColumns = 3 let sensoryInputs1: [MPSNumber] = [1, 2, 3] let sensoryInputs2: [MPSNumber] = [4, 5, 6] neuronsInMatrix1 = makeMatrix(device, sensoryInputs1) neuronsInMatrix2 = makeMatrix(device, sensoryInputs2) let rowStride = MPSMatrixDescriptor.rowBytes(fromColumns: cColumns, dataType: MPSNumberTypeInGPU) neuronsOutMatrix = makeMatrix(device, cRows, cColumnsOut: cColumns, rowStride: rowStride) let adder = MPSMatrixSum( device: device, count: cMatrices, rows: cRows, columns: cColumns, transpose: false ) adder.encode( to: commandBuffer, sourceMatrices: [neuronsInMatrix1!, neuronsInMatrix2!], resultMatrix: neuronsOutMatrix!, scale: nil, offsetVector: nil, biasVector: nil, start: 0 ) commandBuffer.addCompletedHandler { _ in let motorOutputs = self.getComputeOutput(self.neuronsOutMatrix!) let discrete = !self.device.isLowPower && !self.device.isRemovable let caps = "\(self.device.isHeadless ? " headless" : " headful")" + "\(discrete ? ", discrete" : ", not discrete")" + "\(self.device.isLowPower ? ", integrated" : ", not integrated")" + "\(self.device.isRemovable ? ", external" : ", not external")" print("Device \(self.device.name); caps:\(caps); motor outputs \(motorOutputs)") } } func compute() { commandBuffer.commit() commandBuffer.waitUntilCompleted() } } extension MPSNet { func getComputeOutput(_ matrix: MPSMatrix) -> [Double] { let rc = matrix.data.contents() return stride(from: 0, to: matrix.columns * MPSNumberSize, by: MPSNumberSize).map { offset in let rr = rc.load(fromByteOffset: offset, as: MPSNumber.self) return Double(rr) } } func loadMatrix(_ data: MTLBuffer, _ rawValues: [MPSNumber]) { let dContents = data.contents() zip(stride(from: 0, to: rawValues.count * MPSNumberSize, by: MPSNumberSize), rawValues).forEach { z in let (byteOffset, rawValue) = (z.0, MPSNumber(z.1)) dContents.storeBytes(of: rawValue, toByteOffset: byteOffset, as: MPSNumber.self) } } func makeMatrix(_ device: MTLDevice, _ rawValues: [MPSNumber]) -> MPSMatrix { let rowStride = MPSMatrixDescriptor.rowBytes( fromColumns: rawValues.count, dataType: MPSNumberTypeInGPU ) let descriptor = MPSMatrixDescriptor( dimensions: 1, columns: rawValues.count, rowBytes: rowStride, dataType: MPSNumberTypeInGPU ) guard let inputBuffer = device.makeBuffer( length: descriptor.matrixBytes, options: MTLResourceOptions.storageModeManaged ) else { fatalError() } loadMatrix(inputBuffer, rawValues) return MPSMatrix(buffer: inputBuffer, descriptor: descriptor) } func makeMatrix(_ device: MTLDevice, _ cRowsOut: Int, cColumnsOut: Int, rowStride: Int) -> MPSMatrix { let matrixDescriptor = MPSMatrixDescriptor( dimensions: cRowsOut, columns: cColumnsOut, rowBytes: rowStride, dataType: MPSNumberTypeInGPU ) return MPSMatrix(device: device, descriptor: matrixDescriptor) } } let net = MPSNet() net.compute()

swift macos gpu matrix-multiplication
1个回答
0
投票
似乎您未能使用-[MPSMatrix syncnizeOnCommandBuffer:]。在分立设备上,需要一些显式同步,然后数据才能从GPU返回。
© www.soinside.com 2019 - 2024. All rights reserved.