如何在C++;? S>强>我现在尝试动态地在C++中分配大量的数组(使用“新”)< /强>。显然,当“大”变得太大(>4GB)时,我的程序会崩溃并出现“bad_alloc”异常,因为它找不到如此大的可用内存块

如何在C++;? S>强>我现在尝试动态地在C++中分配大量的数组(使用“新”)< /强>。显然,当“大”变得太大(>4GB)时,我的程序会崩溃并出现“bad_alloc”异常,因为它找不到如此大的可用内存块,c++,dynamic-memory-allocation,large-data,dynamic-arrays,deque,C++,Dynamic Memory Allocation,Large Data,Dynamic Arrays,Deque,我可以分别分配数组中的每个元素,然后将指向这些元素的指针存储在单独的数组中。但是,时间在我的应用程序中非常关键,因此我希望尽可能避免缓存未命中。我也可以将这些元素组合成块,但是对于这样一个块来说,最好的尺寸是什么 我的问题是:动态分配一个大型元素数组的最佳方法是什么(按时间)使元素不必连续存储,但必须通过索引(使用[])访问它们?此数组永远不会调整大小,不会插入或删除任何元素 我想我可以使用std::deque来实现这一目的,因为我知道std::deque的元素可能会或可能不会连续存储在内存中,

我可以分别分配数组中的每个元素,然后将指向这些元素的指针存储在单独的数组中。但是,时间在我的应用程序中非常关键,因此我希望尽可能避免缓存未命中。我也可以将这些元素组合成块,但是对于这样一个块来说,最好的尺寸是什么

我的问题是:动态分配一个大型元素数组的最佳方法是什么(按时间)使元素不必连续存储,但必须通过索引(使用[])访问它们?此数组永远不会调整大小,不会插入或删除任何元素

我想我可以使用std::deque来实现这一目的,因为我知道std::deque的元素可能会或可能不会连续存储在内存中,但我了解到有人担心这个容器会占用额外的内存


谢谢你在这方面的帮助

如果您的问题是实际内存不足,分配相当小的块(如deque所做的)不会有帮助,那么跟踪分配的开销只会使情况变得更糟。您需要重新思考您的实现,以便能够在仍然适合内存的块中处理它。对于这样的问题,如果使用基于x86或x64的硬件,我建议使用至少2兆字节的块(较大的页面大小)。

这个问题的答案非常依赖于应用程序和平台。现在,如果您只需要一个大于4GB的小整数因子,如果可能的话,您可以使用64位机器。有时也可以减小数组中元素的大小。(例如,使用16位定点半浮点数而不是32位浮点数。)

除此之外,您还可以研究稀疏阵列或非核心技术。如果不是在数组中的所有位置实际存储元素,则使用稀疏数组。有许多可能的实现,哪种实现最好取决于数据的分布和算法的访问模式。例如,见

Out-of-core涉及显式地将阵列的一部分读写到磁盘或从磁盘中读写。这种情况过去相当普遍,但现在人们努力避免这样做。真正需要这样的应用程序通常构建在数据库或类似数据库之上,以处理数据管理。在科学计算中,最终需要分配计算和数据存储,因此这也有很多复杂性。对于重要问题,整个设计可以通过具有良好的参考位置来驱动

任何稀疏数据结构占用的空间都会增加开销。这可能相当低,但这意味着您必须小心,如果您实际上有一个密集的数组,并且只是希望避免内存碎片


如果您的问题可以分解为更小的部分,一次只能访问数组的一部分,而主要问题是内存碎片导致难以分配一个大的块,那么将数组分解为多个部分,有效地添加指针的外部向量,这是一个很好的选择。如果您对大于4G字节的阵列进行随机访问,并且无法对访问进行本地化,则64位是最佳选择。

这取决于您的内存需求和速度问题,如果您使用的是Linux,您可以尝试使用mmap并模拟某种交换。它可能会慢一些,但您可以映射非常大的尺寸。看

显然,当“大”变得太大(>4GB)时,我的程序就会崩溃 因为找不到这么大的块,所以出现了“bad_alloc”异常 可用内存的数量

此时您应该使用64位CPU和操作系统,分配巨大的连续内存块应该不是问题,除非您的内存实际耗尽。您可能正在构建32位程序。在这种情况下,您将无法分配超过4 GB的内存。您应该构建64位应用程序

如果您想要比普通的
操作符new
更好的东西,那么您的问题是特定于操作系统的。查看操作系统提供的API:在POSIX系统上,您应该在Windows上查找
mmap
VirtualAlloc

大型分配存在多个问题:

  • 出于安全原因,OS内核从来不会给您充满垃圾值的页面,相反,所有新内存都将被零初始化。这意味着您不必初始化该内存,只要零正是您想要的
  • 操作系统在第一次访问时提供真正的内存。如果您正在处理大型阵列,则可能会浪费大量时间来处理页面错误。为了避免这种情况,您可以在Linux上使用
    MAP\u POPULATE
    。在Windows上,您可以尝试
    预回迁虚拟内存
    (但我不确定它是否能完成此任务)。这会使初始化分配变慢,但会减少在内核中花费的总时间
  • 处理大块内存会浪费翻译查找缓冲区(TLB)中的插槽。根据您的内存访问模式,这可能会导致明显的速度减慢。为了避免这种情况,您可以尝试使用大型页面(
    mmap
    MAP\u HUGETLB
    MAP\u-mag\u-2MB
    、Linux上的
    MAP\u-mag\u-1GB
    VirtualAlloc
    MEM\u-large\u-pages
    )。使用大页面并不容易,因为默认情况下它们通常不可用。它们也不能被调出(总是“锁定在内存中”),因此使用它们需要特权

如果你不想使用OS特定的函数,C++中最好的是<代码> STD::CaloC。不同于

std::malloc
操作员新建