我需要在Swift中使用Accelerate Multiply,Complex Conjugate和Exp执行以下操作。我已经使用Complex Swift code by dankogai完成了这项工作,但这对我正在做的工作来说太慢了。我在使用Accelerate框架创建工作版本时遇到了麻烦,我希望加快理解。
let frequencyShift = (2 * M_PI * Double(self.centralFrequency) * delays).i / Double(self.samplingFrequencyHertz)
let result = conj(exp(frequencyShift))
delays
是一个大约200k双精度数组,这些行将被称为几百次。我将它们转换为复杂数字和Swift复杂样式,然后在结果上调用复杂的exp()和conj()方法。
双精度复矢量 - 标量乘法。
vDSP_zvzsmlD
复矢量共轭;双精度。
vDSP_zvconjD
Accelerate中是否有exp()
个等效项,您如何重新组织此代码以执行等效的Accelerate&dd版本的操作?
答案 0 :(得分:0)
我发现首先尝试将代码从使用for循环的朴素实现转换为映射是有帮助的。如果您的代码的结构与地图一起使用,那么切换到加速变得非常容易,因为您已经将算法结构化为矢量化操作。
let array: [Int] = [1, 2, 3, 4]
let array2 = [Int]()
for value in array {
array2 = value * 2
}
let array: [Int] = [1, 2, 3, 4]
array.map({ (value: Int) -> Int in
return value * 2
})
如果您发现要枚举两个或更多相同大小的数组,那么上面的内容可以将地图与枚举结合起来
let alphas: [Double] = betas.enumerate().map({ (index: Int, beta: Double) -> Double in
return beta * phis[index]
})
使用Accelerate的方式并不总是很明显,特别是UnsafePointer
和UnsafeMutablePointer
语法。这基本上是不必要的。
var alphaLowers = [Double](count: elementDelays.count, repeatedValue: 0)
vDSP_vmulD(&alphas, 1, &x_ns, 1, &alphaLowers, 1, UInt(elementDelays.count))
所以Swift通过允许你创建一个自动内存管理对象然后简单地将它与&符号一起传递来避免malloc和free的麻烦。我之所以提到这一点是因为它避免了尝试将对象包装在这个UnsafeMutablePointer<Double>(alphaLowers)
中。
我想做的大多数事情都依赖于涉及复杂数字的操作。因此,要创建可在Accelerate中使用的对象,您可以尝试以下操作。
var reals = [Double](count: 100, repeatedValue: 0)
var imaginaries = [Double](count: 100, repeatedValue: 0)
var complexNumbers = DSPDoubleSplitComplex(realp: &reals, imagp: &imaginaries)
我没有找到exprate的Accelerate等价物,但你可以使用Complex Swift库使用下面说明的Euler方法分解值并对实数和虚数执行必要的操作。
public func exp<T:RealType>(z:Complex<T>) -> Complex<T> {
let r = T.exp(z.re)
let a = z.im
return Complex(r * T.cos(a), r * T.sin(a))
}
我没有找到避免这个问题的好方法,所以我实际上是在不使用Accelerate的情况下执行此步骤。简单地通过否定虚部来计算复共轭。