This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Wrapping simple Eigen functions to be called from C

Tags: None
(comma "," separated)
TDR
Registered Member
Posts
1
Karma
0
Dear Eigen2 folks,

Firstly, let me say that Eigen2 fills a tremendous niche and the developer team deserves our thanks.

In fact, I am ready to jump into C++ and template from a stictly C world. Which leads me to my question. I would like to quickly get started using Eigen within C, as I begin to learn about C++/templates/expression templates etc. I just ordered a bunch of books and have started reading all I can find. I have read through all the Eigen documentation as well. It would really help me if somebody has a concrete example of wrapping a function written in C++ using Eigen in C and calling it from C. I have found answers to all the little questions in various FAQs, but seeing a complete concrete example still helps.

I just need a limited subset of BLAS/LAPACK like functions for dynamic double matrices/vectors.

(a) Create an Eigen dynamic matrix/vector MatrixXd/VectorXd object and Map my own double data array created in C.

(b) A simple matrix expression wrapped as a function (DGEMM): C <- a*op(A)*op(B) + b*C.
I am not sure if to make it efficient when called from C I need multiple specialized functions for each possible invocation:
C = a*A*B + b*C;
C = a*A.Transpose()*B + b*C;
C = a*A*B.Transpose() + b*C;
etc...

(c) I am not sure if I complie C++/Eigen and C code simultaneously that my C library/application will get the full benefit of complie time optimizations that Eigen2 uses.


My eventual goal is to develop everything using Eigen, but I have to start somewhere. Seeing a concrete demonstration will get me started.

Thanking

~Russ
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Hi,

Thanks for the kind words. I was curious to see how that could work anyway, so I gave it a try. Find attached to this post an archive, mix_eigen_with_c.tar.gz.

To try it out, with GCC:
Code: Select all
tar xfzv mix_eigen_with_c.tar.gz
cd mix_eigen_with_c
g++ -c binary_library.cpp -O2 -msse2 -I ~/eigen2
gcc example.c binary_library.o -o example -lstdc++
./example

As you can see, it still requires linking the C program against libstdc++, that's definitely ugly, but fixable, it's just that I'm a noob with these things. Of course it's the binary_library that should be linked against libstdc++. I guess the first step is to make it an actual library instead of just an object file.

(a) Create an Eigen dynamic matrix/vector MatrixXd/VectorXd object and Map my own double data array created in C.


Yep, find this in the code.

(b) A simple matrix expression wrapped as a function (DGEMM)

I didn't add a exactly dgemm but I did matrix multiply and a matrix add functions. I guess you'll be able to generalize that.

(c) I am not sure if I compile C++/Eigen and C code simultaneously that my C library/application will get the full benefit of complie time optimizations that Eigen2 uses.

Inside of each of the functions of the binary library, Eigen can do all its compile time optimizations. So your best interest is to implement large enough functions in this library, instead of implementing just elementary operations. But actually this is standard practice and the DGEMM that you mention does just that: instead of being just a matrix product, it does a little more to offer more optimization opportunities.

FYI, we have the project of implementing a BLAS on top of Eigen, this is a start...


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Ah, now that I think about it, there is one more limitation to the performance of such a C binding library: all objects are created on the heap. This is negligible for a large enough matrix, but not for a lightweight object such as Map_MatrixXd which is just a light wrapper around an existing array. This also wouldn't be good if you wanted tiny matrices.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Hm, thinking about it more, this really shows that it would be much better to have the structs like C_MatrixXd have the same sizeof() and alignment attributes as the Eigen types that they're representing, so that they can be created on the stack. This would allow good performance with tiny matrices (though one would still lose the benefit of expression templates).


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
bakerjonas
Registered Member
Posts
4
Karma
0
Hi!

First off, let me say that I really like Eigen, and I think it's a fantastic lib! It has really nice syntax, and all the flexibility (and more) that I need :) I'm using Eigen for a rather computation intense project, where I end up doing hundreds of thousands of small (approx. 100x100) matrix-matrix multiplies, and smallish (approx. 1000) vector-matrix multiplies. When compiling with '-g -O0' the code (obviously) becomes ridiculously slow, which is a drag during testing, debugging and development. Furthermore, on some systems I don't have access to a high quality optimizing compiler. Although the code is quite fast using g++ with -O3, it's still a far cry from what I can get from for example Intel's icpc with the -fast flag. My current solution is to Eigen for all vectors and matrices, but then use the MatrixXd.data() method to feed the raw data to optimized BLAS routines. Since Eigen is sometimes faster than BLAS with the Intel compiler, I have have plugged in some #ifdef USE_BLAS_BACKEND in certain critical places, so I can choose which backend I use. It would however be nice to have this built in to the library so that one could choose the backend with a toggle, maybe even runtime. Well, that was my 5 cents for now.

Best regards,
-jonas-
Code: Select all
________________________________________________________________________
Dr. Jonas Jusélius             
Centre for Theoretical and    E-mail    : jonas.juselius@uit.no
Comutational Chemistry        Telephone : +47 77644079
Department of Chemistry       Fax       : +47 77644765
University of Tromsø          Mobile ph.: +47 47419869
N-9037 Tromsø, NORWAY         http://jonas.iki.fi
_______________________________________________________________________
[ PGP key    : keyserver or http://jonas.iki.fi/pubkey.asc    ]
[ Fingerprint: 2516 A57A 3012 7962 287D  B66E C1A9 157F 0A59 7A66 ]
User avatar
bjacob
Registered Member
Posts
658
Karma
3
bakerjonas wrote:Hi!
First off, let me say that I really like Eigen, and I think it's a fantastic lib! It has really nice syntax, and all the flexibility (and more) that I need :)

Thanks!

I'm using Eigen for a rather computation intense project, where I end up doing hundreds of thousands of small (approx. 100x100) matrix-matrix multiplies, and smallish (approx. 1000) vector-matrix multiplies. When compiling with '-g -O0' the code (obviously) becomes ridiculously slow, which is a drag during testing, debugging and development.

Yes, we know :( There's light on the horizon however: GCC 4.4 allows per-function optimization flags, so we could try playing with adding such flags to relevant internal trivial functions. Feel free to play with this ;)

Furthermore, on some systems I don't have access to a high quality optimizing compiler. Although the code is quite fast using g++ with -O3, it's still a far cry from what I can get from for example Intel's icpc with the -fast flag.

I'd question that. In our experience, GCC has the best performance out there. But the GCC version is extremely important: use GCC >= 4.2, and ideally, use GCC 4.4. GCC 4.1 and older are very slow with Eigen.

Make sure that you pass -O2 -msse2. Play with -DNDEBUG and -mfpmath=sse. I don't know what icpc's -fast does, but try gcc's -ffast-math.

My current solution is to Eigen for all vectors and matrices, but then use the MatrixXd.data() method to feed the raw data to optimized BLAS routines. Since Eigen is sometimes faster than BLAS with the Intel compiler,


... and with recent GCC properly used...

I have have plugged in some #ifdef USE_BLAS_BACKEND in certain critical places, so I can choose which backend I use. It would however be nice to have this built in to the library so that one could choose the backend with a toggle, maybe even runtime. Well, that was my 5 cents for now.


Yes, this is already the top entry on our todo, http://eigen.tuxfamily.org/index.php?title=Todo


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
bakerjonas
Registered Member
Posts
4
Karma
0
Sweet! And thanks a thousand! Part of the problem is probably my old g++ on OSX...


Bookmarks



Who is online

Registered users: Bing [Bot], daret, Google [Bot], sandyvee, Sogou [Bot]