Silverfrost Forums

Welcome to our forums

Build Rebuild

25 Aug 2018 3:59 #22485

I have noticed that when I have a project open and make a change to one of the Fortran routines, if I then do a build, the change does not seem to be there. However, when I do a re build, the change seems to be there. Questions is:

Significance of: -build -rebuild -rebuild dependencies -clean

What does each do and when to use.

25 Aug 2018 4:54 #22486

On the Project menu you should normally have 'Enable Dependency Checking' switched on.

Then when you make a change to your code and select Build, the change is automatically saved and included in the build process.

When you select Rebuild, then all the project files are recompiled regardless of any changes.

However, you can change this behaviour in the project settings. For example, you can elect to leave a particular file in the list of project files but exclude it from the build process.

26 Aug 2018 7:16 #22487

All such tricks will be lost if not included into added menu 'Tricks everyone has to know'

29 Aug 2018 1:52 #22490

Just two little comments: At the moment, I am working on a project consisting of approximately 450 subroutines and functions. Nearly all of them use a global data module. I would expect that when the global data module is modified, all procedures using it are automatically recompiled. Neither under Plato (“Enable Dependence Checking” is checked) nor for the Visual Studio 2015 plugin this is the case. Only a few procedures are recompiled. Running the produced executable leads to a disaster. A complete rebuild is the solution.

With Plato there is another problem: it does not allow to add all 450 procedures. One can add only around 100. After that, dependency checking starts automatically, which takes rather long. My impression is that during the dependency checking is running, further programs should best not be added. Are there built-in limitations?

KL

29 Aug 2018 1:53 #22491

Just two little comments: At the moment, I am working on a project consisting of approximately 450 subroutines and functions. Nearly all of them use a global data module. I would expect that when the global data module is modified, all procedures using it are automatically recompiled. Neither under Plato (“Enable Dependence Checking” is checked) nor for the Visual Studio 2015 plugin this is the case. Only a few procedures are recompiled. Running the produced executable leads to a disaster. A complete rebuild is the solution.

With Plato there is another problem: it does not allow to add all 450 procedures. One can add only around 100. After that, dependency checking starts automatically, which takes rather long. My impression is that during the dependency checking is running, further programs should best not be added. Are there built-in limitations?

KL

29 Aug 2018 3:27 #22492

KL

As far as Plato is concerned, when there is a change to a module then I would expect that all files in the project that USE that module would be automatically recompiled (when dependency checking is switched on).

Dependency checking can be switched on or off by the user. It will always be applied when switched on. There is no automatic on or off.

In the past there was a problem with the dependency checking for projects with a large number of files but this was fixed and should be OK in the latest version of Plato.

It may be possible to fool Plato by having a module structure in the project that is recursive (e.g. module A depends on module B whilst module B depends on module A, it is usually more complex than that) but even then Plato should time out with an error report.

I have seen user projects where the module structure is recursive and where a clean rebuild is impossible and can only be achieved by bootstrapping in some way.

30 Aug 2018 8:55 #22493

Thank you very much, Paul for your quick reply.

In the program there are only a few modules and there is no recursive module structure. “Enable Dependency checking” is checked, the Plato version is 4.83.

To further investigate the case, I copied today the program into three different directories, from which I created a) a Visual Studio project (VS), b) a Plato project and c) a CodeBlocks project. I ensured again that all files in the three directories are identical. I compiled all projects with the Debug option and ran an identical case. The results of VS and Plato are identical (in the output some cut-offs may have happened), the results of CodeBlock employing the GNU Fortran compiler are the same within the numerical accuracy.

After this test, I added a blank line to the global data module “Global_Data” in all 3 directories. The new build produced the following results:

VS: compilation of “Global_Data” and just **one **subroutine with the corresponding Use statement.

Plato: compilation of “Global_Data” only; For Plato, I have rebuilt dependencies and changed “Global_Data” again. The result was the same.

Code::Blocks: compilation of more than 400 procedures.

Since I have seen this behavior before, my workaround is rather simple: if a module is modified, I always do a rebuild, which I also do from time to time.

Klaus

30 Aug 2018 9:15 #22494

PS. For Visual Studio 2015 I may have found the solution: Tools --> Options --> Projects and Solutions --> Build and Run: Uncheck “Only build startup projects and dependencies on Run”

30 Aug 2018 9:15 #22495

PS. For Visual Studio 2015 I may have found the solution: Tools --> Options --> Projects and Solutions --> Build and Run: Uncheck “Only build startup projects and dependencies on Run”

30 Aug 2018 1:43 #22496

KL

If you are able to zip up and send me your project then I will check it out.

31 Aug 2018 2:06 #22497

Dear Paul,

Thank you very much for your offer. Unfortunately, I am not allowed to release the code.

