-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kind parameters #17
Comments
Hi @raullaasner , I tend to agree with Dr. Fortran (S. Lionel). I generally use my own kind precision module. I use the intrinsic ISO_FORTRAN_ENV only for rapid tests when PENF is far... My best regards. |
I have agonized over these issues more than I probably should have for all the (lack of) actual problems I’ve encountered.
One thing that is clear to me is that the answer (or at least the reasoning behind the answer) is quite different when one is developing a general purpose infrastructure layer than when one is developing a numerical algorithm. For the latter, one would ideally do the necessary analysis to determine the necessary precision, etc. In my experience, physical scientists _rarely_ do anything more sophisticated than using some default that they learned in their youth. Some at least “know” that 32 bit precision is inadequate for at least some part of their code and thus use 64-bit. (And some disciplines know that 64-bit is inadequate - e.g., those that study the long-term stability of orbits in the solar system.)
I too used to use my own kind precision module, but now that I’m involved with a much larger code 3 million+ lines of code with large pieces that have independent origins, the proliferation of such modules becomes a problem of its own. For infrastructure code my goal is usually to provide interfaces that work with “all” the KIND’s that are used in the numerical components developed by others. In practice the IOS_FORTRAN_ENV constants: REAL32 and REAL64 work well and are very portable. But in theory I ought to support at least each of the following that does not have a negative value:
kind(1.)
kind(1.d0)
REAL32
REAL64
REAL128
C_FLOAT
C_DOUBLE
C_LONG_DOUBLE
The trick is to avoid duplicates. For all the current compilers I use:
KIND(1.) == REAL32 == C_FLOAT
KIND(1.D0) == REAL64 == C_DOUBLE
(And I assume REAL128 == C_LONG_DOUBLE, but have never checked.)
And, yes, I know that some vendors do provide additional precisions, but to cover that I’d have to do some sort of nasty loop over range and precision to see the values that are supported by a given vendor. And all that would still be a preprocessing step that was used to do some sort of generic code generation. (Could possibly use Fortran PDT’s in some cases though.)
Sorry for the rambling post.
- Tom
On Jan 12, 2018, at 9:38 AM, Stefano Zaghi <notifications@github.com<mailto:notifications@github.com>> wrote:
Hi @raullaasner<https://github.com/raullaasner> ,
I tend to agree with Dr. Fortran (S. Lionel). I generally use my own kind precision module<https://github.com/szaghi/PENF>. I use the intrinsic ISO_FORTRAN_ENV only for rapid tests when PENF is far...
My best regards.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<#17 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/AF7_4J2QSsOsiQwgY4dyvX76qEBkwV-zks5tJ250gaJpZM4RcXsl>.
|
Hello,
all these are valid and appropriate. Their semantics is different and
therefore are appropriate in different situations, which often overlap.
kind(1.d0)
use when you want precision higher than the default, this may change from
one compiler setting to another.
selected_real_kind
use when you care about about numerical accuracy irrespective of current
compiler options
c_double
use when you want to be compatible with double of the companion C compiler.
You don't have to actually interoperate with C.
real64
use when you care about storage size.
Very often they are quite the same for 32 bit and 64 bit. There are some
issues between 80-bit and 128-bit, don't forget that storage size of 80-bit
reals is also 128!
If you want to be portable and that means not just for you, but for other
users, so NOT make too many assumptions about default reals and double
precisions. They can be changed using compiler options and people DO use
these options (like -fdefault-real or -r8).
In practice you will have to do conversions anyway, when you call a C
function and your Fortran reals are specified other than c_double, you
should be prepared to do a conversion, do not just assume c_double is the
same as real64. If they are, the compiler will optimize it away. If it is
a.code just for you, you can be less defensive, because the compiler will
object if you pass a wrong kind.-
…-----
Regarding integer kinds. That depends on your application. I tend to not
specify the kind unless necessary.
My arrays are 3D and indexes in each direction are small, much less than
even a max 16-bit integer.
However, if I need to work with the number of elements in the array, or
even number of bytes, it could easily overflow, that can be a billion or
more. I do not need that often, though.
BTW, this is a deep problem in MPI, it is specified to use int in C and
cannot therefore work with very large arrays. Do not repeat that mistake.
Best regards,
Vladimir
Dne 12. 1. 2018 3:32 odpoledne napsal uživatel "Raul Laasner" <
notifications@github.com>:
What would be the best way of specifying the kind parameter? Should we
always use the selected_*_kind function,
integer, parameter :: dp = selected_real_kind(15, 307)
real(dp) :: x
or are there better alternatives? According to this
<https://software.intel.com/en-us/blogs/2017/03/27/doctor-fortran-in-it-takes-all-kinds>
blog post the ISO_FORTRAN_ENV constants for kinds do not always work as
intended. Also, is it a good habit to always specify the kind parameter for
integers?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#17>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAskEfX72_XVb6l-vzeBedPp16p8TjCTks5tJ20WgaJpZM4RcXsl>
.
|
FWIW, I'm with @tclune on this one, and my thinking has evolved along the same lines over the years. |
One additional point that might be worth making.
So-called “half-precision” is becoming an important optimization on hardware accelerators when your code can tolerate it.
I suspect that ISO_FORTRAN_ENV should be extended to include a REAL16 parameter. (Which will then get confused with REAL*16. sigh.)
- Tom
|
Hi,
I do agree one should have generic version for multiple kinds prepared, at
least in a library.
I do not agree that one can assume those equalities. I am active on
Stackoverflow and can see what less knowledgeable users of various
libraries do and they do use various kind promoting options in their
compilers.
c_double=real64 will be safe unless a new Unix or other platform emerges
(in terms of LP64 etc.), but that won't happen in this or in the next
decade. We are lucky we are not in the 60s and CPUs now use IEEE standards.
I also do not agree 32bit is necessarily inadequate. In my applications
there is not that much difference introduced and it is much faster. I
compile my program in single or double precision just by changing a
parameter for the build script, so if I do find real64 is necessary
somewhere, I can either compile the whole code as such or find out the
location and force it there.
Regards,
Vladimir
Dne 12. 1. 2018 3:59 odpoledne napsal uživatel "tclune" <
notifications@github.com>:
… I have agonized over these issues more than I probably should have for all
the (lack of) actual problems I’ve encountered.
One thing that is clear to me is that the answer (or at least the
reasoning behind the answer) is quite different when one is developing a
general purpose infrastructure layer than when one is developing a
numerical algorithm. For the latter, one would ideally do the necessary
analysis to determine the necessary precision, etc. In my experience,
physical scientists _rarely_ do anything more sophisticated than using some
default that they learned in their youth. Some at least “know” that 32 bit
precision is inadequate for at least some part of their code and thus use
64-bit. (And some disciplines know that 64-bit is inadequate - e.g., those
that study the long-term stability of orbits in the solar system.)
I too used to use my own kind precision module, but now that I’m involved
with a much larger code 3 million+ lines of code with large pieces that
have independent origins, the proliferation of such modules becomes a
problem of its own. For infrastructure code my goal is usually to provide
interfaces that work with “all” the KIND’s that are used in the numerical
components developed by others. In practice the IOS_FORTRAN_ENV constants:
REAL32 and REAL64 work well and are very portable. But in theory I ought to
support at least each of the following that does not have a negative value:
kind(1.)
kind(1.d0)
REAL32
REAL64
REAL128
C_FLOAT
C_DOUBLE
C_LONG_DOUBLE
The trick is to avoid duplicates. For all the current compilers I use:
KIND(1.) == REAL32 == C_FLOAT
KIND(1.D0) == REAL64 == C_DOUBLE
(And I assume REAL128 == C_LONG_DOUBLE, but have never checked.)
And, yes, I know that some vendors do provide additional precisions, but
to cover that I’d have to do some sort of nasty loop over range and
precision to see the values that are supported by a given vendor. And all
that would still be a preprocessing step that was used to do some sort of
generic code generation. (Could possibly use Fortran PDT’s in some cases
though.)
Sorry for the rambling post.
- Tom
On Jan 12, 2018, at 9:38 AM, Stefano Zaghi ***@***.***<
***@***.***>> wrote:
Hi @raullaasner<https://github.com/raullaasner> ,
I tend to agree with Dr. Fortran (S. Lionel). I generally use my own kind
precision module<https://github.com/szaghi/PENF>. I use the intrinsic
ISO_FORTRAN_ENV only for rapid tests when PENF is far...
My best regards.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<https://github.com/
Fortran-FOSS-Programmers/Best_Practices#17#issuecomment-357254824>,
or mute the thread<https://github.com/notifications/unsubscribe-auth/AF7_
4J2QSsOsiQwgY4dyvX76qEBkwV-zks5tJ250gaJpZM4RcXsl>.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#17 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAskEakPWDs7qRvUFqebHzcghIvHywJMks5tJ3NRgaJpZM4RcXsl>
.
|
These are the kind of corner cases I had in mind, actually. REAL128 has a different effect with GNU and Intel compilers, whereas using SELECTED_REAL_KIND should always be unambiguous. REAL64 should be safe for now and it refers to double precision in all major Fortran compilers, but interestingly nothing in the standard requires it to be double precision. |
On Jan 12, 2018, at 11:12 AM, LadaF <notifications@github.com<mailto:notifications@github.com>> wrote:
Hi,
I do agree one should have generic version for multiple kinds prepared, at
least in a library.
I do not agree that one can assume those equalities.
I’m not exactly assuming these inequalities. I’m just aware that my current implementations _could_ be insufficient on some future architecture. (Very low on my list of concerns.) Considering that most of the client code I support still uses REAL*4 and REAL*8, it’s not even the biggest concern on this front.
I am active on
Stackoverflow and can see what less knowledgeable users of various
libraries do and they do use various kind promoting options in their
compilers.
c_double=real64 will be safe unless a new Unix or other platform emerges
(in terms of LP64 etc.), but that won't happen in this or in the next
decade. We are lucky we are not in the 60s and CPUs now use IEEE standards.
Even then, I think that c_double == real64 will remain true. Increasing the address size should not affect this relationship.
I also do not agree 32bit is necessarily inadequate.
I only meant that _some_ scientists do reach that conclusion. Many agree with your findings. Certainly the bulk of the calculations in the code that I currently use are 32-bit FP operations. Some packages are in 64-bit for no known reason and are on our short list for potential performance optimization. (Halving the precision is one of the easiest optimizations available.) In some cases, the scientist has gone a bit further and used 32-bit as a default and then identified a small number of variables that need to be 64-bit, but usually this is purely empirical. I.e., the code got wrong answers and/or crashed when using 32-bit everywhere and they made educated guesses as to where to back off.
In my applications
there is not that much difference introduced and it is much faster. I
compile my program in single or double precision just by changing a
parameter for the build script, so if I do find real64 is necessary
somewhere, I can either compile the whole code as such or find out the
location and force it there.
I wish our code were in this state, and much of it is. But enough parts cannot be easily changed and pushing this capability competes with other issues. Certainly on codes that I’ve developed myself I’ve generally enabled that functionality. Usually even with quad precision when I can, but library availability often limits that end. Sure I can modify existing FFT and linear algebra libraries.
Cheers,
- Tom
Regards,
Vladimir
Dne 12. 1. 2018 3:59 odpoledne napsal uživatel "tclune" <
notifications@github.com<mailto:notifications@github.com>>:
I have agonized over these issues more than I probably should have for all
the (lack of) actual problems I’ve encountered.
One thing that is clear to me is that the answer (or at least the
reasoning behind the answer) is quite different when one is developing a
general purpose infrastructure layer than when one is developing a
numerical algorithm. For the latter, one would ideally do the necessary
analysis to determine the necessary precision, etc. In my experience,
physical scientists _rarely_ do anything more sophisticated than using some
default that they learned in their youth. Some at least “know” that 32 bit
precision is inadequate for at least some part of their code and thus use
64-bit. (And some disciplines know that 64-bit is inadequate - e.g., those
that study the long-term stability of orbits in the solar system.)
I too used to use my own kind precision module, but now that I’m involved
with a much larger code 3 million+ lines of code with large pieces that
have independent origins, the proliferation of such modules becomes a
problem of its own. For infrastructure code my goal is usually to provide
interfaces that work with “all” the KIND’s that are used in the numerical
components developed by others. In practice the IOS_FORTRAN_ENV constants:
REAL32 and REAL64 work well and are very portable. But in theory I ought to
support at least each of the following that does not have a negative value:
kind(1.)
kind(1.d0)
REAL32
REAL64
REAL128
C_FLOAT
C_DOUBLE
C_LONG_DOUBLE
The trick is to avoid duplicates. For all the current compilers I use:
KIND(1.) == REAL32 == C_FLOAT
KIND(1.D0) == REAL64 == C_DOUBLE
(And I assume REAL128 == C_LONG_DOUBLE, but have never checked.)
And, yes, I know that some vendors do provide additional precisions, but
to cover that I’d have to do some sort of nasty loop over range and
precision to see the values that are supported by a given vendor. And all
that would still be a preprocessing step that was used to do some sort of
generic code generation. (Could possibly use Fortran PDT’s in some cases
though.)
Sorry for the rambling post.
- Tom
On Jan 12, 2018, at 9:38 AM, Stefano Zaghi ***@***.******@***.***><
***@***.***>> wrote:
Hi @raullaasner<https://github.com/raullaasner> ,
I tend to agree with Dr. Fortran (S. Lionel). I generally use my own kind
precision module<https://github.com/szaghi/PENF>. I use the intrinsic
ISO_FORTRAN_ENV only for rapid tests when PENF is far...
My best regards.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<https://github.com/
Fortran-FOSS-Programmers/Best_Practices#17#issuecomment-357254824>,
or mute the thread<https://github.com/notifications/unsubscribe-auth/AF7_
4J2QSsOsiQwgY4dyvX76qEBkwV-zks5tJ250gaJpZM4RcXsl>.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#17 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAskEakPWDs7qRvUFqebHzcghIvHywJMks5tJ3NRgaJpZM4RcXsl>
.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#17 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/AF7_4L893MoHhIsrt0_gIpsY6o4ih4awks5tJ4SAgaJpZM4RcXsl>.
|
What would be the best way of specifying the kind parameter? Should we always use the
selected_*_kind
function,integer, parameter :: dp = selected_real_kind(15, 307)
real(dp) :: x
or are there better alternatives? According to this blog post the
ISO_FORTRAN_ENV
constants for kinds do not always work as intended. Also, is it a good habit to always specify the kind parameter for integers?The text was updated successfully, but these errors were encountered: