使用 Swift 加速 vDSP_ctoz 的分段错误
Segmentation fault using Swift Accelerate vDSP_ctoz
我正在尝试使用 Swift Accelerate 库中的 vDSP_ctoz
将交错的 DSPComplex
向量转换为 DSPSplitComplex
向量。下面代码的最后一行产生错误 Segmentation fault: 11
我不明白为什么 vDSP_ctoz
在我分配了大向量并且只尝试处理少量元素时会尝试访问越界内存。向量大小为 2048,vDSP_ctoz
中 N
(要处理的元素数)的参数为 1。
我也试过在调用 vDSP_ctoz
时使用不同的步幅和 N
值,但无济于事。
// set stride values
let dspComplexStride = MemoryLayout<DSPComplex>.stride
let dspSplitComplexStride = MemoryLayout<DSPSplitComplex>.stride
// make interleaved vector
var interleaved = UnsafeMutablePointer<DSPComplex>.allocate(capacity: 2048)
for index in 0..<16 {
interleaved[index] = DSPComplex(real: Float(2*index), imag: Float(2*index+1))
}
// make split vector
var splitComplex = UnsafeMutablePointer<DSPSplitComplex>.allocate(capacity: 2048)
vDSP_ctoz(
interleaved, dspComplexStride, splitComplex, dspSplitComplexStride, 1
)
DSPSplitComplex
是一个结构包含[=36=]指针数组,
所以你需要一个 DSPSplitComplex
元素并且必须分配
realp
和 imagp
属性的存储空间。
"stride" 参数不是以字节为单位而是以 "element" 为单位。
所以你传递 __IZ == 1
因为你想填充连续的元素
在目标数组中。
你必须为源数组传递 __IC == 2
可能并不明显,即
源数组的步幅以 Float
单位给出,而不是
DSPComplex
个单位。这可以从 vDSP_ctoz
documentation
其中提到该功能有效
for (n = 0; n < N; ++n)
{
Z->realp[n*IZ] = C[n*IC/2].real;
Z->imagp[n*IZ] = C[n*IC/2].imag;
}
最后,vDSP_ctoz
的最后一个参数是元素个数
过程。
综合起来,它应该是这样工作的:
import Accelerate
let N = 16
var interleaved = UnsafeMutablePointer<DSPComplex>.allocate(capacity: N)
for index in 0..<N {
interleaved[index] = DSPComplex(real: Float(2*index), imag: Float(2*index+1))
}
let realp = UnsafeMutablePointer<Float>.allocate(capacity: N)
let imagp = UnsafeMutablePointer<Float>.allocate(capacity: N)
var splitComplex = DSPSplitComplex(realp: realp, imagp: imagp)
vDSP_ctoz(interleaved, 2, &splitComplex, 1, vDSP_Length(N))
for index in 0..<N {
print(splitComplex.realp[index], splitComplex.imagp[index])
}
当然最后还是要释放内存。
我正在尝试使用 Swift Accelerate 库中的 vDSP_ctoz
将交错的 DSPComplex
向量转换为 DSPSplitComplex
向量。下面代码的最后一行产生错误 Segmentation fault: 11
我不明白为什么 vDSP_ctoz
在我分配了大向量并且只尝试处理少量元素时会尝试访问越界内存。向量大小为 2048,vDSP_ctoz
中 N
(要处理的元素数)的参数为 1。
我也试过在调用 vDSP_ctoz
时使用不同的步幅和 N
值,但无济于事。
// set stride values
let dspComplexStride = MemoryLayout<DSPComplex>.stride
let dspSplitComplexStride = MemoryLayout<DSPSplitComplex>.stride
// make interleaved vector
var interleaved = UnsafeMutablePointer<DSPComplex>.allocate(capacity: 2048)
for index in 0..<16 {
interleaved[index] = DSPComplex(real: Float(2*index), imag: Float(2*index+1))
}
// make split vector
var splitComplex = UnsafeMutablePointer<DSPSplitComplex>.allocate(capacity: 2048)
vDSP_ctoz(
interleaved, dspComplexStride, splitComplex, dspSplitComplexStride, 1
)
DSPSplitComplex
是一个结构包含[=36=]指针数组,
所以你需要一个 DSPSplitComplex
元素并且必须分配
realp
和 imagp
属性的存储空间。
"stride" 参数不是以字节为单位而是以 "element" 为单位。
所以你传递 __IZ == 1
因为你想填充连续的元素
在目标数组中。
你必须为源数组传递 __IC == 2
可能并不明显,即
源数组的步幅以 Float
单位给出,而不是
DSPComplex
个单位。这可以从 vDSP_ctoz
documentation
其中提到该功能有效
for (n = 0; n < N; ++n)
{
Z->realp[n*IZ] = C[n*IC/2].real;
Z->imagp[n*IZ] = C[n*IC/2].imag;
}
最后,vDSP_ctoz
的最后一个参数是元素个数
过程。
综合起来,它应该是这样工作的:
import Accelerate
let N = 16
var interleaved = UnsafeMutablePointer<DSPComplex>.allocate(capacity: N)
for index in 0..<N {
interleaved[index] = DSPComplex(real: Float(2*index), imag: Float(2*index+1))
}
let realp = UnsafeMutablePointer<Float>.allocate(capacity: N)
let imagp = UnsafeMutablePointer<Float>.allocate(capacity: N)
var splitComplex = DSPSplitComplex(realp: realp, imagp: imagp)
vDSP_ctoz(interleaved, 2, &splitComplex, 1, vDSP_Length(N))
for index in 0..<N {
print(splitComplex.realp[index], splitComplex.imagp[index])
}
当然最后还是要释放内存。