【问题标题】:matrix multiplication in swift using Accelerate framework 32 bit vs 64 bit使用 Accelerate 框架 32 位与 64 位快速进行矩阵乘法
【发布时间】:2014-12-18 14:16:10
【问题描述】:

我正在尝试使用 Accelerate 框架在 Swift 中进行矩阵乘法。使用了 vDSP_mmulD。这在 iPhone6、6 plus、iPad Air 模拟器(全 64 位架构)中完美运行,但不适用于任何 32 位架构设备。 看起来 vDSP_mmulD 无法被 32 位架构识别并且程序无法构建。显示的错误消息是“使用未解析的标识符'vDSP_mmulD'”有其他人看到这个错误吗?请让我知道你的想法。我正在使用 Xcode 6.1。 谢谢。

【问题讨论】:

  • 没有使用过 Accelerate 框架,但是在 IMO 你应该重新考虑在 32 位上花费太多精力之前。 Apple 要求开发人员专注于 64 位。 developer.apple.com/news/?id=10202014a
  • @chunkyguy 他们鼓励 64 位构建以避免在 64 位设备上加载 32 位库。但是,32 位设备仍然存在,建议编写与各种架构兼容的代码。
  • 如果您复制/粘贴该错误消息,您的问题是您在 vSDP_mmulD 的开头转置了几个字母。
  • @NateCook。那是我的一个错字。在 64 位上它运行良好,但在 32 位设备上该程序将无法构建。

标签: ios swift 32bit-64bit accelerate-framework


【解决方案1】:

简单的解决方案:改用 cblas_dgemm(也是 Accelerate 的一部分)。它在所有系统上至少与vDSP_mmulD 一样快,并且在某些系统上要快得多(在iOS 8 和Yosemite 中,vDSP_mmulD 实际上只是cblas_dgemm 的一个包装器),它实际上应该在这里工作。

我怀疑您的 32 位模拟器构建失败;在 i386 上,vDSP_mmulD 实际上是一个围绕 mmulD 的宏,而 Swift 并不完全支持 C 语言宏。

注意:我怀疑您可能正在使用 3x3 或 4x4 矩阵,在这种情况下,任何 Accelerate 例程都不是您真正想要的(它们针对的是更大的矩阵);你想要像<simd/matrix.h> 中定义的那样的内联向量序列。不幸的是,Swift 不支持 SIMD 向量,所以这不是一个选项。此时最好的选择可能是简单地写出元素计算,并报告一个错误以请求 Swift 支持<simd/simd.h> 接口。

【讨论】:

  • 你听起来更像你知道你在说什么:)
  • 我乘以 1x9 , 9x1 矩阵。谢谢你的提示。我会试试 cblas_dgemm。
  • 尝试了简单的方法(元素计算)。该计划急剧放缓。我需要执行 1620 [1x9]x[9x1] 矩阵乘法来得到结果。我想这目前只能使用 cblas_dgemm 。我正在网上寻找,但没有找到很多帮助。我将继续努力使其发挥作用。现在,我使用 cblas_gemm 时遇到的错误是“无法使用扩充列表调用‘下标’......”请让我知道您对此的看法。谢谢。
  • 1x9x9x1 真的是一个点积。您可能会发现使用 cblas_ddot 更容易。
  • 为了提供更有效的解决方案,您是否将一个向量乘以 1620 个其他向量? 20 个向量中的每一个乘 81 个向量中的每一个?它们在内存中是如何排列的?
【解决方案2】:

所以这都是推测性的,因为我现在没有要测试的 32 位设备,而且我找不到任何文档来支持这一点,但 Accelerate 可能适用于不同的浮点类型两种不同的架构——Float 在 32 位架构上,Double 在 64 位架构上。 D 末尾的 vDSP_mmulD 代表 Double,因此您需要能够在代码中的 32 位架构上使用 Float 版本:vDSP_mmul

您可以使用#if...#else...#endif 预处理块来切换您正在使用的方法(bottom of this page 中的信息)。绕过 Swift 严格的静态类型的一个技巧是在文件顶部放置类似这样的预处理块:

#if arch(x86_64) || arch(arm64)
    typealias M_Float = Double
    let M_vDSP_mmul = vDSP_mmulD
    // add Double versions of other Accelerate functions you need
#else
    typealias M_Float = Float
    let M_vDSP_mmul = vDSP_mmul
    // add Float versions of other Accelerate functions you need
#endif

然后,您不必选择是使用 Float 还是 Double,或者在整个代码中使用哪种方法,您可以只使用 M_Float 和您的 M_... 版本的 Accelerate 函数:

var number: M_Float = 0    // Double on 64-bit, Float on 32-bit
M_vDSP_mmul(...)           // correct version either way

希望有帮助!

【讨论】:

    【解决方案3】:

    我很快就找到了这个collections library。它使用 Accelerate 提供了一个带有乘法运算符的矩阵结构。为我工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-25
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      相关资源
      最近更新 更多