动态分配将数据存储在堆中的随机位置吗?

时间:2019-03-16 08:10:28

标签: c++ caching heap dynamic-memory-allocation

我知道局部变量将有序地存储在堆栈中。

但是,当我像这样用c ++在堆内存中动态分配变量时。

int * a = new int{1};
int * a2 = new int{2};
int * a3 = new int{3};
int * a4 = new int{4};

问题1:这些变量是否存储在连续的内存位置中? 问题2:是否不是因为动态分配将变量存储在堆内存中的随机位置? 问题3:动态分配会增加高速缓存未命中的可能性并降低空间局部性吗?

3 个答案:

答案 0 :(得分:1)

第1部分:单独的分配是否连续?

答案是可能不是。动态分配如何发生取决于实现。如果像上面的示例一样分配内存,则两个单独的分配可能是连续的,但是不能保证会发生这种情况(并且永远不应依赖于这种情况)。

c ++的不同实现使用不同的算法来决定如何分配内存。

第2部分:分配是随机的吗?

有点;但并非完全如此。内存不会以故意随机的方式分配。通常,内存分配器会尝试将彼此相邻的内存块分配在一起,以最大程度地减少页面错误和高速缓存未命中,但并非总是可以这样做。

分配过程分为两个阶段:

  1. 分配器从操作系统请求大量内存
  2. 这些块将占用大量的大块,并在每次调用new时将其返回,直到您请求的内存超过其必须提供的内存为止,在这种情况下,它将从操作系统中请求另一个大块。

在第二阶段,实现可以尝试为您提供接近其他最近分配的内存,但是它对第一阶段几乎没有控制(并且操作系统通常仅提供可用的任何内存,而无需其他任何知识由您的程序分配)。

第3部分:避免缓存丢失

如果高速缓存未命中是代码中的瓶颈,则

  • 尝试减少间接数量(通过使数组按值而不是指针存储对象);
  • 确保您正在操作的内存在设计允许的范围内是连续的(因此,请使用std :: array或std :: vector而不是链接列表,并且应将较大的分配分配给许多较小的分配);和
  • 尝试设计算法,使其必须尽可能少地在内存中跳转。

一个好的通用原则是只使用对象的std :: vector,除非您有充分的理由使用更高级的东西。因为它们具有更好的缓存局部性,所以std :: vector在插入和删除元素方面比std :: list更快,甚至多达数十甚至数百个元素。

最后:尝试利用堆栈。除非有充分的理由使某个东西成为指针,否则只需声明为存在于堆栈中的变量即可。

  • 首选使用MyClass x{};代替MyClass* x = new MyClass{};,并且
  • 首选std::vector<MyClass>而不是std::vector<MyClass*>

通过扩展,如果可以使用静态多态性(即模板),请使用它代替动态多态性。

答案 1 :(得分:0)

恕我直言,这是特定于操作系统/ C ++标准库的实现。

<script type="text/javascript"> var map; // declare as global function initMap() { var uluru = {lat: 37.7749, lng: -122.4194}; //\/ --- initialize the global `map` variable (don't create a new local map variable) map = new google.maps.Map(document.getElementById('map'), { zoom: 10, // standard google map javascript } //end of initMap() $('#id_zoomlevel').on('change', function() { var zoomlevel = $('#id\_zoomlevel :selected').attr('value'); map.setZoom(zoomlevel); }); </script> 最终使用较低级别的虚拟内存分配服务,并通过mmap和munmap之类的系统调用一次分配多个页面。 new的实现可以在相关时重用以前释放的内存空间。 new的实现可以对“大”和“小”分配使用各种不同的策略。

在该示例中,您给系统的第一个new结果用于内存分配(通常是几页),分配的内存可能足够大,因此后续的new调用会导致连续分配。 。但这取决于实现方式

答案 2 :(得分:0)

简而言之:

  1. 一点都不(由于对齐,堆管理数据,分配的块可能被重用等导致填充),

  2. 一点也不(AFAIK,堆算法是确定性的,没有任何随机性),

  3. 通常是(例如,内存池可能对此有所帮助)。