Topic: Proposal std::make_shared/std::make_unique respecting alignment.


Author: Emily <lenkkix@gmail.com>
Date: Tue, 22 Sep 2015 09:02:28 -0700 (PDT)
Raw View
------=_Part_672_403103008.1442937748015
Content-Type: multipart/alternative;
 boundary="----=_Part_673_1987273715.1442937748021"

------=_Part_673_1987273715.1442937748021
Content-Type: text/plain; charset=UTF-8

With the use of SIMD instructions alignment of data types is becoming
increasingly important. The recent C++11 standard brought new tools for
dealing with alignment (alignas(x), alignof(t) etc). However heap
allocations are still required only to conform to the fundamental alignment
of the platform. Meaning that alignas() attributes are ignored for operator
new/delete and by extension make_shared/make_unique/vector etc which
necessitates error-prone manual allocation of aligned memory (or writing a
custom aligned_allocator and consistently using it everywhere).

As the standard provides tools for specifying alignment of types, I believe
it would be desirable to provide a new "std::aligned_allocator<T, size_t
alignment>" allocator type in the standard library. This allocator would
produce aligned memory, for example boost provides such an
allocator: http://www.boost.org/doc/libs/1_58_0/doc/html/align/tutorial.html#align.tutorial.aligned_allocator.
Another implementation can be found
here: https://gist.github.com/donny-dont/1471329 and there exists many
more. This is a common problem.

If such an "aligned_allocator" would be available, then for example
"std::make_shared" could be augmented to automatically allocate aligned
memory, like so:

    template< typename T, std::size_t align = std::alignment_of<T>::value,
typename... Args >
    std::shared_ptr<T> make_shared(Args&&... args){
        constexpr std::size_t default_alignment = ...; // Platform specific
constant

        if (align > default_alignment) {
            typedef aligned_allocator<T, align> alloc_t;
            return std::allocate_shared<T, alloc_t>(alloc_t(),
std::forward<Args>(args)...);
        }
        else {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
}

Note that the alignment is automatically determined and the syntax for
calling make_shared will not change and this change will not break existing
code. In a similar fashion make_unique could also be augmented.

Likewise for std::vector changing:
    template<class T, class Allocator = std::allocator
<http://en.cppreference.com/w/cpp/memory/allocator><T>> class vector;
to
    template<class T, class Allocator = std::aligned_allocator
<http://en.cppreference.com/w/cpp/memory/allocator><T,
std::alignment_of<T>>> class vector;

would not break any existing code (*1,*2,*3) while allowing vector to
respect the alignment of T. Similarly the other std containers can be
augmented to respect the alignment of the contained types.

*1: Any well formed program that functions with the default allocator will
also function with a stricter alignment requirement. Any bit hacks done on
lower bits of the address will still work. Software in any way depending on
particular properties of the default allocators returned addresses (other
than fundamental alignment) has UB anyway.
*2: Any program that was buggy due to improper alignment will have been
automatically fixed.
*3: Any program that has solved the problem already by using their own
aligned allocator will not be affected as they are specifying the allocator
explicitly.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_673_1987273715.1442937748021
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>With the use of SIMD instructions alignment of data t=
ypes is becoming increasingly important. The recent C++11 standard brought =
new tools for dealing with alignment (alignas(x), alignof(t) etc). However =
heap allocations are still required only to conform to the fundamental alig=
nment of the platform. Meaning that alignas() attributes are ignored for op=
erator new/delete and by extension make_shared/make_unique/vector etc which=
 necessitates error-prone manual allocation of aligned memory (or writing a=
 custom aligned_allocator and consistently using it everywhere).</div><div>=
<br></div><div>As the standard provides tools for specifying alignment of t=
ypes, I believe it would be desirable to provide a new &quot;std::aligned_a=
llocator&lt;T, size_t alignment&gt;&quot; allocator type in the standard li=
brary. This allocator would produce aligned memory, for example boost provi=
des such an allocator:=C2=A0http://www.boost.org/doc/libs/1_58_0/doc/html/a=
lign/tutorial.html#align.tutorial.aligned_allocator. Another implementation=
 can be found here:=C2=A0https://gist.github.com/donny-dont/1471329 and the=
re exists many more. This is a common problem.</div><div><br></div>If such =
an &quot;aligned_allocator&quot; would be available, then for example &quot=
;std::make_shared&quot; could be augmented to automatically allocate aligne=
d memory, like so:<div><br></div><div><div>=C2=A0 =C2=A0 template&lt; typen=
ame T, std::size_t align =3D std::alignment_of&lt;T&gt;::value, typename...=
 Args &gt;</div><div>=C2=A0 =C2=A0 std::shared_ptr&lt;T&gt; make_shared(Arg=
s&amp;&amp;... args){</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 constexpr std::=
size_t default_alignment =3D ...; // Platform specific constant<br></div><d=
iv><br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (align &gt; default_alignm=
ent) {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 typedef alig=
ned_allocator&lt;T, align&gt; alloc_t;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 return std::allocate_shared&lt;T, alloc_t&gt;(alloc_t(), =
std::forward&lt;Args&gt;(args)...);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }=
</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 else {</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 return std::make_shared&lt;T&gt;(std::forward&lt;A=
rgs&gt;(args)...);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div>    }<br><b=
r>Note that the alignment is automatically determined and the syntax for ca=
lling make_shared will not change and this change will not break existing c=
ode. In a similar fashion make_unique could also be augmented.<br><br>Likew=
ise for std::vector changing:<br>=C2=A0 =C2=A0 template&lt;class T, class A=
llocator =3D <a href=3D"http://en.cppreference.com/w/cpp/memory/allocator">=
std::allocator</a>&lt;T&gt;&gt; class vector;<br>to<br>=C2=A0 =C2=A0 templa=
te&lt;class T, class Allocator =3D <a href=3D"http://en.cppreference.com/w/=
cpp/memory/allocator">std::aligned_allocator</a>&lt;T, std::alignment_of&lt=
;T&gt;&gt;&gt; class vector;<br></div><div><br></div><div>would not break a=
ny existing code (*1,*2,*3) while allowing vector to respect the alignment =
of T. Similarly the other std containers can be augmented to respect the al=
ignment of the contained types.</div><div><br></div><div>*1: Any well forme=
d program that functions with the default allocator will also function with=
 a stricter alignment requirement. Any bit hacks done on lower bits of the =
address will still work. Software in any way depending on particular proper=
ties of the default allocators returned addresses (other than fundamental a=
lignment) has UB anyway.</div><div>*2: Any program that was buggy due to im=
proper alignment will have been automatically fixed.</div><div>*3: Any prog=
ram that has solved the problem already by using their own aligned allocato=
r will not be affected as they are specifying the allocator explicitly.</di=
v><div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_673_1987273715.1442937748021--
------=_Part_672_403103008.1442937748015--

.