【问题标题】:Contiguous Memory Allocation连续内存分配
【发布时间】:2013-05-17 05:12:08
【问题描述】:

在一个应用程序中,我必须分配两个每个 480 MB 的缓冲区。内存分配是使用 HeapAlloc 方法完成的。该应用程序在运行不多的应用程序的系统中运行良好。但是在其他应用程序也在运行的系统中,由于连续内存不可用,因此不会分配内存。即使内存空间(非连续)可用但未分配。

即使有非连续内存可用,也需要帮助分配两个 480 MB 的缓冲区。

【问题讨论】:

  • 你不能。添加更多内存(交换或 RAM),或使用非连续容器,例如 std::deque
  • 你能通过使用 2 个内存映射文件获得类似的结果吗?此时,系统会管理内存,但您会看到一个扁平的、连续的块 IIRC。
  • @JimR:这与您从普通分配函数中获得的结果并没有太大不同,除了使用普通分配函数时系统内存映射页面文件并且还知道您实际上更愿意避免将更改写入磁盘。
  • @BenVoigt:我想到的好处是系统会为您管理内存问题。可能值得一试...

标签: c++ memory-management


【解决方案1】:

您描述的情况在为每个进程提供自己的地址空间的全功能操作系统中是不可能的。不管有多少其他应用程序正在运行,它们都不会影响进程中可用地址空间的连续性。并且虚拟内存可以将不连续的物理内存地址映射到虚拟地址空间中的一个连续范围。

只有在没有内存管理单元的嵌入式系统中,其他任务的存在才会导致您的程序遭受内存碎片。

HeapAlloc() 建议使用 Windows,它确实为每个进程提供了单独的地址空间。最可能的解释是,您的私有地址空间被加载在分散位置的库 (DLL) 所分割。您可以对您使用的库进行变基以避免这种情况,并提供更大的连续地址空间块。

【讨论】:

  • 用户空间 vs 内核空间 vs 物理内存。在我的每个程序员都应该知道的事情清单上。
【解决方案2】:

您可以将VirtualAlloc 与指定为MEM_LARGE_PAGESfAllocation 一起使用。这会启用large page support,注意必须勾选GetLargePageMinimum,以确保系统支持大页面。

另请注意,这可能会很慢,因为此页面details

大页面内存区域在系统运行时间长后可能难以获得,因为每个大页面的物理空间必须是连续的,但内存可能已经碎片化。在这些情况下分配大页面会显着影响系统性能。因此,应用程序应避免重复分配大页面,而是在启动时一次性分配所有大页面。

【讨论】:

  • 单个页面的大小不会对此产生太大影响。在大数组中进行随机访问时,大页面是可取的,因为页表中的每个条目对应于更大比例的数据,因此需要的条目更少,并且更有可能全部适合转换后备缓冲区(充当页表的缓存)。
【解决方案3】:

使用 VirtualAlloc。支持虚拟页面的底层内存不必是连续的,并且您将始终拥有完整的虚拟地址空间(在 32 位系统上为 2GB,我认为在 Windows x64 上为 8 或 16 TB,我不记得了。)HeapAlloc 可以变成碎片化(通过您的进程使用,而不是其他人。)您的地址空间也可能变得碎片化,因此请尝试在应用程序的早期分配它。我实际上不推荐 HeapAlloc 做任何事情,你可以只使用 new 和 delete(调用 malloc 和 free)对于像你这样的大块 malloc 将在 Windows 上调用 VirtualAlloc。

【讨论】:

  • HeapAlloc 也会调用VirtualAlloc
  • 我不知道,听起来问题是地址空间碎片。正如你所说,可能是由加载的库引起的。
  • 好吧,显然它是创建堆时的一个选项。 “如果 dwMaximumSize 为 0,堆的大小可以增长。堆的大小仅受可用内存的限制。分配大于固定大小堆限制的内存块的请求不会自动失败;相反,系统调用VirtualAlloc 函数获取大块所需的内存。需要分配大块内存的应用程序应将 dwMaximumSize 设置为 0。"
猜你喜欢
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多