Fortran 90 kind parameter
Asked Answered
I

6

54

I am having trouble understanding Fortran 90's kind parameter. As far as I can tell, it does not determine the precision (i.e., float or double) of a variable, nor does it determine the type of a variable.

So, what does it determine and what exactly is it for?

Inaction answered 8/5, 2009 at 5:3 Comment(1)
are you referring to Kind notation?Bagley
P
69

The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.

Beware that although it is common for the KIND parameter to be the same as the number of bytes stored in a variable of that KIND, it is not required by the Fortran standard.

That is, on a lot of systems,

REAl(KIND=4) :: xs   ! 4 byte ieee float
REAl(KIND=8) :: xd   ! 8 byte ieee float
REAl(KIND=16) :: xq   ! 16 byte ieee float

but there may be compilers for example with:

REAL(KIND=1) :: XS   ! 4 BYTE FLOAT
REAL(KIND=2) :: XD   ! 8 BYTE FLOAT
REAL(KIND=3) :: XQ   ! 16 BYTE FLOAT

Similarly for integer and logical types.

(If I went digging, I could probably find examples. Search the usenet group comp.lang.fortran for kind to find examples. The most informed discussion of Fortran occurs there, with some highly experienced people contributing.)

So, if you can't count on a particular kind value giving you the same data representation on different platforms, what do you do? That's what the intrinsic functions SELECTED_REAL_KIND and SELECTED_INT_KIND are for. Basically, you tell the function what sort of numbers you need to be able to represent, and it will return the kind you need to use.

I usually use these kinds, as they usually give me 4 byte and 8 byte reals:

!--! specific precisions, usually same as real and double precision
integer, parameter :: r6 = selected_real_kind(6) 
integer, parameter :: r15 = selected_real_kind(15) 

So I might subsequently declare a variable as:

real(kind=r15) :: xd

Note that this may cause problems where you use mixed language programs, and you need to absolutely specify the number of bytes that variables occupy. If you need to make sure, there are enquiry intrinsics that will tell you about each kind, from which you can deduce the memory footprint of a variable, its precision, exponent range and so on. Or, you can revert to the non-standard but commonplace real*4, real*8 etc declaration style.

When you start with a new compiler, it's worth looking at the compiler specific kind values so you know what you're dealing with. Search the net for kindfinder.f90 for a handy program that will tell you about the kinds available for a compiler.

Pedantry answered 13/5, 2009 at 5:41 Comment(6)
Thanks for pointing out that KIND is not KIND=<number of bytes I want> - have you seen a modern compiler where this is the case? That kindfinder.f90 program is very cool.Kitts
A search of usenet turns up: salford f95 compiler uses kinds 1,2, and 3 to stand for 2- 4- and 8-byte variables; I saw a claim that g77 did the same before g95 and gfortran came along; and a report that the NAG fortran compiler had a compiler switch that allowed the selection between the (1,2,3,4) scheme and the (1,2,4,8) scheme. No doubt there are others. Yes, kindfinder is handy. You can use it to set up a site-specific module file that contains named parameters for the different kinds, so that your real programs aren't littered with nonportable magic numbers.Pedantry
If you really want to specify types by their bytes of storage, Fortran 2003 has the ISO_C_Binding, which provides kind values corresponding to C types, some of which specify storage size. Fortran 2008 provides types in the ISO_FORTRAN_ENV module, such as the real32 kind value for 32 bits, real64 for 64 bits, etc. These have the advantage of being portable, at least as long as you have a Fortran 2003 or 2008 compiler. See the gfortran manual for the list of kinds in these two modules.Wernsman
REAL(n) and REAL(kind=n) they are always the same thing, right?Innocence
@Innocence Late to this, but am currently getting acquainted to these, and I found this : fortranwiki.org/fortran/show/Real+precision Here in first block, a and b are declared using real(kind=dp) and real(dp) respectively, and it appears they both mean the same thing.Adan
@Adan Yes, they do. Be careful with character kinds there the firstvnumber is the length. character(4) is the string of lenght 4. character(c_char) is the string of length c_char. character(kind=c_char) is a single character of length 1.Wagonette
E
11

I suggest using the Fortran 2008 and later; INT8, INT16, INT32, INT64, REAL32, REAL64, REAL128. This is done by calling ISO_FORTRAN_ENV in Fortran 2003 and later. Kind parameters provides inconsistent way to ensure you always get the appropriate number of bit representation

