Ошибка сегментации с использованием Swift Accelerate vDSP_ctoz

Я пытаюсь преобразовать чередующийся вектор DSPComplex в вектор DSPSplitComplex, используя vDSP_ctoz из библиотеки Swift Accelerate. Последняя строка кода ниже выдает ошибку Segmentation fault: 11

Я не понимаю, почему vDSP_ctoz пытается получить доступ к внешней памяти, когда я выделил большие векторы и пытаюсь обработать только небольшое количество элементов. Векторы имеют размер 2048, а аргумент для N (количество элементов для обработки) в vDSP_ctoz равен 1.

Я также пытался использовать разные значения шага и N при вызове vDSP_ctoz, но безрезультатно.

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

person ASDFQWERTY    schedule 07.07.2017    source источник


Ответы (1)


DSPSplitComplex — это структура, содержащая массивы указателей, поэтому вам нужен один элемент DSPSplitComplex, и вы должны выделить память для его свойств realp и imagp.

Аргументы «шага» измеряются не в байтах, а в «элементных» единицах. Таким образом, вы передаете __IZ == 1, потому что хотите заполнить непрерывные элементы в целевых массивах.

Может быть неочевидно, что вы должны передать __IC == 2 для исходного массива, т. е. шаг исходного массива задается в Float единицах, а не в DSPComplex единицах. Это можно сделать из vDSP_ctoz документации, в которой упоминается, что функция эффективно выполняет

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

и, конечно, вы должны освободить память в конце концов.

person Martin R    schedule 08.07.2017