尝试使用动态内存分配以两种不同的方式存储一些数据,我注意到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
需要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
需要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;
}
需要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;
}
需要RAM:~510,000 K
使用的开发环境:英特尔Visual Fortran Studio XE 2013和MS Visual C ++ 2010,均以默认的“发布”模式生成32位可执行文件。
正如所注意到的,C ++对两种方法使用完全相同的RAM量。在Fortran中,我会证明一些细微的差别,但我无法解释。对我而言,这看起来与Fortran本身或某些我不知道的英特尔fortran编译器标志有关。
为什么会发生这种情况和/或在Fortran中以面向对象的方法避免RAM过多RAM的任何建议?
提前谢谢。
答案 0 :(得分:9)
要记住的一件事是分配二维数组和单维数组是不同的。例如:
allocate(node_edges(10, 100))
分配一个可包含1000个项目的内存块。
allocate(nodes(100)) ! 10000000 nodes
do i = 1, 100
allocate(nodes(i)%edges(10)) ! with 10 edges each
end do
分配一个块,可以包含100个项目,每个项目有10个子项目。相同数量的项目如此相同的内存使用情况?
没有。在第二种情况下,您已经分配了100个新阵列。每个都有开销。在Fortran中,这可能非常高,因为它必须跟踪数组维度 - 您可能希望稍后获取数组部分。当分配大小很小时,这尤其明显。在这种情况下它是10并且使用额外的数组信息加上填充它可以使分配的大小加倍 - 在你的情况下它就是。