我需要对包含RGB像素数据的Data执行简单的数学运算。目前我是这样做的:
let imageMean: Float = 127.5
let imageStd: Float = 127.5
let rgbData: Data // Some data containing RGB pixels
let floats = (0..<rgbData.count).map {
(Float(rgbData[$0]) - imageMean) / imageStd
}
return Data(bytes: floats, count: floats.count * MemoryLayout<Float>.size)这是可行的,但是太慢了。我希望我可以使用Accelerate框架来更快地计算,但我不知道如何做到这一点。我保留了一些空间,这样它就不会在这个函数每次启动时都被分配,如下所示:
inputBufferDataNormalized = malloc(width * height * 3) // 3 channels RGB我尝试了几个函数,比如vDSP_vasm,但是我不能让它工作。有人能告诉我如何使用它吗?基本上我需要替换这个map函数,因为它花费的时间太长了。而且,一直使用预先分配的空间可能会很棒。
发布于 2020-08-03 02:21:50
跟进我对你的其他相关问题的评论。您可以使用SIMD并行化操作,但需要将原始数组拆分为块。
这是一个简化的示例,它假设数组完全可以被64整除,例如,一个包含1024个元素的数组:
let arr: [Float] = (0 ..< 1024).map { _ in Float.random(in: 0...1) }let imageMean: Float = 127.5
let imageStd: Float = 127.5
var chunks = [SIMD64<Float>]()
chunks.reserveCapacity(arr.count / 64)
for i in stride(from: 0, to: arr.count, by: 64) {
let v = SIMD64.init(arr[i ..< i+64])
chunks.append((v - imageMean) / imageStd) // same calculation using SIMD
}现在,您可以使用下标访问每个chunk:
var results: [Float] = []
results.reserveCapacity(arr.count)
for chunk in chunks {
for i in chunk.indices {
results.append(chunk[i])
}
}当然,如果数组不能被64整除,则需要处理余数。
发布于 2020-08-03 03:52:46
我已经找到了一种使用Accelerate来完成此任务的方法。首先,我为转换后的缓冲区预留空间,如下所示
var inputBufferDataRawFloat = [Float](repeating: 0, count: width * height * 3)然后我可以像这样使用它:
let rawBytes = [UInt8](rgbData)
vDSP_vfltu8(rawBytes, 1, &inputBufferDataRawFloat, 1, vDSP_Length(rawBytes.count))
vDSP.add(inputBufferDataRawScalars.mean, inputBufferDataRawFloat, result: &inputBufferDataRawFloat)
vDSP.multiply(inputBufferDataRawScalars.std, inputBufferDataRawFloat, result: &inputBufferDataRawFloat)
return Data(bytes: inputBufferDataRawFloat, count: inputBufferDataRawFloat.count * MemoryLayout<Float>.size)运行速度非常快。也许Accelerate有更好的功能,如果有人知道,请让我知道。它需要执行函数(A[n] + B) * C (或者确切地说是(A[n] - B) / C,但第一个函数可以转换为这个函数)。
https://stackoverflow.com/questions/63219100
复制相似问题