是否有可能讓std::vector
的自定義結構分配對齊內存以便進一步處理SIMD指令?如果可以使用Allocator
,有沒有人碰巧擁有這樣一個分配器,他可以分享?讓std :: vector分配對齊的內存
38
A
回答
26
編輯:我按照GManNickG的建議去除了std::allocator
的繼承,並將alignment參數設置爲編譯時間的東西。
我最近寫了這段代碼。它沒有像我想要的那樣測試,所以繼續並報告錯誤。 :-)
enum class Alignment : size_t
{
Normal = sizeof(void*),
SSE = 16,
AVX = 32,
};
namespace detail {
void* allocate_aligned_memory(size_t align, size_t size);
void deallocate_aligned_memory(void* ptr) noexcept;
}
template <typename T, Alignment Align = Alignment::AVX>
class AlignedAllocator;
template <Alignment Align>
class AlignedAllocator<void, Align>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template <class U> struct rebind { typedef AlignedAllocator<U, Align> other; };
};
template <typename T, Alignment Align>
class AlignedAllocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align))/sizeof(T); }
pointer
address(reference x) const noexcept
{ return std::addressof(x); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>(Align);
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment Align>
class AlignedAllocator<const T, Align>
{
public:
typedef T value_type;
typedef const T* pointer;
typedef const T* const_pointer;
typedef const T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align))/sizeof(T); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>(Align);
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator== (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign == UAlign; }
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator!= (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign != UAlign; }
實際分配呼叫的實施只有posix,但您可以輕鬆擴展。
void*
detail::allocate_aligned_memory(size_t align, size_t size)
{
assert(align >= sizeof(void*));
assert(nail::is_power_of_two(align));
if (size == 0) {
return nullptr;
}
void* ptr = nullptr;
int rc = posix_memalign(&ptr, align, size);
if (rc != 0) {
return nullptr;
}
return ptr;
}
void
detail::deallocate_aligned_memory(void *ptr) noexcept
{
return free(ptr);
}
需要C++ 11,順便說一句。
3
是的,應該是可以的。如果你把谷歌這個問題,那麼你將獲得大量的示例代碼,下面是一些令人鼓舞的結果:
+1
儘管此鏈接可能回答問題,但最好在此處包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [發表評論](/ review/low-quality-posts/18787539) –
15
在即將到來的版本1.56,Boost庫將包括Boost.Align。在其他內存對齊幫助程序中,它提供boost::alignment::aligned_allocator
,它可以用於std::allocator
的直接替換,並允許您指定對齊方式。請參閱https://boostorg.github.io/align/
相關問題
- 1. C++的std :: vector的內存/分配
- 2. std :: vector如何分配對象?
- 3. C++:何時需要std :: vector的共享內存分配器?
- 4. 完全重新分配一個std的內存:: vector容器
- 5. 如何知道std :: vector的分配內存大小?
- 6. 如何訪問由std :: vector分配的內存塊?
- 7. Java的內存分配對齊
- 8. 分配32字節對齊內存的分配器
- 9. 2d std :: vector連續內存?
- 10. 在MATLAB中預先分配內存àla std :: vector :: reserve(n)
- 11. 需要爲C++編寫共享內存分配器std :: vector
- 12. 什麼是對齊的內存分配?
- 13. boost :: shared_array和對齊的內存分配
- 14. 如何分配4K對齊的內存
- 15. Win32內存分配與大對齊
- 16. std :: shared_ptr預分配內存
- 17. std :: vector中的自定義分配器
- 18. 釋放std :: vector的內存C++
- 19. 從位內'std :: vector'
- 20. 用_M_allocate理解std :: vector()分配
- 21. 動態分配mpfr_t矩陣與std :: vector
- 22. std :: vector :: assign - 重新分配數據?
- 23. std :: vector交換導致內存碎片?
- 24. 如何從std :: vector中恢復內存?
- 25. 如何使tr1 :: array分配對齊的內存?
- 26. 如何釋放一個包含std :: vector的對象的內存
- 27. 將自動分配的std :: vector轉換爲動態分配的std :: vector而不需要開銷
- 28. 的std :: vector.resize有時不分配內存?
- 29. 緩存對齊英特爾CPU上的內存分配
- 30. 的std :: vector和std ::分鐘行爲
的文檔是否檢查過標準分配器是否已經爲您做了這些工作? – TemplateRex
@rhalbersma:我不這麼認爲,它不需要對齊參數。 –
沒有我的意思是:你的STL實現是否已經爲你調整了內存?你是否計算過'v.begin()'的內存地址並檢查它是否以X字節的倍數開始?即使你不能明確配置對齊方式,std :: allocator可能已經幫你完成了。 – TemplateRex