简体   繁体   English

在Swift中使用Accelerate Framework复数支持

[英]Using Accelerate Framework complex number support in Swift

I need to perform the following operations in Swift with Accelerate Multiply, Complex Conjugate, and Exp. 我需要在Swift中使用Accelerate Multiply,Complex Conjugate和Exp执行以下操作。 I've done this already using the Complex Swift code by dankogai , but it is just too slow for the work I'm doing. 我已经使用dankogaiComplex Swift代码完成了此操作 ,但是对于我正在做的工作来说太慢了。 I'm having trouble creating a working version using the Accelerate framework and I'm hoping to accelerate my understanding. 我在使用Accelerate框架创建工作版本时遇到了麻烦,希望能够加深我的理解。

Swift code SWIFT代码

let frequencyShift = (2 * M_PI * Double(self.centralFrequency) * delays).i / Double(self.samplingFrequencyHertz)
let result = conj(exp(frequencyShift))

delays is an array of about 200k doubles and these lines will be called a couple of hundred times. delays是大约200k倍的数组,这些行将被称为数百次。 I convert them to Complex numbers a la Swift Complex style and then call the complex exp() and conj() methods on the result. 我将它们转换为Swift复杂样式的Complex Number,然后在结果上调用complex exp()和conj()方法。

Multiply

Double-precision complex vector-scalar multiply. 双精度复数矢量标量乘法。

vDSP_zvzsmlD

Conjugate 共轭

Complex vector conjugate; 复合矢量共轭 double precision. 双精度。

vDSP_zvconjD

Is there an exp() equivalent in Accelerate and how would you reorganize this code to perform an equivalent Accelerate'd version of the operations? Accelerate中是否有等效的exp() ,您将如何重组此代码以执行等效的Accelerate'd版本的操作?

General principles of using Accelerate with Swift 在Swift中使用Accelerate的一般原则

I find it helpful to first attempt to convert your code from a naive implementation using for-loops to maps. 我发现第一次尝试将您的代码从使用for循环的幼稚实现转换为映射很有用。 If your code is structured to work with maps then it becomes pretty easy to switch to accelerate since you have already tackled structuring your algorithm into vectorized operations. 如果您的代码结构适合与地图一起使用,则由于您已经解决了将算法结构化为向量化操作的问题,因此切换加速变得非常容易。

For-loop to map 循环映射

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
})

Operating on equal sized arrays version 在相等大小的阵列版本上运行

If you find that you want to enumerate two or more arrays of the same size then the above can combine map with enumerate 如果发现要枚举两个或更多个相同大小的数组,则上述方法可以将map与enumerate结合使用

let alphas: [Double] = betas.enumerate().map({ (index: Int, beta: Double) -> Double in
    return beta * phis[index]
})

Setting up the arrays for use with Accelerate 设置阵列以与Accelerate一起使用

The way to use Accelerate is not always obvious and specifically the UnsafePointer and UnsafeMutablePointer syntax. 使用Accelerate的方法并不总是很明显,特别是UnsafePointerUnsafeMutablePointer语法。 This is basically unnecessary. 这基本上是不必要的。

var alphaLowers = [Double](count: elementDelays.count, repeatedValue: 0)
vDSP_vmulD(&alphas, 1, &x_ns, 1, &alphaLowers, 1, UInt(elementDelays.count))

So Swift avoids the hassles of malloc and free by allowing you to create an automatic memory managed object and then simply passing it along with the ampersand. 因此,Swift允许您创建一个自动的内存管理对象,然后将其与&符号一起传递,从而避免了malloc和free的麻烦。 I mention this because it avoids trying things like wrapping the object in this UnsafeMutablePointer<Double>(alphaLowers) . 我之所以这样说是因为它避免尝试将对象包装在此UnsafeMutablePointer<Double>(alphaLowers)

Complex numbers 复数

Most of what I wanted to do relied on operations involving complex numbers. 我想做的大多数事情都依赖于涉及复数的运算。 So to create an object you can use in Accelerate you might try the following. 因此,要创建可以在Accelerate中使用的对象,可以尝试以下操作。

var reals = [Double](count: 100, repeatedValue: 0)
var imaginaries = [Double](count: 100, repeatedValue: 0)
var complexNumbers = DSPDoubleSplitComplex(realp: &reals, imagp: &imaginaries)

Complex exp() 复杂的exp()

I didn't find an Accelerate equivalent of exp, but you can break up the values and perform the necessary operation on the reals and imaginaries using Euler's method illustrated below using the Complex Swift library. 我没有找到与exp相当的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))
}

I haven't found a good way of avoiding this problem so I actually do this step without using Accelerate. 我没有找到避免此问题的好方法,因此我实际上不使用Accelerate来执行此步骤。 The complex conjugate is calculated simply by negating the imaginary portion. 简单地通过对虚部进行求反即可计算出复共轭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM