如何使用 vDSP 集成 Swift
How to integrate in Swift using vDSP
我试图找到 SciPy's cumtrapz
function function in Swift. I found something called vDSP_vtrapzD
的替代品,但我不知道如何使用它。这是我到目前为止所做的:
import Accelerate
var f1: [Double] = [<some data>]
var tdata: [Double] = [<time vector>]
var output = [Double](unsafeUninitializedCapacity:Int(f1.count), initializingWith: {_, _ in})
vDSP_vtrapzD(&f1, 1, &tdata, &output, 1, vDSP_Length(f1.count))
你很接近,但你使用 Array.init(unsafeUninitializedCapacity:initializingWith:)
不正确。来自 its documentation:
Discussion
Inside the closure, set the initializedCount
parameter to the number of elements that are initialized by the closure. The memory in the range buffer[0..<initializedCount]
must be initialized at the end of the closure’s execution, and the memory in the range buffer[initializedCount...]
must be uninitialized. This postcondition must hold even if the initializer
closure throws an error.
这个 API 比 Array.init(repeating:count:)
更不安全(但性能更高),它分配一个固定大小的数组,并花时间初始化它的所有内容)。这有两个潜在的缺点:
如果数组的目的是提供一个缓冲区来写入结果,那么在此之前对其进行初始化是多余且浪费的
如果您放入该缓冲区的结果最终大于您的
数组,你需要记住手动“trim”多余的部分
将其复制到新数组中。
Array.init(unsafeUninitializedCapacity:initializingWith:)
通过以下方式对此进行了改进:
- 询问您可能需要的最大容量
- 给你一个临时缓冲区的容量
- 重要的是,它未初始化。这使它更快,但如果使用不当也更危险(buffer underflow errors 的风险)。
- 然后您准确地告诉它您实际上使用了多少临时缓冲区
- 它会自动将那么多的缓冲区复制到最终数组中,return 结果就是如此。
您正在使用 Array.init(unsafeUninitializedCapacity:initializingWith:)
,就好像它是 Array.init(repeating:count:)
。要正确使用它,您可以将初始化逻辑放在 initializer
参数中,如下所示:
let result = Array<Double>(unsafeUninitializedCapacity: f1.count, initializingWith: { resultBuffer, count in
assert(f1.count == tdata.count)
vDSP_vtrapzD(
&f1, // Double-precision real input vector.
1, // Address stride for A.
&tdata, // Pointer to double-precision real input scalar: step size.
resultBuffer.baseAddress!, // Double-precision real output vector.
1, // Address stride for C.
vDSP_Length(f1.count) // The number of elements to process.,
)
count = f1.count // This tells Swift how many elements of the buffer to copy into the resultant Array
})
仅供参考,您可以在此处看到 vDSP_vtrapzD
的一个很好的 Swift 版本:https://developer.apple.com/documentation/accelerate/vdsp/integration_functions。 returns 结果使用 unsafeUninitializedCapacity
初始值设定项的变体。
在相关说明中,还有一个很好的 Swift API 到 Quadrature:https://developer.apple.com/documentation/accelerate/quadrature-smu
西蒙
我试图找到 SciPy's cumtrapz
function function in Swift. I found something called vDSP_vtrapzD
的替代品,但我不知道如何使用它。这是我到目前为止所做的:
import Accelerate
var f1: [Double] = [<some data>]
var tdata: [Double] = [<time vector>]
var output = [Double](unsafeUninitializedCapacity:Int(f1.count), initializingWith: {_, _ in})
vDSP_vtrapzD(&f1, 1, &tdata, &output, 1, vDSP_Length(f1.count))
你很接近,但你使用 Array.init(unsafeUninitializedCapacity:initializingWith:)
不正确。来自 its documentation:
Discussion
Inside the closure, set the
initializedCount
parameter to the number of elements that are initialized by the closure. The memory in the rangebuffer[0..<initializedCount]
must be initialized at the end of the closure’s execution, and the memory in the rangebuffer[initializedCount...]
must be uninitialized. This postcondition must hold even if theinitializer
closure throws an error.
这个 API 比 Array.init(repeating:count:)
更不安全(但性能更高),它分配一个固定大小的数组,并花时间初始化它的所有内容)。这有两个潜在的缺点:
如果数组的目的是提供一个缓冲区来写入结果,那么在此之前对其进行初始化是多余且浪费的
如果您放入该缓冲区的结果最终大于您的 数组,你需要记住手动“trim”多余的部分 将其复制到新数组中。
Array.init(unsafeUninitializedCapacity:initializingWith:)
通过以下方式对此进行了改进:
- 询问您可能需要的最大容量
- 给你一个临时缓冲区的容量
- 重要的是,它未初始化。这使它更快,但如果使用不当也更危险(buffer underflow errors 的风险)。
- 然后您准确地告诉它您实际上使用了多少临时缓冲区
- 它会自动将那么多的缓冲区复制到最终数组中,return 结果就是如此。
您正在使用 Array.init(unsafeUninitializedCapacity:initializingWith:)
,就好像它是 Array.init(repeating:count:)
。要正确使用它,您可以将初始化逻辑放在 initializer
参数中,如下所示:
let result = Array<Double>(unsafeUninitializedCapacity: f1.count, initializingWith: { resultBuffer, count in
assert(f1.count == tdata.count)
vDSP_vtrapzD(
&f1, // Double-precision real input vector.
1, // Address stride for A.
&tdata, // Pointer to double-precision real input scalar: step size.
resultBuffer.baseAddress!, // Double-precision real output vector.
1, // Address stride for C.
vDSP_Length(f1.count) // The number of elements to process.,
)
count = f1.count // This tells Swift how many elements of the buffer to copy into the resultant Array
})
仅供参考,您可以在此处看到 vDSP_vtrapzD
的一个很好的 Swift 版本:https://developer.apple.com/documentation/accelerate/vdsp/integration_functions。 returns 结果使用 unsafeUninitializedCapacity
初始值设定项的变体。
在相关说明中,还有一个很好的 Swift API 到 Quadrature:https://developer.apple.com/documentation/accelerate/quadrature-smu
西蒙