在Swift中使用Accelerate进行2D数组的向量乘法。

huangapple go评论61阅读模式
英文:

Vector multiplication on a 2D array using Accelerate in Swift

问题

Accelerate works with flattened arrays, but you can achieve the desired element-wise vector multiplication on a 2D array in Swift using Accelerate by properly reshaping your arrays before performing the multiplication. Here's how you can do it:

import Foundation
import Accelerate

let a: [Float] = [3, 5, 8, 7, 2,
                  1, 4, 9, 1, 3,
                  2, 7, 3, 1, 2,
                  5, 4, 9, 1, 6,
                  4, 2, 9, 6, 7]

let b: [Float] = [2, 0.5, 9, 1, 18]

let numRows = 5 // Number of rows in the 2D array
let numCols = 5 // Number of columns in the 2D array

var c: [Float] = Array(repeating: 0, count: numRows * numCols)

vDSP_mtrans(a, 1, &a, 1, vDSP_Length(numCols), vDSP_Length(numRows))
vDSP_mmul(a, 1, b, 1, &c, 1, vDSP_Length(numCols), 1, vDSP_Length(numRows))

vDSP_mtrans(&c, 1, &c, 1, vDSP_Length(numRows), vDSP_Length(numCols))

print(c)

This code will properly reshape the arrays, perform the element-wise multiplication, and give you the correct result in the c array.

英文:

I have the following NumPy example which does element-wise vector multiplication on a 2D array:

import numpy as np

a = np.array([[3, 5, 8, 7, 2],
              [1, 4, 9, 1, 3],
              [2, 7, 3, 1, 2],
              [5, 4, 9, 1, 6],
              [4, 2, 9, 6, 7]])

b = np.array([[2],
              [0.5],
              [9],
              [1],
              [18]])

c = a * b

print(c)

This prints the following:

[[  6.   10.   16.   14.    4. ]
 [  0.5   2.    4.5   0.5   1.5]
 [ 18.   63.   27.    9.   18. ]
 [  5.    4.    9.    1.    6. ]
 [ 72.   36.  162.  108.  126. ]]

I'm trying to do this calculation in Swift using Accelerate as shown below:

import Foundation
import Accelerate

let a: [Float] = [3, 5, 8, 7, 2,
                  1, 4, 9, 1, 3,
                  2, 7, 3, 1, 2,
                  5, 4, 9, 1, 6,
                  4, 2, 9, 6, 7]

let b: [Float] = [2,
                  0.5,
                  9,
                  1,
                  18]

var c: [Float] = Array(repeating: 0, count: 25)
vDSP_vmul(a, 1, b, 1, &c, 1, 25)

print(c)

The Swift code prints the following which is not correct:

[6.0, 2.5, 72.0, 7.0, 36.0, 0.0, 0.0, 0.0, 1.104904e-39, 4.7331654e-30, 3.7740115e-24, 6.737052e-37, 1.806498e-35, 1.19422e-39, 5.1722454e-26, 5.9787867e-25, 2.7286e-41, 0.0, 0.0, 0.0, 1.6543612e-24, 0.0, 0.0, 5.533857e-39, 3.73e-43]

Accelerate works with flatten arrays whereas NumPy supports 2D arrays. So I'm not sure how to multiply the 2D array with a vector in Accelerate. Is there a different Accelerate function that I should use for this type of multiplication?

答案1

得分: 1

要将这作为列进行相乘,您需要使用步幅(stride)。如果您正在使用 Accelerate,那么您可能也想避免额外的分配。您可以使用 Array(unsafeUninitializedCapacity:) 来填充所有数据,如下所示:

let c = Array(unsafeUninitializedCapacity: a.count) { output, initializedCount in
    a.withUnsafeBufferPointer { abuffer in
        for i in b.indices {
            vDSP_vmul(abuffer.baseAddress! + i, b.count, // 通过列大小逐步遍历 a
                      b, 1,                              // 逐个遍历 b
                      output.baseAddress! + i, b.count,  // 通过列大小逐步遍历输出
                      vDSP_Length(b.count))
        }
        initializedCount = abuffer.count
    }
}

// [6.0, 10.0, 16.0, 14.0, 4.0, 0.5, 2.0, 4.5, 0.5, 1.5, 18.0, 63.0, 27.0, 9.0, 18.0, 5.0, 4.0, 9.0, 1.0, 6.0, 72.0, 36.0, 162.0, 108.0, 126.0]
英文:

To multiply this as a column, you need to use a stride. If you're taking the trouble to use Accelerate, then you probably also want to avoid extra allocations. You can use Array(unsafeUninitializedCapacity:) to fill in all the data like this:

let c = Array(unsafeUninitializedCapacity: a.count) { output, initializedCount in
    a.withUnsafeBufferPointer { abuffer in
        for i in b.indices {
            vDSP_vmul(abuffer.baseAddress! + i, b.count, // stride through a by the column size
                      b, 1,                              // stride one-by-one through b
                      output.baseAddress! + i, b.count,  // stride through the output by the column size
                      vDSP_Length(b.count))
        }
        initializedCount = abuffer.count
    }
}

// [6.0, 10.0, 16.0, 14.0, 4.0, 0.5, 2.0, 4.5, 0.5, 1.5, 18.0, 63.0, 27.0, 9.0, 18.0, 5.0, 4.0, 9.0, 1.0, 6.0, 72.0, 36.0, 162.0, 108.0, 126.0]

huangapple
  • 本文由 发表于 2023年5月18日 05:23:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76276292.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定