Exclosure answered 26/5, 2015 at 15:16 Comment(6)
int8 does (if an appropriate kind is available) specify a kind parameter. I suspect you mean that one should prefer this to an explicit number like, say int(kind=1)? [This latter would be bad practice regardless.] Perhaps you could clarify?Urias
I concur with your comment @UriasExclosure
@francescalus, would it not be useful to make this question a canonical question and have a single "community answer" which sums up all the entire story for various versions of fortran? Often I see code where I would like to refer to such a complete canonical answer. This is the best place here, but the information is completely spread out over different answers and various comments. (sorry this is the best way I figured out to reach you)Rileyrilievo
@kvantour, discussions of canonical questions (scope, desire, etc.) fit well on Meta SO. You'll likely get more than just my opinion there. That's if you think the question itself needs work: if you think an answer here solves the problem then there's little harm pulling everything together into a complete form.Urias
-1. software.intel.com/content/www/us/en/develop/blogs/… -- TLDR: use SELECTED_REAL_KIND()Triangulation
The main issue with this answer is that despite getting many upvotes it simply does not even attempt to answer the question. It just gives some opinion about what choice of kind parameters might be the best.Wagonette
W
4

Just expanding the other (very good) answers, specially Andrej Panjkov's answer:

The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.

Exactly. Even though, for all the numeric intrinsic types, the KIND parameter is used to specify the "model for the representation and behavior of numbers on a processor" (words from the Section 16.5 of the standard), that in practice means their bit model, that's not the only thing a KIND parameter may represent.

A KIND parameter for a type is any variation in its nature, model or behavior that is avaliable for the programmer to choose at compile time. For example, for the intrinsic character type, the kind parameter represents the character sets avaliable on the processor (ASCII, UCS-4,...).

You can even define your own model/behaviour variations on you defined Derived Types (from Fortran 2003 afterwards). You can create a Transform Matrix type and have a version with KIND=2 for 2D space (in which the underlying array would be 3x3) and KIND=3 for 3D space (with a 4x4 underlying array). Just remember that there is no automatic kind conversion for non-intrinsic types.

Wildman answered 24/5, 2018 at 20:40 Comment(0)
K
2

From the Portland Group Fortran Reference, the KIND parameter "specifies a precision for intrinsic data types." Thus, in the declaration

real(kind=4) :: float32
real(kind=8) :: float64

the variable float64 declared as an 8-byte real (the old Fortran DOUBLE PRECISION) and the variable float32 is declared as a 4-byte real (the old Fortran REAL).

