Developer's Corner

Communication between developers

Most discussion happens on Discord or on specific GitLab issues.

Contributors crediting and copyright

Everyone who made even the smallest contibution should add himself/herself to the Credits.

Everyone keeps copyright on his contributions. There is no copyright assignment.

When making a contribution on behalf of your employer, please try making it in your own name, not in your employer’s name, if possible.

When you make large improvements to a source file, it is a good idea to add yourself a copyright line in it, although this is by no means necessary: you do implictly get copyright on the code you wrote.

Every commit should be made using the author’s identity. We explain on the Git page how to generate patches in such a way that you get credited when we import them.

Copying Permissively-Licensed Code into an MPL 2 File: Guidelines for Developers.

Code Quality

Using CMake

We have a little CMake tutorial here.

Unit tests and dashboard

Everything about unit tests and the dashboard, is on the Tests page.

Eigen hacking

Coding rules

We are not very strict about coding rules, however the trends are:

  • indentation with 2 spaces (no tabs !)
  • the best is to show a typical example of a public class:

 template<typename MatrixType  class NameOfTheClass  {      typedef typename MatrixType::Scalar Scalar;    public:      // public functions start with lower case:      Scalar nameOfTheFunction(int i) const;      // public static functions start with upper case:      static NameOfTheClass* Create(const MatrixType& mat);    protected:      // member attributes start with m_:      Scalar m_attributeName;      MatrixType m_matrix;  };    template typename MatrixType::Scalar  NameOfTheClass::nameOfTheFunction(int i) const  {    Scalar res = 0;    if(i>0)    {      for(int j=0; i<m_matrix.cols(); ++j,++i)        res = ei_hypot(res, m_matrix.coeff(i,j));    }    else    {      j = 0;      while (i<m_matrix.rows())      {        res = ei_hypot(res, m_matrix.coeff(i,j));        ++i;        ++j;      }    }    return res;  }

  • global functions and class/struct reserved for internal use start with ei_, eg:

 struct ei_assign_selector;

  • favor explicit names rather than short ones

Developer Documentation

Notes explaining aspects of the architecture of Eigen 3.x are available at the Eigen3 Developer Documentation page

Git workflow

Please read this page to learn more about our Git workflow.

Make a new release

These days it’s very easy, as the docs are automatically generated and uploaded, and the tarballs are auto-generated by GitLab.

So here’s what it takes to make a new release (a new minor version):

  • Announce a week in advance on Discord the upcoming release (give a precise date) so that people can test and/or speak up if they know of an issue. Of course, in case of an emergency, no need to do that :)
  • Concert with other devs, and/or test yourself, to make sure that the test suite passes at the very least for:
    • latest stable GCC
    • some older GCC (ok, it’s hard to check them all), try to cover the oldest GCC we’re supposed to support (see main page)
    • latest MSVC
    • latest Clang
  • Also do think to check “make install”! Remember how it spoiled the 2.0.7 release!
    • Supreme refinement would be to check building the test suite against the installed Eigen.
  • Update the version number (EIGEN_MINOR_VERSION, etc) in the file Eigen/Version.
  • commit that:

git add Eigen/Version git commit

  • Make a tag:

git tag TAGNAME

  • recommended: check that everything is in order.

git show

  • push the release:

git push --tags REMOTENAME BRANCHNAME

e.g. to release a 3.3.X version

git push --tags origin 3.3

  • For a major version, write and keep up-to-date CHANGELOG.md file.
  • For a minor version: make the full changelog. It’s not just a dump of the commit messages: it must be readable and interesting for Eigen users. You can use “git log” again, try to put the grafted/cherry-picked bug fixes first, try to group together what’s related. You can also use git and sed to generate an initial raw dump of the changesets:

 git --no-pager log --pretty=format:"* [https://gitlab.com/libeigen/eigen/-/commit/%H Commit %h]: %s" HEAD...PREVIOUSTAGNAME \    | sed 's/$[Bb]ug$ #$[0-9]*$/Issue #\2/g'

to get the tag of the previous release you can check

