Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

specifying precision at run time?

gregfi04
Beginner
632 Views
One of our codes currently uses of single precision (4-byte) real variables. It would be really great to use double precision math in some circumstances, but it would make solving large problems significantly more cumbersome due to the enhanced memory burden.

Is there a good way to make this an option at run time? I'm particularly concerned about MPI calls, which specify datatypes like "MPI_REAL" as arguments. I suppose I could set up IF statements around each MPI call, and choose "MPI_REAL" or "MPI_DOUBLE_PRECISION" based on some input parameter, but I'm hoping there's an easier way to do this. Likewise with the variable declarations.

Any ideas?

Thanks,
Greg
0 Kudos
2 Replies
Steven_L_Intel1
Employee
632 Views
You could do this with polymorphism, but I think the overhead might be quite a bit for your purposes and would also require significant code changes.
0 Kudos
jimdempseyatthecove
Honored Contributor III
632 Views
Greg,

Consider looking at using generic interfaces and your own derived types. The added overhead might not be too bad when the derived type contains arrays as opposed to scalars

TYPE MYTYPE
REAL(4), ALLOCATABLE :: R4(:) !could be replaced with UNION of POINTERs
REAL(8), ALLOCATABLE :: R8(:)
END TYPE MYTYPE

INTERFACE VEC_ADD(A,B)
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL4
SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL8
SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
END SUBROUTINE VEC_ADD_MYTYPE
END INTERFACE VEC_ADD

...
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
A=A + B
END SUBROUTINE VEC_ADD_REAL4

SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
A = A + B
END SUBROUTINE VEC_ADD_REAL8

SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
IF(ALLOCATED(A%R4)) THEN
IF(ALLOCATED(B%R4)) THEN
A%R4 = A%R4 + B%R4
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
IF(ALLOCATED(A%R8)) THEN
IF(ALLOCATED(B%R8)) THEN
A%R8 = A%R8 + B%R8
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
! OOPS OR IGNORE
ENDIF
ENDIF
END SUBROUTINE VEC_ADD_MYTYPE

Then in your code

...
CALL VEC_ADD(A,B)
...


And you are now free to change A, B either in compile timedeclarations in INCLUDE/USE files or at run time when A and B are MYTYPEs and properly allocated.

Jim Dempsey



0 Kudos
Reply