Make STL containers allocate aligned memory

Z

zr

Hi,

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

red floyd

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

zr

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?
 
M

Maxim Yegorushkin

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);
}
};
 
M

Maxim Yegorushkin

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


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;
 
Z

zr

Usage is:

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

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);
}
 
M

Maxim Yegorushkin

On Nov 26, 5:03 pm, Maxim Yegorushkin <[email protected]>
wrote:
Usage is:
    typedef std::vector<X, aligned_allocator<X, required_alignment> >
VecX;

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&)
{}
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top