Today, I made several tests to recheck some of my experience with Plato:

  • When too many existing files are added, Plato may crash. When reopening the project in this case, all added files were moved to “Include Files”. Pressing “Build” leads to the error message “Error: No source files have been added to this project”. I have reproduced this unbelievable error three times.

  • One would expect that for a new project the modules are compiled first, which is not the case. The build process may take up to three steps. Of course, the modules could be compiled manually first in their right sequence.

  • Plato offers 9 compiler options (Checkmate, Debug and Release each for Win32, x64 and .NET) and the user sees immediately the advantage: It is possible to compile and run Fortran programs under Win32 and x64 as well as produce a .NET dll for linking with other .NET projects, for instance with a .NET GUI, which is a very attractive combination. The compiled programs are stored in separate directories (Checkmate etc.). In the project directory information on modules is stored: *.mod for win32, *.mod64 for x64. I cannot see something similar for .NET and it is rather tricky to switch from Win32 to .NET (again through a three-step build process or the deletion of the *.mod files).

My very personal view is that on one hand side a huge development of Plato took place in the last years (Win64, .NET), but some further consolidation might be needed.

I would like to take this opportunity to report two more specific problems:

  • It seems that there is an inaccuracy in the .NET compiler. Our program analyses a time dependent problem in thousands of time steps. All big arrays are allocated only once at time 0, some subroutines use array sections as arguments. Since .NET languages do not have something equivalent, an array section is probably copied internally to a new array before being passed to a subroutine. On return this array must be copied back into “its” section and the temporary array should be deallocated. (May be that I am completely wrong with that hypothesis). The program works and the starts to run as usual. However, after a couple of time steps the memory is exceeded (“Salford.Fortran.RuntimeException: 199; Run out of heap space”). Since this program runs the same data case on a 20 years old laptop with unbelievably low performance data I presume that the temporary arrays to which the array sections (approximately 2002004) have been copied many times have never been deallocated.

  • In .NET Checkmate there is still an “old” error, which has already been corrected for Win32/Checkmate:

    Subroutine XYZ Implicit none Integer :: i do i = … … end do …. Contains Subroutine A do i = … end do End Subroutine A End Subroutine XYZ

This usage of variable i results in the wrong error message “Salford.Fortran.CheckException: 431; Active Do-loop altered

Klaus

1 Sep 2018 9:19 #22498

Klaus

Thanks for your detailed feedback. Unfortunately we can only offer to fix issues and failures that we are able to reproduce. So, apart from one part of your report (with code for a .NET failure), we would need further information in the form of code that illustrates the problems that you have encountered.

3 Sep 2018 11:04 #22502

Paul, I understand.

Please find below two little test programs for those problems, which I can condense and send out:

Test98 gives for .NET Checkmate 'error 431: Active Do-loop index altered'. It is bad programming anyhow but it should not lead to an error

.
  Program Test98
    Implicit None
    Integer :: abc, i, xyz, n
    xyz = 0; n = 10
    do i = 1,n
      xyz = xyz + i
    end do
    call a
    write (*,*) ' xyz = ', xyz
    write (*,*) ' abc = ', abc
    read  (*,*)
    contains
      subroutine a
        abc = xyz
        do i = 1, n
          abc = abc + i
        end do
      end Subroutine a
  End Program Test98

