I frequently need to align the start of a dynamic array to a 16, 32, or 64 Byte boundary for vectorization, e.g., for SSE, AVX, AVX-512. I am looking for a transparent and safe way to use this in conjunction with smart pointers, in particular std::unique_ptr
.
Given an implementation of allocation and deallocation routines, say
template<class T>
T * allocate_aligned(int alignment, int length)
{
// omitted: check minimum alignment, check error
T * raw = 0;
// using posix_memalign as an example, could be made platform dependent...
int error = posix_memalign((void **)&raw, alignment, sizeof(T)*length);
return raw;
}
template<class T>
struct DeleteAligned
{
void operator()(T * data)const
{
free(data);
}
};
I would like to do something like this
std::unique_ptr<float[]> data(allocate_aligned<float>(alignment, length));
but I could not figure out how to do get unique_ptr
to use the proper Deleter
without requiring from the user to specify it (which is a potential cause for errors). The alternative I found was to use a template alias
template<class T>
using aligned_unique_ptr = std::unique_ptr<T[], DeleteAligned<T>>;
Then we can use
aligned_unique_ptr<float> data(allocate_aligned<float>(alignment, length));
The remaining problem is that nothing keeps the user from putting the raw pointer into a std::unique_ptr
.
Apart from that, do you see anything wrong with this? Is there an alternative which is less error prone, but completely transparent to the user after the allocation was done?
Aucun commentaire:
Enregistrer un commentaire