2016-07-14 80 views
2

考虑一个矩阵尺寸48x16的浮子的和浮子b尺寸1X48型的的向量。快速单精度矩阵乘以向量积

请建议计算b×尽可能快地对常见的桌面处理器(的i5/I7)的一种方式。

背景。 上述产品处于紧密环路中,因此其快速计算至关重要。目前,我有以下天真的算法工作:

inline void Critical(const float A[48][16], const float b[48], float x[16]) const { 
    for (int u = 0; u < 48; ++u) { 
     for (int i = 0; i < 16; ++i) { 
      x[i] += A[u][i] * b[u]; 
     } 
    } 
} 

我试图卸载乘法MKL的SGEMV后来到SGEMM但无济于事。在i7 4800MQ上,天真的实现仍然可以更快地工作。

EDIT1

具有静态分配的特征与原始算法近似一样快。

我已经尝试GCC5,ICC和VC2015U3优化打开(/ O3,快速数学,mtune =本地等)。 ICC似乎在Linux和Windows上生成最快的代码。

EDIT2

的元素是小的,MAX(| _ui |)= 256同样MAX(| b _U |)= 1.0。只要算法比天真的算法更快,合理的近似解决方案也是可以接受的。

+0

您可以查看我的[_Matrix_](https://github.com/ForceBru/Matrix)库,了解如何使用矩阵进行操作。 – ForceBru

+0

@ForceBru我只看非GPU解决方案。 – tovugike

+0

@Angew MKL是由英特尔提供的一项优化的BLAS实施。 – tovugike

回答

2

MKL通常有很大的开销,因此小矩阵的性能很差。另一方面,Eigen具有在小矩阵上表现良好的固定尺寸矩阵优化。您还需要正确的编译选项才能获得Eigen的最高性能。

#include <iostream> 
#include <Eigen/Eigen> 
#include <omp.h> 

inline void Critical(const float A[48][16], const float b[48], float x[16]) { 
    for (int i = 0; i < 16; ++i) { 
    x[i] = 0; 
    } 
    for (int u = 0; u < 48; ++u) { 
    for (int i = 0; i < 16; ++i) { 
     x[i] += A[u][i] * b[u]; 
    } 
    } 
} 

int main() { 
    float a[48][16] = { 0 }; 
    float b[48] = { 0 }; 
    float x[16] = { 0 }; 
    Eigen::Matrix<float, 48, 16> ma; 
    Eigen::Matrix<float, 1, 48> mb; 
    Eigen::Matrix<float, 1, 16> mx; 

    ma.setRandom(); 
    mb.setRandom(); 
    for (int i = 0; i < 48; ++i) { 
    for (int j = 0; j < 16; ++j) { 
     a[i][j] = ma(i, j); 
    } 
    b[i] = mb(i); 
    } 

    double t; 
    int n = 10000000; 

    t = omp_get_wtime(); 
    for (int i = 0; i < n; ++i) { 
    Critical(a, b, x); 
    } 
    t = omp_get_wtime() - t; 
    std::cout << "for-loop time: " << t << std::endl; 

    t = omp_get_wtime(); 
    for (int i = 0; i < n; ++i) { 
    mx = mb * ma; 
    } 
    t = omp_get_wtime() - t; 
    std::cout << "eigen time: " << t << std::endl; 

    Eigen::Map < Eigen::Matrix<float, 1, 16> > native_x(x); 
    std::cout << "error: " << (mx - native_x).norm() << std::endl; 

    return 0; 
} 

当与克++ 5.2.1

$ g++ -fopenmp -O3 -DNDEBUG -I~/program/include/eigen3 -o test/gemv test/gemv.cpp && test/gemv 
for-loop time: 2.53004 
eigen time: 1.17458 
error: 1.49636e-06 

当与ICPC 16.0.2

$ icpc -fopenmp -fast -DNDEBUG -I~/program/include/eigen3 -o test/gemv test/gemv.cpp && test/gemv 
for-loop time: 1.03432 
eigen time: 1.01054 
error: 1.40769e-06 

ICPC编译上使用自动矢量编译从而FOP-循环性能与相同艾根。