Test99 runs successfully for Win31 and x64, but fails for .NET around timestep 230 (“Salford.Fortran.RuntimeException: 199: Run out of heap space”. This depends of course on heap space settings, but since the arrays are allocated only once, there should not be any space problems at all.

.
   Module datatypes
    Integer , Parameter :: i4b = Selected_int_kind (9)
    Integer , Parameter :: i2b = Selected_int_kind (4)
    Integer , Parameter :: i1b = Selected_int_kind (2)
    Integer , Parameter :: sp  = Kind (1.0)
    Integer , Parameter :: dp  = Kind (1.0d0)
    Integer , Parameter :: xp  = Selected_real_kind (18,99)
    Integer , Parameter :: lgt = Kind (.true.)
  End Module Datatypes

  Module CommonData
     Use      DataTypes
    Implicit None
    Real     (dp), Dimension (:,:  ), Allocatable , Save :: vec
    Real     (dp), Dimension (:,:,:), Allocatable , Save :: mat
  End Module CommonData

  Module Interfaces
    Interface
      Subroutine A ( Iter               , &
                     x_new              , &
                     x_old              , &
                     F_new              , &
                     F_old              , &
                     B_m1                   )
        Use DataTypes
        Implicit None
        Integer (i4b),                   Intent (in)    :: Iter
        Real    (dp) , Dimension (:)   , Intent (inout) :: x_new, &
                                                           x_old, &
                                                           F_old
        Real    (dp) , Dimension (:)   , Intent (in)    :: F_new
        Real    (dp) , Dimension (:,:) , Intent (inout) :: B_m1
      End Subroutine A
    End Interface
  End Module Interfaces
  
  Program Test99
 
    Use DataTypes
    Use CommonData
    Use Interfaces
    Implicit None

    Integer (i4b) lb, ub, iter, i

      lb = 3
      ub = 851

      Call Prepare

      do i = 1, 2000  
        iter = i
        vec = 0.0d+00
        mat = 0.0d+00
        
        Call A ( iter                        ,  &
                 vec ( lb :ub ,          1 ) ,  &
                 vec ( lb :ub ,          2 ) ,  &
                 vec ( lb :ub ,          3 ) ,  &
                 vec ( lb :ub ,          4 ) ,  &
                 mat ( lb :ub , lb :ub , 1 )       )

        write (*,*) ' iter, vec, mat = ', iter, vec (lb, 1), mat (lb, lb, 1)

      end do

      write (*,*) 'end reached'
      read (*,*)

  End Program Test99
 



  Subroutine A ( Iter  , &
                 x_new , &
                 x_old , &
                 F_new , &
                 F_old , &
                 B_m1       )
    Use DataTypes
    Implicit None
    Integer (i4b),                   Intent (in)    :: Iter
    Real    (dp) , Dimension (:)   , Intent (inout) :: x_new ,  &
                                                       x_old ,  &
                                                       F_old
    Real    (dp) , Dimension (:)   , Intent (in)    :: F_new     
    Real    (dp) , Dimension (:,:) , Intent (inout) :: B_m1

    x_new = 1.d+00
    B_m1  = 0.1d+00

  End Subroutine A



.
  Subroutine Prepare
    Use DataTypes
    Use CommonData
    Implicit None
    Integer (i4b) :: nDim = 1000
            Allocate ( vec (1:nDim,         1:4 ) )
            Allocate ( mat (1:nDim, 1:nDim, 1:3 ) )

!     --- Initialize matrices
                       vec = 0.0d+00
                       mat = 0.0d+00
  End Subroutine Prepare

Klaus

3 Sep 2018 11:07 #22503
  Subroutine Prepare
    Use DataTypes
    Use CommonData
    Implicit None
    Integer (i4b) :: nDim = 1000
            Allocate ( vec (1:nDim,         1:4 ) )
            Allocate ( mat (1:nDim, 1:nDim, 1:3 ) )

!     --- Initialize matrices
                       vec = 0.0d+00
                       mat = 0.0d+00
  End Subroutine Prepare





 
  Subroutine A ( Iter  , &
                 x_new , &
                 x_old , &
                 F_new , &
                 F_old , &
                 B_m1       )
    Use DataTypes
    Implicit None
    Integer (i4b),                   Intent (in)    :: Iter
    Real    (dp) , Dimension (:)   , Intent (inout) :: x_new ,  &
                                                       x_old ,  &
                                                       F_old
    Real    (dp) , Dimension (:)   , Intent (in)    :: F_new     
    Real    (dp) , Dimension (:,:) , Intent (inout) :: B_m1

    x_new = 1.d+00
    B_m1  = 0.1d+00

  End Subroutine A

Klaus

8 Nov 2018 10:13 #22750

Has anybody looked at Test98 and 99? I am especially interested in Test99 since it seems to be obvious that for the array section to be passed an internal array was initiated but not closed.

Klaus

8 Nov 2018 11:20 #22753

Klaus

My apologies but it appears that I have not logged these issues for investigation. I normally reply with an acknowledgement so it looks like I have simply missed the significance of the post.

8 Nov 2018 12:20 #22755

Klaus

From a brief initial investigation I can confirm that there is a false runtime error when running test98 with /check and /clr.

At the moment I have no idea about test99. For me (when compiling from a command line) the program stops running after about 200 iterations but without any error report.

If, as you say, it is a heap allocation issue then maybe something is going wrong with the .NET automatic garbage collection.

Both programs run correctly for Win32 and x64 with any configuration.

I have made a note of these failures.

8 Nov 2018 1:33 #22759

Paul, thank you very much for your reply. Test99 is extremely important for me since this error stops using our (big) code as a .NET dll in a C# GUI environment. Best regards, Klaus

8 Nov 2018 1:55 #22761

Klaus

if you need a fix urgently then I suggest that you experiment by changing the way in which the arrays are passed to the subroutine A.

For example, you could try copying the array sections to temporary arrays before the call etc.. It seems that something is going wrong with the automatic creation of the temporary 'copy in' arrays (and possibly 'copy out' arrays) that are needed when passing array sections to (and from) subroutines.

I have not looked at the details of your code but as a general rule it is not a good idea to pass array sections. Passing whole arrays is much more efficient and does not require the compiler to provide code that creates temporary storage from the stack or heap.

8 Nov 2018 3:16 #22766

Paul,

I am aware of this possibility. I just thought that internal copying of array sections is faster than copying array sections by do loops.

Fortunately, this error does not cause problems since from my GUI I can call a normal executable as well. I just reported this .NET related problem for further re-consideration.

May be that what you say about using array sections as dummy arguments is the reason that modern languages do not use them.

Thank you for taking a look to my problems.

Klaus

PS. Is there a problem with forum messages? When I press 'Preview' and submit my message, it appears twice.

Please login to reply.