home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 16595 < prev    next >
Encoding:
Text File  |  1992-11-16  |  5.5 KB  |  123 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!utcsri!helios.physics.utoronto.ca!alchemy.chem.utoronto.ca!mroussel
  3. From: mroussel@alchemy.chem.utoronto.ca (Marc Roussel)
  4. Subject: Allowed Fortran and C optimizations
  5. Message-ID: <1992Nov16.153307.4632@alchemy.chem.utoronto.ca>
  6. Sender: mroussel@alchemy.chem.utoronto.ca (Marc Roussel)
  7. Organization: Department of Chemistry, University of Toronto
  8. Date: Mon, 16 Nov 1992 15:33:07 GMT
  9. Lines: 112
  10.  
  11.      A few days ago, I suggested that I might post some example code
  12. showing that better performance can sometimes be obtained from Fortran
  13. than C unless one is willing to hand-tune the C code.  Before I show my
  14. example, I would like to point out that I am not claiming that Fortran
  15. is better than C for everything, only that Fortran sometimes optimizes
  16. better than equivalent C code.
  17.      This example is from an HP Interworks conference (New Orleans,
  18. August 24-27 1992) talk by Bob Montgomery of HP.  All the numbers
  19. reported below will be for the HP 720.  The benchmark is a routine
  20. called vec_mult_add which multiplies a vector v by a scalar a and adds a
  21. vector u, returning vector r.  There is one small restriction:  The
  22. routine must be Fortran-callable, i.e. everything has to be passed by
  23. reference.
  24.      Here is the Fortran code:
  25.  
  26.       subroutine vec_mult_add(u,v,cnt,a,r)
  27.       integer cnt
  28.       real u(cnt),v(cnt),r(cnt),a
  29. *     Comment:  This was obviously written by someone who is used to
  30. *      very old Fortran compilers.  The following "if" is redundant
  31. *      with the loop indices.  I suspect that the optimizer will know
  32. *      that however.
  33.       if (cnt.le.0) return
  34.       do ii=1,cnt
  35.        r(ii) = a*v(ii) + u(ii)
  36.       end do
  37.       end
  38.  
  39. On an HP 720, compiled with the -O flag (which does not invoke the HP
  40. preprocessor but allows all normal optimizations), this snippet, driven
  41. by an appropriate wrapper, achieves 18.50 MFLOPS.  Remember that number.
  42.     The most obvious way to implement this routine in C (remember, it
  43. as to be Fortran-callable) is probably
  44.  
  45. vec_mult_add(u,v,cnt,a,r)
  46. float *u,*v;
  47. int *cnt;
  48. float *a,*r;
  49. {
  50.     int ii;
  51.     if (*cnt <= 0) return;
  52.     for (ii=0; ii<*cnt; ii++) {
  53.         *r++ = (*a * *v++) + *u++;
  54.     }
  55. }
  56.  
  57. This version of vec_mult_add gets you either 4.73 MFLOPS or 7.09 MFLOPS
  58. depending on whether or not you compiled in ANSI mode.  (ANSI mode is
  59. faster because the loop then does not contain implicit float-double
  60. conversions.)  That's pretty sad.
  61.      Now if you know a little bit about C compilers and optimizers (and
  62. I know only a very little) it will be pretty clear what parts of this
  63. routine are inhibiting the optimizer.  To put it simply, the fact that
  64. everything is a pointer is forcing the optimizer to make extremely
  65. conservative assumptions.  Let's make the following modifications:
  66. First, we'll make local copies of cnt and a so that the compiler doesn't
  67. have to worry about aliasing.  Then, we'll use array notation for things
  68. which really are arrays:
  69.  
  70. vec_mult_add(u,v,cnt,a,r)
  71. float u[],v[];
  72. int *cnt;
  73. float *a,r[];
  74. {
  75.     int ii;
  76.     int lcnt = *cnt;
  77.     float la = *a;
  78.     if (lcnt <= 0) return;
  79.     for (ii=0; ii<lcnt; ii++) {
  80.         r[ii]+ = la * v[ii] + u[ii];
  81.     }
  82. }
  83.  
  84. Compiling this in ANSI mode with the -O flag we get 9.93 MFLOPS, i.e.
  85. about half the Fortran performance.  Interestingly, we get 9.93 MFLOPS
  86. without switching to array syntax, i.e. with just the la and lcnt hacks.
  87. HP's C compiler has another optimizer switch which asserts that none of
  88. the arguments of a function call are aliased, the +Om1 flag.  It's only
  89. when we make all the modifications shown above AND turn on this flag
  90. that we get 18.50 MFLOPS.
  91.      Now the +Om1 flag does what I want it to, but I wouldn't want to
  92. compile a library or program written in C by someone else with it:  Since C does
  93. not force you to keep your function parameters distinct, I couldn't
  94. count on the program executing correctly.  That means that in many
  95. scientific codes whose guts are made up mostly of simple loops like the one
  96. shown above, I can expect C to perform about half as well as Fortran.
  97. In my case, that's not a big deal.  For other people whose codes run for
  98. days, it is.
  99.      Note that you can push this argument to the absurd:  HP's hand-coded
  100. assembler version of vec_mult_add cranks out over 28 MFLOPS on a 720.
  101. Assembler is not a good choice for most scientific programming because it
  102. takes too much programmer time and effort.  In the case of C and Fortran
  103. however, since both languages are roughly equally easy to learn and
  104. code, no such argument can be made.
  105.      Furthermore, if I'm allowed to use special compiler flags, the HP's
  106. Fortran preprocessor (invoked with the +OP flag) gives this language an
  107. unfair edge since it should be able to recognize the loop as a
  108. vec_mult_add and call the assembler routine thus producing 28 MFLOPS
  109. performance in the Fortran program.  It would of course be completely
  110. unfair to compare the two languages on this basis.
  111.      What it comes down to is this.  If you write Fortran programs, you
  112. are so constrained that the compiler knows exactly what you mean, right
  113. off the bat.  If you write C, you have to have ways to tell the compiler
  114. what you mean.  Expressiveness, in this case, comes at a performance price.
  115. Whether C or Fortran is the better language for your number crunching
  116. application will depend on whether or not you need C's features.  A lot
  117. of scientific work requires no data structures more sophisticated than
  118. static arrays.  In those cases, Fortran is probably the better choice.
  119. I wouldn't want to create binary trees in Fortran anymore however.
  120.  
  121.                 Marc R. Roussel
  122.                                 mroussel@alchemy.chem.utoronto.ca
  123.