In recent postings, Larry Bauer mentioned f2c, to which Nick Holford
responded:
> I would also caution about the use of f2c. I have used it to create a C
> version of NONMEM that ran about half as fast as the original FORTRAN
> code. That was on a Silicon Graphics irix4d MIPS etc processor.
Earlier this year, someone else tried f2c. When Stuart Beal heard about
it, he sent this message to them:
> There's no way one can verify whether FORTRAN->C code works correctly.
> On first principles, I strongly recommend against this practice.
> I'm not sure whether this is a violation of the license agreement,
> but I am going to check, and if not, I am going to consider
> modifying the license.
So, one must continue to use the original FORTRAN source code and a
FORTRAN compiler for NONMEM.
f2c - FORTRAN to C
4 messages
4 people
Latest: Mar 21, 1994
Nick Holford's observations about f2c seem reasonable. Compilers simply
translate between languages. I fail to see any difference between
translating from Fortran to Object Code to Executable code (Standard
compilation and linking) and translating from Fortran to C to Object Code to
Executable Code (f2c, then using a C compiler and linking). If the C compiler
has better optimization or makes better use of the CPU or FPU, then the latter
approach may be superior (as Nick reported). But neither is a priori wrong,
and neither can be "validated" in any general sense, as clearly shown by Jaap
Mandema's demonstration of compilation problems with the MicroSoft PowerStation
Compiler under some settings.
I am surprised by Stuart's reported remarks. It is absurd to say
"There's no way one can verify whether FORTRAN->C works correctly". For
the particular model I tested the verification was simply that I got the
same results from the f2c translation that I got from the original
FORTRAN.
Of course, Stuart may have meant that there is no way one verify the
correct operation 'in general'. To which I would reply that there is no
way one can verify the correct operation of the FORTRAN code 'in
general'. It has been my experience that not all FORTRAN compilers can
be relied upon to produce the same answers from identical FORTRAN source code.
Here are some condensed results on the identical problem run on an
hp730, an iris4d (FORTRAN) and iris4dc (C from f2c), and a sun4. Notice
that 3 different FORTRAN compilers use different numbers of func evals
and claim different numbers of sig figs. The FORTRAN was from NONMEM
version 3 and the problems were run in 1992. NONMEM has changed since
then and it is quite likely that f2c has been enhanced also. Run times
are hh:mm:sec except for the hp730 which didnt need hh!
hp730O2.lst 22012.500 eval=720 sig=3.6 sub=909 obs=5253
THETA = 28.7 0.0169 -0.0374 -1.42 0c 20.9 61 1.58 13.5 0.001c 1.08 1.76 2.78 1c 1c 1c 1c 1c 1c 1c
ETASD = 0.376829 2.08087 1.25698 1.27671 0 0 0 0 0
ETAR12 = 0.310
ETAR23 = 0.374 0.520
ERRSD = 3.13847 0 0
THETA:se = 0.444 0.00348 0.00838 0.199 0c 6 28.6 0.564 3.43 0c 0.029 0.25 1.09 0c 0c 0c 0c 0c 0c 0c
ETASD:se = 0.0782304 1.41421 0.735527 0.697137
ERRSD:se = 0.614817 0 0
MINIMIZATION ROUTINE SUCCESSFULLY TERMINATED
Jun 17 09:17 user 42:16.1 real 42:52.5
iris4dO2.lst 22012.500 eval=1010 sig=5.2 sub=909 obs=5253
THETA = 28.7 0.0169 -0.0374 -1.42 0c 20.9 61 1.58 13.5 0.001c 1.08 1.76 2.78 1c 1c 1c 1c 1c 1c 1c
ETASD = 0.376829 2.08087 1.25698 1.27671 0 0 0 0 0
ETAR12 = 0.310
ETAR23 = 0.374 0.520
ERRSD = 3.13847 0 0
THETA:se = 0.444 0.00348 0.00838 0.199 0c 6 28.6 0.564 3.43 0c 0.029 0.25 1.09 0c 0c 0c 0c 0c 0c 0c
ETASD:se = 0.0782304 1.41421 0.735527 0.697137
ERRSD:se = 0.614817 0 0
MINIMIZATION ROUTINE TERMINATED
DUE TO MAX. NO. OF FUNCTION EVALUATIONS EXCEEDED
Jun 14 22:14 user 2:15:50.2 real 15:19:22.5
iris4dO2c.lst 22012.500 eval=701 sig=4.5 sub=909 obs=5253
THETA = 28.7 0.0169 -0.0374 -1.42 0c 20.9 61 1.58 13.5 0.001c 1.08 1.76 2.78 1c 1c 1c 1c 1c 1c 1c
ETASD = 0.376829 2.08087 1.25698 1.27671 0 0 0 0 0
ETAR12 = 0.310
ETAR23 = 0.374 0.520
ERRSD = 3.13847 0 0
THETA:se = 0.444 0.00348 0.00838 0.199 0c 6 28.6 0.564 3.43 0c 0.029 0.25 1.09 0c 0c 0c 0c 0c 0c 0c
ETASD:se = 0.0782304 1.41421 0.735527 0.697137
ERRSD:se = 0.614817 0 0
MINIMIZATION ROUTINE SUCCESSFULLY TERMINATED
May 1 22:27 user 2:03:08.9 real 2:16:39.8
sun4O2.lst 22012.500 eval=682 sig=3.8 sub=909 obs=5253
THETA = 28.7 0.0169 -0.0374 -1.42 0c 20.9 61 1.58 13.5 0.001c 1.08 1.76 2.78 1c 1c 1c 1c 1c 1c 1c
ETASD = 0.376829 2.08087 1.25698 1.27671 0 0 0 0 0
ETAR12 = 0.310
ETAR23 = 0.374 0.520
ERRSD = 3.13847 0 0
THETA:se = 0.444 0.00348 0.00838 0.199 0c 6 28.6 0.564 3.43 0c 0.029 0.25 1.09 0c 0c 0c 0c 0c 0c 0c
ETASD:se = 0.0782304 1.41421 0.735527 0.697137
ERRSD:se = 0.614817 0 0
MINIMIZATION ROUTINE SUCCESSFULLY TERMINATED
May 4 12:45 user 4:14:40.0 real 4:73:20.0
I also dont see the point of trying to stop the use of f2c. If someone
found a problem that was attributable to an error in the translation I
would not be surprised if it did not point to a weakness in the way that
the original FORTRAN was coded and NONMEM might be improved by
attempting to make that section of code more robust.
I must also retract my earlier statement that the f2c C source was
slower than the FORTRAN sourced executable. The time per function eval
was slower from the C code but the overall run time was faster with C
code because fewer func evals were required to complete the problem.
[See
topic 13
]
Alison has sucked me into a discussion which I would have
preferred to avoid. She sent out the following quote from me, intended for a
particular individual in a particular context, and not intended for general
discussion. And you all, understandbly, started to discuss this. She
sent all of your discussion to me so that I might see it
> There's no way one can verify whether FORTRAN->C code works correctly.
> On first principles, I strongly recommend against this practice.
> I'm not sure whether this is a violation of the license agreement,
> but I am going to check, and if not, I am going to consider
> modifying the license.
I have checked our license agreement. Developing C-code per se is not
a violation.
I have considered modifying the license. I do not think it should
be modified.
Nick Holford observed that when I said that there was no way to know whether
the C code works correctly, I may have meant "in general". He is
correct. With a *particular* NONMEM problem, one can confirm that both
FORTRAN and C codes are giving essentially the same results.
He also observed that different FORTRAN compilers can give different NONMEM
results, and therefore posed the question whether one can tell whether even the
FORTRAN compiled NONMEM code is correct. This observation too is, of course,
correct. However, unless one FORTRAN compiler has a real bug, while another
doesn't, the difference between their results will be negligible (for reasons
partly explained below). I am concerned that the same may not be true for
NONMEM C-Code.
Incidentally, the NONMEM Project Group does a certain
amount of testing of NONMEM using different FORTRAN compilers. This
helps check the robustness and reliability of our code.
Natural compiler differences, will lead to small differences in results
on the same machine (and natural differences in machines will also lead to
small differences.) By a small difference in results, I mean a small
difference in the minimum objective function and final parameter
estimates. (Nick has on previous occasion, and privately to just a few
of us, noticed differences in results from the Covariance Step and questioned
whether these were small. I replied that they in fact were, although at
first blush, they appeared not to be. Results from the Covariance Step
can be more sensitive to small compiler or machine differences.)
However, when small differences occur, the search path taken to the final
estimate can appear quite different. This path is very sensitive to
small compiler and machine differences. Differences in search paths
appear, for the purposes of this discussion, to be essentially
random. Different search paths to the same final estimate can involve
very different numbers of function evaluations.
If one wants to benchmark NONMEM between different systems, one should
compare the CPU time per function evaluation.
It isn't fair to rate a system as slower because it takes more
function evaluations to get to the same final estimate. Due to
the randomness, with the next problem one tries, it is quite likely that
the benchmark comparison would be reversed.
I doubt that C-code will run faster, using CPU time per function eval.
as our measure, than will FORTRAN code. I haven't tried C-code, and I
really don't know; I could be wrong. However, we try to write code efficiently
*for FORTRAN*, and I can't quite imagine what there is about C-code *per se*
that could improve on the FORTRAN code. (If with the C-compiler there is some
greater degree of optimization or such than is available with the FORTRAN
compiler, improvement could occur. But then, maybe a better FORTRAN
compiler should be obtained). We can do this because we
understand some detailed things about what FORTRAN compilers do.
Indeed, we take advantage of subtle FORTRAN "rules". I am somewhat
uncertain about the extent to which the FORTRAN->C program can be
faithful to *all* FORTRAN rules, or at least to the way they are usually
implemented by FORTRAN. Perhaps some are very faithful. But one
takes a risk here, more of a risk than one takes with choosing some
particular FORTRAN compiler. One reason we use FORTRAN is because there
is a well-developed STANDARD to which all FORTRAN compilers (from which
we assume you will make your choice) must (try to) comply. Not so,
regarding FORTRAN->C conversion programs. I can easily imagine that
nonadherence to all FORTRAN rules could cause problems, not only with
NONMEM efficiency, but with NONMEM accuracy and reliability as well.
The problem might not become apparent with the first NONMEM problem
you try to run, and maybe it will never become apparent while it
nevertheless leads to adverse effects. Because we use different FORTRAN
compilers, and because of the FORTRAN standard, we can give you some confidence
that NONMEM FORTRAN compiled code works well. We are not in a position to
give you this same confidence with NONMEM C compiled code.
So my recommendation is really a caution. I don't think the
benefit (if indeed there is one) will be worth the risk.
But you are free to take this risk.
I can hear someone ask: If FORTRAN search paths are rather variable,
mightn't this swamp FORTRAN-related efficiencies you have tried to use in your
code? The hope is that the "signal" amongst the noise will be
detectable. That is, the hope is that over many NONMEM runs, the net
gain resulting from these efficiencies will be significant.