Note that there are some explanatory texts on larger screens.

plurals
  1. POwhat should I expect when I use Eigen dense matrix data structure?
    primarykey
    data
    text
    <p>I need to use matrix data structure in my program, while C++ has 2d arrays, it's very low level, while some libraries like Eigen provide a higher level of matrix data structure. But in my opinion, no matter how good a library performs in some high-skilled operations such as svd, the fast speed on basic operations, including read(access), write, sum, dot, should be a pre-requirement of such libraries. Because in real applications, such basic operations may be much more frequent than those high-skilled ones, if a library is slow on such operations, it may turn out to be a burden or even bottleneck of the system.</p> <p>So I write some very simple programs using both 2d array and Eigen3 dense matrix (MatrixXd), and compare their performances on 4 basic operations, it turns out that most of the time, 2d array wins Eigen3, which is quite disappointing. I list some of my test result below (the code is in the end appendix):</p> <blockquote> <p><strong>10000X10000 matrix, compile command: g++ -o test.o test.cpp -O0 -msse2</strong></p> <p>Eigen:</p> <p>[!COST] init: 6.8 sec.</p> <p>[!COST] read: 14.85 sec.</p> <p>[!COST] write: 23.02 sec.</p> <p>[!COST] sum: 3.28 sec.</p> <p>[!COST] dot: 3.12 sec.</p> <p>CPP:</p> <p>[!COST] init: 1.81 sec.</p> <p>[!COST] read: 2.4 sec.</p> <p>[!COST] write: 3.4 sec.</p> <p>[!COST] sum: 0.63 sec.</p> <p>[!COST] dot: 0.52 sec.</p> <p><strong>10000X10000 matrix, compile command: g++ -o test.o test.cpp -O3 -msse2</strong></p> <p>Eigen:</p> <p>[!COST] init: 2.44 sec.</p> <p>[!COST] read: 2.16 sec.</p> <p>[!COST] write: 2.18 sec.</p> <p>[!COST] sum: 0.26 sec.</p> <p>[!COST] dot: 0.26 sec.</p> <p>CPP:</p> <p>[!COST] init: 1.71 sec.</p> <p>[!COST] read: 2.06 sec.</p> <p>[!COST] write: 2.24 sec.</p> <p>[!COST] sum: 0.15 sec.</p> <p>[!COST] dot: 0.06 sec.</p> </blockquote> <p>However, I still have some doubts about this, maybe I should not expect higher level abstraction of matrix structure should work as fast as its raw version, if so, what should I expect using library such as Eigen? Please note that in my program, there are some high-skilled operations as SVD, while there are more basic operations such as access the matrix and write the matrix.</p> <p><strong>Appendix</strong>, test.cpp:</p> <pre><code>#include &lt;iostream&gt; #include &lt;Eigen/Dense&gt; #include &lt;ctime&gt; using Eigen::MatrixXf; inline int cpp_testor_read(float **m, const int M, const int N) { float randomTmp = 0; for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { randomTmp += m[i][j]; randomTmp -= m[j][i]; } return randomTmp; } inline int eigen_testor_read(MatrixXf m, const int M, const int N) { float randomTmp = 0; for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { randomTmp += m(i, j); randomTmp -= m(j, i); } return randomTmp; } inline int cpp_testor_write(float **m, const int M, const int N) { for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { m[i][j] += m[j][i]; m[j][i] -= m[i][j]; } return m[rand()%10000][rand()%10000]; } inline int eigen_testor_write(MatrixXf m, const int M, const int N) { for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { m(i, j) += m(j, i); m(j, i) -= m(i, j); } return m(rand()%10000, rand()%10000); } inline int cpp_testor_sum(float **m, const int M, const int N, float val) { for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { m[i][i] += m[i][j]; } return m[rand()%1000][rand()%1000]; } inline int eigen_testor_sum(MatrixXf m, const int M, const int N, float val) { m += m; return m(0, 0); } inline int cpp_testor_dot(float **m, const int M, const int N, float val) { float randomTmp = 0; for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) { m[i][j] *= val; } return m[rand()%1000][rand()%1000]; } inline int eigen_testor_dot(MatrixXf m, const int M, const int N, float val) { m *= val; return m(0, 0); } float** cpp_generator_mtarix(const int M, const int N) { float **m = new float*[M]; for (int i = 0; i &lt; M; i ++) m[i] = new float[N]; return m; } MatrixXf&amp; eigen_generator_matrix(const int M, const int N) { static MatrixXf m(M,N); return m; } int main() { const int M = 10000; const int N = M; int antiopt = 0; srand(time(NULL)); float val1 = rand()%10000 + 1; float val2 = rand()%10000 + 1; std::cout&lt;&lt; M &lt;&lt; " " &lt;&lt; N &lt;&lt; std::endl; std::cout&lt;&lt;"Eigen:" &lt;&lt; std::endl; size_t t = clock(); //MatrixXf m = eigen_generator_matrix(M, N); MatrixXf m(M,N); for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) m(i,j) = rand()%1000 + 1; t = clock() - t; std::cout&lt;&lt; "[!COST] init: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += eigen_testor_read(m,M,N); t = clock() - t; std::cout&lt;&lt; "[!COST] read: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += eigen_testor_write(m,M,N); t = clock() - t; std::cout&lt;&lt; "[!COST] write: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += eigen_testor_sum(m,M,N, val1); t = clock() - t; std::cout&lt;&lt; "[!COST] sum: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += eigen_testor_dot(m,M,N, val2); t = clock() - t; std::cout&lt;&lt; "[!COST] dot: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; std::cout&lt;&lt;"CPP:" &lt;&lt; std::endl; t = clock(); //float **mm = cpp_generator_mtarix(M, N); float **mm = new float*[M]; for (int i = 0; i &lt; M; i ++) mm[i] = new float[N]; for (int i = 0; i &lt; M; i ++) for (int j = 0; j &lt; N; j ++) mm[i][j] = rand()%1000 + 1; t = clock() - t; std::cout&lt;&lt; "[!COST] init: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += cpp_testor_read(mm,M,N); t = clock() - t; std::cout&lt;&lt; "[!COST] read: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += cpp_testor_write(mm,M,N); t = clock() - t; std::cout&lt;&lt; "[!COST] write: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += cpp_testor_sum(mm,M,N, val1); t = clock() - t; std::cout&lt;&lt; "[!COST] sum: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; t = clock(); antiopt += cpp_testor_dot(mm,M,N, val2); t = clock() - t; std::cout&lt;&lt; "[!COST] dot: " &lt;&lt; t/float(CLOCKS_PER_SEC) &lt;&lt; " sec." &lt;&lt;std::endl; std::cout&lt;&lt;antiopt&lt;&lt;std::endl; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload