Генерация случайных данных с использованием Metal Performance Shaders - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь сгенерировать некоторые случайные целочисленные данные для моего приложения с помощью графического процессора, используя MPSMatrixRandom, и у меня есть два вопроса.

  1. В чем разница между MPSMatrixRandomMTGP32 и MPSMatrixRandomPhilox?

    Я понимаю, что эти два шейдера используют разные алгоритмы, но чем они отличаются? Отличается ли производительность или выходные данные этих двух алгоритмов, и если да, то как?

  2. Какой код вы можете использовать для реализации этих шейдеров?

    Я пытался реализовать их сам, но мое приложение постоянно падает с неопределенными сообщениями об ошибках. Мне бы хотелось, чтобы пример реализации этого выполнялся правильно.

1 Ответ

0 голосов
/ 24 апреля 2020

Вот пример, демонстрирующий, как генерировать случайные матрицы с использованием этих двух ядер:

import Foundation
import Metal
import MetalPerformanceShaders

let device = MTLCreateSystemDefaultDevice()!
let commandQueue = device.makeCommandQueue()!

let rows = 8
let columns = 8
let matrixDescriptor = MPSMatrixDescriptor(rows: rows,
                                           columns: columns,
                                           rowBytes: MemoryLayout<Float>.stride * columns,
                                           dataType: .float32)
let mtMatrix = MPSMatrix(device: device, descriptor: matrixDescriptor)

let phMatrix = MPSMatrix(device: device, descriptor: matrixDescriptor)

let distribution = MPSMatrixRandomDistributionDescriptor.uniformDistributionDescriptor(withMinimum: -1.0, maximum: 1.0)

let mtKernel = MPSMatrixRandomMTGP32(device: device,
                                     destinationDataType: .float32,
                                     seed: 0,
                                     distributionDescriptor: distribution)

let phKernel = MPSMatrixRandomPhilox(device: device,
                                     destinationDataType: .float32,
                                     seed: 0,
                                     distributionDescriptor: distribution)


let commandBuffer = commandQueue.makeCommandBuffer()!
mtKernel.encode(commandBuffer: commandBuffer, destinationMatrix: mtMatrix)
phKernel.encode(commandBuffer: commandBuffer, destinationMatrix: phMatrix)
#if os(macOS)
mtMatrix.synchronize(on: commandBuffer)
phMatrix.synchronize(on: commandBuffer)
#endif
commandBuffer.commit()

commandBuffer.waitUntilCompleted() // Only necessary to ensure GPU->CPU sync for display

print("Mersenne Twister values:")
let mtValues = mtMatrix.data.contents().assumingMemoryBound(to: Float.self)
for row in 0..<rows {
    for col in 0..<columns {
        print("\(mtValues[row * columns + col])", terminator: " ")
    }
    print("")
}
print("")

print("Philox values:")
let phValues = phMatrix.data.contents().assumingMemoryBound(to: Float.self)
for row in 0..<rows {
    for col in 0..<columns {
        print("\(phValues[row * columns + col])", terminator: " ")
    }
    print("")
}

Я не могу комментировать статистические свойства этих генераторов; Я бы сослался на статьи, упомянутые в комментариях.

...