geo*_*fas 7 arrays oop ram fortran
尝试使用动态内存分配以两种不同的方式存储一些数据,我注意到RAM要求的巨大差异,我无法解释.一些见解将不胜感激.
在以下示例中,目标是创建一个数据库,该数据库在多边形网格中存储连接到节点的边的ID.但是,问题的性质是无关紧要的.
案例1,使用"普通"数组:
program memorytest
implicit none
integer, dimension(:, :), allocatable :: node_edges
integer :: i
allocate(node_edges(10, 10000000)) ! 10000000 nodes with 10 edges each
node_edges(:, :) = 0
read *, i ! pause
deallocate(node_edges)
end program memorytest
Run Code Online (Sandbox Code Playgroud)
RAM需要:~395,500 K.
案例2,使用节点类型:
program memorytest
implicit none
type node
integer, dimension(:), allocatable :: edges
end type
type(node), dimension(:), allocatable :: nodes
integer :: i
allocate(nodes(10000000)) ! 10000000 nodes
do i = 1, 10000000
allocate(nodes(i)%edges(10)) ! with 10 edges each
end do
do i = 1, 10000000
nodes(i)%edges(:) = 0
end do
read *, i ! pause
do i = 1, 10000000
deallocate(nodes(i)%edges)
end do
deallocate(nodes)
end program memorytest
Run Code Online (Sandbox Code Playgroud)
RAM需要:~1,060,500 K.
为了进行比较,我尝试了C++中的等效方法.
案例1,使用"普通"数组:
#include "stdafx.h"
#include <iostream>
int main()
{
int** node_edges;
int i, j;
node_edges = new int*[10000000]; // 10000000 nodes
for(i = 0; i < 10000000; i++) node_edges[i] = new int[10]; // with 10 edges each
for(i = 0; i < 10000000; i++)
for(j = 0; j < 10; j++) node_edges[i][j] = 0;
std::cin >> i; // pause
for(i = 0; i < 10000000; i++) delete [] node_edges[i];
delete [] node_edges;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
RAM需要:~510,000 K.
案例2,使用节点类:
#include "stdafx.h"
#include <iostream>
class node
{
public:
int* edges;
};
int main()
{
node* nodes;
int i, j;
nodes = new node[10000000]; // 10000000 nodes
for(i = 0; i < 10000000; i++) nodes[i].edges = new int[10]; // with 10 edges each
for(i = 0; i < 10000000; i++)
for(j = 0; j < 10; j++) nodes[i].edges[j] = 0;
std::cin >> i; // pause
for(i = 0; i < 10000000; i++) delete [] nodes[i].edges;
delete [] nodes;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
RAM需要:~510,000 K.
使用的开发环境:英特尔Visual Fortran Studio XE 2013和MS Visual C++ 2010,均在默认的"发布"模式下生成32位可执行文件.
注意,C++对两种方法使用完全相同的RAM量.在Fortran中,我会证明一些细微的差别,但我无法解释.对我而言,这看起来与Fortran本身或某些我不知道的英特尔Fortran编译器标志有关.
任何想法为什么会发生这种情况和/或有什么建议可以避免在Fortran中面向对象的方法中出现过多的RAM需求?
先感谢您.
要记住的一件事是分配二维数组和单维数组是不同的.例如:
allocate(node_edges(10, 100))
Run Code Online (Sandbox Code Playgroud)
分配单个内存块,可以包含1000个项目.
allocate(nodes(100)) ! 10000000 nodes
do i = 1, 100
allocate(nodes(i)%edges(10)) ! with 10 edges each
end do
Run Code Online (Sandbox Code Playgroud)
分配一个块,可以包含100个项目,每个项目有10个子项目.相同数量的项目如此相同的内存使用?
在第二种情况下,您已经分配了100个新阵列.每个都有开销.在Fortran中,这可能非常高,因为它必须跟踪数组维度 - 您可能希望稍后获取数组部分.当分配大小很小时,这尤其明显.在这种情况下它是10并且使用额外的数组信息加上填充它可以使分配的大小加倍 - 它在你的情况下.