When I write linear algebra programs in C++, I use the Armadillo library. It is based on templates, which provide me a way to define vectors of any length that don't necessarily require additional memory allocation, since they are statically assigned an appropriate memory buffer at compile-time. When I use arma::Col<double>::fixed<3>
the compiler creates a "new type" on the fly so that the vector contains a buffer of exactly 3 doubles.
Now I'm working on a linear algebra program in C, and I'm using the GNU Scientific Library (GSL). In order to instantiate a 3D vector, I do: gsl_vector_alloc(3)
that returns a gsl_vector*
. The problem is that this operation causes the dynamic allocation of a small portions of memory, and this happens millions of times during program runtime. My program is wasting a lot of resources to perform tens of millions of malloc
/free
operations.
I've inspected the internal structure of gsl_vector
:
typedef struct
{
size_t size;
size_t stride;
double * data;
gsl_block * block;
int owner;
} gsl_vector;
For the library to work correctly, data
should point to the first element of the vector, usually inside a gsl_block
structure like this:
typedef struct
{
size_t size;
double * data;
} gsl_block;
which contains another data
pointer. So, for instantiating a simple 3D vector, this sequence of malloc
s happen:
- A
gsl_vector
structure ismalloc
'd (something around 40 bytes on x86_64). - A
gsl_block
structure ismalloc
'd (16 bytes) and theblock
pointer of the gsl_vector is set to the memory address of the gsl_block just allocated - An array of 3 doubles is
malloc
'd and its memory address is assigned to bothdata
pointers (the one ingsl_block
and the one ingsl_vector
).
I obtained a 40% performance gain by removing two malloc
s. I created my custom gsl_vector
creation routine, that allocates an array of 3 doubles and sets the data
pointer of the gsl_vector
to the address of this array. Then I return a gsl_vector
(not a pointer).
But doing so, I still get millions of malloc(3 * sizeof(double))
operations.
I didn't manage to "embed" the array of 3 doubles inside the gsl_vector
struct, since if the data
pointer points to something which is inside the struct itself (hacky!), then the pointer is no longer valid when the vector is copied elsewhere!
Do you have any ideas (apart switching to C++ or rolling my own linear algebra library)? I am open to any suggestion.