Fortran:普通数组与存储相同数据量的对象所需的RAM

时间:2013-11-26 15:20:29

标签: arrays oop fortran ram

尝试使用动态内存分配以两种不同的方式存储一些数据,我注意到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的任何建议?

提前谢谢。

1 个答案:

答案 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并且使用额外的数组信息加上填充它可以使分配的大小加倍 - 在你的情况下它就是。