iOS BLAS - 加速框架差矩阵乘法性能

时间:2013-04-02 20:29:27

标签: iphone matrix simd lapack blas

我正在为iPhone实现基于切线距离的OCR解决方案,该解决方案严重依赖于253x7大小的浮点矩阵的快速乘法。为了证明概念,我实现了我自己的天真矩阵例程:

Matrix operator*(const Matrix& matrix) const {
    if(cols != matrix.rows) throw "cant multiply!";

    Matrix result(rows, matrix.cols);
    for(int i = 0; i < result.rows; i++){
        for(int j = 0; j < result.cols; j++){
            T tmp = 0;
            for(int k = 0; k < cols; k++){
                tmp += at(i,k) * matrix.at(k,j);
            }
            result.at(i,j) = tmp;
        }
    }

    return result;
}

如你所见,这是非常基本的。 在PoC表现良好之后,我决定通过合并Accelerate Framework的矩阵乘法(可能使用SIMD和其他奇特的东西来完成繁重的工作......)来进一步提高性能极限:

Matrix operator*(const Matrix& m) const {
    if(cols != m.rows) throw "cant multiply!";

    Matrix result(rows,m.cols);

    cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, rows, m.cols, cols, 1, matrix, cols, m.matrix, m.cols, 1, result.matrix, result.cols);

    return result;
}

令人震惊(至少对我来说),上面的代码花了两倍的时间来乘以矩阵!我尝试使用单精度而不是双精度,因为我怀疑它是与CPU的字大小相关的东西(32位浮点数与32位ARM上的64位双精度),但没有性能提升......

我做错了什么?我的253x7矩阵是否太小而不能显着提升性能?

2 个答案:

答案 0 :(得分:1)

几个问题:

  1. 253 x 7乘以什么尺寸的矩阵?如果你正在做253x7 * 7x1,那么一个通用的乘法例程将花费大部分时间用于修改代码,并且调优的库可以做到这一点很少会使它比一个简单的实现更快

  2. 您正在使用什么硬件,iOS版本是什么?特别是对于双精度,较旧的硬件和较旧的iOS版本在性能方面更受限制。例如,在Cortex-A8上,双精度算术完全没有流水线,所以几乎没有任何一个库可以做任何事情来打败天真的实现。

  3. 如果其他矩阵不是非常小,并且硬件是最近的,请提交一个错误(意外的低性能绝对一个错误)。具有高纵横比的小矩阵很难在通用矩阵乘法中快速生成,但它仍然是一个很好的bug。

    如果硬件/ iOS版本已经过时,您可能仍然希望使用Accelerate,因为它应该在较新的硬件/软件上表现得更好。

    如果另一个矩阵很小,那么可能没什么可做的。 ARM上没有双精度SIMD,矩阵太小而无法从缓存阻塞中受益,并且矩阵的尺寸也太小而无法从循环展开中获益。


    如果您知道先验您的矩阵将完全是253x7 * 7x ???,那么通过完全展开,您应该能够比天真的实现和任何通用库做得更好矩阵乘法的内维。

答案 1 :(得分:0)

基本上,是的。 “x7”部分可能太小,不足以使CBLAS的开销值得。进行函数调用的成本加上CBLAS函数为您提供的所有灵活性需要一段时间才能进行备份。每当您传递CblasNoTrans之类的选项时,请记住其中有if()来管理该选项。 cblas_dgemm特别累积到C中,因此它必须读取前一个结果元素,应用乘法,然后在存储之前添加。这是一项额外的工作。

您可能想要尝试vDSP功能而不是CBLAS。 vDSP_mmul稍微简单一些,不会累积到结果中。我在vDSP_*小数据集(几千个元素)上运气不错。

也就是说,我对此的体验是天真的C实现在小数据集上通常非常快。避免函数调用是一个巨大的好处。说到这一点,请确保内联at()来电。否则你在循环中浪费了很多时间。您可以通过使用指针添加来串行移动矩阵而不是乘法(通过[]随机访问所需)来加速C实现。在矩阵这个小的,它可能或不值得;你需要描述一下。查看汇编器输出非常有启发性。

请记住,您绝对必须在设备上对此内容进行分析。模拟器中的性能无关紧要。这不仅仅是模拟器更快;它完全不同。在模拟器上速度快得多的东西在设备上会慢得多。