我可以将未对齐的大小传递给_mm_malloc吗?

时间:2017-08-31 16:11:34

标签: c memory-management alignment sse allocation

The documentation I've found so far on _mm_malloc()非常稀少。特别是,我无法弄清楚如果我传递的size参数不是align的倍数会发生什么。是UB吗?或者它是否会分配align的下一个更大倍数的字节数?

2 个答案:

答案 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)进行测试。在流程退出之前查看流程的内存占用量。