目前我正在编写 Fortran 95 中的数值模拟代码。我的平台是 WIndows,我利用 MSVC 环境和 Intel Fortran 编译器。该代码与该领域中的许多代码一样,创建了一个待解决的方程组。在数值上,这发生在存储一个方阵和一个已知值的向量。现在,为了优化内存,矩阵以方便的形式存储,如压缩稀疏行格式 (CSR) 或类似格式,因此不存储零值。
鉴于这个简短的介绍,这里有我的疑问。由于在编译时我不知道数组的维度,我只是将它们声明为:
REAL, DIMENSION(:), ALLOCATABLE :: myArray
一旦我检索到这样一个向量的维度,我就会调用
ALLOCATE(myArray(N)) where N is the number of elements that I want to allocate
- 尽管如此,内存还是空的,因为没有存储值,但是为了避免堆栈溢出,会进行内存检查。这样对吗?
现在,用值填充它,占用的空间增加了。Fortran 数组的结构,无论是一维向量还是多维数组,都是在列序中填充一个与值的个数相等的空间。也就是说,如果我们有一个维度为 1000x1000 的 2D 数组,它将存储在按列号排序的 1M 个“连续框”中(首先存储第一列,然后存储第二列,依此类推..)。
如果这是真的,那么数据的结构是相同的,对特定值的访问时间是多维向量和一维向量之间的唯一区别吗?
那么命令是否
RESHAPE
只改变程序“看到”数组的方式?
我需要的数组在每个子例程/函数共享的模块中定义。特别是,子程序分配和填充它。回到主程序,这没有问题,因为我向用户显示了一些关于它的统计数据。假设我们分配了 400M REAL*4 值,使用了大约 1.5GB 的内存。
但是,一旦我进入另一个子程序,程序就会停止说
forrtl: severe(170): Program Exception - Stack Overflow
. 我内存不足。但是如果矩阵已经分配并且我没有分配更多的东西怎么办?注意:子程序使用相同的模块,所以变量已经声明了;我的 RAM 仍有大约 1.3GB 的可用空间;停止在子程序的第一行。子程序(以及函数)是否将数据加倍?我认为在这种情况下,Fortran 会传递我的变量地址,避免复制并直接处理这些值。
最后,和你们中的许多人一样,我喜欢 C++ 中的 STD 库函数,比如 vector::push_back 等等。在 Fortran 中,没有这么漂亮的例程,但仍然有一些非常有用的函数。屏蔽数组,使用WHERE
or COUNT
orMERGE
可以帮助你有效地处理一些操作。
- 但是,当我的矩阵大于 1M 条目时,它们会非常缓慢。在这种情况下,即使是顺序搜索和替换也比创建掩码或使用 where 更快。怎么可能?他们不是多线程的吗?
预先感谢您的耐心等待!!非常欢迎所有建议!