2

I need to perform both single precision and double precision arithmetics on a variable in different parts of my code. So basically, I declare the variable as single precision first. Then I call subroutine sub_a which makes use of double precision version of the variable and performs double precision operations on that:

program main

 implicit none
 integer,parameter :: single = selected_real_kind(p=6,r=37)
 integer,parameter :: double = selected_real_kind(p=15,r=307)

 real(single),allocatable,dimension(:) :: A
 real(double),allocatable,dimension(:) :: B

 allocate(A(3),B(3))
 A=2 ! single precision
 A=A+3 ! single precision

 print '(a,1x,3(f20.15))','sqrt(A),single:',sqrt(A)
 print '(a,1x,I15)','mem_address of A before sub_a:',loc(A)

 call sub_a(real(A,kind=double),B) ! double precision
 print '(a,1x,3(f20.15))','sqrt(A),double:',B

 contains
   subroutine sub_a(a,b)
     real(double),dimension(:),intent(in) :: a
     real(double),dimension(:),intent(inout) :: b

     print '(a,1x,I15)','mem_address of A in sub_a:',loc(a)

     b=sqrt(a)

   end subroutine sub_a

end program main

As seen in the code, I also obtained the memory address of A prior to calling sub_a and the version of A inside sub_a and they are expectedly different.

My questions are:

  1. Is the version of A inside the sub_a allocated in the heap memory so I should not be worried about the size limitation?
  2. is there any potential issue/bug in writing this example?
  3. is there a better way of capturing the purpose described in this example, specially for larger size arrays?

Many Thanks

Update: I haven't experienced any Memory issue for very large arrays, when using gfortran4.6 / ifort13.1 as compiler. I plan to use suggestion by @innoSPG as an alternative approach.

Amir
  • 335
  • 2
  • 11

2 Answers2

1

by the nature of the call, the version of A that you have in sub_a is a temporary array created by a piece of code included by the compiler. However, if you will manipulate very large arrays, it is not a good idea.

For question 2. to my knowledge, there is no bug. The only issue is the temporary array that may be a problem if you have large arrays and limited memory on your system.

For question 3. In the case there is a memory issue, you can write sub_a to accept simple precision, and then convert each element in sub_a before using it in computation.

innoSPG
  • 4,588
  • 1
  • 29
  • 42
0

The temporary array at the call site can be made at the stack or at the heap, it is implementation dependent. Compilers usually have options to control the behavior.

With Intel Fortran it the option -heap-arrays n (n cannot be ommited or too low, because performance would be bad).

Gfortran would put them on the heap automatically if it doesn't know the size beforehand. It is good to use -fstack-arrays for better performance (it is included in -Ofast).

You will find similar options in other compiler's documentation.

I would not fear and avoid the temporary arrays at all cost. The possibility of much shorter (and more readable!) code is sometimes more important. Many codes have portions that are done only once during initialization or final output where the performance penalty is often irrelevant. I personally use it to make my code cleaner in these parts (not in the computational core).

  • I receive "error: unrecognized command line option ‘-fstack-arrays’" when using -fstack-arrays along with gfortran 4.6.4. "-Ofast" works though. Side question: when using -O3 followed by -Ofast, is the last one only considered or the options of both ones are included? – Amir Apr 04 '14 at 20:21
  • Looks like fstack-arrays was added to gfortran in 4.7 or 4.8. It is therefore not in Ofast either. Using both O3 and Ofast doesn't make any sense, the larger probably wins. – Vladimir F Героям слава Apr 04 '14 at 21:15