2016-12-01 12 views
1

Я использую следующий код для проверки собственной производительности.Умножение матрицы на матрицу медленнее, чем cblas?

#include <iostream> 
#include <chrono> 
#define EIGEN_NO_DEBUG 
#include <eigen3/Eigen/Dense> 
#include <cblas.h> 
using namespace std; 
using namespace std::chrono; 

int main() 
{ 
    int n = 3000; 

    high_resolution_clock::time_point t1, t2; 

    Eigen::MatrixXd A(n, n), B(n, n), C(n, n); 

    t1 = high_resolution_clock::now(); 
    C = A * B; 
    t2 = high_resolution_clock::now(); 
    auto dur = duration_cast<milliseconds>(t2 - t1); 
    cout << "eigen: " << dur.count() << endl; 

    t1 = high_resolution_clock::now(); 
    cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 
       n, n, n, 1.0, A.data(), n, B.data(), n, 1.0, C.data(), n); 
    t2 = high_resolution_clock::now(); 
    dur = duration_cast<milliseconds>(t2 - t1); 
    cout << "cblas: " << dur.count() << endl; 

    return 0; 
} 

я скомпилировать его с помощью следующей команды:

g++ test.cpp -O3 -fopenmp -lblas -std=c++11 -o test 

Результаты:

собственные: 1422 мс

cblas: 432 мс

я делаю что-то неправильно? Согласно их эталону, он должен быть быстрее.

Другая проблема заключается в том, что с помощью NumPy я получаю 24 мс

import time 
import numpy as np 

a = np.random.random((3000, 3000)) 
b = np.random.random((3000, 3000)) 
start = time.time() 
c = a * b 
print("time: ", time.time() - start) 
+0

Какую версию Eigen и g ++ вы используете? –

+2

С массивами numpy, '*' is * element-wise * умножение. Измените 'c = a * b' на' c = a.dot (b) '. Или, если вы используете достаточно новую версию Python 3 и numpy, вы можете написать 'c = a @ b'. –

+0

Avi Ginsburg, Eigen version 3.2, g ++ version 4.9.2, проблема заключалась в использовании Eigen 3.2 –

ответ

1

Сказать, что вы используете cblas дают очень мало информации, потому что cblas это просто API. В основе BLAS-библиотеки могут быть BLAS, OpenBLAS, ATLAS, Intel MKL, Apple, Accelerate или даже EigenBlas. Учитывая ваши измерения, довольно очевидно, что ваш базовый BLAS является высоко оптимизированным, использующим многопоточность AVX + FMA + , Поэтому для справедливого сравнения вы также должны включить эту функцию на стороне Eigen, скомпилировав ее с помощью -march=native -fopenmp и убедитесь, что вы используете Eigen 3.3. Тогда производительность должна быть примерно одинаковой.

Что касается numpy, Уоррен Уокессер уже решил проблему. Вы могли бы понять, что 24ms для выполнения операций с плавающей запятой 2*3000^3=54e9 на стандартном компьютере невозможно.

+0

спасибо, проблема заключалась в использовании Eigen 3.2. Я переключился на Eigen 3.3, теперь это 500 против 350. Я не знаю, какую библиотеку blas я использовал, я установил пакет libblas3 и libblas-dev. Вот что говорит apt-cache search: libblas3 - реализация базовых линейных алгебр-ссылок, общая библиотека, libblas-dev - базовые подпрограммы линейной алгебры 3, статическая библиотека –

+0

С Eigen 3.2 компиляция с -march = native ничего не меняла, но если i компилировать без этой опции, используя Eigen 3.3, она работает намного медленнее –