_alloca()
的文档说here:
_alloca例程返回指向已分配空间的void指针, 保证适当地对齐以存储任何类型的 对象
然而,here它说:
_alloca需要16字节对齐,并且还需要使用帧指针。
所以看来在第一个参考文献中他们忘记了32字节对齐的AVX / AVX2类型,如__m256d
。
让我感到困惑的另一件事是第一页说_alloca()
已被弃用,而它建议使用一个可以从堆而不是堆栈分配内存的函数(这在我的多线程中是不可接受的)应用程序)。
那么有人能指出我是否有一些现代的(可能是新的C / C ++标准?)方式来进行对齐的堆栈内存分配?
澄清1 :请不要提供需要数组大小为编译时常量的解决方案。我的函数根据运行时参数值分配可变数量的数组项。
答案 0 :(得分:4)
使用_alloca()进行总体定位,然后手动对齐。像这样:
const int align = 32;
void *p =_alloca(n + align - 1);
__m256d *pm = (__m256d *)((((int_ptr_t)p + align - 1) / align) * align);
如有必要,请将const
替换为#define
。
答案 1 :(得分:1)
C ++ 11引入了alignof
运算符:
alignof表达式产生其操作数类型的对齐要求。
您可以按如下方式使用它:
struct s {};
typedef s __attribute__ ((aligned (64))) aligned_s;
std::cout << alignof(aligned_s); // Outputs: 64
注意:如果类型的对齐方式大于其大小,编译器将不允许您声明数组类型的数组(请参阅更多here):
错误:数组元素的对齐大于元素大小
但是,如果您的类型的对齐方式小于其大小,则可以 安全地分配数组:
aligned_s arr[32];
-- OR --
constexpr size_t arr_size = 32;
aligned_s arr[arr_size];
支持VLA的编译器也允许使用新定义类型的编译器。
答案 2 :(得分:1)
&#34;现代&#34;方式是:
Don't make variable-length allocation on the stack.
在你的问题的上下文中 - 想要在堆上进行分配而不是这样做 - 我假设你可能正在分配超过一些小的编译时常量内存。在这种情况下,您只需使用alloca()
电话粉碎您的筹码即可。而是使用线程安全的内存分配器。我确定在GitHub上有这样的库(在最坏的情况下,你可以使用全局互斥锁来保护分配调用,但如果你需要大量的互斥锁,它会很慢)。
另一方面,如果你事先知道分配大小的上限 - 只需在线程本地存储中预先分配那么多内存;或使用固定大小的本地数组(将在堆栈上分配)。
答案 3 :(得分:1)
_alloca()
当然不是处理堆栈对齐的标准或可移植方式。幸运的是,在C ++ 11中,我们获得了alignas
和std::aligned_storage
。这些都没有强迫你把任何东西放在堆上,所以它们应该适用于你的用例。例如,要将结构数组对齐到32字节边界:
#include <type_traits>
struct bar { int member; /*...*/ };
void fun() {
std::aligned_storage<sizeof(bar), 32>::type array[16];
auto bar_array = reinterpret_cast<bar*>(array);
}
或者,如果您只想将堆栈上的单个变量与边界对齐:
void bun() {
alignas(32) bar b;
}
您还可以使用alignof
运算符来获取给定类型的对齐要求。