Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 : Does new return contiguous memory?

Tags:

c++

c++11

float* tempBuf = new float[maxVoices]();

Will the above result in

1) memory that is 16-byte aligned?

2) memory that is confirmed to be contiguous?

What I want is the following:

float tempBuf[maxVoices] __attribute__ ((aligned));

but as heap memory, that will be effective for Apple Accelerate framework.

Thanks.

like image 347
lppier Avatar asked Dec 01 '22 13:12

lppier


2 Answers

The memory will be aligned for float, but not necessarily for CPU-specific SIMD instructions. I strongly suspect on your system sizeof(float) < 16, though, which means it's not as aligned as you want. The memory will be contiguous: &A[i] == &A[0] + i.

If you need something more specific, new std::aligned_storage<Length, Alignment> will return a suitable region of memory, presuming of course that you did in fact pass a more specific alignment.

Another alternative is struct FourFloats alignas(16) {float[4] floats;}; - this may map more naturally to the framework. You'd now need to do new FourFloats[(maxVoices+3)/4].

like image 108
MSalters Avatar answered Dec 09 '22 21:12

MSalters


Yes, new returns contiguous memory.

As for alignment, no such alignment guarantee is provided. Try this:

template<class T, size_t A>
T* over_aligned(size_t N){
  static_assert(A <= alignof(std::max_align_t),
    "Over-alignment is implementation-defined."
  );
  static_assert( std::is_trivially_destructible<T>{},
    "Function does not store number of elements to destroy"
  );
  using Helper=std::aligned_storage_t<sizeof(T), A>;
  auto* ptr = new Helper[(N+sizeof(Helper)-1)/sizeof(Helper)];
  return new(ptr) T[N];
}

Use:

float* f = over_aligned<float,16>(37);

Makes an array of 37 floats, with the buffer aligned to 16 bytes. Or it fails to compile.

If the assert fails, it can still work. Test and consult your compiler documentation. Once convinced, put compiler-specific version guards around the static assert, so when you change compilers you can test all over again (yay).

If you want real portability, you have to have a fall back to std::align and manage resources separately from data pointers and count the number of T if and only if T has a non-trivial destructor, then store the number of T "before" the start of your buffer. It gets pretty silly.

like image 22
Yakk - Adam Nevraumont Avatar answered Dec 09 '22 22:12

Yakk - Adam Nevraumont