2

I need to debug a program that includes forall blocks. Inside of them are pure subroutines or functions. In order to temporarily disable the pure predicate I use the C precompiler as in the following question posed by me:

Gfortran: Treat pure functions as normal functions for debugging purposes?

The problem now is, that if the subroutines or functions inside the forall block are not pure I get an error compiling. Is there a possibility to treat these errors

Error: Reference to non-PURE function 'pvkp' at (1) inside a FORALL block

only as warnings or is there maybe an easy possibility to use the C precompiler for turning

forall (i=1:n)
   ...
end forall

into

do i=1,n
   ...
end do 

Any ideas are appreciated!

Community
  • 1
  • 1
Wauzl
  • 941
  • 4
  • 20
  • 3
    Given that `forall` [doesn't do what it was supposed to do](http://stackoverflow.com/questions/4122099/do-fortran-95-constructs-such-as-where-forall-and-spread-generally-result-in-fa/4141572#4141572) (and also [this one](http://stackoverflow.com/questions/8602596/fortran-forall-restrictions)), why not just replace all `forall` with `do` anyway? – Kyle Kanos Feb 08 '14 at 18:36
  • I completely understand the concept of `forall`. I believe that the `forall` blocks will actually improve the speed of my program (once it is debugged). – Wauzl Feb 08 '14 at 20:28
  • I hope you plan on *testing* your assertion and not running with it purely on belief. In any event, you may want to check your assembler output to ensure that it is indeed using `forall` and not just transforming it into `do...enddo`. – Kyle Kanos Feb 08 '14 at 20:36
  • I second Kyle's comment. `forall` probably won't speed-up your code, they only make it shorter. Compilers are very good at optimizing do-loops and `forall` is sometimes too difficult to do without a temporary array. – Vladimir F Героям слава Feb 08 '14 at 20:51
  • There are some situations like `forall (i=1:3) A(i,i) = 1.0 end forall` where a `do` loop would be optimized by the compiler as good as the `forall` assignment. But I have some other cases, where I use `pure` functions that actually do more complicated stuff. Of course, `forall` is just an array definition and that’s how I use it. There is this construct for this task, so why not use it? Can you give me a hint on how to check how the blocks in question are optimized? – Wauzl Feb 08 '14 at 21:03
  • *There is this construct for this task, so why not use it?* Because it has been shown to not be as effective as the designers had hoped, as stated in my first comment. You'd have to read the assembler output (`gfortran -S file.f90` will do it) and compare the two cases. – Kyle Kanos Feb 10 '14 at 02:40
  • Thanks for the hint. Can you give a reference where is has been shown that `forall` blocks are not as effective as the designers had hoped? (I can’t really understand in which cases a `do` block would be optimized better than a `forall` block) – Wauzl Feb 10 '14 at 08:45

1 Answers1

2

One simplification is to use a do concurrent loop instead of a forall block. This reduces the number of linked changes required in the code: one need only change the loop specification, not change an end forall to an end do.

An approach not to be proud of, using cpp, and suitable for only simple cases:

#ifdef DEBUG
#define conloop(var, lower, upper) do var=lower, upper
#else
#define conloop(var, lower, upper) do concurrent (var=lower:upper)
#endif

  conloop(i,1,n)  ! Either a DO or DO CONCURRENT depending on DEBUG
  ...
  end do
end

The above does have the obvious extension to using a forall construct (with the extra #define for the ending) if that is really what you want. Alternatively, although more tedious to produce, using such things as

#ifdef DEBUG
do i=1,n
#else
forall (i=1:n)
#endif
  ...
#ifdef DEBUG
end do
#else
end forall
#end

This is horrible, but I imagine that's true for all pre-processor approaches. It does allow more complicated masks and is more localized.

francescalus
  • 30,576
  • 16
  • 61
  • 96