# Get all tags git tag # Filter for tags git tag --list 'PATTERN'

  • Update the Main Page, that is the announcement at the top and the Download section. Make sure that the tarball links point to the new release, and that any example of how to get the latest tag also refers to the new tag.
    • To add a news, simply create a new page in the “news” section.
  • Add the release notes into the ChangeLog.
  • Write an announcement on [Discord][/#discord].

Debugging tips

Debugging under Visual Studio

![“Examplary view of the enhanced debugger output.”](Eigen_debug.jpg ““Examplary view of the enhanced debugger output.””) The Visual Studio IDE supports specialized debug visualizers for custom C/C++ types.

Eigen debug visualizers for Visual Studio 2012 and newer can be downloaded from eigen.natvis. The file is typically copied to %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers, where %VSINSTALLDIR% is the Visual Studio installation folder. More info can be found in Create Custom Views of Native Objects on MSDN.

For Visual Studio 2010 and older debug visualizers are defined in %VSINSTALLDIR%\..\Packages\Debugger\autoexp.dat. Adding the data found in this file right after the [Visualizer] section activates new visualization rules for some Eigen types.

Studying assembly output

Using GCC

We have a macro EIGEN_ASM_COMMENT (currently defined only on GCC! please port it, it is in Macros.h):

You can use assembly comments to make it much easier to find the asm code corresponding to a particular portion of your code:

EIGEN_ASM_COMMENT("begin");
Vector4f u = v + 3*w;
EIGEN_ASM_COMMENT("end");

Then tell your compiler to output assembly code, for example with GCC it is the -S option, so you’d do:

 g++ myprogram.cpp -O2 -S -o myprogram.s

Very important: GCC doesn’t seem to optimize correctly code inside the main() function. So make sure to put your critical code in another, non-inlined, function. You can use EIGEN_DONT_INLINE to prevent inlining of a function. But actually, the easiest might be to put your code in a function foo() taking references to the Eigen objects as arguments and not putting any main() function, and then compiling with “g++ -c”. So your code could look like:

#include<Eigen/Core>
using namespace Eigen;
void foo(Vector4f& u, Vector4f& v, Vector4f& w)
{
  EIGEN_ASM_COMMENT("begin");
  u = v + 3*w;
  EIGEN_ASM_COMMENT("end");
}

And you then compile it with:

 g++ myprogram.cpp -O2 -c -S -o myprogram.s

The resulting asm code is now very easy to find, just search for “begin”:

 #APP  # 5 "x.cpp" 1    #begin  # 0 "" 2  #NO_APP    movss   .LC2(%rip), %xmm0    shufps  $0, %xmm0, %xmm0    mulps   (%rdx), %xmm0    addps   (%rsi), %xmm0    movaps  %xmm0, (%rdi)  #APP  # 7 "x.cpp" 1    #end  # 0 "" 2  #NO_APP

Using Visual Studio

In a first step you need to compile your program with the correct compiler and linker switches as given below:

 * C/C++ -> General -> Debug Information Format -> Program Database /Zi  * C/C++ -> General -> Optimization -> Optimization -> Maximize Speed /O2  * C/C++ -> General -> Code Generation -> Basic Runtime Checks -> Default  * C/C++ -> General -> Code Generation -> Enable Enhanced Instruction Set -> Streaming SIMD Extensions 2 /arch:SSE2  * Linker -> Debugging -> Generate Debug Info -> Yes /DEBUG

Optional settings are:

 * C/C++ -> Output Files -> Assembler Output -> Assembly With Source Code /FAs  * Linker -> Advanced -> Randomized Base Address -> Disable Image Randomization /DYNAMICBASE:NO  * Linker -> Advanced -> Fixed Base Address -> Generate a relocation section /FIXED:NO

The second last entry (Radmonized Base Address) is useful when you actually need to debug assembly code since it guarantees that each time you start your program it will occupy the same address space. The very last option (Fixed Base Address) is essential when you are working with Intel’s VTune for performance profiling.

The remaining part is to correctly setup your test-bed in order to prevent the rather intelligent compiler from converting your code into NOP’s when it reallized the code is unused. One way is to return the result of your computations - you won’t see the assembly of the assignment since we are explicitly preventing inlining of the code via the macro EIGEN_DONT_INLINE. Using this macro is actually one of the more important aspects in order to encapsulate the code you are interested in, since we are lacking GCC’s comment capabilities. A sample test-bed could look as follows:

 template   struct VectorAddition  {    typedef VectorType ReturnType;    EIGEN_DONT_INLINE static VectorType run(int)    {      VectorType a,b,c,d;      return a+b+c+d;    }  };  int main()  {    Vector4f res = VectorAddition::run();  }

Now, when you have correctly configured your project, you should be able to place a break point within the run method. When running your program by hitting F5 (Start Debugging) you should end up at your breakpoint in the run method. The final step is to hit ALT-8 and you’re welcome in the wonderful world of assembly code.

Profiling tips

Using timers

In the file bench/BenchTimer.h we have a little timer that can be used for that.

Documentation tips

We use Doxygen, see the commands. See existing source code for example usage. Here are some best practices:

  • Make generous use of “see also” tags: \sa
  • Always use tags for parameters and return values (e.g. \param and \returns), that makes things easier to find in a glance.
  • If possible, add a code snippet. All you have is to add it in doc/snippets (see existing files there). CMake will complete your snippet into working form, compile it, run it, and record its output into a .out file. Then in your doxygen comment, just put:

 \include mysnippet.cpp  Output: \verbinclude mysnippet.out

  • Alternatively, if you want to add a full self-compilable example (so you dont want CMake to add stuff to make it compilable), put your example file in doc/examples.

Resources

Linear algebra

Matrix products

CPU level optimizations

Meetings

On separate Meetings page.