Re: Why C is much slower than Fortran

Daniel Barker <sokal@holyrood.ed.ac.uk>
18 Apr 1999 01:58:52 -0400

          From comp.compilers

Related articles
Re: Why C is much slower than Fortran sokal@holyrood.ed.ac.uk (Daniel Barker) (1999-04-18)
Re: Why C is much slower than Fortran telken@sgi.com (Thomas Elken) (1999-04-29)
Re: Why C is much slower than Fortran sokal@holyrood.ed.ac.uk (Daniel Barker) (1999-04-30)
Problems with "ANSI aliasing" [was: Why C is much slower ..] trt@cs.duke.edu (1999-04-30)
Re: Problems with "ANSI aliasing" [was: Why C is much slower ..] bglbv@my-dejanews.com (1999-05-03)
Re: Why C is much slower than Fortran harley@corton.inria.fr (Robert Harley) (1999-05-03)
Re: Problems with "ANSI aliasing" [was: Why C is much slower ..] zalman@netcom.com (1999-05-07)
[15 later articles]
| List of all articles for this month |
From: Daniel Barker <sokal@holyrood.ed.ac.uk>
Newsgroups: comp.lang.c++,comp.lang.fortran,comp.compilers
Date: 18 Apr 1999 01:58:52 -0400
Organization: Edinburgh University
References: <3710584B.1C0F05F5@hotmail.com> <7esvkr$v8g$1@camel29.mindspring.com> <37122569.BF79CD19@hotmail.com> <3712311D.BA9027D4@hotmail.com> <7etenl$nk5$1@alexander.INS.CWRU.Edu>
Keywords: C, Fortran, performance

On 12 Apr 1999, Jonathan Stott wrote:


[snip]


> I have an idea that one of the optimizers is simply much better than
> the other. Perhaps your Fortran compiler discovered that the second
> loop always sets the matrix E[][][] to zero and so only needs to be
> computed once?
>
> Running your sample programs through gcc and g77 (current versions of
> each) on an old Ultrix workstation gives essentially the same
> result (within 1%):


[snip]


I used the you kindly provided, below, on a couple of systems.


Firstly, on a Sun SPARCcenter 2000, using GNU C as "gcc -O4", Sun C as
"cc -fast" and Sun FORTRAN 77 as "f77 -fast", I got:


GNU C: 16.4 seconds
Sun C: 8.5 seconds
Sun FORTRAN: 5.4 seconds


(The FORTRAN binary warned "Note: Nonstandard floating-point mode
enabled".)


Much more interestingly, I repeated it on a SGI PowerChallenge, using MIPS
C as "cc -Ofast" and MIPS FORTRAN 77 as "f77 -Ofast", and got:


C: 0.01 seconds
FORTRAN: 0.01 seconds


I assume the MIPS compilers correctly note that the results of the loop
are irrelevant to program output, and remove the loop entirely.


Such excellent optimization aside, the program is unusual, in that it
theoretically has no reason to run faster in either C or FORTRAN.


There is NO reason for greater inefficiency due to aliasing trouble in the
C version, since the arrays are defined and used in the same function. The
compiler knows, when it comes to the loop, that it is dealing with
non-overlapping arrays. This would NOT be so if the arrays were defined in
main(), but communicated to a different function containing the loop.


Note that expressions such as "A1[ ID[i][j][k] ]", in C, and
"A1( ID(i,j,k) )", in FORTRAN, CAN cause aliasing trouble, but it does not
matter in this case since the expressions are only read, not written. The
compiler would not generally not know, at the time of the loop, whether
each "A1( ID(i,j,k) )" occupies a different location in memory or not. (It
could do here, since it can see how "ID" was set up, but I would not blame
a compiler for failing to notice this probably unusual arrangement.)


In conclusion, the program is not well suited to showing up the
differences between C and FORTRAN, but IS well suited to showing up the
differences between different compilers. These differences are shown to be
extreme.




> The code I used for the two tests is below. I fixed a few things
> that looked like syntax errors and made the C look less like
> Fortran, but otherwise things are as originally posted.
>
> -JS
>
> /**********************************************************************/
>
> #include <stdio.h>
>
> #define imax 34
> #define jmax 20
> #define kmax 50
>
> int main(int argc, char *argv[])
> {
> float E[36][21][52], H1[36][21][52], H2[36][21][52];
> float A1[10], A2[10], A3[10];
> short ID[43][31][52];
> int i, j, k, nlp, nmax;
>
> /* ============== input nmax ================= */
>
> nmax = 1000;
>
> /* ----------- set initial conditions ---------- */
>
> for (i = 0; i < imax; i++)
> for (j = 0; j < jmax; j++)
> for (k = 0; k < kmax; k++)
> {
> ID[i][j][k] = 0;
> E[i][j][k] = 4.0;
> H1[i][j][k] = 5.0;
> H2[i][j][k] = 6.0;
> }
>
> A1[0] = 0.0;
> A2[0] = 2.0;
> A3[0] = 3.0;
>
> /* ############################## */
>
> for (nlp = 0; nlp < nmax; nlp++)
> for (i = 0; i < imax; i++)
> for (j = 0; j < jmax; j++)
> for (k = 0; k < kmax; k++)
> E[i][j][k] = A1[ ID[i][j][k] ] * E[i][j][k]
> + A2[ ID[i][j][k] ] * (H1[i][j][k] - H1[i][j - 1][k])
> + A3[ ID[i][j][k] ] * (H2[i][j][k] - H2[i][j][k - 1]);
>
> return(0);
> }
>
> C **********************************************************************
>
> PROGRAM sample
>
> REAL E(36,21,52), H1(36,21,52), H2(36,21,52)
> REAL A1(10), A2(10), A3(10)
> INTEGER*2 ID(43,31,52)
>
> INTEGER i, j, k, nlp, nmax
> INTEGER imax, jmax, kmax
>
> C /* ============= set parameters ============== */
>
> PARAMETER(imax = 35)
> PARAMETER(jmax = 20)
> PARAMETER(kmax = 50)
>
> C /* ============== input nmax ================= */
>
> nmax = 1000
>
> C /* ----------- set initial conditions ---------- */
>
> DO 100, k = 1, kmax
> DO 200, j = 1, jmax
> DO 300, i = 1, imax
> ID(i,j,k) = 1
> E(i,j,k) = 4.0
> H1(i,j,k) = 5.0
> H2(i,j,k) = 6.0
> 300 CONTINUE
> 200 CONTINUE
> 100 CONTINUE
>
> A1(1) = 0.0
> A2(1) = 2.0
> A3(1) = 3.0
>
> C /* ############################## */
>
> DO 400, nlp = 1, nmax
> DO 500, k = 1, kmax
> DO 600, j = 1, jmax
> DO 700, i = 1, imax
> E(i,j,k) = A1( ID(i,j,k) )*E(i,j,k)
> $ + A2( ID(i,j,k) )*(H1(i,j,k) - H1(i,j-1,k))
> $ + A3( ID(i,j,k) )*(H2(i,j,k) - H2(i,j,k-1))
> 700 CONTINUE
> 600 CONTINUE
> 500 CONTINUE
> 400 CONTINUE
>
> RETURN
> END




Daniel Barker.


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.