Sie benötigen ausgerichtete Zuordner.
Aber es ist keinen Grund, warum Sie sie nicht bündeln können:
template<class T, size_t align>
struct aligned_free {
void operator()(T* t)const{
ASSERT(!(uint_ptr(t) % align));
_mm_free(t);
}
aligned_free() = default;
aligned_free(aligned_free const&) = default;
aligned_free(aligned_free&&) = default;
// allow assignment from things that are
// more aligned than we are:
template<size_t o,
std::enable_if_t< !(o % align) >* = nullptr
>
aligned_free(aligned_free<T, o>) {}
};
template<class T>
struct aligned_free<T[]>:aligned_free<T>{};
template<class T, size_t align=1>
using mm_ptr = std::unique_ptr< T, aligned_free<T, align> >;
template<class T, size_t align>
struct aligned_make;
template<class T, size_t align>
struct aligned_make<T[],align> {
mm_ptr<T, align> operator()(size_t N)const {
return mm_ptr<T, align>(static_cast<T*>(_mm_malloc(sizeof(T)*N, align)));
}
};
template<class T, size_t align>
struct aligned_make {
mm_ptr<T, align> operator()()const {
return aligned_make<T[],align>{}(1);
}
};
template<class T, size_t N, size_t align>
struct aligned_make<T[N], align> {
mm_ptr<T, align> operator()()const {
return aligned_make<T[],align>{}(N);
}
}:
// T[N] and T versions:
template<class T, size_t align>
auto make_aligned()
-> std::result_of_t<aligned_make<T,align>()>
{
return aligned_make<T,align>{}();
}
// T[] version:
template<class T, size_t align>
auto make_aligned(size_t N)
-> std::result_of_t<aligned_make<T,align>(size_t)>
{
return aligned_make<T,align>{}(N);
}
jetzt mm_ptr<float[], 4>
ist ein einzigartiger Zeiger auf ein Array von float
s, die 4 Byte ausgerichtet sind. Sie erstellen es über make_aligned<float[], 4>(20)
, die 20 floats 4-Byte-ausgerichtet oder make_aligned<float[20], 4>()
erstellt (Kompilierzeitkonstante nur in dieser Syntax). make_aligned<float[20],4>
gibt mm_ptr<float[],4>
nicht mm_ptr<float[20],4>
zurück.
Ein mm_ptr<float[], 8>
kann sich bewegen mm_ptr<float[],4>
aber nicht umgekehrt, was ich denke, ist nett.
mm_ptr<float[]>
kann jede Ausrichtung übernehmen, garantiert aber keine.
Overhead, wie mit einem std::unique_ptr
, ist grundsätzlich Null pro Zeiger. Code Overhead kann durch aggressive inline
ing minimiert werden.
Ein bisschen off topic, aber denken Sie daran, 'delete []' zu verwenden, wenn Sie etwas löschen, das mit 'new []' zugewiesen wurde. – anorm
hast du _mm_malloc statt neu versucht? – Alexander
@anorm wahr. Bearbeitet – romeric