3

I do some operations on array using SIMD, so I need to have them aligned in memory. When I place arrays on the stack, I simply do this and it works:

#define BUFFER_SIZE 10000
alignas(16) float approxFreqMuls_Float[BUFFER_SIZE];
alignas(16) double approxFreqMuls_Double[BUFFER_SIZE];

But now I need to allocate more memory (such as 96k doubles, or more): so I think the heap is the way; but when I do this:

int numSteps = 96000;
alignas(16) float *approxFreqMuls_Float = new float[numSteps];
alignas(16) double *approxFreqMuls_Double = new double[numSteps];

It thrown error on ostream. Not really sure about the message (I'm on MSVC, nothing appair).

How would you allocate aligned arrays on heap?

trincot
  • 317,000
  • 35
  • 244
  • 286
markzzz
  • 47,390
  • 120
  • 299
  • 507

1 Answers1

4

Heap allocations are aligned to the maximum native alignment by default, so as long as you don't need to over-align, then you don't need to do anything in particular to align it.

If you do need over-alignment, for some reason, you can use the aligned new syntax new (std::align_val_t(16)) float[numSteps]; (or std::aligned_alloc which is in the malloc family of functions and the memory must therefore be freed rather than deleted).

If you don't have C++17, then you need to allocate size + align - 1 bytes instead if size, and std::align the pointer - or use a non-standard aligned allocation function provided on your target platform.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • `Heap allocations are aligned to the maximum native alignment by default` what does it means this? Shouldn't align to 16 using SIMD? i.e. __mm_load_pd https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE2&text=_mm_load&expand=3287 (mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated.) – markzzz Feb 08 '19 at 11:03
  • In fact, If I remove the align, it crash as well :) – markzzz Feb 08 '19 at 11:04
  • 1
    @markzzz It means that (regardless of the type given to `new`), the memory will be aligned sufficiently for any and all types except those that use `alignas` with larger values than `alignof(std::max_align_t)` i.e. types that are over-aligned. If max native alignment is 16, then you're all good. If it is less, then you need over-alignment. If you need specific alignment and don't know the native alignment, then using aligned allocation is a safe choice. – eerorika Feb 08 '19 at 11:05
  • how can I check the "max native alignment"? – markzzz Feb 08 '19 at 11:07
  • @markzzz using `alignof(std::max_align_t)`. – eerorika Feb 08 '19 at 11:07
  • 1
    that print 8. So I think I need to `over-align`. – markzzz Feb 08 '19 at 11:08
  • `float *approxFreqMuls_Float = static_cast(_mm_malloc(sizeof(float) * numSteps, 16));` + `_mm_free(approxFreqMuls_Float);` seems to works nice on MSVC... – markzzz Feb 08 '19 at 14:34