Fortran Coder

查看: 339|回复: 3

[讨论] 大数组整体操作的堆栈问题

[复制链接]

36

帖子

12

主题

0

精华

熟手

F 币
142 元
贡献
80 点
发表于 2022-12-20 17:06:48 | 显示全部楼层 |阅读模式
先贴代码
-----------------------------------------------------
[Fortran] 纯文本查看 复制代码
  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行一列的数组,
捕获2.PNG

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

1820

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
760 元
贡献
305 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2022-12-20 17:27:14 | 显示全部楼层
100万行1列,如果是real类型的话,只占4MB(double占8MB)。你看看你一行代码里需要几个这样的数组?
乘上去,就能算出所需的内存(堆栈部分),一般不需要调到1000000000这么大。(这个数字是1GB)

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

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

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

36

帖子

12

主题

0

精华

熟手

F 币
142 元
贡献
80 点
 楼主| 发表于 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来实现吧?

1820

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
760 元
贡献
305 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 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 我没有了解,关于它的问题,我也不甚清楚。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2023-2-4 17:15

Powered by Tencent X3.4

© 2013-2023 Tencent

快速回复 返回顶部 返回列表