【问题标题】:Allocate several GBs of memory for std::vector为 std::vector 分配几 GB 的内存
【发布时间】:2015-09-24 06:07:07
【问题描述】:

我需要从传感器获取数 GB 的数据。当我尝试使用 malloc(10 或更多 GB。我的系统有 32 GB)分配一个大数组时,它返回 NULL。所以我认为这个问题可以通过向量的迭代器链表来解决。

但是我不知道如何设置。我试着声明“ list" 但我无法为每个向量分配内存(e/o 应该有 1000~2000 个元素)。你知道有什么方法可以做到这一点,或者对于这个大内存分配有更好的解决方案吗?

【问题讨论】:

  • 如果你不需要连续的内存,你可以试试deque,它会分配更小的块。
  • “我的系统有 32GB” - 我假设是 RAM。 RAM 与所有这些无关。您需要了解虚拟内存管理,以及地址空间如何施加真正的限制。
  • 为什么要使用迭代器列表而不是例如向量的向量? (本质上这就是双端队列,但不确定块大小是多少。
  • 您将需要使用保留那么多内存的操作系统功能(因此没有其他应用程序可以使用它)。还要研究如何关闭 virtual memorypaging。您可能必须等待其他程序终止或强制其他程序终止,以便获取它们的内存。
  • @papanoel87 如果您不能获得超过 2GB 的空间,那么您可能拥有 32 位操作系统或应用程序版本。将所有内容移至 64 位,如果仍有问题,请返回。并且请定义“快速”,这不是一个非常精确的术语 - 现在计算机对于大多数操作来说都快得令人眼花缭乱,即使没有优化。

标签: c++ list memory vector std


【解决方案1】:

对于这种数据量,我通常会使用内存映射文件或共享内存映射。

这样,您根本不受可用物理(进程)内存量的限制。您可以根据需要让操作系统页面进出。碎片化不再是一个问题(除非您实际上对逻辑地址空间进行了碎片化,这在 64 位架构上很难实现)。


更多信息

我有很多关于 SO 的答案,其中展示了在共享内存/映射文件中存储向量和各种更复杂数据结构的示例。您可能想要查找 mapped_file_device(来自 Boost Iostreams)或 managed_shared_memorymanaged_mapped_file(来自 Boost Interprocess)

【讨论】:

    【解决方案2】:

    当您必须处理大块内存时,最好完全跳过 malloc 并直接向操作系统调用内存分配。

    【讨论】:

      【解决方案3】:

      如果您使用的是 64 位操作系统,那么 malloc 应该能够毫无问题地分配大尺寸。

      例如,此代码在我的 windows 机器(64 位 windows)上运行并完美分配 10GB 内存:

      #include <stdio.h>
      #include <malloc.h>
      int main(int argc, char *argv[]) {
          long int size = 10L * 1024 * 1024 * 1024;
          printf("size = %ld\n", size);
          char *x = (char *)malloc(size);
          printf("x = 0x%lx\n", x);
          long int i;
          for (i = 0; i < size; i += 1024*1024) {
              x[i] = 'h';
          }
          printf("Done1\n");
      }
      

      但是,如果您有 32 位操作系统,您将遇到麻烦,并且无法分配超过某些限制(可能是 3 GB,但可能取决于系统)

      在这种情况下,您需要将数据写入文件。

      但是,如果您使用的是胖文件系统,那么您也无法写入那么大的文件。在这种情况下,您必须将数据拆分到许多小于 2gb 的文件中。

      您需要实际检查 malloc 结果是否为 NULL,以确保 malloc 正常工作并且可以获取内存。

      【讨论】:

      • 如果因为其他应用程序正在使用内存而无法获取块怎么办?
      • @Thomas:嗯,欢迎来到 21 世纪,我们有进程隔离。每个进程都有自己的地址空间!风靡一时!
      • 我在 64 位窗口下。它可以以 32 位编译吗?我正在使用代码块
      • @papanoel87,这是你的问题!,代码块说,“注意:codeblocks-13.12mingw-setup.exe 文件包括来自 TDM-GCC 的 GCC 编译器和 GDB 调试器(版本 4.7.1, 32 位)。codeblocks-13.12mingw-setup-TDM-GCC-481.exe 文件包括 TDM-GCC 编译器,版本 4.8.1,32 位。而 v4.7.1 是坚如磐石的(我们用它来编译 C ::B), v4.8.1 是为了方便而提供的,这个版本有一些与 Code::Blocks 本身的编译有关的已知错误。所以它是 32 位编译器。瞧!使用 64 位编译器,你'会好的
      • @StarPilot: /LARGEADDRESSAWARE 默认启用 64 位版本,使用 Microsoft 的工具链。我希望 Code::Blocks 使用同样合理的默认值(我知道,它可能不会......)。
      【解决方案4】:

      您需要在 Windows 64 位操作系统下分配此空间。您还必须设置“大地址空间感知”标志,否则由于虚拟内存系统在 Windows 上的工作方式,您只能获得 2 GB 的 RAM。

      如果您不是绝对必须拥有一个 10 GB 的大块连续内存,您可能需要考虑使用内存映射文件,正如 sehe 在他的回答中所建议的那样。如果您必须为 Windows 32 位构建应用程序,那么这将是唯一的答案,因为 Windows 32 位通常只允许 2 GB 内存,除非选项设置为“大地址空间感知”标志,此时它将允许使用 3 GB 的内存。

      【讨论】:

      • 如果在 PE 标头中设置了 Large Address Aware 标志,则 32 位进程可以使用 4GB 的地址空间64 位 Windows。它在使用 /3GB boot.ini-switch 启动的 32 位 Windows 系统上获得 3GB。为 32 位进程处理大于 4GB 的数据缓存的标准方法是使用 Address Windowing Extensions
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-08
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多