forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Strange behaviour in common block initialisation?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> 64-bit
View previous topic :: View next topic  
Author Message
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Tue Apr 27, 2021 2:17 pm    Post subject: Strange behaviour in common block initialisation? Reply with quote

The following code
Code:
      PROGRAM TEST
      INTEGER*2 I2, I2C
      INTEGER*4 I4, I4C
      REAL*4 R4, R4C
      REAL*8 R8, R8C
      Common /COMTES/ R8C,R4C,I4C,I2C
#IF _WIN64
      write(*,*) '64 Bit exe'
#ELSE
      write(*,*) '32 Bit exe'
#ENDIF
      WRITE(*,*) 'I2: ', I2, I2C
      WRITE(*,*) 'I4: ', I4, I4C
      WRITE(*,*) 'R4: ', R4, R4C
      WRITE(*,*) 'R8: ', R8, R8C                 
      END

named test.for is compiled using both the 32 bit and the 64 bit Version of SALFORD ftn95 version 8.70.0.

The resulting executable produces output which consists of 2 columns, the first of which consists of 4 local variables I2, I4, R4 and R8, the second of which consists of 4 common block variables I2C, I4C, R4C and R8C.
For the 32 bit version of the executables all variables are initialised to 0. For the 64 bit version of the executable the common block variables are not always initialised to 0. Unfortunately, we cannot reproduce this behaviour, we observed many cases where the common block variables are initialised correctly for the 64 bit version, as well. The mistaken initialisation (to a non zero value) occurs for all types of common variables (i.e. for I2C, I4C, R4C and R8C).

We compiled the 64 bit executable via
Code:
ftn95 test  /64 /ALL_WARNINGS/NON_STANDARD/SINGLE_THREADED/OLD_ARRAYS/ALT_KINDS/PERSIST/ZEROISE/UNLIMITED_ERRORS/FIXED_FORMAT/SAVE/NO_WARN73/WIDE_SOURCE /WINDOWS /include ..;..\..\subinc /CFPP /DEFINE CLEARWIN 1  /DEFINE SALFORD64 1     /debug /link


We do not have any explation for this behaviour, we thought all variable should be initialised to 0 because of ftn95 option /SAVE being set.

The version number of both clearwin64.dll and salflibc64.dll loaded by the executable are 23.1.18.7 .

Has anybody observed similar behviour?

We would appreciate any hint ...

Regards
Dietmar
Back to top
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2446
Location: South Pole, Antarctica

PostPosted: Tue Apr 27, 2021 9:22 pm    Post subject: Reply with quote

Allocatable arrays initialized to zero, Paul claimed here. If this is standard then i will not bother zeroizing myself, in my case this takes a lot of time sometimes.

But as to the common blocks, the standard does not guarantee you zeroes initially, so you have to do that manually. /zeroize does not work with /64 anymore
Back to top
View user's profile Send private message
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Wed Apr 28, 2021 8:34 am    Post subject: Reply with quote

Thanks Dan,

but I thought ftn95 option /SAVE would make the common block variables static and hence automatically initialised to zero. And this seems to be true for the 32 bit version.

Regards,
Dietmar
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7095
Location: Salford, UK

PostPosted: Wed Apr 28, 2021 9:51 am    Post subject: Reply with quote

Regarding unintialised COMMON data, for 32 bits you do appear to get zeros (with or without SAVE) but at the moment I don't know if this is by chance or by design.

For 64 bits you don't get zeros.

One solution is represented here...

Code:
      PROGRAM TEST
      INTEGER*2 I2C
      INTEGER*4 I4C
      REAL*4 R4C
      REAL*8 R8C
      COMMON /COMTES/ R8C,R4C,I4C,I2C
      DATA  R8C,R4C,I4C,I2C/4*0/
      PRINT*, R8C,R4C,I4C,I2C
      END


If there is more that one common block then it might be simpler to use BLOCK DATA.

Initialised COMMON data is packed into the executable and you can use a binary reader to see it after creating an executable using this sample...
Code:
      program test
      common /acomtes/i4a(1000)
      common /bcomtes/i4b(1000)
      data i4a/1000*-1/
      data i4b/1000*-2/
      print*,i4a(1000),i4b(1000)
      end


Another approach is to look at the assembler code produced by using /EXPLIST.
Back to top
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2341
Location: Sydney

PostPosted: Wed Apr 28, 2021 11:41 am    Post subject: Reply with quote

Assuming variables are initialised to zero is not standard conforming and so not portable. I don't know why this approach would be used with new code.
I really don't know what the following combination of options would mean ? "/NON_STANDARD/SINGLE_THREADED/OLD_ARRAYS/ALT_KINDS/PERSIST/ZEROISE"
I don't think /NON_STANDARD is the same as not standard conforming ?
It is a bit different to my /64 /ERROR_NUMBERS /IMPLICIT_NONE /INTL /LOGL,
but this is not the point of your post.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7095
Location: Salford, UK

