2
$\begingroup$

I have been experimenting in building a C++ project for a FDTDS system for Electro-Magnetics. I have implemented a class [see below] which I called mesh using the Armadillo library. The 3D matrices {Cubes} for the fields Ex, Ey, Ez, Hx, Hy, Hz are declared as private members of the class. The size of these 3D Matrices are determined by the constructor. During the nuts and bolts part of the program these fields are updated by public functions [see below] void updateE(void) and void updateH(void). The program works well but is extremely slow. I have experimented with a timer and have found that the access to individual elements of the 3D matrices is of the order 2e-5. In a similar project I built in the C language but using macros and dynamic memory allocation and pointers I can get accessing times of the order of one thousand sec quicker. I must be doing something wrong. I am new to both Armadillo and C++.

#include <armadillo>

using namespace arma;

class mesh
{
  private:

    //size of mesh
    int SizeX;
    int SizeY;
    int SizeZ;

   /* declaration of Matrices/Cubes */
   cube  Hx;
   ....
    ....


public:
   mesh(int sizex, int sizey, int sizez); //construct mesh and init values
   void updateE(void);         // Update Electric field
   void updateH(void);         // Update Magnetic field
   .......


};


mesh::mesh( int sizex, int sizey, int sizez)
{
    // allocate size
    SizeX= sizex;
    SizeY= sizey;
    SizeZ= sizez;

    /* memory allocation and zeroed*/

    Hx      = zeros<cube>( SizeX, SizeY - 1, SizeZ - 1);

    ........




}


void mesh::updateH(void) {
  int mm, nn, pp;

   for (mm = 0; mm < SizeX; mm++)
      for (nn = 0; nn < SizeY - 1; nn++)
        for (pp = 0; pp < SizeZ - 1; pp++)
            Hx(mm, nn, pp) = Chxh(mm, nn, pp) * Hx(mm, nn, pp) +
            Chxey(mm, nn, pp) * (Ey(mm, nn, pp + 1) - Ey(mm, nn, pp) ) -
            Chxez(mm, nn, pp) *(Ez(mm, nn + 1, pp) - Ez(mm, nn, pp));

   for (mm = 0; mm < SizeX - 1; mm++)
      for (nn = 0; nn < SizeY; nn++)
        for (pp = 0; pp < SizeZ - 1; pp++)
            Hy(mm, nn, pp) = Chyh(mm, nn, pp) * Hy(mm, nn, pp) +
            Chyez(mm, nn, pp) * (Ez(mm + 1, nn, pp) - Ez(mm, nn, pp)) -
            Chyex(mm, nn, pp) * (Ex(mm, nn, pp + 1) - Ex(mm, nn, pp));

   for (mm = 0; mm < SizeX - 1; mm++)
      for (nn = 0; nn < SizeY - 1; nn++)
        for (pp = 0; pp < SizeZ; pp++)
            Hz(mm, nn, pp) = Chzh(mm, nn, pp) * Hz(mm, nn, pp) +
            Chzex(mm, nn, pp) * (Ex(mm, nn + 1, pp) - Ex(mm, nn, pp)) -
            Chzey(mm, nn, pp) * (Ey(mm + 1, nn, pp) - Ey(mm, nn, pp));


 return;
 } /* 
$\endgroup$
1
  • 5
    $\begingroup$ Typically, arrays in C++ are laid out in row-major order. However, the Armadillo documentation says that the Cube object is stored in column-major order instead. If you switch the array order -- mm last and pp first -- then that might help. Writing loops with the wrong array ordering can cause enormous performance penalties due to caching effects. $\endgroup$ Dec 11, 2015 at 22:17

1 Answer 1

5
$\begingroup$

I finally obtained comparable speeds with C++/Armadillo and C/arrays.

  1. Firstly, I switched as suggested by Daniel the order of the loops to column-major order.

  2. Secondly I changed the counters of the loops from int to uword.

  3. Finally I used the function .at() to disable the bound checking.

$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.