为什么大多数平台上都没有'aligned_realloc'?

时间:2019-06-16 14:13:12

标签: c++ c memory-management c++17 c11

MSVC具有自己的非标准功能_aligned_malloc_aligned_realloc_aligned_free

C ++ 17和C11引入了(std::)aligned_alloc,其结果可以用freerealloc进行 de 分配。但是realloc不能真正用于重新分配aligned_alloc返回的内存,因为它不使用 alignment 参数,因此不能保证返回的指针将正确对齐。

我什至找不到任何非标准扩展,它们可以在Microsoft Windows / Visual C ++以外的平台上重新分配对齐的内存(保留对齐)。

我搜索错误吗?还是在POSIX和其他平台上确实没有_aligned_realloc替代方案?

如果是这样,

  1. 为什么?
  2. 在那些平台上可以代替使用什么?有没有什么比使用新的对齐方式调用aligned_alloc然后在成功时对旧指针进行memcpyfree更好的了?

2 个答案:

答案 0 :(得分:5)

虽然POSIX(在大多数平台上倾向于充当最低的公分母)没有aligned_realloc,但确实有aligned_allocmemcpy。因此,您可以非常轻松地实现自己的aligned_realloc,可以保证使用这些malloc可以在任何符合posix的合理平台上工作。但是,请注意,没有posix标准方法来获取realloc'd内存区域的大小。您必须自己进行跟踪。

编辑:有一些空闲时间,所以我将其扩展为回答最常见的批评

正如敏锐的评论者所指出的,我所建议的是realloc在内部的工作方式。

在后台,您的标准__extern_always_inline float vec4_len(const float *v) { __m128 vec1 = _mm_load_ps(v); __m128 xmm1 = _mm_mul_ps(vec1, vec1); __m128 xmm2 = _mm_hadd_ps(xmm1, xmm1); __m128 xmm3 = _mm_hadd_ps(xmm2, xmm2); return sqrtf(_mm_cvtss_f32(xmm3)); } 实现将竭尽全力避免执行上述的malloc和memcpying行为,然后再免费提供。在求助于回退之前,它将尝试使用两种行为之一。 1)如果新的大小小于旧的大小,它将在适当的位置调整内存大小,避免分配,复制或释放内存。 2)如果新的大小大于旧的大小,它将(以简化的方式)查看是否有足够的空闲内存相邻,如果是,它将吞噬该内存并适当调整大小。如果不是,则求助于后备。

我提出了一种幼稚的方法,因为我认为大多数提出这个问题的人都不想实现自己的malloc实现。 (尽管我强烈建议这样做是出于教育目的)

希望这可以满足所有投诉!

答案 1 :(得分:2)

Intel Math Kernel Library(免费;适用于Windows,Linux和macOS)版本。 > = 11.3.1具有mkl_realloc可以保持对齐:

简单的例子:

auto p1 = std::aligned_alloc(1024, 1000);
std::cout << reinterpret_cast<std::uintptr_t>(p1) % 1024 << std::endl;
auto p2 = std::realloc(p1, 2000);
std::cout << reinterpret_cast<std::uintptr_t>(p2) % 1024 << std::endl;
auto p3 = std::realloc(p2, 3000);
std::cout << reinterpret_cast<std::uintptr_t>(p3) % 1024 << std::endl;

auto q1 = mkl_malloc(1000, 1024);
std::cout << reinterpret_cast<std::uintptr_t>(q1) % 1024 << std::endl;
auto q2 = mkl_realloc(q1, 2000);
std::cout << reinterpret_cast<std::uintptr_t>(q2) % 1024 << std::endl;
auto q3 = mkl_realloc(q2, 3000);
std::cout << reinterpret_cast<std::uintptr_t>(q3) % 1024 << std::endl;

我的机器上的输出是:

0
784
784
0
0
0