This is nice because it allows you to fix the precision for your variables independent of the compiler and machine you are running on. If you are running a computation that requires more precision that the traditional IEEE-single-precision real (which, if you're taking a numerical analysis class, is very probable), but declare your variable as real :: myVar, you'll be fine if the compiler is set to default all real values to double-precision, but changing the compiler options or moving your code to a different machine with different default sizes for real and integer variables will lead to some possibly nasty surprises (e.g. your iterative matrix solver blows up).

Fortran also includes some functions that will help pick a KIND parameter to be what you need - SELECTED_INT_KIND and SELECTED_REAL_KIND - but if you are just learning I wouldn't worry about those at this point.

Since you mentioned that you're learning Fortran as part of a class, you should also see this question on Fortran resources and maybe look at the reference manuals from the compiler suite that you are using (e.g. Portland Group or Intel) - these are usually freely available.

Kitts answered 8/5, 2009 at 20:30 Comment(1)
Nope, this is not portable. Don't recommend it to beginners please.Wagonette
F
-2

One of the uses of kind could be to make sure that for different machine or OS, they truly use the same precision and the result should be the same. So the code is portable. E.g.,

integer, parameter :: r8 = selected_real_kind(15,9) 
real(kind=r8) :: a

Now this variable a is always r8 type, which is a true "double precision" (so it occupies 64 bits of memory on the electronic computer), no matter what machine/OS the code is running on.

Also, therefore you can write things like,

a = 1.0_r8

and this _r8 make sure that 1.0 is converted to r8 type.

Fungosity answered 23/7, 2021 at 7:53 Comment(20)
Why is a guaranteed to be an 8-byte real for every processor?Urias
This is just wrong. The different machine might use some non IEEE floating point types. Alas, the 8-byte float may not even exist on such a machine and still the machine could have a conforming Fortran 90 compiler.Wagonette
@VladimirF defining r8 type by doing selected_real_kind, is exactly what we do in HPC computing, to ensure the results on a laptop or on the supercomputer, on windows or linux are the same. It is just not wrong. I actually would like to see how you define true real 8 for all the machine.Fungosity
@Urias Because we defined the type at the beginning of the code, r8=selected_real_kind(15,9), it means that then as real(kind=r8) :: a , a will be a r8 type which uses 8 Byte. This is a typical thing we define in all of our massively parallelized quantum Monte Carlo codes which sometimes requires tens of millions of core hours. If this is wrong then I do not know what.Fungosity
@VladimirF r8=selected_real_kind(15,9) , It just means uses 8 Byte memory to store a true real 8 number, how can it be impossible? I am very confused. I am talking about true real 8, not real 800000.Fungosity
selected_real_kind is simply not about storage size at all. It does not really matter what you do in your HPC. It is about numerical precision. It says how big and precise numbers can be. I repeat, a conforming Fortran processor can exist on a machine that does not even have to have any 8-byte type. Those that do have it will have real64 defined in iso_fortran_env and that is the true way to define a true 8-byte real. And if an IEEE conforming 8-type is available, you can use the ieee_selected_real_kind, where the correspondende between numerical precision and storage size more certain.Wagonette
I am not saying that what you do will not work for you on a typical IEEE conforming machine in this day and age. I am saying that the claim "which is real 8 (means uses 8 Bytes) type no matter what machine/OS it is running on." is incorrect from a language lawyer point of view. It also does not guarantee that the results will be the same.Wagonette
@VladimirF Nowadays, a modern and well written Fortran code, gives the same results (up to machine precision) no matter it is on windows/linux/mac, this is guaranteed. If your code gives different results on different OS, it is a sign that something in your code may not be well written. On the other hand, of course, it depends on the person who wrote the code, not the Fortran language itself. Therefore in this sense, you can say it is not guaranteed.Fungosity
Using selected_real_kind in this answer you have asked for a minimal decimal precision and range. You haven't asked for a storage size, radix, IEEE conformance or exact range and precision. There is nothing in the Fortran language that says you will get an 8-byte real with this kind parameter.Urias
The point is in "nowadays". This is not about my code or your code. It is not about windows/mac/linux. It is about what the standard allows. It is about possible CPUs that existed throughout the 20th century and could exist in the future. It is about various compilers that might exist on these systems. Their numbers do not even have to be binary, for example. They might not even have numbers as small as 8 bytes.Wagonette
@Urias Do you agree all electronic computers use 10101010101....? If so, selected_real_kind(15,9) returns 8, 8 means it requires 8 Byte, this means exactly in Fortran you can get a real 8 byte number, period. What you are saying is like, "because fortran does not have internal spherical harmonic functions, therefore there is no way fortran can calculate spherical harmonics." It does not make sense.Fungosity
@VladimirF selected_real_kind(15,9) returns 8, 8 means it requires 8 Byte, this means exactly in Fortran you can get a real 8 byte number. I repeat, selected_real_kind, is a generic, valid, and good way of defining true real 4, 8 , or anything kind you want. The highest voted answer already explains it well.Fungosity
It does not matter what it returns on your compiler at all. BTW, it wil return 2 for some other xompilers ecxactly as the highest-voted answer shows. selected_real_kind() does NOT return number of bytes. storage_size() retirns number of bits instead. I repeat, selected_real_kind() is NOT for sepectimg any bytes, it is for selecting numerical precision, radix,... And that is what the highest-voted answer, which I upvoted explains very well. Please read it again, because you have not understood it yet.Wagonette
I don't know what using "10101010101" means, but I certainly don't agree that selected_real_kind(15,9) must have value 8 or that even if it had value 8 a real with kind parameter 8 must have 8-byte storage. Let's say I asked you what output you think I'd get running the Fortran program print '(L1)', 1.>0.; end. And then I ask "how many bytes did you use for those real constants when calculating?", would I make sense?Urias
@VladimirF selected_real_kind() is the way, and the generic way to go. As stated clearly by the highest voted answer. The reason Fortran has this selected_real_kind() is really to make sure that even on different machine or OS, eg. by doing selected_real_kind(15,9), a variable can indeed be the same true real 8 type which means 8 bytes so occupy 64 bits in the memory. if you have chance to look at how people's code for true HPC on supercomputer like Summit, Sierra, etc. I really did not find people use things like iso c binding stuff as you did in your github repos.Fungosity
@Urias In order to represent the precision of selected_real_kind(15,9), you need 8 bytes so 64 bits on any electronic computer. Please name one example, such that selected_real_kind(15,9) does not return 8 and please explain why, if possible. 10101.... simply means electronic computer uses 0 or 1 to represent anything. At the end of the day, any variable with selected_real_kind(15,9) does require 8 Bytes of memory. It is really just math, without 8 Bytes you simply cannot reach that precision.Fungosity
@VladimirF if for example, selected_real_kind(15,9) return 8, then may I ask, what does this 8 mean? I mean selected_real_kind() will return a number, right? The number has a meaning, right? We know if it returns a negative number then it means something is wrong. But if it returns a positive number, like 4, 8, 16, 32, then what does those number 4, 8, 16, 32 mean?Fungosity
@VladimirF I read many stackoverflow questions and answers, I have impression about your name because you answered many questions. Many of them are useful. But here about selected_real_kind(), it is just a good and generic way to make the code portable. Nothing wrong with it. A true real 8 does require 64 bits of memory.Fungosity
The NAG compiler will return 2 by default, and there is an option to have it return 202 (or some other large number, I don't recall which, but that's because the exact number is completely irrelevant). Either way, a Fortran compiler isn't required to provide a real decimal precision larger than 10 and isn't required to provide a real with 8-byte storage. If you disagree with those points then further discussion will be fruitless.Urias
@Urias I am not going to continuing the argument. All what I wanted to say is that defining r8 = selected_real_kind(15,9) works very well. That is all.Fungosity
P
-8

To summarize other answers: the kind parameter specifies storage size (and thus indirectly, the precision) for intrinsic data types, such as integer and real.

However, the recommended way now is NOT to specify the kind value of variables in source code, instead, use compiler options to specify the precision we want. For example, we write in the code: real :: abc and then compile the code by using the compiling option -fdefault-real-8 (for gfortran) to specify a 8 byte float number. For ifort, the corresponding option is -r8.

Update:

It seems Fortran experts here strongly object to the recommended way stated above. In spite of this, I still think the above way is a good practice that helps reduce the chance of introducing bugs in Fortran codes because it guarantees that you are using the same kind-value throughout your program (the chance that you do need use different kind-values in different parts of a code is rare) and thus avoids the frequently encountered bugs of kind-value mismatch between dummy and actual arguments in a function call.

Paxton answered 23/5, 2019 at 0:29 Comment(7)
Recommended by whom? This is the archaic way, not the modern way. It is also not just about "precision".Wagonette
Wait, what? Recommended by whom [2]? 1) Explicit is better than implicit, 2) Kind specifiers is the most portable alternative, 3) 8 byte float is about data storage not about precision.Wildman
Recommented by tokamak fusion scientists from General Atomics. They gave a list of FORTRAN coding conventions used in the GACODE build system. All latest General Atomics modeling codes follow these conventions. What's nice about them is that, when porting the code to any new platform (cori, titan, summit ...), all that's needed is to set up the correct platform environment variable in the makefile. The GACODE build system has been set up on many computer systems in the world.Paxton
@Rodrigo , It seems to me that a real number stored by 8 bytes is more accurate than that stored by 4 bytes, so storage and precision are related. Is this right?Paxton
@YoujunHu a real number stored in 8 bytes can be (and probably will, obviously) more acurate than a 4 bytes, but does this say anything about how much precise it is? how many decimal places? maximum exponent? If you care about a specific requirement in precision, use selected_real_kind. If you care about a specific storage size, use iso_fortran_env kind constants. Refer to this answer for more details.Wildman
We specify storage by using compiling options. Then suitable decimal digits and maximum exponent are automatically determined by the compiler or by programmers using compiling options (if they exist). In summary, it seems more natural to specify storage and precision via compiling options, rather than via source codes.Paxton
I am not saying -fdefault-real-8 is evil, I am saying that this is not the most recommended approach by Fortran community, because it changes implictly the behaviour you expect when you look at the code. Help forums are full of: "why my calls to libraries (Lapack, mkl...) fail or give wrong result when the signature of the function seems to match the passed arguments?". Oh, it's because there is a line in the makefile (totally away from the source code) that says that, in this project, double precision actually means double double precision... ¬¬Wildman

© 2022 - 2024 — McMap. All rights reserved.