(j3.2006) "Rejected" proposal from 12-195

Rafik Zurob rzurob
Thu Nov 22 08:02:08 EST 2012


Hi Van

I'm trying to understand the problem and proposed solution.  Say we have 
this example:

module m
private
type, public :: dt
contains
  procedure, pass(this) :: proc1 => real_proc1
  procedure, pass(this) :: proc2 => real_proc2
end type

contains
  subroutine real_proc1(a, this)
    integer a
    class(dt) this
  end subroutine
  subroutine real_proc2(this, a)
    class(dt) this
    integer a
  end subroutine
end module

use m
type(dt) x
procedure(??), pointer :: p  ! <-- (1)
if (some_condition) then
  p => x%proc1
else
  p => x%proc2
endif
call p(10, x)  ! <-- (2)
end

Questions:

(1) What procedure interface would you use for the procedure pointer? 
Would you create an abstract interface to describe the interface of the 
pointer?  How would you know the position of the passed object dummy 
argument if the documentation of the module only tells you the arguments 
you have to provide?
(2) What would the syntax of the call be?  Would the user have to 
explicitly specify the passed object dummy argument?  If so, how would 
they know what its position is?  The compiler wouldn't be able to simply 
provide it.  e.g. Imagine that this pointer is passed to another 
procedure, and the call is made from that other procedure.  Or imagine 
that in the if statement before call to p above, the if part was "p => 
x%proc1" while the else part was "p => y%proc2".

For both (1) and (2) above, we should ensure that any solution would not 
require source changes to the main program if the creator of the module 
decided to change the positions of the passed object dummy arguments in a 
new revision of the module.

If you had access and permission to change the module source in this case, 
what would you change?

It's possible that the problem your colleague is facing is already solved 
by compiler optimizations that version the loop.  I tried the following 
code with "xlf2003 -qhot" and the compiler split the loop into two loops 
so that the condition check is outside the loop.

some_condition = get_condition()
do i=1, 1000
  if (some_condition) then
    call x%proc1(i)
  else
    call x%proc2(i)
  endif
end do

got changed into something like:

some_condition = get_condition()
if (some_condition) then
  do i=1, 1000
    call x%proc1(i)
  end do
else
  do i=1, 1000
    call x%proc2(i)
  end do
endif

Obviously, a more complicated program might have things that will make the 
compiler decide not to version the loop.  But my point is that perhaps 
this should be left up to compiler optimizations instead of the language.

Regards

Rafik


j3-bounces at mailman.j3-fortran.org wrote on 15/11/2012 10:59:10 PM:

> From: Van Snyder <Van.Snyder at jpl.nasa.gov>
> To: fortran standards email list for J3 <j3 at mailman.j3-fortran.org>, 
> Date: 15/11/2012 10:59 PM
> Subject: (j3.2006) "Rejected" proposal from 12-195
> Sent by: j3-bounces at mailman.j3-fortran.org
> 
[snip]
> 
> One of my colleagues has a contractual obligation to use a specific
> module.  He has no funding to develop an alternative implementation of
> its functionality, and has explicit instructions not to do so.
> 
> The only public identifier in the module is a type name.  In particular,
> the names of the procedures bound to the type are not public.  He has
> documentation of the components and type-bound procedures of the module.
> He does not have the source code, or even a printed listing, and has no
> funding to request that the provider make changes to it, or to pay for
> recertification even if he had funding for changes.
> 
> He has a complicated decision process to decide which type-bound
> procedures to use.
> 
> The procedures are invoked within his inner loop, but the decision
> process is independent of the loop.  He'd like to hoist it out to
> improve performance.
> 
> I suggested that the decision process compute an index, and his inner
> loop use a case construct to invoke the type-bound procedures.  He
> already thought of this.  A case selector still apparently imposed more
> overhead than he thought it ought to.
> 
> He asked why he can't encode the decision as a procedure pointer or
> procedure argument, which he has done in similar situations in other
> parts of his program, where the procedure names were public (if by
> "overhead" he means runtime instead of code bulk, maybe that's how he
> measured the overhead of a case selector).
> 
> I explained that the syntax for procedure pointer assignment or
> procedure actual arguments does not admit data-ref%binding-name.  He and
> I became curious whether this syntactic irregularity is really
> necessary.  I proposed in 12-195 that it is not necessary.  No
> counter-argument to the proposition that this irregularity is
> unnecessary has been forthcoming.
> 
> Regularizing this irregularity would require replacing <procedure-name>
> and <proc-component-ref> in R740 and R1223 with <procedure-designator>
> (i.e., simplifying two syntax rules) and adding a constraint on each of
> them:
> 
> Cxxxx (Ryyyy) If <procedure-designator> is <data-ref>%<binding-name>,
> <data-ref> shall not be polymorphic and <binding-name> shall not be
> generic.
> 
> Regardless of the avenue by which I and my colleague arrived at the
> observation of this tiny syntactic irregularity, and our conclusion that
> it is not necessary, repairing it is a tiny project that seems to fit
> well within the scope of M6 (and the edits are effectively done).
> 
> This won't be done in time to improve performance in my colleague's code
> next week, but JPL has very long-lived codes -- some over fifty years
> old -- that undergo continuous development.  Maybe someday, one of his
> professional descendants could improve performance by exploiting this
> tiny feature.
> 
> 
> _______________________________________________
> J3 mailing list
> J3 at mailman.j3-fortran.org
> http://mailman.j3-fortran.org/mailman/listinfo/j3
> 




More information about the J3 mailing list