The documentation I've found so far on _mm_malloc()
非常稀少。特别是,我无法弄清楚如果我传递的size
参数不是align
的倍数会发生什么。是UB吗?或者它是否会分配align
的下一个更大倍数的字节数?
答案 0 :(得分:1)
这是两个独立因素:size
指示原始大小,align
只是已分配块的位置。在实际代码中,您可能会看到相关性,因此您希望对齐的原因通常是因为size
是某个因素的偶数倍,但这并不是一个很难的要求。
您可能有一个完全正确的理由来分配以8字节为基础的79字节。
答案 1 :(得分:1)
英特尔针对_mm_malloc
in their own compiler的文档仅说“此[align]约束必须是2的幂。”
没有要求大小是对齐的倍数,因为它的主要用例是SIMD,在这种情况下,分配一个阵列的对齐方式大于单个成员的宽度是完全正常的。 (例如,对于AVX,float*
与32B对齐)。或者用于缓存行/页面/巨页边界。例如为了更好地利用透明的大页面,你可以为大于2MB的任何分配分配2MB对齐。
唯一对齐的分配器我知道确实有你担心的限制是C11 / C++17 aligned_alloc
,不幸的是,当需要失败时size % align != 0
。请参阅How to solve the 32-byte-alignment issue for AVX load/store operations?上的答案。 TL; DR:原始C11 aligned_alloc
是UB,具有非多对齐大小,因此实际实现选择使其按预期工作,就像其他对齐的分配器一样(例如posix_memalign
)。但是在那种情况下,它被改为 required 失败(返回错误),而不是UB,所以允许它工作的实现在技术上违反了(愚蠢的)标准。 C ++ 17具有必需的失败版本。
显然,英特尔没有犯下标准委员会对aligned_alloc
所做的同样的错误,因为它会破坏_mm_malloc
优化的目的。当然,他们考虑了SIMD和内存边界用例。 (IDK标准委员会没有,看起来非常明显,作为类型/缓冲区的主要用例,比最宽泛类型的自然对齐更多的对齐。真的令人失望的是一个函数与最好的API不安全使用。(aligned_alloc
返回可用free
释放的内存,并且不会通过将指针的地址作为posix_memalign
之类的输入来取消优化(这导致编译器担心别名)。)
或者它是否会分配对齐的下一个较大倍数的字节数?
对于像32B或64B这样的小对齐,这可能是有效的。根据实现情况,可能不会将最后的松弛空间留给malloc
的较小分配或_mm_malloc
的较小对齐调用。读取对齐边界是没有错误的(如果它小于4k页)是安全的,但如果你没有明确地分配它,就不要写入它。
在任何高质量的实现中,大对齐都不会浪费多个整页。您可以通过执行许多具有大量对齐的分配(例如_mm_malloc(3M, 2M)
)和一些可以使用该空间的分配(例如_mm_malloc(512k, 4k)
),然后sleep(100)
进行测试。在流程退出之前查看流程的内存占用量。