Skip to content

spectrum: Introduce optional support for the Eigen linear algebra library

Matteo Pagin requested to merge gsoc-2022-eigen into gsoc-2022-simpl-mimo-ch

This commit introduces support for the open-source linear algebra Eigen, with the goal of bringing performance improvements to the 3GPP TR 38.901 framework which is currently available in the ns-3 mainline. Moreover, the installation of Eigen is set as optional, and the code runs as usual whenever the library is not installed in the system.

The library has been integrated in ns-3 by mimicking the support for other third-party libraries such as SQLite. In particular, the Eigen library is set as an optional dependency in the build-support/macros-and-definitions.cmake file and its presence in the system is shown to the user by exposing whether it has been found or not int the build-support/custom-modules/ns3-configtable.cmake file (see image below). The linking of the Eigen's sources with the ns3 source files is taken care of using the FindEigen3.cmake file provided by the library itself, as suggested in the related ns-3 guide.

Screenshot_from_2022-08-02_15-49-17

The main design goal has been minimizing the portion of the code which varies based on Eigen’s availability in the system (dictated by the value of the CMake-defined HAVE_EIGEN3 flag). Since most of the needed operators can not be overloaded for STL C++ vectors (for instance, ()), a uniform interface for both Eigen and STL’s based vectors and matrices has been implemented by defining ad-hoc structs with custom operators. In particular, this interface has been implemented for the PhasedArrayModel::ComplexVector and the MatrixBasedChannelModel::Complex2DVector data structures, since they are involved in computationally intensive linear algebra operations.

The interface has been designed with Eigen's API in mind, striving to provide the same API also for STL C++ data-structures, whenever Eigen's is not installed in the system. Specifically, yhe main differences are:

  • size () does not exist for Eigen’s matrices. Instead, the methods rows () and cols () are to be used to get the respective sizes of a matrix. On the other hand, Eigen’s vectors provide the size () method, thus they are aligned with STL’s vectors in this regard.
  • resize () takes as inputs both the numbers of rows and columns in the case of Eigen’s matrices. On the other hand, Eigen’s vectors provide a single-argument resize () method, thus they are aligned with STL’s vectors in this regard.
  • the elements of Eigen’s matrices are to be accessed using the () operator, taking as input the row and column indexes of the specific element to be accessed. This is in contrast to the [] operator provided by STL vectors. On the other hand, Eigen’s vectors provide a single-argument [] operator, thus they are aligned with STL’s vectors in this regard.

Moreover, this MR includes also the optimizations to the channel matrix generation procedure for the three-gpp-channel-model originally presented in MR !897.

To measure the improvements brought by these changes, I setup a benchmark script which is based on cttc-nr-demo and varied the main simulation parameters which have an impact on the simulation runtime, i.e., the update period of the 3GPP channel (how often new channels and related long terms are generated), the number of antenna elements at the gNB and the number of gNBs and UEs in the simulation. The figures below depict the results which I obtained:

Channel update period (pre-GSoC on the left):

Number of radiating elements (pre-GSoC on the left):

Number of gNBs, with a fixed number of UEs per gNB (pre-GSoC on the left):

In my opinion results are good, but I would still like to aim for further improvements. Towards such end, I found that currently the main bottleneck is represented by the calls to std::sin and std::cos of the CalcBeamformingGain function, which (despite the name) computes and applies the Doppler to the cached long terms. At the moment, I am investigating how this function can be sped up. The main candidates are:

  • using Eigen's vector- and/or matrix-wide trigonometricsp functions; or
  • use the fast trigonometric functions library FastTrigo

P.S.: Due to the draft status, I have not documented yet the changes in RELEASE_NOTES.md, CHANGES.html and the manual. As soon as I will get some positive feedback on the general structure of these modifications I will take care of this as well.

Edited by Matteo Pagin

Merge request reports