Make STL containers allocate aligned memory

Discussion in 'C++' started by zr, Nov 26, 2008.

  1. zr

    zr Guest

    Hi,

    I need to use STL containers that allocate aligned memory. My compiler
    provides an aligned_malloc routine.
    How can this be accomplished?
    zr, Nov 26, 2008
    #1
    1. Advertising

  2. zr

    red floyd Guest

    On Nov 26, 8:42 am, zr <> wrote:
    > Hi,
    >
    > I need to use STL containers that allocate aligned memory. My compiler
    > provides an aligned_malloc routine.
    > How can this be accomplished?


    I believe you need to write a custom allocator.
    red floyd, Nov 26, 2008
    #2
    1. Advertising

  3. zr

    zr Guest

    On Nov 26, 6:53 pm, red floyd <> wrote:
    > On Nov 26, 8:42 am, zr <> wrote:
    >
    > > Hi,

    >
    > > I need to use STL containers that allocate aligned memory. My compiler
    > > provides an aligned_malloc routine.
    > > How can this be accomplished?

    >
    > I believe you need to write a custom allocator.


    Could you please show an example of implementing such an allocator and
    its usage for instantiating a vector object?
    zr, Nov 26, 2008
    #3
  4. On Nov 26, 4:42 pm, zr <> wrote:

    > I need to use STL containers that allocate aligned memory.


    Why?

    > My compiler provides an aligned_malloc routine.


    It is probably provided by a library shipped with the compiler, not by
    compiler itself.

    > How can this be accomplished?


    Something like this:

    #include <memory>
    #include <stdexcept>

    template<class T, size_t alignment>
    struct aligned_allocator : std::allocator<T>
    {
    template<class U>
    struct rebind { typedef aligned_allocator<U, alignment> other; };

    typedef std::allocator<T> base;

    typedef typename base::pointer pointer;
    typedef typename base::size_type size_type;

    pointer allocate(size_type n)
    {
    if(pointer p = (pointer)aligned_malloc(n, alignment))
    return p;
    throw std::bad_alloc("aligned_allocator");
    }

    pointer allocate(size_type n, void const*)
    {
    return this->allocate(n);
    }

    void deallocate(pointer p, size_type)
    {
    aligned_free(p);
    }
    };

    --
    Max
    Maxim Yegorushkin, Nov 26, 2008
    #4
  5. On Nov 26, 5:03 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 26, 4:42 pm, zr <> wrote:
    >
    > > I need to use STL containers that allocate aligned memory.

    >
    > Why?
    >
    > > My compiler provides an aligned_malloc routine.

    >
    > It is probably provided by a library shipped with the compiler, not by
    > compiler itself.
    >
    > > How can this be accomplished?

    >
    > Something like this:
    >
    > #include <memory>
    > #include <stdexcept>
    >
    > template<class T, size_t alignment>
    > struct aligned_allocator : std::allocator<T>
    > {
    >     template<class U>
    >     struct rebind { typedef aligned_allocator<U, alignment> other; };
    >
    >     typedef std::allocator<T> base;
    >
    >     typedef typename base::pointer pointer;
    >     typedef typename base::size_type size_type;
    >
    >     pointer allocate(size_type n)
    >     {
    >         if(pointer p = (pointer)aligned_malloc(n, alignment))
    >             return p;
    >         throw std::bad_alloc("aligned_allocator");
    >     }
    >
    >     pointer allocate(size_type n, void const*)
    >     {
    >         return this->allocate(n);
    >     }
    >
    >     void deallocate(pointer p, size_type)
    >     {
    >         aligned_free(p);
    >     }
    >
    > };


    Usage is:

    typedef std::vector<X, aligned_allocator<X, required_alignment> >
    VecX;

    --
    Max
    Maxim Yegorushkin, Nov 26, 2008
    #5
  6. zr

    zr Guest

    On Nov 26, 7:32 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 26, 5:03 pm, Maxim Yegorushkin <>
    > wrote:
    >
    >
    >
    > > On Nov 26, 4:42 pm, zr <> wrote:

    >
    > > > I need to use STL containers that allocate aligned memory.

    >
    > > Why?

    >
    > > > My compiler provides an aligned_malloc routine.

    >
    > > It is probably provided by a library shipped with the compiler, not by
    > > compiler itself.

    >
    > > > How can this be accomplished?

    >
    > > Something like this:

    >
    > > #include <memory>
    > > #include <stdexcept>

    >
    > > template<class T, size_t alignment>
    > > struct aligned_allocator : std::allocator<T>
    > > {
    > >     template<class U>
    > >     struct rebind { typedef aligned_allocator<U, alignment> other; };

    >
    > >     typedef std::allocator<T> base;

    >
    > >     typedef typename base::pointer pointer;
    > >     typedef typename base::size_type size_type;

    >
    > >     pointer allocate(size_type n)
    > >     {
    > >         if(pointer p = (pointer)aligned_malloc(n, alignment))
    > >             return p;
    > >         throw std::bad_alloc("aligned_allocator");
    > >     }

    >
    > >     pointer allocate(size_type n, void const*)
    > >     {
    > >         return this->allocate(n);
    > >     }

    >
    > >     void deallocate(pointer p, size_type)
    > >     {
    > >         aligned_free(p);
    > >     }

    >
    > > };

    >
    > Usage is:
    >
    >     typedef std::vector<X, aligned_allocator<X, required_alignment> >
    > VecX;
    >
    > --
    > Max


    Max, thanks. I wrote a quick test on your proposal. Unfortunately, got
    a compilation error:
    C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility
    (419) : error C2664: 'aligned_allocator<T,alignment>::aligned_allocator
    (const aligned_allocator<T,alignment> &) throw()' : cannot convert
    parameter 1 from 'aligned_allocator<T,alignment>' to 'const
    aligned_allocator<T,alignment> &'
    with
    [
    T=std::_Aux_cont,
    alignment=64
    ]
    and
    [
    T=int,
    alignment=64
    ]
    and
    [
    T=std::_Aux_cont,
    alignment=64
    ]
    Reason: cannot convert from 'aligned_allocator<T,alignment>'
    to 'const aligned_allocator<T,alignment>'
    with
    [
    T=int,
    alignment=64
    ]
    and
    [
    T=std::_Aux_cont,
    alignment=64
    ]
    No user-defined-conversion operator available that can perform
    this conversion, or the operator cannot be called
    C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    \xutility(417) : while compiling class template member function
    'std::_Container_base_aux_alloc_real<_Alloc>::_Container_base_aux_alloc_real
    (_Alloc)'
    with
    [
    _Alloc=aligned_allocator<int,64>
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    \vector(421) : see reference to class template instantiation
    'std::_Container_base_aux_alloc_real<_Alloc>' being compiled
    with
    [
    _Alloc=aligned_allocator<int,64>
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    \vector(439) : see reference to class template instantiation
    'std::_Vector_val<_Ty,_Alloc>' being compiled
    with
    [
    _Ty=int,
    _Alloc=aligned_allocator<int,64>
    ]
    .\main.cpp(38) : see reference to class template instantiation
    'std::vector<_Ty,_Ax>' being compiled
    with
    [
    _Ty=int,
    _Ax=aligned_allocator<int,64>
    ]

    Following is the source of the test:


    #include <malloc.h>
    #include <memory>
    #include <stdexcept>
    #include <vector>

    template<class T, size_t alignment>
    struct aligned_allocator : std::allocator<T>
    {
    template<class U>
    struct rebind { typedef aligned_allocator<U, alignment> other; };

    typedef std::allocator<T> base;

    typedef typename base::pointer pointer;
    typedef typename base::size_type size_type;

    pointer allocate(size_type n)
    {
    if(pointer p = (pointer)_aligned_malloc(n, alignment))
    return p;
    throw std::bad_alloc("aligned_allocator");
    }

    pointer allocate(size_type n, void const*)
    {
    return this->allocate(n);
    }

    void deallocate(pointer p, size_type)
    {
    _aligned_free(p);
    }

    };

    int main(int argc, char* argv[])
    {
    std::vector<int, aligned_allocator<int, 64> > v(1024);
    }
    zr, Nov 26, 2008
    #6
  7. zr

    zr Guest

    On Nov 26, 7:03 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 26, 4:42 pm, zr <> wrote:
    >
    > > I need to use STL containers that allocate aligned memory.

    >
    > Why?


    I'm using IA SIMD instructions that perform best on memory aligned to
    16 bytes.
    zr, Nov 26, 2008
    #7
  8. zr

    Ron AF Greve Guest

    Ron AF Greve, Nov 26, 2008
    #8
  9. On Nov 26, 6:06 pm, zr <> wrote:
    > On Nov 26, 7:32 pm, Maxim Yegorushkin <>
    > wrote:
    >
    >
    >
    > > On Nov 26, 5:03 pm, Maxim Yegorushkin <>
    > > wrote:

    >
    > > > On Nov 26, 4:42 pm, zr <> wrote:

    >
    > > > > I need to use STL containers that allocate aligned memory.

    >
    > > > Why?

    >
    > > > > My compiler provides an aligned_malloc routine.

    >
    > > > It is probably provided by a library shipped with the compiler, not by
    > > > compiler itself.

    >
    > > > > How can this be accomplished?

    >
    > > > Something like this:

    >
    > > > #include <memory>
    > > > #include <stdexcept>

    >
    > > > template<class T, size_t alignment>
    > > > struct aligned_allocator : std::allocator<T>
    > > > {
    > > >     template<class U>
    > > >     struct rebind { typedef aligned_allocator<U, alignment> other; };

    >
    > > >     typedef std::allocator<T> base;

    >
    > > >     typedef typename base::pointer pointer;
    > > >     typedef typename base::size_type size_type;

    >
    > > >     pointer allocate(size_type n)
    > > >     {
    > > >         if(pointer p = (pointer)aligned_malloc(n, alignment))
    > > >             return p;
    > > >         throw std::bad_alloc("aligned_allocator");
    > > >     }

    >
    > > >     pointer allocate(size_type n, void const*)
    > > >     {
    > > >         return this->allocate(n);
    > > >     }

    >
    > > >     void deallocate(pointer p, size_type)
    > > >     {
    > > >         aligned_free(p);
    > > >     }

    >
    > > > };

    >
    > > Usage is:

    >
    > >     typedef std::vector<X, aligned_allocator<X, required_alignment> >
    > > VecX;

    >
    > > --
    > > Max

    >
    > Max, thanks. I wrote a quick test on your proposal. Unfortunately, got
    > a compilation error:
    > C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility
    > (419) : error C2664: 'aligned_allocator<T,alignment>::aligned_allocator
    > (const aligned_allocator<T,alignment> &) throw()' : cannot convert
    > parameter 1 from 'aligned_allocator<T,alignment>' to 'const
    > aligned_allocator<T,alignment> &'
    >         with
    >         [
    >             T=std::_Aux_cont,
    >             alignment=64
    >         ]
    >         and
    >         [
    >             T=int,
    >             alignment=64
    >         ]
    >         and
    >         [
    >             T=std::_Aux_cont,
    >             alignment=64
    >         ]
    >         Reason: cannot convert from 'aligned_allocator<T,alignment>'
    > to 'const aligned_allocator<T,alignment>'
    >         with
    >         [
    >             T=int,
    >             alignment=64
    >         ]
    >         and
    >         [
    >             T=std::_Aux_cont,
    >             alignment=64
    >         ]
    >         No user-defined-conversion operator available that can perform
    > this conversion, or the operator cannot be called
    >         C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    > \xutility(417) : while compiling class template member function
    > 'std::_Container_base_aux_alloc_real<_Alloc>::_Container_base_aux_alloc_real
    > (_Alloc)'
    >         with
    >         [
    >             _Alloc=aligned_allocator<int,64>
    >         ]
    >         C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    > \vector(421) : see reference to class template instantiation
    > 'std::_Container_base_aux_alloc_real<_Alloc>' being compiled
    >         with
    >         [
    >             _Alloc=aligned_allocator<int,64>
    >         ]
    >         C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
    > \vector(439) : see reference to class template instantiation
    > 'std::_Vector_val<_Ty,_Alloc>' being compiled
    >         with
    >         [
    >             _Ty=int,
    >             _Alloc=aligned_allocator<int,64>
    >         ]
    >         .\main.cpp(38) : see reference to class template instantiation
    > 'std::vector<_Ty,_Ax>' being compiled
    >         with
    >         [
    >             _Ty=int,
    >             _Ax=aligned_allocator<int,64>
    >         ]
    >
    > Following is the source of the test:
    >
    > #include <malloc.h>
    > #include <memory>
    > #include <stdexcept>
    > #include <vector>
    >
    > template<class T, size_t alignment>
    > struct aligned_allocator : std::allocator<T>
    > {
    >     template<class U>
    >     struct rebind { typedef aligned_allocator<U, alignment> other; };
    >
    >     typedef std::allocator<T> base;
    >
    >     typedef typename base::pointer pointer;
    >     typedef typename base::size_type size_type;
    >
    >     pointer allocate(size_type n)
    >     {
    >         if(pointer p = (pointer)_aligned_malloc(n, alignment))
    >             return p;
    >         throw std::bad_alloc("aligned_allocator");
    >     }
    >
    >     pointer allocate(size_type n, void const*)
    >     {
    >         return this->allocate(n);
    >     }
    >
    >     void deallocate(pointer p, size_type)
    >     {
    >         _aligned_free(p);
    >     }
    >
    > };
    >
    > int main(int argc, char* argv[])
    > {
    >         std::vector<int, aligned_allocator<int, 64> > v(1024);
    > }


    Strange, it compiles fine with M$VC 2005. It looks like
    aligned_allocator needs a conversion constructor. Try adding these
    constructors:

    aligned_allocator()
    {}

    template<class U>
    aligned_allocator(U const&)
    {}

    --
    Max
    Maxim Yegorushkin, Nov 27, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    415
  2. Wiseguy
    Replies:
    1
    Views:
    395
    Jerry Coffin
    Mar 13, 2005
  3. Replies:
    8
    Views:
    1,913
    Csaba
    Feb 18, 2006
  4. Divick
    Replies:
    11
    Views:
    508
    Pete Becker
    Sep 7, 2006
  5. Andrey Vul
    Replies:
    6
    Views:
    567
    James Kanze
    Oct 22, 2009
Loading...

Share This Page