2016-07-14 79 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-循環性能與相同艾根。