Memory allocation in Fortran does not lead to an error, but during initialization the program is destroyed by the OS

Given the minimum working example below, do you know why a memory allocation error does not occur at the memory allocation stage? When I checked, when I use valgrind to run the code or add the source = 0.0 parameter to the memory allocation instruction, then I have, as expected, a memory allocation error.

Update: I reproduced the problem with a minimal working example:

 program memory_test

  implicit none

  double precision, dimension(:,:,:,:), allocatable :: sensitivity
  double precision, allocatable :: sa(:)
  double precision, allocatable :: sa2(:)

  integer :: ierr,nnz
  integer :: nx,ny,nz,ndata

  nx = 50
  ny = 50
  nz = 100
  ndata = 1600

  allocate(sensitivity(nx,ny,nz,ndata),stat=ierr)

  sensitivity = 1.0

  nnz = 100000000

  !allocate(sa(nnz),source=dble(0.0),stat=ierr)
  allocate(sa(nnz),stat=ierr)
  if(ierr /= 0) print*, 'Memory error!'

  !allocate(sa2(nnz),source=dble(0.0),stat=ierr)
  allocate(sa2(nnz),stat=ierr)
  if(ierr /= 0) print*, 'Memory error!'

  print*, 'Start initialization'

  sa = 0.0
  sa2 = 0.0

  print*, 'End initialization'

end program memory_test

When I run it, I do not have the message "Memory Error!". printed, but have the message "Start initialization", and then the program will be destroyed by the OS. If I use memory allocation with the "source" parameter (as indicated in the code), then I have the message "Memory error!".

"free" :

             total       used       free     shared    buffers     cached
Mem:       8169952    3630284    4539668      46240       1684     124888
-/+ buffers/cache:    3503712    4666240
Swap:            0          0          0
+4
3

, linux. , , ( , Fortran, ). , . , .

:

program test
   implicit none
   real,allocatable :: array(:) 

   allocate(array(1000000000)) !4 gb array

   print *,'Check memory - 4 GB allocated'
   read *

   array(1:1000000) = 1.0

   print *,'Check memory - 4 MB assigned'
   read *

   array(1000000:100000000) = 2.0

   print *,'Check memory - 400 MB assigned'
   read *

   array = 5.0

   print *,'Check memory - 4 GB assigned'
   read *

end program

4 , 4 , 396 ( = 400 ) , , ( = 4 ). , .

, :

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                           
29192 casey     20   0 3921188   1176   1052 S   0.0  0.0   0:00.00 fortranalloc

(VIRT), (RES).

4 :

29192 casey     20   0 3921188   5992   1984 S   0.0  0.0   0:00.00 fortranalloc

396 :

29192 casey     20   0 3921188 392752   1984 S   0.0  1.6   0:00.18 fortranalloc

4 :

29192 casey     20   0 3921188 3.727g   1984 S  56.6 15.8   0:01.88 fortranalloc 

, , . , , , allocate() . source allocate, , , , .

, , , , - linux OOM Killer, , . , OOM Killer , , , . , , . ( ), - , .

+6

, :

Fortran ; . ,

real :: myvar = 0.0

- .

real :: myvar
....
myvar = 0.0

. , , , ,

isensit%sa(:) = 0.0

0.0 isensit%sa(:). ( ), , , , , :

isensit%sa = 0.0

0.0 isensit%sa. , , , Fortran , . , , , .

, , , , allocate, , . , , , , , .

,

allocate(isensit%sa(isensit%nnz),source=0.0,stat=ierr)

, , .

, : use mpi ( use mpi_mod , include mpif.h). () , mpi . - , , .

+4

allocate():

program mem_test
    implicit none
    integer, allocatable :: a(:,:,:)
    integer ierr, n1, n2, L, method

    n1 = 250000 ; n2 = 1000    !! 1-GB subarray

    print *, "Input: method, L"
    read *, method, L

    select case ( method )
    case ( 1 )
        allocate( a( n1, n2, L ) )              !! request L-GB virtual mem
    case ( 2 )
        allocate( a( n1, n2, L ), stat=ierr )   !! request L-GB virtual mem
        if ( ierr /= 0 ) stop "Memory error!"
    case ( 3 )
        allocate( a( n1, n2, L ), source=0 )    !! request L-GB resident mem
    endselect

    print *, "allocate() passed (type any key)"
    read *
end

- Linux (x86_64) 64 64 . ulimit -v "". (method= 1,2,3) L > ~ 120, .. . method= 1,3

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

method= 2, stat=ierr . L 120 , method= 2 0... , , allocate(), -, + ( ), ulimit -v .


, allocate(), ulimit -v. 4 2 .

program alloc_test
    implicit none
    real, allocatable :: a(:), b(:)
    integer ierr, n

    n = 500000000

    allocate( a( n ), stat=ierr )   !! requests 2GB virtual memory
    if ( ierr /= 0 ) stop "Memory error! (a)"

    allocate( b( n ), stat=ierr )   !! requests 2GB virtual memory
    if ( ierr /= 0 ) stop "Memory error! (b)"

    print *, "before assignment (type any key)"
    call system( "ps aux | grep a.out" )
    read *

    print *, "now writing values..."
    a(:) = 0.0    !! request 2GB resident memory                        

    print *, "after assignment (type any key)"
    call system( "ps aux | grep a.out" )
    read *
end

./a.out , allocate(). 1GB

$ ( ulimit -v 1000000 ; ./a.out )

STOP Memory error! (a)

2,2

STOP Memory error! (b)

Finally, if we install it on> 4 GB, the assignment begins

before assignment (type any key)
<username>    12380  0.0  0.0 3918048  652 pts/1    S+   07:59   0:00 ./a.out

now writing values...

after assignment (type any key)
<username>    12380 38.0  2.9 3918048 1953788 pts/1 S+   07:59   0:00 ./a.out

Thus, we can limit the amount of virtual memory (if necessary) to allocate( ..., stat=ierr )cause an error with respect to general purpose.

+1
source

All Articles