静待花开 发表于 2022-12-20 17:06:48

大数组整体操作的堆栈问题

先贴代码
-----------------------------------------------------
X = 0.5*(-MATMUL((R+S), VX(:, temp_A)) + MATMUL((1.0+R), VX(:, temp_B)) + MATMUL((1.0+S), VX(:, temp_C)))
Y = 0.5*(-MATMUL((R+S), VY(:, temp_A)) + MATMUL((1.0+R), VY(:, temp_B)) + MATMUL((1.0+S), VY(:, temp_C)))
-----------------------------------------------------
运行后提示溢出(如下所示),调试发现问题就出在上面这两行代码。X 是50万行1列的数组,Y也是50万行1列的数组。VX和VY都 是约7500行1列的数组,R和S是66行一列的数组,


后来查到可以在IVF里按下面做调整(运行fortran出现stack overflow错误怎么办-百度经验 (baidu.com))。把0调整到最大1000000000。可以运行成功,得到了想要的结果。但有个疑问,就是如果X和Y的数组规模更大一点呢?达到100万行1列呢?这样设置是否能仍然有效呢?是否能把这两行代码做一些调整,可以不需要调整这个参数,并且能适用于更大规模数组呢?


fcode 发表于 2022-12-20 17:27:14

100万行1列,如果是real类型的话,只占4MB(double占8MB)。你看看你一行代码里需要几个这样的数组?
乘上去,就能算出所需的内存(堆栈部分),一般不需要调到1000000000这么大。(这个数字是1GB)

如果是你自己用的代码,堆栈只要能调出来,能算下去,就无所谓。

而像我这样写商业软件的,堆栈会比较节省。因为还要给UI部分预留内存,要考虑到多线程使用(每个线程的堆栈是独立的)。
    此外,不知道客户的电脑硬件配置如何,只能尽可能降低程序对硬件的要求。

更大型数组,应该避免使用内部函数进行整体操作。还是分块,或者老老实实循环吧。

静待花开 发表于 2022-12-20 20:06:34

fcode 发表于 2022-12-20 17:27
100万行1列,如果是real类型的话,只占4MB(double占8MB)。你看看你一行代码里需要几个这样的数组?
乘上 ...

非常感谢您的回复。
X,R和S,VX和VY,都是real(kind=8)类型 ,算下来也没有占多大空间,没想到会溢出。我想到的就是用了内部函数MATMUL的原因。在网上也查了,有人做了对比:自己编码和使用内部函数MATMUL,最后发现还是用MATMUL的计算效率最高。我这个程序,100万行也不是最大的,X和Y最高可能达上500~600万行。我的这个代码是纯计算,没有界面,不用考虑UI占用内存。有两个问题想请教您。
(1)老老实实循环,是就完全可以避免溢出了吗?就不需要调整上面两个参数吗?
(2)像上面那样设置成1G的话,这样运行程序时,要求计算机必须有1G以上的内存吗?
(3)您讲的分块,就是可以借助CUDA-FORTRAN来实现吧?

fcode 发表于 2022-12-21 08:26:21

是的,很多时候,在编程中,时间优势和空间优势不可兼得。
某个操作让你降低了对内存空间的需求,多半需要牺牲时间来换取。反之同理。

在回答你的问题前,有几个前置知识你需要了解:
1. 你编写的程序,能使用的内存空间。并不直接等于运行该程序计算机的物理内存。
实际上,操作系统(比如windows/linux)会接管对内存的管理。
最终可用多少,取决于多种因素。包括但不限于:
a. 物理内存
b. 操作系统的位数(32位/64位。注意32位理论寻址空间只有4GB,除去程序代码和必要数据,留给程序员的空间在2-3GB左右)
c. 同时运行的其他进程(软件)
d. 操作系统自身开启的服务;
e. 虚拟内存(windows)或交换区(linux)的设置等。

2. 在可用的内存空间中,有一块特殊的,叫做堆栈。显然,堆栈的大小必须小于可用内存空间。
如果你把你居住的房子比做可用内存的话,堆栈大概相当于你的桌子。桌子不能太大,需要给房间的其他东西留有足够的余地。
堆栈比其他内存的部分,更适合于需要临时存储,快速读取和存放的内容。想一想你要在桌子上工作,哪些东西你会放在桌子上,哪些东西你会放在衣柜里?

3. 你的问题,是堆栈溢出。(不一定是整个可用内存空间不足)

回到你的问题:
1. 老老实实循环,可以降低对堆栈的需求。可以避免堆栈溢出。但不能避免可用内存不足的问题。
   上面的2个参数,是调整堆栈的大小。再次强调,堆栈不应该太大。设置成1GB大多数时候是不合理的。(当然你只是要求自己用,能算出结果就行,那无所谓)
2. 把堆栈设置成1GB,并不一定要求计算机的物理内存需要有1GB,如上所述,操作系统有虚拟内存或交换区。再说,现在谁的电脑还没有1G内存?
3. 我说的分块,是指:比如算一个10W的矩阵,先算1-10000的部分。再算10001-20000的部分......以此内推,直到所有分块都计算完成。
   Cuda-Fortran 我没有了解,关于它的问题,我也不甚清楚。
页: [1]
查看完整版本: 大数组整体操作的堆栈问题