#pragma once #include #include #include #include #include // ASSERT_ALIGNED宏需要 constexpr size_t ALIGNMENT_SSE = 16; // SSE要求16字节对齐 constexpr size_t ALIGNMENT_AVX = 32; // AVX要求32字节对齐 constexpr size_t ALIGNMENT_AVX512 = 64; // AVX-512要求64字节对齐 constexpr size_t ALIGNMENT_CACHE = 64; // CPU缓存行对齐(通常为64字节) inline auto aligned_malloc(size_t size, size_t alignment) -> void* { if (alignment == 0 || (alignment & (alignment - 1)) != 0) { // 对齐值必须是2的幂 return nullptr; } #if ALICHO_PLATFORM_WINDOWS return _aligned_malloc(size, alignment); #elif ALICHO_PLATFORM_POSIX || ALICHO_PLATFORM_UNIX void* ptr = nullptr; if (posix_memalign(&ptr, alignment, size) != 0) { return nullptr; } return ptr; #else // 回退实现:手动对齐 // 分配额外空间来存储原始指针和进行对齐 size_t total_size = size + alignment + sizeof(void*); void* raw_ptr = std::malloc(total_size); if (!raw_ptr) { return nullptr; } // 计算对齐后的地址 uintptr_t raw_addr = reinterpret_cast(raw_ptr); uintptr_t aligned_addr = (raw_addr + sizeof(void*) + alignment - 1) & ~(alignment - 1); void* aligned_ptr = reinterpret_cast(aligned_addr); // 在对齐地址前存储原始指针 (reinterpret_cast(aligned_ptr))[-1] = raw_ptr; return aligned_ptr; #endif } inline void aligned_free(void* ptr) { if (!ptr) { return; } #if ALICHO_PLATFORM_WINDOWS _aligned_free(ptr); #elif ALICHO_PLATFORM_POSIX || ALICHO_PLATFORM_UNIX std::free(ptr); #else // 回退实现:获取原始指针并释放 void* raw_ptr = (reinterpret_cast(ptr))[-1]; std::free(raw_ptr); #endif } // 对齐分配器模板类 template class aligned_allocator { public: using value_type = T; using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; using size_type = std::size_t; using difference_type = std::ptrdiff_t; template struct rebind { using other = aligned_allocator; }; aligned_allocator() noexcept = default; template aligned_allocator(const aligned_allocator&) noexcept {} auto allocate(size_type n) -> pointer { if (n == 0) return nullptr; size_type size = n * sizeof(T); void* ptr = aligned_malloc(size, Alignment); if (!ptr) { throw std::bad_alloc(); } return static_cast(ptr); } void deallocate(pointer p, size_type) noexcept { aligned_free(p); } template void construct(U* p, Args&&... args) { ::new(static_cast(p)) U(std::forward(args)...); } template void destroy(U* p) { p->~u(); } static auto max_size() noexcept { return std::numeric_limits::max() / sizeof(T); } }; template bool operator==(const aligned_allocator&, const aligned_allocator&) noexcept { return A1 == A2; } template bool operator!=(const aligned_allocator&, const aligned_allocator&) noexcept { return A1 != A2; } // 类型别名,方便使用不同对齐方式的分配器 template using sse_aligned_allocator = aligned_allocator; template using avx_aligned_allocator = aligned_allocator; template using avx512_aligned_allocator = aligned_allocator; template using cache_aligned_allocator = aligned_allocator; template auto is_aligned(void* ptr) -> bool { return (reinterpret_cast(ptr) % Alignment) == 0; } inline auto is_aligned(const void* ptr, size_t alignment) -> bool { return (reinterpret_cast(ptr) % alignment) == 0; } inline auto align_size(size_t size, size_t alignment) -> size_t { return (size + alignment - 1) & ~(alignment - 1); } template auto align_pointer(void* ptr) -> void* { const auto addr = reinterpret_cast(ptr); const auto aligned_addr = (addr + Alignment - 1) & ~(Alignment - 1); return reinterpret_cast(aligned_addr); } template class aligned_buffer { public: aligned_buffer() = default; explicit aligned_buffer(size_t size) : size_(size) { allocate(size); } void allocate(size_t new_size) { if (data_) { deallocate(); } if (new_size == 0) { data_ = nullptr; size_ = 0; return; } data_ = static_cast(aligned_malloc(new_size * sizeof(T), Alignment)); if (!data_) { throw std::bad_alloc(); } size_ = new_size; // 对于非POD类型,需要构造对象 if constexpr (!std::is_trivially_constructible_v) { for (size_t i = 0; i < size_; ++i) { new(&data_[i]) T(); } } } void deallocate() { if (!data_) return; // 对于非POD类型,需要析构对象 if constexpr (!std::is_trivially_destructible_v) { for (size_t i = 0; i < size_; ++i) { data_[i].~T(); } } aligned_free(data_); data_ = nullptr; size_ = 0; } void resize(size_t size) { if (size == size_) return; allocate(size); } auto data() noexcept { return data_; } auto data() const noexcept { return data_; } auto size() const noexcept { return size_; } auto empty() const noexcept { return size_ == 0; } auto& operator[](size_t index) noexcept { return data_[index]; } const auto& operator[](size_t index) const noexcept { return data_[index]; } auto begin() noexcept { return data_; } auto end() noexcept { return data_ + size_; } auto begin() const noexcept { return data_; } auto end() const noexcept { return data_ + size_; } [[nodiscard]] auto is_properly_aligned() const noexcept -> bool { return is_aligned(data_); } private: T* data_ = nullptr; size_t size_ = 0; }; #if ALICHO_DEBUG #define ASSERT_ALIGNED(ptr, alignment) \ do { \ if (!is_aligned(ptr, alignment)) { \ throw std::runtime_error("Pointer is not properly aligned"); \ } \ } while (0) #else #define ASSERT_ALIGNED(ptr, alignment) #endif