PostPosted: Wed Apr 28, 2021 1:27 pm    Post subject: Reply with quote

John

Just for information, /INTL and /LOGL are the defaults.
Back to top
View user's profile Send private message AIM Address
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Wed Apr 28, 2021 2:28 pm    Post subject: Reply with quote

Thanks for your infos, Paul, John,

however, I am confused now about what is a static variable.

ftn95 help for the /SAVE option says:

The following types of variables will automatically be static:
Any variable that appears in a SAVE statement.
...
Any variable that is initialised, e.g. INTEGER::I = 1
All other variables will be made static if the /SAVE option is used.

In another post (8.20 and /ZEROISE) Paul said:
Quote:
In the following description, local variables and arrays that are given the SAVE attribute are called static variables.
and
Quote:
FTN95 presets the value of all static variables to zero.

Now having read this post it is still unclear to me if a variable of a common block is static or not. My current opinion: for 32 bit it is static for 64 bit it is not.

John C,

I do not know if it is standard conforming if common block variables are initialised to zero or not. But assumed that Salford's 32 bit version of ftn95 initialises common block variables to zero then I would expect this to be the case for the 64 bit version, as well.

This problem arose from the port of a big 32 bit application to 64 bit and hence the origin of the problem is not related to new code.

Moreover if a compiler guarantees that special variables are initialised to zero (as e.g. is the case using static variables in C code) why should I not rely on that behaviour? I could argue that initialising them twice (by the compiler and explicitly in the code) would be redundant.

Concerning the compile options: some of them are "historical" some necessary. However, I would not remove any of them for I do not know if this would result in additional diffculties Wink

Regards
Dietmar
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7095
Location: Salford, UK

PostPosted: Wed Apr 28, 2021 3:06 pm    Post subject: Reply with quote

Dietmar

I am not sure that it would help if I tried to explain what SAVE means in Fortran or for FTN95. The main point is that initialised COMMON data appears to be set to zero (possibly by design) for 32 bits but not for 64 bits.

If it turns out that the 32 bit behaviour is by design then there is certainly a case for us to see if we can provide the same behaviour for 64 bits. At the moment I don't know if this would be feasible or how long it would take to implement.

In the meantime you will probably want to explore ways to do the initialising in the code. In addition to my comments above, you could also consider using a local integer array (IARRAY) of suitable size which you EQUIVALENCE to the first item in a common block. You can then use the simple assignment statement "IARRAY = 0" in order to preset all the data to zero.
Back to top
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2341
Location: Sydney

PostPosted: Thu Apr 29, 2021 4:48 am    Post subject: Reply with quote

Dietmar,
DietmarSiepmann wrote:
Moreover if a compiler guarantees that special variables are initialised to zero (as e.g. is the case using static variables in C code) why should I not rely on that behaviour?

The Fortran Standard definitely does not guarantee this and I am not sure if FTN95 does either.

SAVE : static variables are allocated a fixed memory address and do not go out of scope. For large programs, it is helpful to differentiate between "global static variables" which always exist and "local dynamic variables" which are typically located on the stack and released when exiting the routine (going out of scope)
Some load maps show where static variables are stored for each routine.
The concept of dynamic variables (not static) is essential for recursive and multi-threaded approaches.

Initialised variables : your claims of initialised variables differ slightly from static variables.
In standard Fortran, initialised variables (via data or declaration) imply SAVE. The programmer codes the initial values.
Initialised variables are stored in the .exe and can make the .exe much larger.

ZERO initialisation : This is a slightly different case to initialisation. Having zeroised variables in 32-bit is a FTN95 extension.
Having zeroised variables in 64-bit, if provided, would be a FTN95 extension which has the potential to increase the execution time when entering a routine, especially for large dynamic arrays.
A related extension in FTN95 is that ALLOCATE variables are initialised to zero. I am not sure if this is both 32-bit and 64-bit. I never assume zeroised!
There is an important difference in Fortran between variables in a routine that are SAVED and initialised vs variables that are initialised in an executed statement.

The Fortran Standard implies that a variable that is not explicitly initialised (either declaration or execution statement) does not have an initial value.
It is incorrect to assume uninitialized variables are zero, which is a very common error, especially when moving from a compiler (like FTN95 /32) that provides this extension.
While there could be an argument that default initialising to zero would eliminate many errors and make Fortran more robust, the standards committee have not chosen this approach.
I also find not initialising variables to be an alarming approach that is not robust coding.

I did not learn these differences in my first course in FORTRAN !

I hope I have not made too many mistakes in this description !!
Back to top
View user's profile Send private message
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Thu Apr 29, 2021 9:24 am    Post subject: Reply with quote

Paul, John C,

thanks again for your informations.

