lppier
lppier

Reputation: 1987

C++11 : Does new return contiguous memory?

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.

Upvotes: 4

Views: 592

Answers (4)

MSalters
MSalters

Reputation: 179981

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].

Upvotes: 10

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275740

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.

Upvotes: 6

Yam Marcovic
Yam Marcovic

Reputation: 8141

  1. It's guaranteed to be aligned properly with respect to the type you're allocating. So if it's an array of 4 floats (each supposedly 4 bytes), it's guaranteed to provide a usable sequence of floats. It's not guaranteed to be aligned to 16 bytes.
  2. Yes, it's guaranteed to be contiguous (otherwise what would be the meaning of a single pointer?)

If you want it to be aligned to some K bytes, you can do it manually with std::align. See MSalter's answer for a more efficient way of doing this.

Upvotes: 2

Bathsheba
Bathsheba

Reputation: 234785

If tempBuf is not nullptr then the C++ standard guarantees that tempBuf points to the zeroth element of least maxVoices contiguous floats.

(Don't forget to call delete[] tempBuf once you're done with it.)

Upvotes: 0

Related Questions