是否有可能让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