3

我正在尝试编写一个会占用大量内存的 Fortran 程序(有关其背后的原因,请参阅本问题末尾的注释)。我通过分配一个 3 维大小的数组(n,n,n)然后释放它来做到这一点 - 不断增加n直到我用完内存(这应该在使用 ~16 GB 内存时发生)。不幸的是,在我看到系统资源达到 16 GB 之前,我的程序似乎内存不足。

这是我的示例代码:

 1 program fill_mem
 2   implicit none
 3   integer, parameter :: ikind = selected_int_kind(8)
 4   integer, parameter :: rkind = 8
 5
 6   integer(kind = ikind) :: nfiles = 100
 7   integer(kind = ikind) :: n = 1200
 8   integer(kind = ikind) :: i, nn
 9
10   real(kind = rkind), allocatable :: real_arr(:,:,:)
11
12   character(500) :: sysline
13
14
15   call system('echo ''***no_allocation***'' > outfile')
16   call system('ps aux | grep fill_mem.exe >> outfile')
17   !call system('smem | grep fill_mem.exe >> sm.out')
18   allocate(real_arr(n, n, n))
19
20   nn = 100000
21   do i = 1,nn
22     deallocate(real_arr)
23     n = n + 10
24     print*, 'n = ', n
25     allocate(real_arr(n, n, n))
26     call system('echo ''*************'' >> outfile')
27     write(sysline, *) 'allocation', i, '... n = ', n
28
29     write(*, '(f10.5, a)') 100.0*real(i)/real(nn), '%'
30
31     call system(trim(adjustl('echo '//sysline//'>> outfile')))
32     call system('ps aux | grep fill_mem.exe >> outfile')
33   enddo
34
35 end program fill_mem

这是示例输出:

 1 ***no_allocation***
 2 1000     12350  0.0  0.0  12780   760 pts/1    S+   13:32   0:00 ./fill_mem.exe
 3 1000     12352  0.0  0.0   4400   616 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
 4 1000     12354  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
 5 *************
 6 allocation 1 ... n = 1210
 7 1000     12350  0.0  0.0 13853104 796 pts/1    S+   13:32   0:00 ./fill_mem.exe
 8 1000     12357  0.0  0.0   4400   616 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
 9 1000     12359  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
10 *************
11 allocation 2 ... n = 1220
12 1000     12350  0.0  0.0 14199096 952 pts/1    S+   13:32   0:00 ./fill_mem.exe
13 1000     12362  0.0  0.0   4400   612 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
14 1000     12364  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
15 *************
16 allocation 3 ... n = 1230
17 1000     12350  0.0  0.0 14550804 956 pts/1    S+   13:32   0:00 ./fill_mem.exe
18 1000     12367  0.0  0.0   4400   612 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
19 1000     12369  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
20 *************
21 allocation 4 ... n = 1240
22 1000     12350  0.0  0.0 14908284 956 pts/1    S+   13:32   0:00 ./fill_mem.exe
23 1000     12372  0.0  0.0   4400   612 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
24 1000     12374  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
25 *************
26 allocation 5 ... n = 1250
27 1000     12350  0.0  0.0 15271572 956 pts/1    S+   13:32   0:00 ./fill_mem.exe
28 1000     12377  0.0  0.0   4400   612 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
29 1000     12379  0.0  0.0   9384   916 pts/1    S+   13:32   0:00 grep fill_mem.exe
30 *************
31 allocation 6 ... n = 1260
32 1000     12350  0.0  0.0 15640720 956 pts/1    S+   13:32   0:00 ./fill_mem.exe
33 1000     12382  0.0  0.0   4400   616 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
34 1000     12384  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe
35 *************
36 allocation 7 ... n = 1270
37 1000     12350  0.0  0.0 16015776 956 pts/1    S+   13:32   0:00 ./fill_mem.exe
38 1000     12387  0.0  0.0   4400   616 pts/1    S+   13:32   0:00 sh -c ps aux | grep fill_mem.exe >> outfile
39 1000     12389  0.0  0.0   9384   920 pts/1    S+   13:32   0:00 grep fill_mem.exe

现在,我看到 VSZ 部分高达 ~15 GB,所以我假设当我尝试解决更多问题时,它会失败

Operating system error: Cannot allocate memory
Allocation would exceed memory limit

因为没有那么多内存。但是,为什么 RSS 远低于这个值呢?当我实际查看我的系统资源时,我发现大约有 140 MB 被用完(我在 Linux VM 中运行它并通过 Windows 监视系统资源 - 我已经给 GM 16 GB 的 RAM 以供使用,所以我应该看到虚拟机内存不断增加,直到达到 16 GB 标记 - 就其价值而言,虚拟机具有 VT-x/嵌套分页/PAE/NX,因此它应该使用物理架构,就像本机操作系统一样)。

谁能解释为什么我没有看到我的程序实际上用尽了 16 GB 的 RAM,以及我如何编写代码以将我正在创建的这些数组保留在 RAM 中 - 充分利用我的可用硬件?

注意:我试图编写一个读取大量内存的示例程序的原因是我正在处理在 ascii 文本中占用大约 14 GB 空间的数据。在整个程序过程中,我需要处理大量数据,因此我想一次将其全部读入,然后在整个程序期间从 RAM 中引用它。为了确保我正确地执行此操作,我正在尝试编写一个简单的程序,它将一次在内存中存储一​​个非常大的数组(~15 GB)。

4

2 回答 2

7

(警告:Fortran 标准没有说明应该如何实现这样的东西等,下面的描述是指 Fortran 编译器通常如何在当前操作系统上实现。)

当您执行 ALLOCATE 语句(或等效地,在 C、FWIW 中调用 malloc() )时,您实际上并没有保留物理内存,而只是为您的进程映射地址空间。这就是为什么 VSZ 上升,而不是 RSS。实际上,仅在您第一次访问内存时才会为您的进程保留物理内存(通常以页面大小粒度,即最新硬件上的 4 KB)。因此,只有当您开始将一些数据放入阵列时,RSS 才会开始攀升。例如像这样的声明

real_arr = 42.

应该将您的 RSS 提高到 VSZ 附近。

于 2013-10-13T21:07:15.810 回答
1

您可能需要增加分配给堆栈的内存。例如,请参阅http://software.intel.com/en-us/articles/intel-fortran-compiler-increased-stack-usage-of-80-or-higher-compilers-causes-segmentation-fault

于 2013-10-13T19:01:43.760 回答