使用ArraySlice和Accelerate函数的更好方法是什么?

时间:2016-07-08 00:44:32

标签: arrays swift accelerate-framework vdsp

我有一些非常大的数组,我必须执行数百万次计算。在Objective-C中,数组将存储为NSData,我将它们抽象为C数组以使用Accelerate函数(sum,add等)。但是,(考虑到在任何地方使用指针的明显问题)我喜欢更多地使用Swift数组内置的边界检查。因此,我可以使用嵌套的withUnsafeBufferPointer来处理两个数组。

func mult(_ x: ArraySlice<Double>, _ y: ArraySlice<Double>) -> [Double] {
    assert(x.count == y.count)

    var results = [Double](repeating:0, count: x.count)

    x.withUnsafeBufferPointer({xBuffer in
        y.withUnsafeBufferPointer({yBuffer in
            vDSP_vmulD([Double](xBuffer), 1, [Double](yBuffer), 1, &results, 1, vDSP_Length(xBuffer.count))
        })
    })

    return results
}

var testArray = [Double]([0,1,2,3,4,5,6,7,8,9,10])
var testArray2 = [Double]([2,2,2,2,2,2,2,2,2,2,2])

let results = mult(testArray[5...10], testArray2[5...10])
print("\(results)")

首先,如果编译器已经知道如何转换[Double]本身(在块内部传递的指针是UnsafeBufferPointer<Double>类型,而vDSP函数),则将指针重新设置为预期类型似乎很奇怪期待UnsafePointer<Double>(再次,如果我传递数组变量本身就没有抱怨))。其次,必须嵌套withUnsafeBufferPointer看起来很奇怪,虽然我理解其用法。最后,如果我使用ArraySlice<Double>作为输入参数类型,那么我不能将该函数概括为Double数组和该数组的切片。

有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

  1. 重铸确实是一个问题,它会创建一个全新的数组。为避免这种情况,您可以使用baseAddress的{​​{1}}属性(并在Swift 3中解包)

  2. 嵌套的UnsafeBuffer确实是正确的,无法避免(据我所知)。缓冲区指针仅在闭包内有效。

  3. 您可以为

  4. 创建协议

    总而言之,以下是包含这些更改的代码:

    withUnsafeBufferPointer

    强制解包会很好,因为三种符合类型的类型永远不会给你一个空指针。