Приведение [Float] к [simd_float4] в Swift - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть эта функция c, которую я вызываю из Swift, но я думаю, что это возможно реализовать в Swift, хитрость заключается в том, чтобы иметь возможность преобразовывать память для массива с плавающей точкой в ​​массив simd_float4.Ниже моя функция c и как я ее называю в Swift

swift

sumFloats(&y, y1, n, anAmplitudes[z]);

C

void sumFloats(float * y, const float * x, const int yc, const float a) {
    simd_float4 theA = simd_make_float4(a,a,a,a);
    simd_float4 * theY = (simd_float4*)y;
    simd_float4 * theX = (simd_float4*)x;
    assert( (yc&0x3) == 0 );
    for( int t = 0, theYC = yc >> 2; t < theYC; t ++ ) {
        theY[t] += theA * theX[t];
    }
}

также мое понимание - массив не гарантирует непрерывногоблок памяти, поэтому при вызове кода C должно происходить какое-то преобразование, я могу это исправить, используя ContiguousArray, но я не могу использовать ContiguousArray для вызова C.

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

Глядя на то, как Apple определяет функции vForce, ответ Мартина Р. можно упростить как:

func sumFloats(y: UnsafeMutablePointer<Float>, x: UnsafePointer<Float>, yc: Int, a: Float) {
    let theA = simd_float4(a, a, a, a)
    x.withMemoryRebound(to: simd_float4.self, capacity: yc / 4) { theX in
        y.withMemoryRebound(to: simd_float4.self, capacity: yc / 4) { theY in
            for t in 0..<yc/4 {
                theY[t] += theA * theX[t]
            }
        }
    }
}

, и его все равно можно вызывать так же, как аргументы [Float].

0 голосов
/ 21 декабря 2018

withUnsafe(Mutable)BufferPointer() можно использовать для получения указателя на (изменяемое) хранилище массива, а withMemoryRebound() для доступа к массиву Float в виде массива float4:

func sumFloats(y: inout [Float], x: [Float], yc: Int, a: Float) {
    let theA = simd_float4(a, a, a, a)
    x.withUnsafeBufferPointer {
        $0.baseAddress!.withMemoryRebound(to: simd_float4.self, capacity: yc / 4) { theX in
            y.withUnsafeMutableBufferPointer {
                $0.baseAddress!.withMemoryRebound(to: simd_float4.self, capacity: yc / 4) { theY in
                    for t in 0..<yc/4 {
                        theY[t] = theA * theX[t]
                    }
                }
            }
        }
    }
}

Пример:

let x: [Float] = [1, 2, 3, 4, 5, 6, 7, 8]
var y: [Float] = [0, 0, 0, 0, 0, 0, 0, 0]

sumFloats(y: &y, x: x, yc: 8, a: 2.0)
print(y) // [2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0]
...