Yes, date and time are correct
Fortran 2003/2008
Dan,
I have created a timing module (library) which contains routines that use most of the timing routines I have used with FTN95. I have copied it to dropbox. It includes estimates of calling time penalty and also the precision of the timers. The approach I have taken is to provide 3 functions to interface each timer, being: integer8 function timer_tick () ! which returns the number of ticks integer8 function timer_frequency () ! which returns ticks per second real*8 function timer_sec () ! which returns the seconds
For elapsed time, CPU_CLOCK@ and QueryPerformanceCounter perform well. Most other timers perform very poorly, as their value is updated 64 times per second. This included all estimates of processor time. It is important to understand that all timers have an update frequency, which is different from the tick rate and those with an update frequency of 64 cycles per second are not worth using. This includes the intrinsics CPU_TIME, Date_and_Time and Salford's DCLOCK@.
My preference is to use CPU_CLOCK@ and ignore the warning message, as I have never experienced the problem reported. I have provided a routine to calculate the clock rate for cpu_clock@, which runs fairly quickly ( < .001 seconds).
John
https://www.dropbox.com/s/yvsck1xysec4crm/timing_routines.f90
Would be good to check these timers with my parallel library, which might mess something but I'm out of place right now. Want to try yourself?
Dan,
Email me the links to the library etc and I'll give it a test. I don't think I have the libraries you are refering to.
John
DavidB,
Thanks for contributing the fast_asm_ddotprod code. I had occasion to look at it as part of John Campbell's code, where he experienced huge slowdowns caused by similar routines compiled from Fortran code.
Here is a minor tweak to take care of the part where you wrote
Can't get final reduction to work, so will do this in Fortran for now
80 movupd v, xmm0% ; move xmm0 to v array
edoc
! Final reduction, the result is the sum of the two values in v
fast_asm_ddotprod = sum(v)
end function fast_asm_ddotprod
The change, which will not really affect the speed much, but make your code 'clean SSE', is as follows:
80 movaps xmm1,xmm0
unpckhpd xmm1,xmm0
addsd xmm0,xmm1
movsd v,xmm0
edoc
fast_asm_ddotprod = v
end function fast_asm_ddotprod
The declaration of the local variable v should be changed to REAL*8 v. Unfortunately, FTN95 does not know the instruction unpckhpd, so instead of inline assembler one may (i) produce an obj file from your original code, (ii) dumpbin /disasm > asm file, (iii) edit file and make the changes indicated above, (iv) assemble the asm file.
Perhaps you felt all this was not worth the trouble, and that is what you meant by 'cannot get ... to work'.
When I found that the assembly code I needed (unpckhpd) wasn't included in the FTN95 inline assembler I just fell back on using Fortran as I felt it was easier (Paul did look into adding support for unpckhpd and others but found it was not trivial so it wasn't pursued).
Your solution is better but requires more work to get a working subroutine. It probably does not make much difference in terms of efficiency.
How about 64bit Vec_Add_SSE and Vec_Sum_SSE previously written in assembler for 32bits ? Anyone try to use FTN95 own or have done own 64bit version?
Dan,
The 64-bit routines work well and provide vector instruction speed-up. For real*8, I have used:
real*8 function Vec_Sum_SSE ( a, b, n )
!
! Performs the vector opperation Vec_Sum_DO = [a] . [b]
integer*4 n
real*8 a(n), b(n), s
!
integer*8 n8
real*8 DOT_PRODUCT8@
external DOT_PRODUCT8@
!
if (n > 1) then
n8 = n
s = DOT_PRODUCT8@ (a, b, n8 )
else if (n==1) then
s = a(1) * b(1)
else
s = 0
end if
!
vec_sum_SSE = s
end function vec_sum_SSE
subroutine Vec_add_SSE ( Y, X, a, n )
!
! Performs the vector operation [Y] = [Y] + a * [X]
!
integer*4 n
real*8 Y(n), X(n), a
integer*8 n8
!
if ( n > 1 ) then
! Y = Y + a * X
n8 = n
call AXPY8@ (y, x, n8, a)
else if ( n == 1 ) then
Y(1) = Y(1) + a * X(1)
end if
end subroutine Vec_add_SSE
note: integer*8 n8 check the 64 bit documentation for other routines.
Cool, thanks John, I owe you ! And great job, Silverfrost
Paul,
Somewhere I suggested I would post a list of additions to FTN95 to include some features of F03 and F08 that are hopefully 'easier' to include. Supporting F03 and F08 syntax can be helpful for compatibility with other Fortran environments.
This is my limited list:-
I have reviewed the F03 and F08 changes and have listed some changes which I think could be introduced.
- New system routines (some already supported)
F2003 routines COMMAND_ARGUMENT_COUNT GET_COMMAND GET_COMMAND_ARGUMENT GET_ENVIRONMENT_VARIABLE
F2008 routines Compiler_Version Compiler_Options Execute_command_Line Leadz Trailz Storage_size
Changes to I/O to support new standardised syntax IOMSG= NEWUNIT= *(..) unlimited format item Support for stream I/O syntax (in conjunction with TRANSPARENT, such as positioning)
Support for ISO_FORTRAN_ENV module for features available in F95
The main outstanding problem I see is support for Integer constants as subroutine arguments, especially Integer*8 constants, eg 999_8 for an 8-byte integer and 999_4 for a 4-byte integer are not portable
These suggested changes omit any new code structures, which I anticipate would be more complex.
I hope this is a realistic list and would be easily achieved.
John
Thank you for the feedback.
The following items are already available or have been added for the next release.
COMMAND_ARGUMENT_COUNT GET_COMMAND GET_COMMAND_ARGUMENT GET_ENVIRONMENT_VARIABLE EXECUTE_COMMAND_LINE
IOMSG=
Integer constants should already work correctly although the native KIND values are different. For example, by default 999_4 represents 999 as a 64 bit integer constant. For portability you can use 999_k where k is calculated via a call to SELECTED_INT_KIND. Alternatively the command line option /ALT_KINDS provides for KIND values based on byte size.
Paul,
I would like to make recommendations of how FTN95 can better support KIND values, especially constants, although my past recommendations for non-standard extensions have not worked well, eg SIZE for /64.
FTN95 now supports two concepts for KIND. It would be good if they could be merged, with FTN95 supporting both concepts, without compile options. It remains how to treat the conflicts, which is mainly 11_4 or 'integer(4) :: I'
For REAL, a non-standard extension should have little side effects. I suggest that kind values of 1,2,3 and 4,8,10 all be accepted, so that 2.0_4 and 2.0_1 are both seen as a 4-byte real. I don't think FTN95 supports REAL*16, so there should not be any confusion with kind = 4.
For INTEGER, there is significant confusion with kind = 4 (and =3), while kind values of 1,2,3 and 8 are not in dispute. Kind = 7 is a useful although non-portable introduction. However, providing 11_4 as an 8-byte constant would work as a subroutine argument. There can be problems providing an 8-byte constant for some intrinsic functions, such as TRANSFER. I would recommend providing a warning for use of integer kind=4 constants, as with the warning of comparing 2 real values for equality.
I can not provide recommendations for COMPLEX as I am not familiar with their use. (Can someone who knows, recommend how to handle the complex*8 vs complex(8) problem, again with a warning perhaps?)
This approach can be useful, when using some 3rd party software that it can be used without modifying the code. I do this in Plato on a regular basis. (access to modifying the default X64/Win32 and Checkmate/Debug/Release compile options in PLATO would also be a useful addition). Also, the use of 8-byte integer constants in a concise and portable way is always annoying.
In summary, it would be good if an extended set of kind values could be recognised by the FTN95 compiler with minimal complaint, especially where there should be no confusion as to what is extended. The real values of 4,8,16 and integer values of 1,2,4,8 are becoming an increasingly used, but nonstandard / not recommended approach.
Any other opinions before this might be implemented ?
John
Also, the use of 8-byte integer constants in a concise and portable way is always annoying.
Is there a directive similar to INTS and INTL? Compile time options are all very well, but one can forget to apply them. OPTIONS, on the other hand, is embedded in the source code. (Remembering, of course, that once like me you have invested heavily in Clearwin+, there aren't really any alternative compilers ...)
Eddie
John
Your suggestion that FTN95 ought to accept all unambiguous KIND values is worth considering. There is only one ambiguous value (integer kind=4) at the moment and only one that I can think of (real kind=4) that could conceivably be ambiguous in the future. Logical kind=4 is like integer kind=4.
So how does one deal with kind=4 and should unambiguous values be accepted?
Eddie
Any of the compiler options INTS, INTL, DREAL, XREAL and ALT_KINDS can appear in an OPTIONS directive. INTL was inherited from FTN77 and sets the default integer kind to 32 bit integers. This is the default for FTN95.
Paul,
Thanks.I realised that INTL (INTEGER4) was the default for FTN95 32-bit. Is INTEGER8 the default for 64 bit, especially for constants? I suspect not.
FTN95 is rather intelligent, so that writing:
PROGRAM IntLongLong
INTEGER*8 I
I = 9223372036854775807
WRITE(*,'(I24)') I
END
simply gives one the rather clever warning:
WARNING - Constant is out of range for INTEGER(KIND=3) - has been promoted to INTEGER(KIND=4)
The correct answer is output.
The same warning is given in 32 bit AND 64 bit modes, so I suspect that the default for constants is normally INTEGER*4.
Not to be unKIND, but KIND seems to me to be a way of imposing chaos, not removing it.
Eddie
Eddie
The default integer kind is 32 bit integers for both 32 and 64 bit mode. At one point there was a context where there was an bug his was not the case but it should now be always true.
Eddie,
The standard conforming compiler response to 'I = 9223372036854775807' is to treat the constant as a default 4-byte integer and so produce the overflowed result. Fortunately in this case FTN95 provides a better result.
What integer kind should default for a 64 bit compiler is an interesting question.
Most compilers have adopted 4-byte, which is much easier for portability of 32-bit ode.
Providing an integer that copes with the 64 bit memory address is also a possible interpretation. While my earlier non-conforming recomendation for SIZE providing an 8-byte reult was a failure for the language purists, I wonder how many of them regularly use large memory programs, where the required answer is clearly 8-byte, rather than resorting to more complex syntax to get the obvious answer required.
My solution is to define all variables and not use 'integer'. I use 'integer4' or 'integer8' which although again offensive to some (as a Fortran extension) is a very robust, portable and concise description. For constants, I would like to use 11_8, rather than integer(4). When referencing FTN95.chm, I am always confused by examples like 'INTEGER(4),PARAMETER::n=100' as in 'vector processing via SSE/AVX'
Compilers should be more friendly, but unfortuntely the language standard does not share my view, eg real8 :: x = 0.1 integer8 :: I = 9223372036854775807 write (,) 'x = ',x write (,) 'i = ',i end
What integer kind should be the default for a 64 bit compiler is an interesting question.
Of course it is. But it is only a subsidiary question as to what a 64 bit compiler is, or should be. In the present case, it means that the default addressing mode is 64 bit. In that respect it matches what a 32 bit compiler is. But the 16 bit compilers weren’t limited to 16 bit addressing – with segmentation it’s effectively 20 bits. There's also something funny about 8 bits, which wouldn’t be much use to anyone, and were probably 16 bit anyway (like CPM).
The default REAL can’t be 64 bits, because then there would be no DOUBLE PRECISION, and if the default INTEGER for constants is *4 while the variables are *8 (OK, I’ve oversimplified) there’s a mismatch waiting to cause mayhem. FTN95 is at least smart about this case if it's explicit enough.
The great thing about (say) DREAL and INTL is that the constants match the variables.
By the way, regarding your 32-bit ode – I couldn’t manage one in 32-bits, but here’s one in 32 words!
I wrote my ode
In Fortran code
Many years ago.
But it’s still fun
To compile and run
And get results to show.
Without the cost
Of languages lost
And consequential woe.
Eddie
PS You may deduce that I favour words over bytes. Cue opening line from The Go Between.
JohnS,
I was only suggesting there is a problem as what is the default integer for a 64-bit system.
My suggestion is the default integer should be able to address the size of memory that is available ( I can't recall a reference for this requirement )
However Eddie has raised the impracticability of this as; given there is a default integer and real of the same size, there also has to be a double precision real available. Without a real16 available, this implies that integer4 and real*4 are the only possible default integer and real that can be used for Fortran 95, while complying with this aspect of the Fortran standard.
My problem is that the development in the Fortran Standard to provide sensible values requires the use of 'KIND=', while I would suggest that for the 64-bit compiler 'sensible values' should be automatically provided.
My past recommendation for SIZE to return a 'sensible value' was not compatible with my recent suggestion for FTN95 'Supporting F03 and F08 syntax can be helpful for compatibility with other Fortran environments' To me, it is just stupid that SIZE returns an overflowed value for a large array in 64-bit Fortran. The standard only addresses this required functionality in a clumsy way, but that is the standard !
I am just getting in early and apologizing for my new suggestions if I am sending Paul on another conflicted extension to FTN95 /64.
John
There isn’t a problem, really. The 64-bit appellation is the addressing mode, not the number of bits in a LOGICAL, INTEGER or REAL. It happens to be the number of bits in a COMPLEX, and a DOUBLE PRECISION, but that’s an accident.
Coincidentally, 32-bit meant the addressing mode, and in that case it was also coincidentally the number of bits in a LOGICAL, INTEGER or REAL. It wasn’t the number of bits in a COMPLEX or a DOUBLE PRECISION.
As I pointed out, 16-bit wasn’t the addressing mode – but then FTN95 never supported that, so we should forget it.
If one returns to the past, and ran Fortran on 16k words, using a machine where both REAL and INTEGER took 2 words, then DOUBLE PRECISION was such a luxury that it might just as well not been available (sometimes it wasn’t), so it never bothers me that OPTIONS(DREAL) simply means that REAL is good enough for almost everything, whereas when REAL is REAL4, it often isn’t much use. Incidentally, DOUBLE PRECISION / REAL8 wasn’t all that useful on a machine with the sort of usable RAM that one got with an early PC.
OPTIONS(DREAL) simply means that REAL is REAL8 and there isn’t a DOUBLE PRECISION, which I’m fine with, and even 1 Gb allows for a lot of REAL8 variables.
The integer case is a difficult one, because we use integers to calculate addresses. Hence, for a 64-bit addressing mode we have to have an INTEGER8 type. If you are a fan of declaring the type of every variable and disapprove of IMPLICIT type, then you can declare every variable to be INTEGER8 or however you like to do it with KIND. If you like implicit type, then use IMPLICIT INTEGER8 – presumably. The problem is with constants, which are by default INTEGER4. That probably hardly matters with most constants used in expressions, as for the commonest – 2, 3 etc - even INTEGER*4 is overkill. For the few integer constants where it does matter, FTN95 is smart. You, the programmer, can be smart too, and make those few integer constants into variables, like iTWO, iTHREE and iFOUR to give a few implicitly typed examples.
As to enumerating things with an integer number, the 4 billion of INTEGER*4 ought to be enough for most purposes , although perhaps not for the monks in a particular Tibetan Lamasery:
https://en.wikipedia.org/wiki/The_Nine_Billion_Names_of_God
Eddie
(PS. When I was first acquainted with the Arthur C. Clarke story, we Brits used billion to mean 1012 not the US 109 which usage has overtaken us. It then seemed an even more intractable target. It seems that a Tibetan language version of Windows has existed since Vista, so the monks can jolly well get on with the job themselves).