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