The /SAVE option seems to be very complicated and to me it seems that one cannot rely on COMMON BLOCK VARIABLEs to be set to zero if /SAVE is specified for every Fortran compiler.

One of my intent was to express that it would be worthwhile that SALFORD's ftn95 compiler behaves in the same way for 32 bit and 64 bit wherever it is possible.

This would be a big help in the porting process from 32 bit to 64 bit Smile

Regards,
Dietmar
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2341
Location: Sydney

PostPosted: Thu Apr 29, 2021 12:14 pm    Post subject: Reply with quote

Understanding the difference between static or dynamic variables is essential for understanding Fortran 90+. It should not be complicated.
If you require the use of /SAVE or /ZERO, then you are not writing standard conforming programs and they will be difficult for others to maintain.

Ways of making variables static are
via declaration : INTEGER, SAVE :: I
or when initialising : INTEGER :: I = 1
or : INTEGER I ; DATA I / 1 /
You should understand the difference between the following
Code:
  subroutine a1 (res)
   integer :: res, ii = 1    ! ii is static
   ii = ii+1
   res = ii
  end subroutine a1

  subroutine a2 (res)
   integer :: res, ii    ! ii is dynamic
   ii = 1
   ii = ii+1
   res = ii
  end subroutine a2

  subroutine a3 (res)
   integer :: res, ii
   data ii / 1 /    ! ii is static
   ii = ii+1
   res = ii
  end subroutine a3

  subroutine a4 (res)
   integer :: res, ii        ! ii is dynamic
   ii = ii+1                   ! what is the value of ii ?
   res = ii
  end subroutine a4


If a variable, array or derived type are defined in a routine, they remain defined/allocated while they are in scope, either in the routine or a called routine.
Typically local or automatic arrays are placed on the stack or ALLOCATE on the heap and remain there until you exit from the routine.

If variables are defined in COMMON or MODULE, they remain defined while the COMMON or MODULE remains in scope, which is typically for the duration of the program.

ALLOCATE local arrays by default remain defined until execution exits the routine or DEALLOCATE is used.

For large memory arrays, this can be important (even in 64-bit) as the performance can be impacted by unnecessary memory wastage.

If you go to multi-threading, as well as SAVE vs dynamic, there is also SHARED vs PRIVATE. The management of these differences is essential for correct outcomes, as well as manageing the initialising of these variables.

Having all variables as /SAVE and assuming /ZERO is both lazy and limits accress to the functionality that these differences provide.

It is worth better understanding these issues, write standard conforming Fortran and don't rely on compile options such as /SAVE or /ZERO
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7095
Location: Salford, UK

PostPosted: Mon May 03, 2021 10:44 am    Post subject: Reply with quote

Dietmar

A new version of SLINK64 is now available via the Support "sticky" post. With this version, uninitialised common block data is preset to zero unless /UNDEF is used on the FTN95 command line.
Back to top
View user's profile Send private message AIM Address
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Mon May 03, 2021 12:50 pm    Post subject: Reply with quote

Paul,

thanks, with this new version the 64 bit vesion of test.exe presets common block data to zero analogously to the 32 bit version Smile

Regards,
Dietmar
Back to top
View user's profile Send private message
DietmarSiepmann



Joined: 03 Jun 2013
Posts: 279

PostPosted: Mon May 03, 2021 4:15 pm    Post subject: Reply with quote

Paul,

having competeley upgraded to version 8.72 (debuggers, dlls, ftn95, clearwin+, slink64) via the support "sticky" post I ran into problems with sdbg64 when debugging test.exe. Test.exe has been created via comand
Code:
ftn95 test.for /debug /cfpp /link /64

Starting the test.exe without debugger works as expected. Executing command
Code:
sdbg64 test.EXE
comes up with an Error dialog displaying lines

Assert failure: expr = ciu->address
File = StackFrame.cpp
Line= 385

while the command window in which sdbg64.exe was started displays line
CreateFileMapping returned 57CreateFileMapping returned 57

Setting a check mark to executabele sdbg64.exe within the resource manager shows the lines following for the associated modules:

Module name - Version
clearwin64.dll - 23.5.3.6
salflibc64.dll - 23.5.3.6
sdbg64.exe - 8.70.0.0

The third line confuses me because I would expect sdbgdll.dll instead of sdbg64.exe. However sdbgdll.dll does not occur in the resource manager listing of associated modules. The sdbgdll.dll of the ftn95 installation is dated as follows:

08.11.2020 17:30 522.752 sdbgdll.dll

Regards,
Dietmar
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7095
Location: Salford, UK

PostPosted: Tue May 04, 2021 9:28 am    Post subject: Reply with quote

Dietmar

Thank you for the feedback.

At the moment I can't explain this failure. It may be necessary for us to rebuild SDBG64.

mecej4 has reported a failure with the new SLINK64 so we should aim to fix that first and then see if a rebuild of SDBG64 is needed.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> 64-bit All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group