Home > front end >  How to modernize memalign in a C codebase?
How to modernize memalign in a C codebase?

Time:09-28

I am modernizing/updating some old code that was originally written in C but is now used in a C codebase (no need to be backwards compatible). A bunch of this code is memory optimized with memalign with which I am very inexperienced with so my question is how one would update this code (or just leave it like it is) and whether there's even still any point to having it there at all:

The declaration:

float *table_pf;

And how it's initialized in the constructor:

table_pf = (float*)memalign(32, sizeof(float) * TALBLE_SIZE);

I was unable to find any equivalent for modern C but I may also have just missed it. Usually I would simply convert the pointer to a std::vector or std::array but this does not work when using memalign.

CodePudding user response:

If std::array is an option for you, it's easy to align (same applies to bare arrays):

alignas(32) std::array<TALBLE_SIZE, float> table;

The standard function for dynamically allocating over-aligned memory inherited from C is std::aligned_alloc. It's nearly identical to the non-standard memalign; only difference is that it's stricter in requiring the size to be a multiple of the alignment. A pure C option is to use the operator new with std::align_val_t operand which will by default use std::aligned_alloc.

It's not a good idea to use the bare pointer returned by the allocation function though: You should use RAII. One option is to use std::vector with an allocator that uses over-aligned allocation function. Standard library doesn't provide such allocator though, so a custom one needs to be used. A more straightforward but less flexible option is to use std::unique_ptr with a deleter that calls std::free (or operator delete in case you had used operator new).

CodePudding user response:

You can use C 17 aligned new[]:

// new
auto* table_pf = new (std::align_val_t(32)) float[TALBLE_SIZE];
// delete
::operator delete[](table_pf, std::align_val_t(32));

CodePudding user response:

The code returns a TABLE_SIZE array of floats, the address would be aligned to 32 bytes.
malloc would have used the default alignment, which normally means double size alignment (but can be larger, implementation dependent).
For an array of floats - normal allocation and alignment is sufficient.
You would use memalign or the c aligned_alloc or posix_memalign to return a non regular alignment.
For instance, when using SSE or other SIMD extensions, that may require larger memory alignment than the default one.
My advice is to read the code, see if memory alignment is indeed needed, and either lose it for a normal allocation or move to std::aligned_alloc if it is really required.
The use of the literal 32 is suspicious in my opinion.

  • Related