C/C++ 中非常大的静态数组的算术运算

Posted

技术标签:

【中文标题】C/C++ 中非常大的静态数组的算术运算【英文标题】:Arithmetic operation on very large static arrays in C/C++ 【发布时间】:2013-03-26 01:26:32 【问题描述】:

我是High Performance Computing 的新手,也是我在这个论坛上的第一个问题,我已经阅读了很长时间。

基本上我需要对非常大的数组进行算术运算,例如

double variable [9][4][300][300][300] (uninitialized)

案例 1: 如果我将上面的数组声明为 local/automatic,那么如果我在没有优化的情况下编译 like "g++ file.cpp" 就会出现运行时错误。 .(错误是分段错误——堆栈溢出???)

案例 2: 在与上述相同的情况下,如果我进行了优化编译,代码将按预期运行。 "g++ -O2 file.cpp"(现在是bss 中的array???)

案例3:如果我创建变量global/static,那么它编译得很好,但它仍然没有运行,只是在终端上给出一条消息“killed”并终止。

没有真正的问题,但我很好奇,想了解当声明超大数组时会发生什么,以及它们驻留在内存中的位置,具体取决于它们的数据类型。

我也知道在运行时使用 malloc 或 new 生成这些数组的方法。那么它当然会在堆上。

所以对我来说最重要的问题是 --> 当使用g++ 编译并在linux clusters 上运行时,这是处理大型数组的最有效方法(即内存中数组计算期间的最小运行时间) .

感谢您的耐心阅读。

【问题讨论】:

那个数组简直是疯了。您需要使用更智能的解决方案来处理大量数据,除非您的目标平台是某种野兽般的机器。由于情况似乎并非如此,因此请以块或类似的方式从磁盘流式传输数据。 这些数组是不可避免的。它们代表 4 维空间中的变量。并且记忆操作解决了复杂的非线性微分方程。最终,代码将在 50 个节点的集群上运行,并且内存超过 100 GB。数据确实是从磁盘读取的。我的好奇心是了解这些数据在运行时的位置以及哪个部分(bss/stack/heap)会提供最快的运行时性能。 我真的建议您根据一些数学库(如犰狳或 BLAS)来完成您的工作。你做的任何事情,我的意思是任何事情,都无法超越这些库的性能。考虑从一开始就使用它们:) @physicist:数据是不可避免的,存储和处理方法不是。就像我说的那样,将该数组 存储在您的可执行文件中 是行不通的,除非您可以假设您的代码只会在可以处理它的机器上运行。由于情况并非如此,因此您必须改变方法。您可以将数据存储在磁盘上并一次读取块。分解、处理、存储相关信息并读取下一个块。 不要在这里重新发明***。如果您是这种计算的新手,那么您想使用一些东西来使这一切尽可能轻松。我使用过的两个非线性偏微分方程库是dealii.org 和libmesh.sourceforge.net,它们可以满足您的需求(包括集群支持等)。如果他们没有,那里有很多类似的库。 【参考方案1】:

我可以提出一些类似的建议:

typedef double slice[300][300][300];

std::vector<slice> variable[9] =  4, 4, 4, 4, 4, 4, 4, 4, 4 ;

这样4个slice对象的每个向量都会被动态分配,9个向量的内容不需要相互连续,堆栈消耗只够9个向量的元数据。

【讨论】:

这是一种有趣的方法。让我试试看。谢谢。【参考方案2】:

无论优化标志如何,局部变量总是在堆栈上。这个数组大约有 7 GB!比任何可能的堆栈都要大。

大小也可能是它无法启动的原因,就好像你把它作为一个全局/静态变量那么你需要有超过 7 GB 或虚拟内存 空闲连续甚至能够加载程序。

【讨论】:

所以对于案例 2(来自问题),数组仍在堆栈中。我认为堆栈的大小限制为 8kb?我没听错吗?我没有提供任何编译时间选项来增加堆栈限制。 除非变量被优化掉,否则它一无是处。 @physicist 大多数现代系统上的堆栈大小在 1 到 4 兆字节之间。您可能可以将标志传递给某些系统的链接器以更改它,但是堆栈将是整个程序的大小,并且大多数时候只有一小部分(可能不到 7GB 的 0.5%)将是用过的。大量的内存浪费。在普通家用 PC 上处理大型数据集有更好的方法,例如内存映射文件。 @physicist Stack vs BSS vs DATA vs heap 并不是“速度”的一个因素。特别是因为无论如何它都将被放入 CPU 缓存中。 @physicist:虽然如此大的数据结构不是任何程序员的首选,但如果您需要它们,堆的设计就是为了让它工作。 OTOH 自动和全局变量并非旨在支持如此大的大小。

以上是关于C/C++ 中非常大的静态数组的算术运算的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp C中的算术运算符

c/c++ 运算溢出问题

0202 算术运算符

MATLAB-算术运算

算术运算符

Elasticsearch:使用算术运算的临时 Runtime field