Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
fluiddyn
fluiddyn_papers
Commits
2cdac4807db5
Commit
835b4ffa
authored
May 18, 2018
by
Pierre Augier
Browse files
Profiling fluidsim.
parent
a1b6f8f648ca
Changes
4
Hide whitespace changes
Inline
Side-by-side
fluidsim/Makefile
View file @
2cdac480
...
...
@@ -29,14 +29,14 @@ vimtex:
doit
:
vimtex $(name).pdf
zathura
$(name)
.pdf &
fig
data
:
sync
data
:
python Python/sync.py
figures
:
fig
data tmp/fig_compare_with_ns3d.pdf
figures
:
sync
data tmp/fig_compare_with_ns3d.pdf
Python/make_fig_profile.py
$(name).pdf
:
tmp/fig_compare_with_ns3d.pdf
$(name).log
$(name).pdf
:
figures
$(name).log
@
#
$(LATEX)
$(name)
.tex
@
if
[
`
grep
"Package rerunfilecheck Warning: File"
$(name)
.log |
wc
-l
`
!=
0
]
;
then
$(LATEX)
$(name)
.tex
;
fi
@
if
[
`
grep
"Rerun to get cross-references right."
$(name)
.log |
wc
-l
`
!=
0
]
;
then
$(LATEX)
$(name)
.tex
;
fi
...
...
fluidsim/Python/make_fig_profile.py
View file @
2cdac480
...
...
@@ -2,8 +2,12 @@
import
os
import
getpass
from
pathlib
import
Path
import
matplotlib.pyplot
as
plt
from
fluidsim.util.console
import
profile
as
pf
from
fluiddyn.util
import
modification_date
from
base
import
matplotlib_rc
,
titles
,
curdir
...
...
@@ -21,15 +25,17 @@ if not os.path.exists(root):
patterns2d
=
[
# TODO: replace np=1 case
(
root
/
'beskow_1024x1024/'
).
glob
(
'*np=2*fftwmpi2d*'
),
(
root
/
'beskow_1024x1024/'
).
glob
(
'*np=
16
*fftwmpi2d*'
),
(
root
/
'beskow_1024x1024/'
).
glob
(
'*np=
8
*fftwmpi2d*'
),
]
patterns3d
=
[
# TODO: replace np=1 case
(
root
/
'beskow_128x128x128/'
).
glob
(
'*np=2*fftwmpi3d*'
),
(
root
/
'beskow_128x128x128/'
).
glob
(
'*np=8*fftwmpi3d*'
),
(
root
/
'beskow_512x512x512/'
).
glob
(
'*np=64*fftwmpi3d*'
),
(
root
/
'beskow_512x512x512/'
).
glob
(
'*np=128*fftwmpi3d*'
),
(
root
/
'beskow_1024x1024x1024/'
).
glob
(
'*np=1024*fftwmpi3d*'
),
# (root / 'beskow_1024x1024x1024/').glob('*np=1024*p3dfft*'),
# (root / 'beskow_1024x1024x1024/').glob('*np=1024*fftwmpi3d*'),
]
def
paths_from_patterns
(
patterns
):
...
...
@@ -40,6 +46,10 @@ def paths_from_patterns(patterns):
return
path_stats
paths2d
=
paths_from_patterns
(
patterns2d
)
paths3d
=
paths_from_patterns
(
patterns3d
)
def
plot
(
path
,
ax
,
title
=
''
,
**
kwargs
):
path_dir
=
os
.
path
.
dirname
(
path
)
nb_dim
=
path_dir
.
split
(
'_'
)[
1
].
count
(
'x'
)
+
1
...
...
@@ -63,32 +73,55 @@ def modif_title(title, path, with_resolution=True):
resol
=
resol
.
replace
(
'x'
,
r
'$\times$'
)
if
with_resolution
:
title
+=
' '
+
resol
+
','
title
+=
' '
+
nb_proc
+
' processes'
title
+=
' '
+
nb_proc
+
' process'
if
int
(
nb_proc
)
>
1
:
title
+=
'es'
return
title
pies2d
=
[]
fig2d
,
axes2d
=
plt
.
subplots
(
1
,
2
)
for
path
,
ax
,
title
in
zip
(
paths_from_patterns
(
patterns2d
),
axes2d
.
ravel
(),
titles
):
title
=
modif_title
(
title
,
path
,
with_resolution
=
False
)
pies2d
.
append
(
plot
(
path
,
ax
,
title
))
# labeldistance=0.))
pies3d
=
[]
fig3d
,
axes3d
=
plt
.
subplots
(
2
,
2
)
for
path
,
ax
,
title
in
zip
(
paths_from_patterns
(
patterns3d
),
axes3d
.
ravel
(),
titles
):
title
=
modif_title
(
title
,
path
)
pies3d
.
append
(
plot
(
path
,
ax
,
title
))
fig2d
.
set_size_inches
(
figx
,
figy
)
fig3d
.
set_size_inches
(
figx
,
2
*
figy
)
for
fig
,
pies
in
zip
((
fig2d
,
fig3d
),
(
pies2d
,
pies3d
)):
fig
.
tight_layout
()
if
save
:
path
=
curdir
+
'/../tmp/fig_profile{}.pdf'
fig2d
.
savefig
(
path
.
format
(
'2d'
))
fig3d
.
savefig
(
path
.
format
(
'3d'
))
modif_date_input_2d
=
min
(
modification_date
(
path
)
for
path
in
paths2d
)
modif_date_input_3d
=
min
(
modification_date
(
path
)
for
path
in
paths3d
)
path_fig
=
curdir
+
'/../tmp/fig_profile{}.pdf'
path_fig2d
=
path_fig
.
format
(
'2d'
)
path_fig3d
=
path_fig
.
format
(
'3d'
)
if
Path
(
path_fig2d
).
exists
():
modif_date_fig_2d
=
modification_date
(
path_fig2d
)
has_to_make2d
=
modif_date_fig_2d
<
modif_date_input_2d
else
:
has_to_make2d
=
True
if
Path
(
path_fig3d
).
exists
():
modif_date_fig_3d
=
modification_date
(
path_fig3d
)
has_to_make3d
=
modif_date_fig_3d
<
modif_date_input_3d
else
:
has_to_make3d
=
True
if
has_to_make2d
:
pies2d
=
[]
fig2d
,
axes2d
=
plt
.
subplots
(
1
,
2
)
for
path
,
ax
,
title
in
zip
(
paths2d
,
axes2d
.
ravel
(),
titles
):
title
=
modif_title
(
title
,
path
,
with_resolution
=
False
)
pies2d
.
append
(
plot
(
path
,
ax
,
title
))
# labeldistance=0.))
fig2d
.
set_size_inches
(
figx
,
figy
)
fig2d
.
tight_layout
()
if
save
:
fig2d
.
savefig
(
path_fig2d
)
if
has_to_make3d
:
pies3d
=
[]
fig3d
,
axes3d
=
plt
.
subplots
(
2
,
2
)
for
path
,
ax
,
title
in
zip
(
paths3d
,
axes3d
.
ravel
(),
titles
):
title
=
modif_title
(
title
,
path
)
pies3d
.
append
(
plot
(
path
,
ax
,
title
))
fig3d
.
set_size_inches
(
figx
,
2
*
figy
)
fig3d
.
tight_layout
()
if
save
:
fig3d
.
savefig
(
path_fig3d
)
if
not
save
and
(
has_to_make2d
or
has_to_make3d
):
plt
.
show
()
fluidsim/Python/sync.py
View file @
2cdac480
...
...
@@ -3,7 +3,7 @@ import os
import
getpass
from
subprocess
import
call
import
matplotlib.pyplot
as
plt
#
import matplotlib.pyplot as plt
from
fluiddyn.util
import
modification_date
...
...
@@ -36,21 +36,21 @@ else:
os
.
chdir
(
here
)
def
save_fig_scaling
(
dir_name
,
dim
,
n0
,
n1
,
n2
=
None
):
path_dir
=
os
.
path
.
join
(
path_fluidsim_bench_results
,
dir_name
)
path_fig
=
os
.
path
.
join
(
here_tmp
,
'fig_'
+
dir_name
+
'.pdf'
)
if
not
os
.
path
.
exists
(
path_fig
)
or
\
modification_date
(
path_dir
)
>
modification_date
(
path_fig
):
print
(
'make fig'
,
path_fig
)
fig
=
plot_scaling
(
path_dir
,
None
,
dim
,
n0
,
n1
,
n2
,
show
=
False
,
for_latex
=
True
)
fig
.
set_size_inches
(
10
,
5
)
fig
.
suptitle
(
''
)
fig
.
tight_layout
(
pad
=
1.02
,
h_pad
=
None
,
w_pad
=
None
,
rect
=
(
-
0.01
,
-
0.02
,
1
,
1
)
)
fig
.
savefig
(
path_fig
,
dpi
=
800
)
#
def save_fig_scaling(dir_name, dim, n0, n1, n2=None):
#
path_dir = os.path.join(path_fluidsim_bench_results, dir_name)
#
path_fig = os.path.join(here_tmp, 'fig_' + dir_name + '.pdf')
#
if not os.path.exists(path_fig) or \
#
modification_date(path_dir) > modification_date(path_fig):
#
print('make fig', path_fig)
#
fig = plot_scaling(path_dir, None, dim, n0, n1, n2, show=False,
#
for_latex=True)
#
fig.set_size_inches(10, 5)
#
fig.suptitle('')
#
fig.tight_layout(
#
pad=1.02, h_pad=None, w_pad=None, rect=(-0.01, -0.02, 1, 1)
#
)
#
fig.savefig(path_fig, dpi=800)
#
# save_fig_scaling('legi_cluster8_320x640x640', '3d', 320, 640, 640)
...
...
fluidsim/fluidsim_paper.tex
View file @
2cdac480
...
...
@@ -601,12 +601,12 @@ following sections.
\subsubsection*
{
Profiling
}
It is straightforward to perform profiling with the help of the
\href
{
https://docs.python.org/3/library/profile.html
}{
cProfile
}
module,
available
in the Python standard library. Here, we have analy
s
ed both 2D and
3D
Navier-Stokes solvers in Beskow, and plotted the
m
in
\href
{
https://docs.python.org/3/library/profile.html
}{
cProfile
}
module,
available
in the Python standard library. Here, we have analy
z
ed both 2D and
3D
Navier-Stokes solvers in Beskow, and plotted the
results
in
Fig.~
\ref
{
fig:profile2d
}
and Fig.~
\ref
{
fig:profile3d
}
respectively. Functions
which cumulatively consume less than
$
2
\%
$
of the total time are displayed in
the
\emph
{
other
}
category.
which cumulatively consume less than
$
2
\%
$
of the total time are displayed in
the
\emph
{
other
}
category.
% todo: redo these figures (API changes + better speed). Use with_pyfftw for
% sequential runs.
...
...
@@ -616,7 +616,7 @@ the \emph{other} category.
\includegraphics
[width=\linewidth]
{
tmp/fig
_
profile2d
}
\caption
{
Profiling analysis of the 2D Navier-Stokes
(
\codeinline
{
fluidsim.solvers.ns2d
}
) solver using a grid sized
$
1024
\times
1024
$
(a) in sequential with
\codeinline
{
fft2d.with
\_
fftw1d
}
operator and (b) with
16
(a) in sequential with
\codeinline
{
fft2d.with
\_
fftw1d
}
operator and (b) with
8
processes with
\codeinline
{
fft2d.mpi
\_
with
\_
fftwmpi2d
}
operator.
}
\label
{
fig:profile2d
}
\end{figure}
...
...
@@ -624,38 +624,51 @@ operator.}\label{fig:profile2d}
In Fig.~
\ref
{
fig:profile2d
}
both sequential and parallel profiles of the 2D
Navier-Stokes solver shows that majority of time is spent in inverse and forward
FFT calls (
\codeinline
{
ifft
\_
as
\_
arg
}
and
\codeinline
{
fft
\_
as
\_
arg
}
). For the
sequential solver, over
$
97
\%
$
of the time is spent in compiled C++ extensions,
built using
\pack
{
Cython
}
and
\pack
{
Pythran
}
and all pure Python functions limited
in the
\emph
{
other
}
category.
\pack
{
Cython
}
extensions are responsible for
interfacing with FFT operators and also for the time-step algorithm.
\pack
{
Pythran
}
extensions are used to translate most of the linear algebra
operations into optimized, statically compiled extensions. With 16 processes
deployed in parallel, time spent in compiled extensions falls to around
$
93
\%
$
,
with increased contribution from
\codeinline
{
tendencies
\_
nonlin
}
, a Python
function which is responsible for computing non-linear tendencies, or in other
words the advection term of the 2D Navier-Stokes equation.
sequential case, approximately 0.3
\%
of the time is spent in pure Python
functions, i.e. functions not built using
\pack
{
Cython
}
and
\pack
{
Pythran
}
.
%
\pack
{
Cython
}
extensions are responsible for interfacing with FFT operators and
also for the time-step algorithm.
\pack
{
Pythran
}
extensions are used to translate
most of the linear algebra operations into optimized, statically compiled
extensions.
%
We also see that only 1.3
\%
of the time is not spent in the main six functions
(category
\emph
{
other
}
in the figure).
%
With 8 processes deployed in parallel, time spent in pure Python function
increases to 1.1
\%
of the total time.
%
These results show that during the optimization process, we have to focus on a
very small number of functions.
\begin{figure}
[htp]
\centering
\includegraphics
[width=\linewidth]
{
tmp/fig
_
profile3d
}
\caption
{
Profiling analysis of the 3D Navier-Stokes
(
\codeinline
{
fluidsim.solvers.ns3d
}
) solver using a grid sized
$
128
\times
128
\times
128
$
solved (a) sequentially using
\codeinline
{
fft3d.with
\_
fftw3d
}
operator and (b) with 2 processes using
\codeinline
{
fft3d.mpi
\_
with
\_
fftwmpi3d
}
operator in the top row. In the bottom
row are similar results for the same solver using
\codeinline
{
fft3d.mpi
\_
with
\_
fftwmpi3d
}
operator (c) with 128 processes on a grid
sized
$
512
\times
512
\times
512
$
, and (d) with 1024 processes on a grid sized
$
1024
\times
1024
\times
1024
$
.
}
\label
{
fig:profile3d
}
\centering
\includegraphics
[width=\linewidth]
{
tmp/fig
_
profile3d
}
\caption
{
Profiling analysis of the 3D Navier-Stokes
(
\codeinline
{
fluidsim.solvers.ns3d
}
) solver.
%
Top row: grid sized
$
128
\times
128
\times
128
$
solved (a) sequentially using
\codeinline
{
fft3d.with
\_
fftw3d
}
operator and (b) with 8 processes using
\codeinline
{
fft3d.mpi
\_
with
\_
fftwmpi3d
}
operator.
%
Bottom row: grid sized
$
512
\times
512
\times
512
$
using
\codeinline
{
fft3d.mpi
\_
with
\_
fftwmpi3d
}
operator (c) with 64 processes and (d)
with 128 processes.
}
\label
{
fig:profile3d
}
\end{figure}
From Fig.~
\ref
{
fig:profile3d
}
it can be shown that, for the 3D Navier-Stokes
solver for all cases majority of time is attributed to FFT calls
(
\codeinline
{
ifft
}
and
\codeinline
{
fft
}
). The overall time spent in compiled
extensions range from around
$
70
\%
$
in sequential mode with
$
128
^
3
$
grid points
to
$
90
\%
$
in parallel mode with
$
1024
^
3
$
grid points. There is also substantial
contribution from the Python function
\codeinline
{
vgradv
\_
from
\_
v
}
which is
responsible for computing the non-linear term in the solver.
solver for all cases majority of time is attributed to FFT calls. The overall time
spent in pure Python function range from 0.07
\%
for
$
512
^
3
$
grid points and 64
processes to 0.46
\%
for
$
128
^
3
$
grid points and 8 processes.
%
This percentage tends to increase with the number of processes used since the real
calculation done in compiled extensions take less time.
%
This percentage is also higher for the coarser resolution for the same reason.
%
However, the time in pure Python remains for all cases largely negligible compared
to the time spent in compiled extensions.
\subsubsection*
{
Scalability
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment