Polyhedron tests on Intel Darwin8/9

Dominique Dhumieres dominiq@lps.ens.fr
Wed Nov 21 14:28:00 GMT 2007


> What did you implement?

Paul,

You are challenging me!-) 

I did the optimizations a very long time ago when the dot products were not
inlined neither in g95 nor in gfortran and induct took a couple of minutes.
So basically I replaced (taken from mutual_ind_quad_cir_coil):

coil_tmp_vector(1) = -sin(theta)
coil_tmp_vector(2) = cos(theta)
coil_tmp_vector(3) = 0.0_longreal
coil_current_vec(1) = dot_product(rotate_coil(1,:),coil_tmp_vector(:))
coil_current_vec(2) = dot_product(rotate_coil(2,:),coil_tmp_vector(:))
coil_current_vec(3) = dot_product(rotate_coil(3,:),coil_tmp_vector(:))

by

coil_tmp_vector(1) = - sin(theta)
coil_tmp_vector(2) = cos(theta)
coil_tmp_vector(3) = 0.0_longreal
coil_current_vec(1) = rotate_coil(1,1) * coil_tmp_vector(1) + &
		      rotate_coil(1,2) * coil_tmp_vector(2)
coil_current_vec(2) = rotate_coil(2,1) * coil_tmp_vector(1) + &
		      rotate_coil(2,2) * coil_tmp_vector(2)
coil_current_vec(3) = rotate_coil(3,1) * coil_tmp_vector(1) + &
		      rotate_coil(3,2) * coil_tmp_vector(2)

ans so on, noticing that coil_tmp_vector(3) was null.  Then I noticed that
there were several loop invariants in:

do i = 1, 2*m
...
    do j = 1, 9
...
	do k = 1, 9
...
	end do
    end do
end do

for instance I moved outside the loops

do k = 1, 9
    q_vector(1) = 0.5_longreal * a * (x2gauss(k) + 1.0_longreal)
    q_vector(2) = 0.5_longreal * b1 * (y2gauss(k) - 1.0_longreal)
    rot_q1_vector(k,1) = rotate_quad(1,1) * q_vector(1) + &
			 rotate_quad(1,2) * q_vector(2)
    rot_q1_vector(k,2) = rotate_quad(2,1) * q_vector(1) + &
			 rotate_quad(2,2) * q_vector(2)
    rot_q1_vector(k,3) = rotate_quad(3,1) * q_vector(1) + &
			 rotate_quad(3,2) * q_vector(2)
end do

In addition in induct_v3 I merged two loops.  You can find the modified
codes at

http://www.lps.ens.fr/~dominique/polyhedron/indu.v3.f90

These optimization could probably be found by a "perfect" compiler, but are
probably not trivial to implement (and may be not generic).  Also the
induct variants are the result of incremental optimizations and I never
timed the improvement due to each step.  As you have seen yourself, I have
found the optimization of induct quite deceptive: the program is fairly
long and complex and I have tested only a limited set of options, typically
-O3 -ffast-math -funroll-loops.

BTW my post was motivated by the change in timing between Darwin8 and 9 on 
aermod, and to a lesser extent on channel.  The only explanation I have 
is a "good" change (that happens!) in the OS, but I don't understand what 
it could be.

Have fun

Dominique
             
PS If you are interested, the list of available variants is

ac.v1.f90       capacita_10.f90 indu.v2.f90     linpk_u.f90     test_fpu_v1.f90
air_u.f90       capacita_8.f90  indu.v3.f90     mdbx_u.f90      tfft_10.f90
air.v1.f90      fatigue_10.f90  indu.vm.f90     nf_10.f90       tfft_8.f90
channel_10.f90  gas_dyn_u.f90   kepler.f90      protein_10.f90  tfft_u.f90
chan.v1.f90     induct_10.f90   kepler_10.f90   test_fpu_10.f90

where *_u.f90 are variants allowing to set the default real (-r4/8/10 in 
g95 syntax).

The timings for a G5 1.8Ghz are:

================================================================================
Date & Time     : 20 Nov 2007 16:08:34
Test Name       : pbharness
Compile Command : gfc %n.f90 -O3 -ffast-math -funroll-loops -o %n
Benchmarks      : ac aermod air capacita channel doduc fatigue gas_dyn induct linpk mdbx nf protein rnflow test_fpu tfft
Maximum Times   :      200.0
Target Error %  :      0.000
Minimum Repeats :     2
Maximum Repeats :     5

   Benchmark   Compile  Executable   Ave Run  Number   Estim
	Name    (secs)     (bytes)    (secs) Repeats   Err %
   ---------   -------  ----------   ------- -------  ------
	  ac     10.82       52648    118.89       2  0.0168
      aermod    286.19     1135076     94.10       3  0.0264
	 air     18.82       70688     45.12       5  1.1895
    capacita      8.01       62200    194.57       2  0.3549
     channel      4.97       40572     16.49       5  0.3605
       doduc     43.76      144340     71.91       3  0.4436
     fatigue     15.54       74336     24.31       5  0.1151
     gas_dyn     13.19      677360     57.69       4  0.2721
      induct     36.04      137720     74.17       3  0.0416
       linpk      2.45       40248     34.86       5  0.0600
	mdbx      8.95       66544     35.08       5  0.2959
	  nf      6.16       52768     59.68       4  0.2084
     protein     25.79       95476     76.41       3  0.0580
      rnflow     23.65      123848     93.27       3  0.1254
    test_fpu     17.70      102660     38.61       5  0.1379
	tfft      2.83       36496     17.53       5  0.3129

Geometric Mean Execution Time =      53.32 seconds

================================================================================

Note the very bad result for ac, but that induct is significantly faster
(xlf gives 50.8s, 25.8s for induct.v2, and 28.7 for induct.v3).



More information about the Fortran mailing list