thesis version
This commit is contained in:
commit
6cc2e76b2a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build/
|
88
CMakeLists.txt
Normal file
88
CMakeLists.txt
Normal file
@ -0,0 +1,88 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(thesis)
|
||||
|
||||
set(LATEX_COMPILER_FLAGS "-interaction=batchmode -file-line-error -shell-escape"
|
||||
CACHE STRING "Flags passed to latex.")
|
||||
include(UseLATEX.cmake)
|
||||
|
||||
# Global
|
||||
set(LATEX_USE_SYNCTEX ON)
|
||||
set(imgdir img)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pdf)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/buildfig)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/figures)
|
||||
|
||||
# Functions
|
||||
macro(subdirlist result curdir)
|
||||
file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${curdir}/*)
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child})
|
||||
subdirlist(${result} ${child})
|
||||
list(APPEND ${result} ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
set(imgdirs ${imgdir})
|
||||
subdirlist(imgdirs ${imgdir})
|
||||
|
||||
# Document
|
||||
set(modes oneside twoside print genfigures)
|
||||
set(srcdir src)
|
||||
set(stydir sty)
|
||||
|
||||
file(GLOB_RECURSE src RELATIVE ${CMAKE_SOURCE_DIR} ${srcdir}/*.tex)
|
||||
file(GLOB_RECURSE bib RELATIVE ${CMAKE_SOURCE_DIR} ${srcdir}/*.bib)
|
||||
file(GLOB_RECURSE sty RELATIVE ${CMAKE_SOURCE_DIR} ${stydir}/*.sty)
|
||||
|
||||
set(latex_document_options)
|
||||
set(custom_command_options ALL)
|
||||
|
||||
foreach(mode ${modes})
|
||||
set(maintex main_${mode})
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${srcdir}/${maintex}.tex
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${maintex}.tex
|
||||
)
|
||||
|
||||
add_latex_document(
|
||||
${srcdir}/main_${mode}.tex
|
||||
INPUTS ${src} ${lst} ${sty}
|
||||
BIBFILES ${bib}
|
||||
IMAGE_DIRS ${imgdirs}
|
||||
USE_BIBLATEX
|
||||
USE_GLOSSARY
|
||||
${latex_document_options}
|
||||
)
|
||||
|
||||
if(NOT ${mode} STREQUAL genfigures)
|
||||
set(synctex_file ${CMAKE_PROJECT_NAME}_${mode}.synctex.gz)
|
||||
add_custom_target(pdf_${synctex_file} ${custom_command_options}
|
||||
DEPENDS ${maintex}.pdf
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${maintex}.synctex.gz pdf/${synctex_file}
|
||||
)
|
||||
|
||||
set(pdf_file ${CMAKE_PROJECT_NAME}_${mode}.pdf)
|
||||
add_custom_target(pdf_${pdf_file} ${custom_command_options}
|
||||
DEPENDS ${maintex}.pdf
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${maintex}.pdf pdf/${pdf_file}
|
||||
)
|
||||
|
||||
add_custom_target(pdf_${CMAKE_PROJECT_NAME}_${mode} DEPENDS pdf_${synctex_file} pdf_${pdf_file})
|
||||
endif()
|
||||
|
||||
set(latex_document_options EXCLUDE_FROM_ALL)
|
||||
set(custom_command_options)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(generate_figures
|
||||
DEPENDS main_genfigures_pdf
|
||||
)
|
||||
|
||||
add_custom_command(TARGET generate_figures POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/buildfig/*.pdf
|
||||
${CMAKE_CURRENT_BINARY_DIR}/figures
|
||||
)
|
109
README.md
Normal file
109
README.md
Normal file
@ -0,0 +1,109 @@
|
||||
# About
|
||||
|
||||
Thesis title: using template metaprogramming to design active libraries for assisted parallelisation.
|
||||
|
||||
(French: *application de la métaprogrammation template à la conception de bibliothèques actives
|
||||
de parallélisation assitée*)
|
||||
|
||||
## Download
|
||||
|
||||
- [Computer version](https://phd.pereda.fr/assets/thesis/alexis_pereda_thesis.pdf);
|
||||
- [Print version](https://phd.pereda.fr/assets/thesis/alexis_pereda_thesis_print.pdf).
|
||||
|
||||
## Abstract
|
||||
|
||||
<div align="justify">
|
||||
Hardware performance has been increasing through the addition of computing cores rather than through
|
||||
increasing their frequency since the early 2000s.
|
||||
This means that parallel programming is no longer optional should you need to make the best use of
|
||||
the hardware at your disposal.
|
||||
Yet many programs are still written sequentially: parallel programming introduces numerous
|
||||
difficulties.
|
||||
Amongst these, it is notably hard to determine whether a sequence of a program can be executed in
|
||||
parallel, i.e. preserving its behaviour as well as its overall result.
|
||||
Even knowing that it is possible to parallelise a piece of code, doing it correctly is another
|
||||
problem.
|
||||
In this thesis, we present two approaches to make writing parallel software easier.
|
||||
|
||||
We present an active library (using C++ template metaprogramming to operate during the compilation
|
||||
process) whose purpose is to analyse and parallelise loops.
|
||||
To do so, it builds a representation of each processed loop using expression templates through an
|
||||
embedded language.
|
||||
This allows to know which variables are used and how they are used.
|
||||
For the case of arrays, which are common within loops, it also acquires the index functions.
|
||||
The analysis of this information enables the library to identify which instructions in the loop can
|
||||
be run in parallel.
|
||||
Interdependent instructions are detected by knowing the variables and their access mode for each
|
||||
instruction.
|
||||
Given a group of interdependent instructions and the known index functions, the library decides if
|
||||
the instructions can be run in parallel or not.
|
||||
We want this library to help developers writing loops that will be automatically parallelised
|
||||
whenever possible and run sequentially as without the library otherwise.
|
||||
Another focus is to provide this to serve as a framework to integrate new methods for parallelising
|
||||
programs and extended analysis rules.
|
||||
|
||||
We introduce another active library that aims to help developers by assisting them in writing
|
||||
parallel software instead of fully automating it.
|
||||
This library uses algorithmic skeletons to let the developer describe its algorithms with both its
|
||||
sequential and parallel parts by assembling atomic execution patterns such as a series of tasks or a
|
||||
parallel execution of a repeated task.
|
||||
This description includes the data flow, that is how parameters and function returns are
|
||||
transmitted.
|
||||
Usually, this is automatically set by the algorithmic skeleton library, however it gives the
|
||||
developer greater flexibility and it makes it possible, amongst other things, for our library to
|
||||
automatically transmit special parameters that must not be shared between parallel tasks.
|
||||
One feature that this allows is to ensure repeatability from one execution to another even for
|
||||
stochastic algorithms.
|
||||
Considering the distribution of tasks on the different cores, we even reduce the number of these
|
||||
non-shared parameters.
|
||||
Once again, this library provides a framework at several levels.
|
||||
Low-level extensions consist of the implementation of new execution patterns to be used to build
|
||||
skeletons.
|
||||
Another low-level axis is the integration of new execution policies that decide how tasks are
|
||||
distributed on the available computing cores.
|
||||
High-level additions will be libraries using ours to offer ready-to-use algorithmic skeletons for
|
||||
various fields.
|
||||
</div>
|
||||
|
||||
Keywords: template metaprogramming; assisted parallelisation; automatic parallelisation; active libraries; algorithmic skeletons; repeatability.
|
||||
|
||||
## Related publications
|
||||
|
||||
- "Repeatability with Random Numbers Using Algorithmic Skeletons", ESM 2020 (https://hal.archives-ouvertes.fr/hal-02980472);
|
||||
- "Modeling Algorithmic Skeletons for Automatic Parallelization Using Template Metaprogramming", HPCS 2019 (IEEE) [10.1109/HPCS48598.2019.9188128](https://doi.org/10.1109/HPCS48598.2019.9188128);
|
||||
- "Processing Algorithmic Skeletons at Compile-Time", ROADEF 2020 (https://hal.archives-ouvertes.fr/hal-02573660);
|
||||
- "Algorithmic Skeletons Using Template Metaprogramming", ICAST 2019;
|
||||
- "Parallel Algorithmic Skeletons for Metaheuristics", ROADEF 2019 (https://hal.archives-ouvertes.fr/hal-02059533);
|
||||
- "Static Loop Parallelization Decision Using Template Metaprogramming", HPCS 2018 (IEEE) [10.1109/HPCS.2018.00159](https://doi.org/10.1109/HPCS.2018.00159).
|
||||
|
||||
## Related projects
|
||||
|
||||
- [AlSk](https://phd.pereda.fr/dev/alsk), an algorithmic skeletons active library;
|
||||
- [pfor](https://phd.pereda.fr/dev/pfor), an automatic parallelisation active library;
|
||||
- [ROSA](https://phd.pereda.fr/dev/rosa), an algorithmic skeletons collection for [OR](https://en.wikipedia.org/wiki/Operations_research) algorithms;
|
||||
- [TMP](https://phd.pereda.fr/dev/tmp), template metaprogramming library used to implement this library.
|
||||
|
||||
## Usage
|
||||
|
||||
To produce the `Makefile`:
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
```
|
||||
|
||||
Compilation has been tested with `texlive-full` version 2020.20210202-3.
|
||||
|
||||
To build the project:
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
Be patient, it takes *some* time.
|
||||
|
||||
Make can be run with these arguments:
|
||||
- `pdf_thesis_oneside`: to build the "computer" version, including dynamic figures (default);
|
||||
- `pdf_thesis_twoside`: same as oneside but better for double-page display;
|
||||
- `pdf_thesis_print`: printing version (no dynamic figures, double-page and blank pages where required).
|
||||
|
||||
PDF files are generated in `build/pdf/`.
|
2074
UseLATEX.cmake
Normal file
2074
UseLATEX.cmake
Normal file
File diff suppressed because it is too large
Load Diff
BIN
img/alsk/exptt.pdf
Normal file
BIN
img/alsk/exptt.pdf
Normal file
Binary file not shown.
BIN
img/alsk/lineartt.pdf
Normal file
BIN
img/alsk/lineartt.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_dj38_24_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_dj38_24_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_dj38_24_20_20_seq.pdf
Normal file
BIN
img/alsk/rt_graspels_dj38_24_20_20_seq.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_12_20_20_speedup.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_12_20_20_speedup.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_16_20_20_speedup.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_16_20_20_speedup.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_20_20_20_speedup.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_20_20_20_speedup.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_24_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_24_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_24_20_20_seq.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_24_20_20_seq.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_20_20_speedup.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_20_20_speedup.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v12_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v12_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v16_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v16_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v1_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v1_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v2_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v2_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v30_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v30_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v40_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v40_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v4_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v4_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v50_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v50_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_4_v8_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_4_v8_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_8_20_20_speedup.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_8_20_20_speedup.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_1.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_1.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_10.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_10.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_12.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_12.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_14.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_14.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_16.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_16.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_18.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_18.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_2.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_2.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_4.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_4.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_6.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_6.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_8.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_all_20_20_speedup_8.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_v12_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_v12_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_v16_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_v16_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_v20_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_v20_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_v4_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_v4_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_v8_20_20_par.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_v8_20_20_par.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_var_els_iter_max_par_legend.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_var_els_iter_max_par_legend.pdf
Normal file
Binary file not shown.
BIN
img/alsk/rt_graspels_qa194_var_grasp_par_legend.pdf
Normal file
BIN
img/alsk/rt_graspels_qa194_var_grasp_par_legend.pdf
Normal file
Binary file not shown.
0
img/gnx/placeholder
Normal file
0
img/gnx/placeholder
Normal file
1
img/mp/placeholder
Normal file
1
img/mp/placeholder
Normal file
@ -0,0 +1 @@
|
||||
-- only to force git to track parent directory --
|
BIN
img/par/raymarching.png
Normal file
BIN
img/par/raymarching.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 160 KiB |
BIN
img/pfor/fixediv.pdf
Normal file
BIN
img/pfor/fixediv.pdf
Normal file
Binary file not shown.
BIN
img/pfor/fixedv.pdf
Normal file
BIN
img/pfor/fixedv.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_cores.pdf
Normal file
BIN
img/pfor/rt_cores.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_1.pdf
Normal file
BIN
img/pfor/rt_par_1.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_10.pdf
Normal file
BIN
img/pfor/rt_par_10.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_12.pdf
Normal file
BIN
img/pfor/rt_par_12.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_14.pdf
Normal file
BIN
img/pfor/rt_par_14.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_16.pdf
Normal file
BIN
img/pfor/rt_par_16.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_18.pdf
Normal file
BIN
img/pfor/rt_par_18.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_2.pdf
Normal file
BIN
img/pfor/rt_par_2.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_4.pdf
Normal file
BIN
img/pfor/rt_par_4.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_6.pdf
Normal file
BIN
img/pfor/rt_par_6.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_par_8.pdf
Normal file
BIN
img/pfor/rt_par_8.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_seq.pdf
Normal file
BIN
img/pfor/rt_seq.pdf
Normal file
Binary file not shown.
BIN
img/pfor/rt_speedup.pdf
Normal file
BIN
img/pfor/rt_speedup.pdf
Normal file
Binary file not shown.
92
merge
Executable file
92
merge
Executable file
@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
|
||||
[ ! -d .git ] && exit 1
|
||||
|
||||
opt=$1; shift
|
||||
|
||||
chapters="par gnx mp pfor alsk"
|
||||
subdirs="alg fig lst"
|
||||
acronyms=
|
||||
commands=
|
||||
|
||||
for subdir in $(echo ${subdirs}); do
|
||||
rm -rf "src/${subdir}/*"
|
||||
done
|
||||
|
||||
rm -f 'src/tikz/*'
|
||||
|
||||
# gather chapter sources
|
||||
chn=0
|
||||
|
||||
cp '../remerciements/src/thanks.tex' "src/${chn}_1_thanks.tex"
|
||||
|
||||
for chapter in $(echo ${chapters}); do
|
||||
rm -rf "src/${chapter}"
|
||||
cp -rf "../${chapter}/src/${chapter}" 'src'
|
||||
chn=$((chn+1))
|
||||
|
||||
if [ "${opt}" != 'contents' ]; then
|
||||
cp "../${chapter}/src/${chapter}.tex" "src/${chn}_${chapter}.tex"
|
||||
fi
|
||||
|
||||
rm -rf "img/${chapter}"
|
||||
cp -rf "../${chapter}/img/${chapter}" 'img'
|
||||
|
||||
cp "../${chapter}/src/tikz/"* 'src/tikz/'
|
||||
|
||||
for subdir in $(echo ${subdirs}); do
|
||||
dir="../${chapter}/src/${subdir}/${chapter}"
|
||||
if [ -d "${dir}" ]; then
|
||||
cp -rf "${dir}" "src/${subdir}/"
|
||||
fi
|
||||
done
|
||||
|
||||
acronymsfile="../${chapter}/src/acronyms.tex"
|
||||
if [ -f "${acronymsfile}" ]; then
|
||||
acronyms="${acronyms} ${acronymsfile}"
|
||||
fi
|
||||
|
||||
commandsfile="../${chapter}/src/commands.tex"
|
||||
if [ -f "${commandsfile}" ]; then
|
||||
commands="${commands} ${commandsfile}"
|
||||
fi
|
||||
done
|
||||
|
||||
# merge all acronyms files
|
||||
letter=A
|
||||
previous=
|
||||
while read line; do
|
||||
current=$(echo "${line}"|cut -d'{' -f2|cut -d'}' -f1)
|
||||
curletter=$(echo "${current}"|cut -c1)
|
||||
if [ "${curletter}" != "${letter}" ]; then
|
||||
echo
|
||||
letter="${curletter}"
|
||||
fi
|
||||
if [ "${current}" = "${previous}" ]; then
|
||||
echo>&2 "[acronyms] incoherent duplicate for {${current}}"
|
||||
fi
|
||||
previous="${current}"
|
||||
echo "${line}"
|
||||
done<<<$(sort -u ${acronyms}|grep -Ev '^$'|sed 's,\\,\\\\,g')>src/acronyms.tex
|
||||
|
||||
# merge all commands files
|
||||
declare -A arrcmds
|
||||
for cmds in ${commands}; do
|
||||
chapter=$(echo "${cmds}"|cut -d'/' -f2)
|
||||
echo "%{{{ ${chapter} \""
|
||||
while read line; do
|
||||
cmd=$(sed -re 's/[^{]*\{([^}]+)\}.*/\1/'<<<"${line}")
|
||||
if [ -n "${cmd}" ]; then
|
||||
if [ ${arrcmds[${cmd}]+x} ]; then
|
||||
if [ ${arrcmds[${cmd}]} != ${line} ]; then
|
||||
echo>&2 "[commands] incoherent duplicate for ${cmd}"
|
||||
fi
|
||||
echo -n "% "
|
||||
else
|
||||
arrcmds[${cmd}]="${line}"
|
||||
fi
|
||||
echo "${line}"
|
||||
fi
|
||||
done<<<$(sed 's,\\,\\\\,g' ${cmds})
|
||||
echo "%}}}"
|
||||
done>src/commands.tex
|
71
src/0_0_titlepage.tex
Normal file
71
src/0_0_titlepage.tex
Normal file
@ -0,0 +1,71 @@
|
||||
\date{01/07/2021}
|
||||
\def\university{Université Clermont Auvergne}
|
||||
\def\unived{École doctorale des sciences pour l'ingénieur}
|
||||
|
||||
\def\jury{%
|
||||
Alexandre \textsc{Guitton} & Professeur des universités & Université Clermont Auvergne & Président \\
|
||||
Joël \textsc{Falcou} & Maître de conférences HDR & Université Paris-Saclay & Rapporteur \\
|
||||
Françoise \textsc{Baude} & Professeur des universités & Université Côte d'Azur & Rapportrice \\
|
||||
Éric \textsc{Innocenti} & Maître de conférences & Université de Corse & Examinateur \\
|
||||
Bruno \textsc{Bachelet} & Maître de conférences HDR & Université Clermont Auvergne & Directeur de thèse\\
|
||||
David \textsc{Hill} & Professeur des universités & Université Clermont Auvergne & Directeur de thèse\\
|
||||
}
|
||||
\def\juryinvited{%
|
||||
Claude \textsc{Mazel} & Maître de conférences & Université Clermont Auvergne & Invité \\
|
||||
Jian-Jin \textsc{Li} & Maître de conférences & Université Clermont Auvergne & Invitée \\
|
||||
}
|
||||
|
||||
\makeatletter
|
||||
\begin{titlepage}
|
||||
\newgeometry{width=180mm}
|
||||
\setlength\parskip{1.5ex}
|
||||
\begin{center}
|
||||
% Academic
|
||||
\textsc{\large\university}
|
||||
|
||||
{\large\unived}
|
||||
|
||||
\vspace{5ex}
|
||||
|
||||
% Author
|
||||
{\large Thèse présentée par}
|
||||
|
||||
{\Large\@author}
|
||||
|
||||
\vspace{5ex}
|
||||
|
||||
% Ph.D
|
||||
en vue de l'obtention du grade de
|
||||
|
||||
{\LARGE Docteur d'université}
|
||||
|
||||
{\Large Spécialité : informatique}
|
||||
|
||||
\vspace{8ex}
|
||||
|
||||
% Title
|
||||
\rule[2ex]{\textwidth}{1pt}
|
||||
{\LARGE\@title}
|
||||
\rule[0ex]{\textwidth}{1pt}
|
||||
|
||||
\vspace{8ex}
|
||||
|
||||
% Defense
|
||||
{\large Soutenue publiquement le \@date{} devant le jury composé de :}
|
||||
% {\large devant le jury composé de :}
|
||||
|
||||
\vspace{5ex}
|
||||
|
||||
\vfill
|
||||
|
||||
% Jury
|
||||
\bgroup
|
||||
\def\arraystretch{1.3}
|
||||
\begin{tabular}{l >{\it}l l l}
|
||||
\jury
|
||||
\juryinvited
|
||||
\end{tabular}
|
||||
\egroup
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
\makeatother
|
46
src/0_1_thanks.tex
Normal file
46
src/0_1_thanks.tex
Normal file
@ -0,0 +1,46 @@
|
||||
\begin{thesisthanks}
|
||||
Je remercie avant tout mes directeurs de thèse, Bruno Bachelet et David Hill.
|
||||
Bruno pour avoir proposé ce sujet de thèse (spécialement pour la partie \og métaprogrammation \fg)
|
||||
et m'avoir choisi pour travailler dessus, mais surtout pour son aide, sa disponibilité, sa
|
||||
patience et sa confiance indéfectible durant ces quelques années.
|
||||
David pour avoir rendu cette thèse possible et pour son aide indispensable quant à certaines
|
||||
difficultés... scientifiques et administratives.
|
||||
Je remercie Claude Mazel, co-encadrant qui n'aura eu de cesse de me vitupérer pour d'importantes
|
||||
vétilles, aussi bien pour ses relectures que pour les nombreuses discussions que nous avons eues,
|
||||
évidemment toujours expressément au sujet de la thèse.
|
||||
|
||||
Je remercie également Joël Falcou, Françoise Baude, Éric Innocenti, Alexandre Guitton ainsi que
|
||||
Jian-Jin Li pour avoir fait partie de mon jury de thèse, et en particulier Joël et Françoise pour
|
||||
leur travail de rapporteurs.
|
||||
|
||||
\cutout r (-4.5em,3.3ex)\Shapepar{\hexagonshape}
|
||||
Ce document a été écrit en utilisant \LaTeX{} et en profitant de nombreux paquets sans lesquels ce
|
||||
travail de rédaction aurait été bien moins appréciable.
|
||||
Je tiens donc à remercier toute personne ayant participé au développement de ces outils, et plus
|
||||
généralement à l'expansion du logiciel libre.
|
||||
|
||||
\indent Je remercie aussi l'ensemble des personnes travaillant au LIMOS et à l'ISIMA. Loïc,
|
||||
notamment pour m'avoir épargné, de force quelques fois, certaines besognes en faveur de l'avancement
|
||||
de la thèse ; Yves-Jean qui a toujours pris le temps de discuter de mathématiques, y compris
|
||||
quelquefois utiles à mes travaux ; Fréd avec qui j'ai pu attendre Kaamelott ; l'équipe technique et
|
||||
le personnel administratif qui m'ont facilité bien des démarches.
|
||||
\hfill\break\indent
|
||||
Merci aux quelques docteurs -- ou presque -- que j'ai cotoyé durant cette thèse pour l'avoir en
|
||||
partie animée.
|
||||
David et Kévin pour les multiples discussions autour de problèmes variés et les
|
||||
\textit{occasionnelles} parties de billard ; Théo, futur artiste qui m'a évité bien des soliloques ;
|
||||
et bien sûr Cyrille avec qui j'ai pu explorer différents domaines de l'informatique, des autres
|
||||
sciences et de tant d'autres thèmes.
|
||||
|
||||
\begin{CJK}{UTF8}{min}
|
||||
ICAST2019を開催した熊本大学とそれにかかわった人たちに感謝します。
|
||||
特に岸田先生には滞在中お世話になり、初めての日本訪問を楽しむことができました。
|
||||
\end{CJK}
|
||||
|
||||
Merci au théorème fondamental de l'ingénierie logicielle, à savoir que tout problème peut être résolu
|
||||
en ajoutant un niveau d'indirection, d'être vrai, au moins dans le cadre des développements
|
||||
effectués durant cette thèse.
|
||||
|
||||
J'étends enfin ces remerciements à mes proches, nommément Gwénaëlle qui a dû accepter un emploi du
|
||||
temps chaotique, et m'a malgré cela soutenu inlassablement.
|
||||
\end{thesisthanks}
|
133
src/0_2_abstract.tex
Normal file
133
src/0_2_abstract.tex
Normal file
@ -0,0 +1,133 @@
|
||||
%{{{ résumé "
|
||||
\begin{abstract}
|
||||
%{{{
|
||||
L'écriture de programmes parallèles, par opposition aux programmes \og classiques \fg{} séquentiels
|
||||
et n'utilisant donc qu'un processeur, est devenue une nécessité.
|
||||
En effet, si jusqu'au début du millénaire la puissance de calcul des ordinateurs dépendait
|
||||
principalement de la fréquence du processeur, elle est maintenant liée au nombre de cœurs de calcul
|
||||
qui sont de plus en plus nombreux.
|
||||
Pourtant, à cause des difficultés introduites par la parallélisation, la plupart des programmes sont
|
||||
toujours écrits de manière \og classique \fg.
|
||||
En particulier, il peut être compliqué de déterminer, étant donné une sous partie d'un programme, si
|
||||
la parallélisation est possible, c'est-à-dire si elle n'introduira pas un changement de comportement
|
||||
du programme.
|
||||
Cependant, même en sachant précisément ce qui peut être parallélisé, le faire correctement est aussi
|
||||
une tâche difficile.
|
||||
Cette thèse présente deux approches pour simplifier l'écriture de programmes parallèles.
|
||||
|
||||
Nous proposons une bibliothèque active -- par métaprogrammation template, elle agit durant la
|
||||
compilation -- qui acquiert des informations à propos d'une portion de programme, correspondant à
|
||||
une boucle, au moyen de patrons d'expression.
|
||||
Celles-ci sont utilisées pour analyser les instructions et identifier lesquelles peuvent être
|
||||
exécutées en parallèle.
|
||||
Cette analyse repose sur deux niveaux de connaissance : l'ensemble des variables utilisées en
|
||||
distinguant les accès en lecture de ceux en écriture, et, puisqu'il s'agit souvent de tableaux, des
|
||||
fonctions d'indice.
|
||||
Les variables et leur mode d'accès permettent de savoir quelles instructions sont interdépendantes
|
||||
tandis que les fonctions d'indice nous servent à déterminer, pour un groupe d'instructions, s'il
|
||||
est possible de procéder à une exécution parallèle des itérations de la boucle.
|
||||
L'objectif de cette bibliothèque est de proposer un cadre, à la fois pour les développeurs afin
|
||||
d'écrire des boucles qui seront automatiquement exécutées en parallèle si cela est possible, mais
|
||||
aussi à un niveau plus élevé pour intégrer de nouvelles méthodes de parallélisation ou d'autres
|
||||
règles à utiliser pour l'analyse.
|
||||
|
||||
Nous proposons également une seconde bibliothèque, active elle aussi, orientée sur la
|
||||
parallélisation assistée en utilisant la technique des squelettes algorithmiques comme interface
|
||||
pour le développeur.
|
||||
Celle-ci permet de représenter des algorithmes complets comme des assemblages de motifs d'exécution
|
||||
: séquence de tâches ; exécution répétée d'une tâche en parallèle ; ...
|
||||
En utilisant cette connaissance, nous pouvons mettre en place des choix dans la manière de répartir
|
||||
les tâches exécutées en parallèle sur les différents processeurs.
|
||||
Par ailleurs, nous avons choisi d'expliciter l'expression de la transmission des données entre les
|
||||
tâches, contrairement à ce qui est habituellement fait.
|
||||
Grâce à cela, la bibliothèque automatise notamment la transmission de paramètres qui ne doivent pas
|
||||
être partagés par des tâches parallèles.
|
||||
Cela nous permet en particulier de garantir la répétabilité des exécutions y compris lorsque, par
|
||||
exemple, les tâches utilisent des nombres pseudo-aléatoires.
|
||||
En tenant compte de la politique d'exécution choisie et des nombres de processeurs possibles, nous
|
||||
réduisons la quantité nécessaire de ces paramètres ne devant pas être partagés.
|
||||
Ainsi, cette seconde bibliothèque propose elle aussi un cadre de programmation à plusieurs niveaux.
|
||||
Celle-ci est extensible au niveau de ses politiques d'exécution ou des motifs pour la construction
|
||||
des squelettes algorithmiques.
|
||||
On peut l'utiliser pour définir une variété de squelettes algorithmiques, lesquels serviront ensuite
|
||||
à un développeur pour écrire des programmes dont la parallélisation sera facilitée.
|
||||
%}}}
|
||||
|
||||
\vfill
|
||||
\noindent\textbf{Mots-clés} :
|
||||
métaprogrammation template ;
|
||||
parallélisation assistée ;
|
||||
parallélisation automatique ;
|
||||
bibliothèques actives ;
|
||||
squelettes algorithmiques ;
|
||||
répétabilité.
|
||||
\end{abstract}
|
||||
%}}}
|
||||
|
||||
%{{{ abstract "
|
||||
\begin{otherlanguage}{english}
|
||||
\begin{abstract}
|
||||
%{{{
|
||||
Hardware performance has been increasing through the addition of computing cores rather than through
|
||||
increasing their frequency since the early 2000s.
|
||||
This means that parallel programming is no longer optional should you need to make the best use of
|
||||
the hardware at your disposal.
|
||||
Yet many programs are still written sequentially: parallel programming introduces numerous
|
||||
difficulties.
|
||||
Amongst these, it is notably hard to determine whether a sequence of a program can be executed in
|
||||
parallel, i.e. preserving its behaviour as well as its overall result.
|
||||
Even knowing that it is possible to parallelise a piece of code, doing it correctly is another
|
||||
problem.
|
||||
In this thesis, we present two approaches to make writing parallel software easier.
|
||||
|
||||
We present an active library (using C++ template metaprogramming to operate during the compilation
|
||||
process) whose purpose is to analyse and parallelise loops.
|
||||
To do so, it builds a representation of each processed loop using expression templates through an
|
||||
embedded language.
|
||||
This allows to know which variables are used and how they are used.
|
||||
For the case of arrays, which are common within loops, it also acquires the index functions.
|
||||
The analysis of this information enables the library to identify which instructions in the loop can
|
||||
be run in parallel.
|
||||
Interdependent instructions are detected by knowing the variables and their access mode for each
|
||||
instruction.
|
||||
Given a group of interdependent instructions and the known index functions, the library decides if
|
||||
the instructions can be run in parallel or not.
|
||||
We want this library to help developers writing loops that will be automatically parallelised
|
||||
whenever possible and run sequentially as without the library otherwise.
|
||||
Another focus is to provide this to serve as a framework to integrate new methods for parallelising
|
||||
programs and extended analysis rules.
|
||||
|
||||
We introduce another active library that aims to help developers by assisting them in writing
|
||||
parallel software instead of fully automating it.
|
||||
This library uses algorithmic skeletons to let the developer describe its algorithms with both its
|
||||
sequential and parallel parts by assembling atomic execution patterns such as a series of tasks or a
|
||||
parallel execution of a repeated task.
|
||||
This description includes the data flow, that is how parameters and function returns are
|
||||
transmitted.
|
||||
Usually, this is automatically set by the algorithmic skeleton library, however it gives the
|
||||
developer greater flexibility and it makes it possible, amongst other things, for our library to
|
||||
automatically transmit special parameters that must not be shared between parallel tasks.
|
||||
One feature that this allows is to ensure repeatability from one execution to another even for
|
||||
stochastic algorithms.
|
||||
Considering the distribution of tasks on the different cores, we even reduce the number of these
|
||||
non-shared parameters.
|
||||
Once again, this library provides a framework at several levels.
|
||||
Low-level extensions consist of the implementation of new execution patterns to be used to build
|
||||
skeletons.
|
||||
Another low-level axis is the integration of new execution policies that decide how tasks are
|
||||
distributed on the available computing cores.
|
||||
High-level additions will be libraries using ours to offer ready-to-use algorithmic skeletons for
|
||||
various fields.
|
||||
%}}}
|
||||
|
||||
\vfill
|
||||
\noindent\textbf{Keywords}:
|
||||
template metaprogramming;
|
||||
assisted parallelisation;
|
||||
automatic parallelisation;
|
||||
active libraries;
|
||||
algorithmic skeletons;
|
||||
repeatability.
|
||||
\end{abstract}
|
||||
\end{otherlanguage}
|
||||
%}}}
|
98
src/0_3_preamble.tex
Normal file
98
src/0_3_preamble.tex
Normal file
@ -0,0 +1,98 @@
|
||||
\chapterx*{Avant-propos}
|
||||
|
||||
Ce document présente les travaux effectués durant ma thèse.
|
||||
Les projets correspondants sont accessibles à l'adresse \url{https://phd.pereda.fr/dev}.
|
||||
Parmi ces projets se trouvent les deux bibliothèques principales :
|
||||
\begin{itemize}
|
||||
\item \url{https://phd.pereda.fr/dev/pfor} qui est présentée dans \acref{ch:pfor} ;
|
||||
\item \url{https://phd.pereda.fr/dev/alsk} qui est présentée dans \acref{ch:alsk}.
|
||||
\end{itemize}
|
||||
|
||||
De nombreux extraits de code source sont étudiés.
|
||||
Ceux-ci sont la plupart du temps simplifiés pour se concentrer sur les points intéressants.
|
||||
En général, le langage de programmation est indiqué et, en particulier pour le C et le C++, le
|
||||
standard à partir duquel le code est valide.
|
||||
Ces indications sont
|
||||
\tikz[remember picture,anchor=base,inner sep=0pt]{\node(tikz preamble anchor 0){en dessous à droite};}
|
||||
des extraits de code.
|
||||
|
||||
\begin{cppcode}
|
||||
// source code
|
||||
\end{cppcode}
|
||||
\mincpp{\tikz[overlay,remember picture]{
|
||||
\node(tikz preamble anchor 1)[draw=green!30!black!70,very thick,dashed,rectangle,
|
||||
rounded corners=1mm,minimum width=5.5em,minimum height=4ex, shift={(-1.2em,+.6ex)}]{};
|
||||
\draw[draw=green!30!black!70,ultra thick,->,>=stealth,opacity=.5]
|
||||
([shift={(3ex,-.5mm)}]tikz preamble anchor 0.south) to[bend right] ([xshift=-.5mm]tikz preamble anchor 1.west);
|
||||
}14}
|
||||
|
||||
Certaines figures sont dynamiques\footnote{Sauf si le document a été compilé spécifiquement pour
|
||||
impression.}.
|
||||
Dans ce cas se trouvera sous la figure concernée le symbole $\triangleright$ suivi d'indications
|
||||
spécifiques.
|
||||
|
||||
\begin{ocg}{Exemples d'OCG}{ocgexamples}{1}
|
||||
\begin{multicols}{2}
|
||||
\begin{ocg}{Exemple TikZ}{ocgexample0}{1}
|
||||
\begin{figure}[H]
|
||||
\def\prefix{tikz-preamble-ocg-example0}
|
||||
\centering
|
||||
\ocgcase{\prefix}{\prefix-off}{on}{%
|
||||
\begin{tikzpicture}%
|
||||
\node[common/drawfill=black,circle,minimum size=12mm,show ocg={\prefix-on}]{Test};
|
||||
\end{tikzpicture}%
|
||||
}%
|
||||
\ocgcase{\prefix}{\prefix-on}{off}{%
|
||||
\begin{tikzpicture}%
|
||||
\node[common/drawfill=green!35!black,circle,minimum size=12mm]{\checkmark};
|
||||
\end{tikzpicture}%
|
||||
}%
|
||||
\\
|
||||
{%
|
||||
\small $\triangleright$ cliquer sur le disque \og Test \fg pour tester%
|
||||
}%
|
||||
\end{figure}
|
||||
\end{ocg}
|
||||
\columnbreak
|
||||
\begin{ocg}{Exemple avec liens}{ocgexample1}{1}
|
||||
\begin{figure}[H]
|
||||
\def\prefix{tikz-preamble-ocg-example1}
|
||||
\centering
|
||||
\ocmdcase{\prefix-0}{%
|
||||
\begin{tikzpicture}%
|
||||
\node[common/drawfill=black,rectangle,rounded corners,minimum width=12mm,minimum height=12mm]{\num{0}};
|
||||
\end{tikzpicture}%
|
||||
}%
|
||||
\foreach \i in {1,...,5} {%
|
||||
\pgfmathtruncatemacro{\ii}{\i*\i}%
|
||||
\ocmdcase{\prefix-\i}{%
|
||||
\begin{tikzpicture}%
|
||||
\node[common/drawfill=black,rectangle,rounded corners,minimum width=12mm,minimum height=12mm]{\num{\ii}};
|
||||
\end{tikzpicture}%
|
||||
}%
|
||||
}%
|
||||
\\
|
||||
{%
|
||||
\small $\triangleright$ afficher le carré de :%
|
||||
\ocgradio{\prefix}{\prefix-0}{0}{on}%
|
||||
\foreach \i in {1,...,5} {%
|
||||
\ocgradio{\prefix}{\prefix-\i}{\i}{off}%
|
||||
}%
|
||||
}%
|
||||
\end{figure}
|
||||
\end{ocg}
|
||||
\end{multicols}
|
||||
\end{ocg}
|
||||
|
||||
Si le symbole $\triangleright$ apparaît mais que rien ne se passe lors du clic, le lecteur utilisé
|
||||
n'est pas compatible.
|
||||
Les lecteurs testés sont les suivants :
|
||||
\begin{itemize}
|
||||
\item Evince ;
|
||||
\item Okular ;
|
||||
\item Adobe Acrobat Reader DC.
|
||||
\end{itemize}
|
||||
|
||||
Quoi qu'il arrive, la figure affichée par défaut est celle dont il est question au sein du texte.
|
||||
Les éléments dynamiques peuvent apporter une aide à la compréhension ou des éléments supplémentaires
|
||||
mais ne sont en aucun cas indispensables à la lecture.
|
33
src/0_3_preamble_print.tex
Normal file
33
src/0_3_preamble_print.tex
Normal file
@ -0,0 +1,33 @@
|
||||
\chapterx*{Avant-propos}
|
||||
|
||||
Ce document présente les travaux effectués durant ma thèse.
|
||||
Les projets correspondants sont accessibles à l'adresse \url{https://phd.pereda.fr/dev}.
|
||||
Parmi ces projets se trouvent les deux bibliothèques principales :
|
||||
\begin{itemize}
|
||||
\item \url{https://phd.pereda.fr/dev/pfor} qui est présentée dans \acref{ch:pfor} ;
|
||||
\item \url{https://phd.pereda.fr/dev/alsk} qui est présentée dans \acref{ch:alsk}.
|
||||
\end{itemize}
|
||||
|
||||
De nombreux extraits de code source sont étudiés.
|
||||
Ceux-ci sont la plupart du temps simplifiés pour se concentrer sur les points intéressants.
|
||||
En général, le langage de programmation est indiqué et, en particulier pour le C et le C++, le
|
||||
standard à partir duquel le code est valide.
|
||||
Ces indications sont
|
||||
\tikz[remember picture,anchor=base,inner sep=0pt]{\node(tikz preamble anchor 0){en dessous à droite};}
|
||||
des extraits de code.
|
||||
|
||||
\begin{cppcode}
|
||||
// source code
|
||||
\end{cppcode}
|
||||
\mincpp{\tikz[overlay,remember picture]{
|
||||
\node(tikz preamble anchor 1)[draw=green!30!black!70,very thick,dashed,rectangle,
|
||||
rounded corners=1mm,minimum width=5.5em,minimum height=4ex, shift={(-1.2em,+.6ex)}]{};
|
||||
\draw[draw=green!30!black!70,ultra thick,->,>=stealth,opacity=.5]
|
||||
([shift={(3ex,-.5mm)}]tikz preamble anchor 0.south) to[bend right] ([xshift=-.5mm]tikz preamble anchor 1.west);
|
||||
}14}
|
||||
|
||||
Ce document a été compilé spécifiquement pour impression.
|
||||
La version numérique comporte des figures dynamiques.
|
||||
Celles-ci ont toujours un rendu par défaut qui est le seul dont il est question au sein du texte.
|
||||
Les éléments dynamiques peuvent apporter une aide à la compréhension ou des éléments supplémentaires
|
||||
mais ne sont en aucun cas indispensables à la lecture.
|
170
src/0_intro.tex
Normal file
170
src/0_intro.tex
Normal file
@ -0,0 +1,170 @@
|
||||
\chapterx*{Introduction}
|
||||
|
||||
%{{{ introduction "
|
||||
L'informatique est employée dans de nombreux domaines, que ce soit comme sujet d'étude ou comme
|
||||
outil d'application, notamment en sciences, y compris dans le cadre de démonstrations mathématiques.
|
||||
L'évolution de celle-ci repose de manière croissante sur la puissance de calcul qu'apportent les
|
||||
ordinateurs.
|
||||
Or, jusqu'au début des années \num{2000}, la puissance d'un ordinateur dépendait sensiblement de la
|
||||
fréquence du processeur qui effectue les calculs, laquelle a été confrontée à une limite physique au
|
||||
delà de laquelle les fuites de courants étaient trop importantes, allant même jusqu'à faire fondre
|
||||
les processeurs~\autocite{ref:namsungkim2003}.
|
||||
|
||||
Depuis, pour outrepasser cette limite, les processeurs se voient pourvus de cœurs de calcul de plus
|
||||
en plus nombreux.
|
||||
En dehors de notions élémentaires, l'utilisation de l'informatique comme outil pour résoudre des
|
||||
problèmes nécessite surtout des connaissances dans le domaine du problème.
|
||||
Mais l'utilisation concurrente de plusieurs cœurs de calcul introduit des difficultés propres à
|
||||
l'informatique et donc une expertise que n'ont pas la plupart de ses utilisateurs, et qu'ils ne
|
||||
devraient pas être contraints à maîtriser.
|
||||
Ces difficultés couvrent des sujets variés, incluant la connaissance du fonctionnement du matériel,
|
||||
de son interaction avec les couches logicielles les plus basses jusqu'à des principes propres à la
|
||||
programmation concurrente : gestion de la communication entre les éléments concurrents ;
|
||||
synchronisation du travail effectué ; implémentation de patrons de conception dédiés ; maintien de
|
||||
la répétabilité malgré l'utilisation de nombres pseudo-aléatoires ; ...
|
||||
Du fait de ces difficultés, une majorité de programmes sont développés sans bénéficier réellement du
|
||||
potentiel du matériel à disposition.
|
||||
%}}}
|
||||
|
||||
%{{{ solutions existantes "
|
||||
Des solutions ont naturellement été étudiées, permettant d'abord l'utilisation des mêmes primitives
|
||||
indépendamment de l'architecture exacte sur laquelle est déployé le programme, là où initialement
|
||||
chaque système fournissait sa propre interface.
|
||||
Des instructions spécifiques, mettant en place tout ce qui est nécessaire à la parallélisation, ont
|
||||
été introduites, notamment au sein de certains compilateurs.
|
||||
Cette technique va jusqu'à la création de langages dédiés exposant des syntaxes adaptées.
|
||||
Tout cela a participé à assister les développeurs dans l'écriture de programmes s'exécutant en
|
||||
parallèle sur plusieurs processeurs.
|
||||
|
||||
Il s'est également agit de proposer l'automatisation de la génération de programmes parallèles à
|
||||
partir de leur écriture séquentielle classique.
|
||||
Différentes techniques existent, dont, à nouveau, l'exploitation des compilateurs pour analyser le
|
||||
code source et produire, sans que soit nécessaire une intervention de la part du développeur, un
|
||||
programme dont l'exécution est
|
||||
parallèle~\autocite{ref:zima1988,ref:blume1995,ref:ahmad1997,ref:fonseca2016}.
|
||||
Similairement, des langages de programmation se sont mis à intégrer des constructions orientées vers
|
||||
la parallélisation et plus ou moins transparentes pour le
|
||||
développeur~\autocite{ref:roscoe1988,ref:loveman1993,ref:chamberlain2007,ref:rieger2019}.
|
||||
|
||||
Autant pour l'implémentation d'outils simplifiant la mise en œuvre de la parallélisation que pour
|
||||
son automatisation, de nombreuses bibliothèques logicielles sont disponibles et permettent
|
||||
d'apporter à l'existant -- langages et compilateurs -- de nouvelles
|
||||
possibilités~\autocite{ref:kuchen2002a,ref:chan2004,ref:falcou2008,ref:videau2018,ref:ernstsson2018}.
|
||||
Il est même possible, dans certains cas, qu'une bibliothèque logicielle (indépendante du
|
||||
compilateur) agisse pratiquement aussi profondément que le peut une extension de compilateur (à
|
||||
l'inverse, spécifique à celui-ci).
|
||||
Ces bibliothèques, dites actives~\autocite{ref:veldhuizen1998a}, ouvrent la voie à de nouvelles
|
||||
façons de proposer des outils aux développeurs.
|
||||
%}}}
|
||||
|
||||
%{{{ besoin "
|
||||
Les solutions aux problèmes de la parallélisation basées sur des bibliothèques logicielles actives
|
||||
sont relativement peu nombreuses par rapport aux autres approches.
|
||||
Elles sont plus contraignantes à produire qu'une extension de compilateur.
|
||||
Il est notamment difficile d'en écrire une qui ne cause effectivement pas un surcoût rédhibitoire en
|
||||
temps d'exécution, en mémoire utilisée ou encore en temps de compilation, comparé à une
|
||||
implémentation manuelle ou à ce qui se fait au niveau des compilateurs.
|
||||
Selon le cadre dans lequel la bibliothèque active est conçue, il peut également être
|
||||
particulièrement difficile de déboguer.
|
||||
|
||||
Le C++ et ses templates, supportant une forme de métaprogrammation à la base de ce qui permet
|
||||
l'élaboration de bibliothèques actives au sein de ce langage, est connu pour cela.
|
||||
En partie parce que ces templates n'ont pas été pensé initialement pour cela (ils servent avant tout
|
||||
à la dimension générique du langage), il est difficile de suivre ce qu'ils causent durant la
|
||||
compilation.
|
||||
Malgré cette limite, qui tend par ailleurs à s'amoindrir avec les évolutions du langage, cette forme
|
||||
de métaprogrammation est très employée car elle permet, lorsqu'elle est bien utilisée, d'atteindre
|
||||
des résultats très proches de ce que l'on obtiendrait en écrivant soi-même le code produit.
|
||||
%}}}
|
||||
|
||||
%{{{ proposition "
|
||||
Avec cette thèse, nous voulons proposer principalement deux nouveaux outils.
|
||||
Le premier est un outil de parallélisation automatique, avec une bibliothèque active détectant
|
||||
elle-même ce qui peut validement être exécuté en parallèle et qui génère le code correspondant.
|
||||
La détection doit reposer sur des mécanismes extensibles afin de permettre l'ajout de nouvelles
|
||||
règles, déterminant, à partir des accès aux variables, ce qu'il est possible de faire de chaque
|
||||
instruction.
|
||||
Similairement, la génération de code doit avoir la capacité de fonctionner indépendamment de la
|
||||
méthode de parallélisation sous-jacente.
|
||||
Pour cela, il faut donc voir la manière de paralléliser comme une simple configuration qui peut être
|
||||
indiquée à la bibliothèque plutôt que comme un élément qui lui est central.
|
||||
À l'inverse, le fonctionnement de la bibliothèque ne doit pas affecter négativement et
|
||||
significativement la performance du programme par rapport à ce qui peut être accompli similairement
|
||||
\og à la main \fg.
|
||||
Cela doit en particulier être vrai lorsque son utilisation aboutit à un programme non parallélisé.
|
||||
|
||||
Le second outil relève, quant à lui, de la parallélisation assistée, laquelle laisse au moins à la
|
||||
charge du développeur le soin de décider quelles sections du programme doivent être parallélisées
|
||||
avec une deuxième bibliothèque, également active.
|
||||
Pour ceci, nous proposons une nouvelle vision des squelettes algorithmiques avec davantage de
|
||||
contrôle de la part du développeur.
|
||||
Un but est de permettre une utilisation très flexible des squelettes algorithmiques, par exemple sur
|
||||
l'aspect de la transmission des paramètres entre les différentes parties d'un squelette.
|
||||
Un autre but est l'analyse des squelettes algorithmiques durant la compilation pour en déduire, par
|
||||
exemple, des optimisations possibles de celui-ci ou des schémas efficaces d'exécution parallèle.
|
||||
La parallélisation, particulièrement lorsqu'elle est combinée à l'utilisation de nombres
|
||||
pseudo-aléatoires, rend plus difficile la préservation de la répétabilité d'un programme,
|
||||
c'est-à-dire la capacité à exécuter plusieurs fois ce programme dans les mêmes conditions en
|
||||
obtenant systématiquement le même résultat.
|
||||
Sans répétabilité, la capacité de débogage est illusoire, et pour cette raison, nous voulons
|
||||
proposer un moyen de garantir cette répétabilité grâce aux squelettes algorithmiques.
|
||||
%}}}
|
||||
|
||||
%{{{ structure "
|
||||
Ce document présente les travaux effectués au titre de cette thèse.
|
||||
Pour ce faire, il est scindé en \num{5} chapitres.
|
||||
\Acref{ch:par} traite de la parallélisation en partant des notions élémentaires matérielles et
|
||||
logicielles et en allant jusqu'aux concepts spécifiques de plus haut niveau qui permettent de
|
||||
résoudre des problèmes introduits par cette discipline.
|
||||
Ce chapitre détaille ensuite différentes couches supérieures qui simplifient l'application de la
|
||||
parallélisation, principalement sur les deux aspects que sont la parallélisation automatique et la
|
||||
parallélisation assistée.
|
||||
|
||||
\Acref{ch:gnx} introduit un paradigme de programmation nommé \og généricité \fg, en particulier en
|
||||
C++.
|
||||
En effet, la généricité de ce langage fonctionnant durant la compilation grâce, entre autres, aux
|
||||
templates, est à la base de la métaprogrammation template.
|
||||
Y sont donc traitées la création et l'utilisation de templates, ainsi que leur spécialisation et les
|
||||
contraintes de sélection associées à celles-ci.
|
||||
Ce chapitre aborde aussi des problématiques spécifiques à cette généricité et les solutions qui y
|
||||
répondent.
|
||||
|
||||
\Acref{ch:mp} détaille ensuite la métaprogrammation, notamment celle du C++ avec la notion de
|
||||
template, les travaux effectués pour cette thèse reposant tous sur cette possibilité du langage C++.
|
||||
En utilisant les notions de généricité du chapitre précédent, il présente l'implémentation de
|
||||
différents algorithmes dont le déroulement s'effectue durant la compilation du programme.
|
||||
Il progresse sur ce sujet jusqu'aux patrons d'expression, une technique en métaprogrammation
|
||||
template permettant la représentation et l'utilisation, durant la compilation, de portions de code
|
||||
source.
|
||||
|
||||
\Acref{ch:pfor} présente une bibliothèque active en C++ et utilisant la métaprogrammation template
|
||||
pour la parallélisation automatique de boucles.
|
||||
Cette proposition est expliquée en commençant par le détail des tests effectués par la bibliothèque
|
||||
pour déterminer l'indépendance d'instructions et leur capacité à être exécutées en parallèle sans
|
||||
créer de conflit d'accès aux données.
|
||||
Ensuite, le chapitre traite de la détection des données nécessaires à l'application de ces tests,
|
||||
qui repose sur des patrons d'expression, et qui permet d'acquérir une vision fine des instructions.
|
||||
La génération du code éventuellement parallèle, incluant donc l'exécution des tests durant la
|
||||
compilation, est subséquemment exposée.
|
||||
Pour finir, l'efficacité de l'utilisation de cette bibliothèque est évaluée au moyen de mesures de
|
||||
temps de compilation et d'exécution.
|
||||
Cela est effectué pour différents cas et pour des codes utilisant la bibliothèque par rapport à des
|
||||
codes équivalents ne l'utilisant pas.
|
||||
|
||||
Le \hyperref[ch:alsk]{cinquième et dernier chapitre} présente une seconde bibliothèque active,
|
||||
utilisant également la métaprogrammation template du C++, cette fois-ci orientée vers la
|
||||
parallélisation assistée au moyen de squelettes algorithmiques.
|
||||
Ce chapitre introduit un problème de \gls{RO} et des métaheuristiques utilisées pour le résoudre.
|
||||
Ces métaheuristiques sont ensuite utilisées pour illustrer les concepts généraux de squelettes
|
||||
algorithmiques ainsi que ceux propres à notre proposition.
|
||||
Le chapitre se poursuit avec l'étude de la répartition des tâches à exécuter en parallèle en
|
||||
fonction du squelette algorithmique et de sa structure.
|
||||
Le problème de la répétabilité des exécutions parallèles en tenant compte, notamment, de
|
||||
l'utilisation de nombres pseudo-aléatoires est ensuite traité.
|
||||
Après les premières sections qui présentent chacune un aspect de la conception des squelettes
|
||||
algorithmiques en utilisant cette bibliothèque, ce chapitre montre comment ceux-ci peuvent être
|
||||
utilisés en pratique, notamment par le biais d'une syntaxe alternative définissant un langage
|
||||
embarqué au sein du C++.
|
||||
Cette bibliothèque est testée pour résoudre des instances de \gls{TSP} et est comparée en temps
|
||||
d'exécution avec des implémentations équivalentes ne l'utilisant pas.
|
||||
%}}}
|
8
src/1_par.tex
Normal file
8
src/1_par.tex
Normal file
@ -0,0 +1,8 @@
|
||||
\chapterx{par}{Parallélisation automatique et assistée}
|
||||
|
||||
\inputsrc{0_intro}
|
||||
\inputsrc{1_general}
|
||||
\inputsrc{2_comp}
|
||||
\inputsrc{3_auto}
|
||||
\inputsrc{4_assist}
|
||||
\inputsrc{5_conclusion}
|
17
src/2_gnx.tex
Normal file
17
src/2_gnx.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\chapterx{gnx}{Généricité en C++}
|
||||
|
||||
\inputsrc{0_intro}
|
||||
\inputsrc{1_cpp}
|
||||
\inputsrc{2_ccpp}
|
||||
\inputsrc{3_syntax}
|
||||
\inputsrc{4_tad}
|
||||
\inputsrc{5_spe}
|
||||
\inputsrc{6_sfinae}
|
||||
\inputsrc{7_concepts}
|
||||
\inputsrc{8_inst}
|
||||
\inputsrc{9_overload}
|
||||
\inputsrc{a_auto}
|
||||
\inputsrc{b_forward}
|
||||
\inputsrc{c_pack}
|
||||
\inputsrc{d_ifcx}
|
||||
\inputsrc{e_conclusion}
|
6
src/3_mp.tex
Normal file
6
src/3_mp.tex
Normal file
@ -0,0 +1,6 @@
|
||||
\chapterx{mp}{Métaprogrammation template}
|
||||
|
||||
\inputsrc{0_intro}
|
||||
\inputsrc{1_types}
|
||||
\inputsrc{2_mpt}
|
||||
\inputsrc{3_conclusion}
|
9
src/4_pfor.tex
Normal file
9
src/4_pfor.tex
Normal file
@ -0,0 +1,9 @@
|
||||
\chapterx{pfor}{Analyse et parallélisation automatique de boucles}
|
||||
|
||||
\inputsrc{0_intro}
|
||||
\inputsrc{1_relwork}
|
||||
\inputsrc{2_conditions}
|
||||
\inputsrc{3_detection}
|
||||
\inputsrc{4_generation}
|
||||
\inputsrc{5_results}
|
||||
\inputsrc{6_conclusion}
|
11
src/5_alsk.tex
Normal file
11
src/5_alsk.tex
Normal file
@ -0,0 +1,11 @@
|
||||
\chapterx{alsk}{Parallélisation et répétabilité par les squelettes algorithmiques}
|
||||
|
||||
\inputsrc{0_intro}
|
||||
\inputsrc{1_relwork}
|
||||
\inputsrc{2_app}
|
||||
\inputsrc{3_concept}
|
||||
\inputsrc{4_exec}
|
||||
\inputsrc{5_repeat}
|
||||
\inputsrc{6_usage}
|
||||
\inputsrc{7_results}
|
||||
\inputsrc{8_conclusion}
|
219
src/6_conclusion.tex
Normal file
219
src/6_conclusion.tex
Normal file
@ -0,0 +1,219 @@
|
||||
\chapterx*{Conclusion}
|
||||
|
||||
%{{{ introduction "
|
||||
La programmation parallèle induit de nombreuses difficultés par rapport à la programmation
|
||||
séquentielle classique.
|
||||
En premier lieu, il faut identifier les portions de code source qui peuvent être exécutées en
|
||||
parallèle sans invalider leur comportement, c'est-à-dire en conservant le même déroulement lors de
|
||||
leur exécution jusqu'à l'obtention du même résultat.
|
||||
Lorsque ces portions de code sont identifiées, la mise en place d'une stratégie de parallélisation
|
||||
demande un nouvel effort.
|
||||
De plus, une évolution du programme, même mineure, peut nécessiter une maintenance coûteuse
|
||||
puisqu'il faut évaluer à nouveau s'il est possible de l'exécuter en parallèle et mettre à jour le
|
||||
code en conséquence.
|
||||
Un programme efficacement parallélisé, s'il utilise par exemple des nombres pseudo-aléatoires, peut
|
||||
ne plus être répétable d'une exécution à l'autre.
|
||||
D'autre part, en matière de vérification, il est précieux de pouvoir tester les résultats d'un
|
||||
programme parallèle par rapport à son équivalent exécuté séquentiellement.
|
||||
Cette thèse présente des outils conçus pour répondre à différents problèmes introduits par la
|
||||
programmation parallèle, dont la répétabilité de codes stochastiques faisant usage de nombres
|
||||
pseudo-aléatoires.
|
||||
|
||||
Afin de pouvoir expliquer la théorie et le fonctionnement des propositions faites dans cette thèse,
|
||||
celle-ci explique les rudiments de la programmation parallèle ainsi que les différentes abstractions
|
||||
et automatisations qui existent.
|
||||
Deux chapitres sont ensuite dédiés à la généricité, notamment en C++, et à la métaprogrammation,
|
||||
notamment celle dite template du C++.
|
||||
Ils détaillent en particulier les fonctionnalités permises par ces paradigmes et qui servent ensuite
|
||||
dans l'implémentation des bibliothèques actives que sont les outils proposés.
|
||||
%}}}
|
||||
|
||||
%{{{ pfor "
|
||||
La première bibliothèque, présentée dans \acref{ch:pfor}, propose une interface pour automatiser la
|
||||
parallélisation d'instructions au sein d'une boucle.
|
||||
Celle-ci emploie les patrons d'expressions pour acquérir une représentation des instructions de la
|
||||
boucle sous la forme d'un \gls{ASA}.
|
||||
Cet \gls{ASA} détaille jusqu'aux opérations sur les indices d'accès aux tableaux -- appelées
|
||||
fonctions d'indice -- dont les opérandes sont alors connus dès la compilation.
|
||||
Grâce à cela, la bibliothèque vérifie si tous les accès aux données permettent une exécution
|
||||
parallèle, et ce selon les caractéristiques des fonctions d'indice :
|
||||
\begin{enumerate}
|
||||
\item si toutes sont affines, la bibliothèque répond, avec une spécificité et une sensibilité
|
||||
parfaite, en calculant l'existence de solutions à un ensemble d'équations diophantiennes ;
|
||||
\item sinon, si toutes sont injectives, elle répond, avec une sensibilité imparfaite, en utilisant
|
||||
un test simplifié ;
|
||||
\item sinon la bibliothèque suppose par défaut que les instructions ne peuvent être parallélisées.
|
||||
\end{enumerate}
|
||||
Cette séquence de tests garantit une spécificité parfaite et empêche donc la parallélisation d'un
|
||||
code qui ne peut l'être sainement.
|
||||
|
||||
Ces tests sont appliqués à des groupes d'instructions qui sont formés de sorte que deux instructions
|
||||
quelconques venant de groupes différents sont indépendantes quant aux données qu'elles utilisent.
|
||||
De cette manière, les instructions qui ne doivent être exécutées en parallèle peuvent être
|
||||
maintenues séparées de celles pouvant être exécutées en parallèle si elles sont indépendantes.
|
||||
Ainsi, la non-parallélisabilité de ces premières instructions ne gêne pas la parallélisabilité des
|
||||
dernières, alors qu'une analyse sur l'ensemble complet aurait logiquement rapporté une réponse
|
||||
négative quant à la possibilité d'exécuter les instructions en parallèle.
|
||||
|
||||
À partir des fonctions d'indices seules, la bibliothèque détermine automatiquement si celles-ci sont
|
||||
affines.
|
||||
Quant aux autres propriétés telles que l'injectivité, elles peuvent être indiquées voire déduites.
|
||||
C'est par exemple le cas de l'injectivité si la fonction d'indice est strictement croissante ou
|
||||
strictement décroissante.
|
||||
|
||||
Une fois que les ensembles d'instructions parallélisables et non parallélisables sont ainsi définis,
|
||||
la bibliothèque reproduit le code représenté par l'\gls{ASA} en intégrant ce qui est nécessaire pour
|
||||
que soient exécutées en parallèles les instructions concernées.
|
||||
Pour cela, il est possible d'utiliser différents générateurs.
|
||||
La bibliothèque propose une parallélisation avec OpenMP ou en utilisant des \en{threads} \gls{POSIX}
|
||||
ou encore une génération des instructions en utilisant la technique du déroulement de boucle.
|
||||
|
||||
La bibliothèque a été testée en comparant ses performances avec des programmes équivalents écrits
|
||||
dans les meilleures règles de l'art, de façon \og artisanale \fg (et donc sans l'utiliser).
|
||||
Les temps de compilation, bien qu'il y ait certainement encore des améliorations possibles sur cet
|
||||
aspect, sont raisonnables et permettent une utilisation au sein de projets.
|
||||
Les temps d'exécution montrent que l'abstraction apportée par la bibliothèque n'implique que des
|
||||
surcoûts minimes.
|
||||
%}}}
|
||||
|
||||
%{{{ alsk "
|
||||
La seconde proposition faite dans cette thèse est une autre bibliothèque active ayant pour objectif
|
||||
la parallélisation assistée par les squelettes algorithmiques.
|
||||
Contrairement à la première proposition, les portions du programme qui peuvent être exécutées en
|
||||
parallèle sont intrinsèquement liées au squelette algorithmique que définit le développeur.
|
||||
|
||||
Cette bibliothèque dispose de sa propre manière de concevoir des squelettes algorithmiques.
|
||||
Celle-ci repose sur une séparation initiale de deux concepts : la structure et les liens.
|
||||
La structure du squelette est une composition d'autres structures et d'os, les éléments structurels
|
||||
atomiques introduits dans cette thèse.
|
||||
Chaque os correspond à un motif d'exécution, par exemple l'exécution séquentielle de plusieurs
|
||||
tâches ou l'exécution parallèle d'une même tâche répétée, suivie d'une autre pour sélectionner le
|
||||
meilleur résultat produit.
|
||||
Quant aux liens, il s'agit d'une description des transferts de données entre les différentes tâches
|
||||
à exécuter.
|
||||
Cela se définit en utilisant des paramètres spéciaux, lesquels indiquent à la bibliothèque ce par
|
||||
quoi ils doivent être remplacés (un paramètre de la tâche appelante, la valeur de retour d'une
|
||||
autre, ...).
|
||||
|
||||
La structure du squelette permet de savoir quels éléments peuvent être exécutés en parallèle.
|
||||
Il est donc par exemple possible de déterminer le nombre de niveaux de parallélisation dont on
|
||||
dispose pour un squelette donné.
|
||||
Pour cela, une bibliothèque annexe d'outils pour la métaprogrammation template est utilisée.
|
||||
Celle-ci comporte des algorithmes pour parcourir des listes et des arbres de types, et un squelette
|
||||
algorithmique peut être transformé en arbre (et un arbre en liste si nécessaire).
|
||||
|
||||
En utilisant, notamment, l'information du nombre de niveaux parallélisables, la bibliothèque permet
|
||||
l'optimisation de la répartition des tâches sur les différents \en{threads} selon plusieurs
|
||||
politiques d'exécution : \en{thread pool} ; répartition équilibrée ; répartition équilibrée
|
||||
n'utilisant que le premier niveau ; ...
|
||||
Dans le cas du \en{thread pool}, l'équilibrage de la charge entre les différents \en{threads} est
|
||||
automatique et dynamique, au coût d'une synchronisation à effectuer pour l'accès aux tâches à
|
||||
exécuter.
|
||||
La répartition équilibrée proposée suppose une durée similaire dans l'exécution des différentes
|
||||
tâches et les distribue aux \en{threads} de manière à ce que chacun en ait, à une près, le même
|
||||
nombre.
|
||||
Cette hypothèse semble raisonnable en particulier pour des os répétant une même tâche plusieurs
|
||||
fois, os fréquemment utilisés dans l'implémentation de métaheuristiques.
|
||||
|
||||
Grâce aux connaissances apportées par le choix d'une politique d'exécution et au contrôle permis par
|
||||
les liens, cette thèse propose une solution au problème de la perte de répétabilité lors de
|
||||
l'exécution parallèle d'un programme utilisant des nombres pseudo-aléatoires.
|
||||
Cette solution permet plus généralement le maintien de la répétabilité lors de l'utilisation de
|
||||
données qui doivent n'être utilisées que par un unique \en{thread}.
|
||||
Ces données doivent donc être associées aux tâches qui partagent le \en{thread} qui les exécute.
|
||||
Une solution triviale consiste à fournir à chaque tâche ses propres données.
|
||||
Lorsqu'il s'agit de nombres pseudo-aléatoires, cela signifie qu'il faut déterminer une séquence
|
||||
indépendante pour chaque tâche, ce qui devient coûteux, entre autres en mémoire, lorsque le nombre
|
||||
de tâches augmente et que le statut initial du générateur est conséquent (proche de
|
||||
\SI{2.5}{\kibi\octet} par exemple pour un état initial de Mersenne Twister MT19937).
|
||||
En tenant compte de la distribution des tâches sur les \en{threads}, et ce pour différentes
|
||||
quantités de \en{threads}, on détermine quelles tâches sont toujours exécutées par un \en{thread}
|
||||
commun (indépendamment du nombre de \en{threads}) et on leur associe une séquence de nombres
|
||||
pseudo-aléatoires commune (état initial partagé).
|
||||
Ceci permet de garantir la répétabilité non seulement d'une exécution à l'autre, mais également
|
||||
lorsque le nombre de \en{threads} varie.
|
||||
Les tâches ayant besoin de nombres pseudo-aléatoires peuvent alors en recevoir un automatiquement au
|
||||
moyen d'un paramètre spécial que les liens permettent d'utiliser.
|
||||
|
||||
Cette bibliothèque a été utilisée pour résoudre des instances de \gls{TSP} par la métaheuristique
|
||||
\graspels{}.
|
||||
Les temps d'exécution sont comparés à ceux obtenus avec une implémentation manuelle d'un \graspels{}
|
||||
et correspondent à des exécutions parallèles et à des exécutions séquentielles (afin de valider que,
|
||||
même dans ce cas, la bibliothèque n'induit pas de surcoût).
|
||||
Dans tous les cas, les temps obtenus sont analogues.
|
||||
%}}}
|
||||
|
||||
\chapterx*{Limites et perspectives}
|
||||
|
||||
%{{{ perspectives "
|
||||
%{{{ pfor "
|
||||
Nous avons bien conscience que notre première proposition, orientée sur l'analyse et la
|
||||
parallélisation automatique de boucles, est incomplète dans la mesure où de multiples boucles
|
||||
imbriquées ne sont pas détectées.
|
||||
Pour le moment, l'utilisation de multiples boucles imbriquées signifie qu'une seule sera traitée
|
||||
pour la parallélisation.
|
||||
Ce fait n'est pas gênant si l'on considère les architectures matérielles multi-cœurs actuelles.
|
||||
La bibliothèque ne propose pas d'outil pour mettre en place une parallélisation automatique sur
|
||||
plusieurs niveaux car elle ne permet pas, à ce stade, l'utilisation de l'indice d'un niveau à un
|
||||
niveau inférieur.
|
||||
C'est une piste de recherche que nous envisageons d'explorer à l'avenir.
|
||||
|
||||
De plus, il sera intéressant de tester différentes méthodes pour appliquer la parallélisation.
|
||||
Notamment l'utilisation d'un \en{thread pool} afin de voir si l'introduction de sections critiques
|
||||
induit un coût négligeable par rapport au gain supposé apporté par le fait d'éviter la recréation de
|
||||
\en{threads} à chaque nouvelle boucle parallélisée.
|
||||
|
||||
Au niveau de l'analyse et particulièrement des tests permettant de déterminer la parallélisabilité
|
||||
des instructions, l'implémentation du modèle polyédral est également une piste.
|
||||
Celle-ci peut notamment être utile au support de multiples boucles imbriquées, mais peut
|
||||
éventuellement également servir à augmenter la sensibilité du test pour des boucles à un seul niveau
|
||||
lorsque les fonctions d'indice ne sont ni affines ni injectives.
|
||||
|
||||
Une autre piste d'amélioration consiste en l'application de transformations sur le code source
|
||||
traité.
|
||||
Actuellement, celui-ci est analysé pour sa parallélisabilité, et s'il ne passe pas le test, il est
|
||||
exécuté séquentiellement.
|
||||
Il est possible, en modifiant astucieusement les instructions, de conserver le comportement du
|
||||
programme en éliminant des dépendances, augmentant donc potentiellement sa parallélisabilité.
|
||||
%}}}
|
||||
|
||||
%{{{ alsk "
|
||||
Par rapport à la seconde proposition, axée sur la parallélisation assistée par l'utilisation de
|
||||
squelettes algorithmiques, le travail effectué était principalement centré sur l'abstraction
|
||||
apportée par la bibliothèque de squelettes algorithmiques, au détriment de l'optimisation des
|
||||
différentes politiques d'exécution fournies.
|
||||
Ces politiques d'exécution ne sont donc pas implémentées de manière optimale.
|
||||
Une personne dont la parallélisation est le domaine d'expertise pourrait améliorer cela.
|
||||
En outre, il serait très intéressant de tester la piste évoquée dans
|
||||
\acref{subsubsec:alsk/exec/impl/static}, à savoir la préparation, dès la compilation, de la séquence
|
||||
complète des tâches qu'exécutera chaque \en{thread} afin d'éviter un défaut actuel de la politique
|
||||
d'exécution répartissant les tâches de manière équilibrée : les \en{threads} des niveaux parallèles,
|
||||
à l'exception du tout premier, sont créés de multiples fois.
|
||||
|
||||
Une autre idée est de permettre l'ajustement du poids des tâches à exécuter afin de ne plus supposer
|
||||
un temps d'exécution homogène.
|
||||
En utilisant ces poids, une distribution équilibrée des tâches sur les différents \en{threads} peut,
|
||||
peut-être, être aussi efficace en termes d'équilibrage de charge que ce que peut accomplir
|
||||
dynamiquement un \en{thread pool}.
|
||||
De plus, une exécution, partielle ou sur des données réduites, du programme permettrait
|
||||
éventuellement la génération automatique de ces poids.
|
||||
|
||||
Les os proposés au sein de cette thèse répondent aux besoins levés par l'applicatif en \gls{RO} que
|
||||
nous avons utilisé.
|
||||
Néanmoins, des motifs tels que le \en{pipeline}, sont manquants pour une utilisation réellement
|
||||
générale.
|
||||
Certains de ces nouveaux os pourraient nécessiter l'ajout de primitives au sein des exécuteurs.
|
||||
|
||||
Le système de liens apporte des avantages intéressants, mais également une syntaxe plus lourde pour
|
||||
le développeur qui, en utilisant d'autres bibliothèques de squelettes algorithmiques, pourrait
|
||||
préférer une valeur par défaut.
|
||||
L'\gls{EDSL} introduit en partie cette possibilité de valeur par défaut et même de déduction de
|
||||
liens, mais cela manque aux couches plus basses.
|
||||
|
||||
Ce système de liens permet par ailleurs de connaître exactement quelles tâches nécessitent
|
||||
l'utilisation, par exemple, de nombres pseudo-aléatoires.
|
||||
En utilisant cette information, il est possible de réduire encore le nombre de \gls{PRNG} devant
|
||||
être créés pour garantir la répétabilité du programme.
|
||||
%}}}
|
||||
%}}}
|
||||
|
80
src/acronyms.tex
Normal file
80
src/acronyms.tex
Normal file
@ -0,0 +1,80 @@
|
||||
\newacronym{ABI}{ABI}{\en{Application Binary Interface}}
|
||||
\newacronym{API}{API}{\en{Application Programming Interface}}
|
||||
\newacronym{ASA}{ASA}{arbre syntaxique abstrait}
|
||||
\newacronym{AST}{AST}{\en{Abstract Syntax Tree}}
|
||||
\newacronym{AVX}{AVX}{\en{Advanced Vector eXtensions}}
|
||||
|
||||
\newacronym{BLP}{BLP}{\en{Bit-Level Parallelism}}
|
||||
|
||||
\newacronym{C++ AMP}{C++ AMP}{C++ {\en{Accelerated Massive Parallelism}}}
|
||||
\newacronym{CPP}{CPP}{\en{C PreProcessor}}
|
||||
\newacronym{CPU}{CPU}{\en{Central Processing Unit}}
|
||||
\newacronym{CTAD}{CTAD}{\en{Class Template Argument Deduction}}
|
||||
\newacronym{CUDA}{CUDA}{\en{Compute Unified Device Architecture}}
|
||||
|
||||
\newacronym{DSL}{DSL}{\en{Domain Specific Language}}
|
||||
\newacronym{DSP}{DSP}{\en{Digital Signal Processor}}
|
||||
|
||||
\newacronym{EBO}{EBO}{\en{Empty Base Optimization}}
|
||||
\newacronym{EDSL}{EDSL}{\en{Embedded Domain Specific Language}}
|
||||
\newacronym{ELS}{ELS}{\en{Evolutionary Local Search}}
|
||||
\newacronym{ET}{ET}{\en{Expression Templates}}
|
||||
|
||||
\newacronym{FIFO}{FIFO}{\en{First In, First Out}}
|
||||
\newacronym{FPGA}{FPGA}{\en{Field-Programmable Gate Array}}
|
||||
|
||||
\newacronym{GPGPU}{GPGPU}{\en{General-Purpose computing on \gls{GPU}}}
|
||||
\newacronym{GPPL}{GPPL}{\en{General Purpose Programming Language}}
|
||||
\newacronym{GPU}{GPU}{\en{Graphics Processing Unit}}
|
||||
\newacronym{GRASP}{GRASP}{\en{Greedy Randomized Adaptive Search Procedure}}
|
||||
|
||||
\newacronym{HPC}{HPC}{\en{High Performance Computing}}
|
||||
|
||||
\newacronym{ID}{ID}{\en{Instruction Decode}}
|
||||
\newacronym{IEEE}{IEEE}{\en{Institute of Electrical and Electronics Engineers}}
|
||||
\newacronym{IF}{IF}{\en{Instruction Fetch}}
|
||||
\newacronym{ILP}{ILP}{\en{Instruction-Level Parallelism}}
|
||||
\newacronym{ILS}{ILS}{\en{Iterative Local Search}}
|
||||
\newacronym{IPC}{IPC}{\en{Inter-Process Communication}}
|
||||
|
||||
\newacronym{MA}{MA}{\en{Memory Access}}
|
||||
\newacronym{MIMD}{MIMD}{\en{Multiple-Instruction stream -- Multiple-Data stream}}
|
||||
\newacronym{MISD}{MISD}{\en{Multiple-Instruction stream -- Single-Data stream}}
|
||||
\newacronym{MMX}{MMX}{\en{multimedia extensions}}
|
||||
\newacronym{MPI}{MPI}{\en{Message Passing Interface}}
|
||||
\newacronym{MPT}{MPT}{métaprogrammation template}
|
||||
|
||||
\newacronym{NUMA}{NUMA}{\en{Non-Uniform Memory Access}}
|
||||
|
||||
\newacronym{OpenCL}{OpenCL}{\en{Open Computing Language}}
|
||||
\newacronym{OpenMP}{OpenMP}{\en{Open Multi-Processing}}
|
||||
|
||||
\newacronym{PEPS}{PEPS}{Premier Entré, Premier Sorti}
|
||||
\newacronym{PGCD}{PGCD}{plus grand commun diviseur}
|
||||
\newacronym{POO}{POO}{Programmation Orientée Objet}
|
||||
\newacronym{POSIX}{POSIX}{\en{Portable Operating System Interface}}
|
||||
\newacronym{PRNG}{PRNG}{\en{Pseudorandom Number Generator}}
|
||||
|
||||
\newacronym{RAII}{RAII}{\en{Resource Acquisition Is Initialisation}}
|
||||
\newacronym{RAW}{RAW}{\en{Read After Write}}
|
||||
\newacronym{RO}{RO}{Recherche Opérationnelle}
|
||||
\newacronym{RRID}{RRID}{\en{Resource Release Is Destruction}}
|
||||
|
||||
\newacronym{SFINAE}{SFINAE}{\en{Substitution Failure Is Not An Error}}
|
||||
\newacronym{SIMD}{SIMD}{\en{Single-Instruction stream -- Multiple-Data stream}}
|
||||
\newacronym{SISD}{SISD}{\en{Single-Instruction stream -- Single-Data stream}}
|
||||
\newacronym{SMP}{SMP}{\en{Symmetric MultiProcessing}}
|
||||
\newacronym{SSE}{SSE}{\en{Streaming \gls{SIMD} Extension}}
|
||||
|
||||
\newacronym{TAD}{TAD}{\en{Template Argument Deduction}}
|
||||
\newacronym{TBB}{TBB}{\en{Threading Building Blocks}}
|
||||
\newacronym{TMP}{TMP}{\en{template metaprogramming}}
|
||||
\newacronym{TSP}{TSP}{\en{Travelling Salesman Problem}}
|
||||
|
||||
\newacronym{UAL}{UAL}{Unité Arithmétique et Logique}
|
||||
\newacronym{UMA}{UMA}{\en{Uniform Memory Access}}
|
||||
\newacronym{UVF}{UVF}{Unité de calcul en Virgule Flottante}
|
||||
|
||||
\newacronym{WAR}{WAR}{\en{Write After Read}}
|
||||
\newacronym{WAW}{WAW}{\en{Write After Write}}
|
||||
\newacronym{WB}{WB}{\en{WriteBack}}
|
20
src/alg/alsk/app/els.tex
Normal file
20
src/alg/alsk/app/els.tex
Normal file
@ -0,0 +1,20 @@
|
||||
\begin{algorithmic}
|
||||
\Function{ELS}{$P, S, N, M$}
|
||||
\State $S \gets \Call{rechercheLocaleInitiale}{P, S}$
|
||||
\State $S^* \gets S$
|
||||
|
||||
\For{$i = 1..N$}
|
||||
\For{$j = 1..M$}
|
||||
\State $S_j \gets \Call{mutation}{S}$
|
||||
\State $S_j \gets \Call{rechercheLocale}{P, S_j}$
|
||||
\EndFor
|
||||
\State $S' \gets \Call{sélection1}{\{S_1, S_2, \dots, S_{M}\}}$
|
||||
\State $S^* \gets \Call{sélection2}{S^*, S'}$
|
||||
|
||||
\If{\Call{critèreAcceptation}{$S'$}}
|
||||
\State $S \gets S'$
|
||||
\EndIf
|
||||
\EndFor
|
||||
\State \Return $S^*$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
10
src/alg/alsk/app/grasp.tex
Normal file
10
src/alg/alsk/app/grasp.tex
Normal file
@ -0,0 +1,10 @@
|
||||
\begin{algorithmic}
|
||||
\Function{GRASP}{$N, P$}
|
||||
\For{$i = 1..N$}
|
||||
\State $S_i \gets \Call{heuristiqueConstructive}{P}$
|
||||
\State $S_i \gets \Call{rechercheLocale}{P, S_i}$
|
||||
\EndFor
|
||||
\State $S^* \gets \Call{sélection}{\{S_1, S_2, \dots, S_{N}\}}$
|
||||
\State \Return $S^*$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
12
src/alg/alsk/app/greedy.tex
Normal file
12
src/alg/alsk/app/greedy.tex
Normal file
@ -0,0 +1,12 @@
|
||||
\begin{algorithmic}
|
||||
\Function{glouton}{$P$}
|
||||
\State $S \gets \emptyset$
|
||||
\State Construire la liste $L$ des éléments insérables dans $S$ à partir de $P$
|
||||
\While{$L \neq \emptyset$}
|
||||
\State Évaluer le coût d'insertion de chaque élément de $L$
|
||||
\State Retirer de $L$ l'élément de coût minimal
|
||||
\State Insérer cet élément dans $S$
|
||||
\EndWhile
|
||||
\State \Return $S$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
17
src/alg/alsk/app/ils.tex
Normal file
17
src/alg/alsk/app/ils.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\begin{algorithmic}
|
||||
\Function{ILS}{$P, S, N$}
|
||||
\State $S \gets \Call{rechercheLocaleInitiale}{P, S}$
|
||||
\State $S^{*} \gets S$
|
||||
|
||||
\For{$i = 1..N$}
|
||||
\State $S' \gets \Call{mutation}{S}$
|
||||
\State $S' \gets \Call{rechercheLocale}{P, S'}$
|
||||
\State $S^{*} \gets \Call{sélection}{S^{*}, S'}$
|
||||
|
||||
\If{\Call{critèreAcceptation}{$S'$}}
|
||||
\State $S \gets S'$
|
||||
\EndIf
|
||||
\EndFor
|
||||
\State \Return $S^{*}$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
16
src/alg/par/assist/barrier.tex
Normal file
16
src/alg/par/assist/barrier.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{threadPrincipal}{}
|
||||
\State $promesse\_type\;promesse$
|
||||
\State $future\_type\;future$
|
||||
\State $thread\_type\;thread(\textsc{travail}, promesse)$
|
||||
\State \Comment{travail précédant la barrière de synchronisation}
|
||||
\State $\Call{obtenirResultat}{future}$ \Comment{la valeur retournée n'importe pas}
|
||||
\State \Comment{travail réalisé après la barrière de synchronisation}
|
||||
\EndProcedure
|
||||
|
||||
\Procedure{travail}{$promesse$}
|
||||
\State \Comment{travail précédant la barrière de synchronisation}
|
||||
\State $promesse \gets \epsilon$ \Comment{la valeur donnée n'importe pas}
|
||||
\State \Comment{travail réalisé après la barrière de synchronisation}
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
16
src/alg/par/assist/futurepromise.tex
Normal file
16
src/alg/par/assist/futurepromise.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{threadPrincipal}{}
|
||||
\State $promesse\_type\;promesse$ \Comment{\og promesse \fg{} qui sera donnée au second \en{thread}}
|
||||
\State $future\_type\;future \gets \Call{obtenirFuture}{promesse}$ \Comment{construction de la
|
||||
\og future \fg{} correspondante}
|
||||
\State $thread\_type\;thread(\textsc{travail}, promesse)$
|
||||
\State \Comment{le \en{thread} principal peut travailler indépendament ici}
|
||||
\State $resultat \gets \Call{obtenirResultat}{future}$ \Comment{synchronisation entre les deux
|
||||
\en{threads}}
|
||||
\EndProcedure
|
||||
|
||||
\Procedure{travail}{$promesse$}
|
||||
\State \Comment{production d'un résultat}
|
||||
\State $promesse \gets resultat$
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
15
src/alg/par/assist/pthread.tex
Normal file
15
src/alg/par/assist/pthread.tex
Normal file
@ -0,0 +1,15 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $m \gets PTHREAD\_MUTEX\_INITIALIZER$
|
||||
|
||||
\Procedure{threadPrincipal}{}
|
||||
\State $thread\_id \gets \Call{pthread\_create}{\textsc{travail}}$
|
||||
\State $\Call{travail}{}$ \Comment{cet appel est exécuté dans le \en{thread} principal}
|
||||
\State $\Call{pthread\_join}{thread\_id}$
|
||||
\EndProcedure
|
||||
|
||||
\Procedure{travail}{}
|
||||
\State $\Call{pthread\_mutex\_lock}{m}$
|
||||
\State ... \Comment{modification d'une variable partagée}
|
||||
\State $\Call{pthread\_mutex\_unlock}{m}$
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
13
src/alg/par/assist/stdthread.tex
Normal file
13
src/alg/par/assist/stdthread.tex
Normal file
@ -0,0 +1,13 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $mutex\_type\;m$ \Comment{le constructeur initialise correctement}
|
||||
\Procedure{threadPrincipal}{}
|
||||
\State $thread\_type\;thread(\textsc{travail})$
|
||||
\Comment{le constructeur appelle \texttt{pthread\_create}}
|
||||
\State $\Call{travail}{}$
|
||||
\EndProcedure \Comment{le destructeur de $thread\_type$ appelle \texttt{ptread\_join}}
|
||||
|
||||
\Procedure{travail}{}
|
||||
\State $mutex\_locker\_type\;lock(m)$ \Comment{le constructeur prend le \en{mutex}...}
|
||||
\State \Comment{modification d'une variable partagée}
|
||||
\EndProcedure \Comment{... et le destructeur le libère}
|
||||
\end{algorithmic}
|
9
src/alg/par/auto/ast.tex
Normal file
9
src/alg/par/auto/ast.tex
Normal file
@ -0,0 +1,9 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $i = 10$
|
||||
\State $r = 0$
|
||||
\While{$i \neq 0$}
|
||||
\State $r = r+i$
|
||||
\State $i = i-1$
|
||||
\EndWhile
|
||||
\State \Return $r$
|
||||
\end{algorithmic}
|
5
src/alg/par/auto/depcontrol.tex
Normal file
5
src/alg/par/auto/depcontrol.tex
Normal file
@ -0,0 +1,5 @@
|
||||
\begin{algorithmic}[1]
|
||||
\If{$R_1 = A$}
|
||||
\State $R_2 \gets B$ \Comment{L'exécution de cette instruction dépend de l'instruction $R_1 = A$}
|
||||
\EndIf
|
||||
\end{algorithmic}
|
4
src/alg/par/auto/depraw.tex
Normal file
4
src/alg/par/auto/depraw.tex
Normal file
@ -0,0 +1,4 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $R_1 \gets A$ \Comment{Une ressource utilisée en écriture...}
|
||||
\State $R_2 \gets R_1$ \Comment{... puis en lecture}
|
||||
\end{algorithmic}
|
4
src/alg/par/auto/depwar.tex
Normal file
4
src/alg/par/auto/depwar.tex
Normal file
@ -0,0 +1,4 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $A \gets R_1$ \Comment{Une ressource est utilisée en lecture...}
|
||||
\State $R_1 \gets B$ \Comment{... puis en écriture}
|
||||
\end{algorithmic}
|
5
src/alg/par/auto/depwar_solved.tex
Normal file
5
src/alg/par/auto/depwar_solved.tex
Normal file
@ -0,0 +1,5 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $V \gets R_1$ \Comment{Introduction d'une nouvelle variable}
|
||||
\State $A \gets V$ \Comment{Cette instruction ne dépend plus de la suivante}
|
||||
\State $R_1 \gets B$
|
||||
\end{algorithmic}
|
4
src/alg/par/auto/depwaw.tex
Normal file
4
src/alg/par/auto/depwaw.tex
Normal file
@ -0,0 +1,4 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State $R_1 \gets A$ \Comment{Une ressource utilisée en écriture...}
|
||||
\State $R_1 \gets B$ \Comment{... puis à nouveau en écriture}
|
||||
\end{algorithmic}
|
17
src/alg/par/comp/barrier.tex
Normal file
17
src/alg/par/comp/barrier.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{barrière}{} \Comment{procédure exécutée par les $N_t$ \en{threads}}
|
||||
\State $\Call{P}{m}$ \Comment{sémaphore utilisé comme \en{mutex} pour protéger $N_b$}
|
||||
\State $N_b \gets N_b + 1$ \Comment{$N_b$ compte le nombre de \en{thread} arrivés}
|
||||
\If{$N_b = N_t$} \Comment{Le dernier \en{thread} exécutera la première branche}
|
||||
\State $N_b \gets N_b - 1$
|
||||
\Repeat
|
||||
\State $\Call{V}{b}$ \Comment{libération des autres \en{threads}}
|
||||
\State $N_b \gets N_b - 1$
|
||||
\Until{$N_b = 0$}
|
||||
\State $\Call{V}{m}$
|
||||
\Else \Comment{pour les $N_t-1$ premiers \en{threads}}
|
||||
\State $\Call{V}{m}$
|
||||
\State $\Call{P}{b}$ \Comment{bloqué jusqu'à l'arrivée du dernier \en{thread}}
|
||||
\EndIf
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
13
src/alg/par/comp/barrier2.tex
Normal file
13
src/alg/par/comp/barrier2.tex
Normal file
@ -0,0 +1,13 @@
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{thread1}{} \Comment{procédure exécutée par l'un des deux \en{threads}}
|
||||
\State ...
|
||||
\State $\Call{V}{a}$
|
||||
\State $\Call{P}{b}$
|
||||
\EndProcedure
|
||||
|
||||
\Procedure{thread2}{} \Comment{procédure exécutée par l'autre \en{thread}}
|
||||
\State ...
|
||||
\State $\Call{P}{a}$
|
||||
\State $\Call{V}{b}$
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
8
src/alg/par/comp/mutex.tex
Normal file
8
src/alg/par/comp/mutex.tex
Normal file
@ -0,0 +1,8 @@
|
||||
\begin{algorithmic}[1]
|
||||
\State \Comment{Le sémaphore $m$ existe et a été initialisé à 1}
|
||||
\Procedure{}{} \Comment{procédure exécutée par de multiples \en{threads}}
|
||||
\State $\Call{P}{m}$
|
||||
\State ... \Comment{section critique}
|
||||
\State $\Call{V}{m}$
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
19
src/alg/pfor/conditions/groupdependent.tex
Normal file
19
src/alg/pfor/conditions/groupdependent.tex
Normal file
@ -0,0 +1,19 @@
|
||||
\begin{algorithmic}
|
||||
\State entrée : un ensemble d'instructions $P = \{I_1, ..., I_n\}$
|
||||
\State sortie : l'ensemble des sous-ensembles d'instructions dépendantes
|
||||
\Function{GrouperInstructionsDépendantes}{$P$}
|
||||
\State $G \gets \emptyset$
|
||||
\ForAll{$I_k \in P$}
|
||||
\State $P_a \gets \{I_k\}$
|
||||
\State $P_c \gets P_a$
|
||||
\ForAll{$P_b \in G$}
|
||||
\If{not \Call{TestBernstein}{$P_a$, $P_b$}}
|
||||
\State $G \gets G \setminus \{P_b\}$
|
||||
\State $P_c \gets P_c \cup P_b$
|
||||
\EndIf
|
||||
\EndFor
|
||||
\State $G \gets G \cup \{P_c\}$
|
||||
\EndFor
|
||||
\State \Return $G$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
30
src/alsk/0_intro.tex
Normal file
30
src/alsk/0_intro.tex
Normal file
@ -0,0 +1,30 @@
|
||||
\section{Introduction}
|
||||
|
||||
La parallélisation automatique permet au développeur de ne pas se préoccuper du tout de la
|
||||
problématique de parallélisation au sein de son programme.
|
||||
En contrepartie, il perd une partie du contrôle dont il pourrait disposer sur sa parallélisation.
|
||||
Ce chapitre traite d'une solution de parallélisation assistée utilisant le concept de squelettes
|
||||
algorithmiques~\autocite{ref:cole1989}.
|
||||
|
||||
L'objectif principal est de proposer une bibliothèque
|
||||
active\footnote{\url{https://phd.pereda.fr/dev/alsk}} permettant à un développeur de décrire ses
|
||||
algorithmes en spécifiant lui-même quelles parties peuvent être exécutées en parallèles, et de
|
||||
quelle manière elles doivent l'être en assemblant un ensemble de motifs d'exécution fournis.
|
||||
|
||||
Ce chapitre présente d'abord la recherche existante autour des squelettes algorithmiques puis
|
||||
introduit un ensemble d'outils classiques de \gls{RO} ainsi qu'un problème de \gls{RO}.
|
||||
Ceux-ci sont utilisés comme application aux travaux présentés dans ce chapitre car ils ont des
|
||||
propriétés intéressantes pour mettre en évidence des problématiques liées à la parallélisation et
|
||||
donc les solutions proposées, notamment pour le problème de la répétabilité.
|
||||
Ce chapitre se poursuit avec la présentation de notre conception des squelettes algorithmiques, en
|
||||
détaillant en particulier leur structure et la possibilité de décrire les transmissions de données
|
||||
entre les différentes parties de l'algorithmique représenté.
|
||||
Ensuite, le chapitre explique comment se fait la répartition des tâches de l'algorithme afin de le
|
||||
rendre parallèle et expose différentes stratégies pour ce faire.
|
||||
Après cela, nous abordons le problème de la répétabilité, notamment pour le cas de l'utilisation de
|
||||
nombres pseudo-aléatoires, et des méthodes pour optimiser la procédure initiale en tenant compte de
|
||||
la stratégie de répartition des tâches adoptée et du degré de parallélisation.
|
||||
Ce chapitre introduit ensuite un \gls{EDSL} servant d'interface pour simplifier l'utilisation de la
|
||||
bibliothèque.
|
||||
Enfin, il se termine sur une étude des performances obtenues en utilisant la bibliothèque en la
|
||||
confrontant à des codes écrits sans l'utiliser.
|
160
src/alsk/1_relwork.tex
Normal file
160
src/alsk/1_relwork.tex
Normal file
@ -0,0 +1,160 @@
|
||||
\section{Travaux connexes}
|
||||
|
||||
Les squelettes algorithmiques, introduits par \autocite{ref:cole1989}, proposent une solution de
|
||||
parallélisation assistée.
|
||||
L'objectif des squelettes est de masquer l'implémentation parallèle d'un algorithme en fournissant
|
||||
une interface permettant au développeur de choisir parmi des patrons de conception celui qui
|
||||
correspond à son besoin.
|
||||
Un avantage des squelettes par rapport à des interfaces plus simples, comme un ensemble de fonctions
|
||||
correspondant directement aux différents patrons, réside dans leur capacité à être
|
||||
composés~\autocite{ref:benoit2005}.
|
||||
|
||||
\autocite{ref:cole1989} les définit comme des fonctions d'ordre supérieur, c'est-à-dire des
|
||||
fonctions capables d'utiliser des fonctions comme paramètres ou retournant d'autres fonctions.
|
||||
L'exemple de la fonction d'ordre supérieur \og map \fg{} y est donné ainsi :
|
||||
\begin{align*}
|
||||
map : (a \to b) \to ([a] \to [b]).
|
||||
\end{align*}
|
||||
|
||||
Il s'agit d'une fonction acceptant une autre fonction en paramètre et retournant une nouvelle
|
||||
fonction.
|
||||
Cette dernière agit sur un vecteur d'éléments du type de l'unique paramètre de la fonction unaire en
|
||||
entrée ($a$) et retournant un vecteur d'éléments du même type que ce qui est retourné par la
|
||||
fonction en entrée ($b$).
|
||||
Pour produire le vecteur de type $[b]$, la fonction en entrée est appliquée sur chaque élément du
|
||||
vecteur de type $[a]$.
|
||||
Des fonctions d'ordre supérieur ont été présentées dans \acref{ch:mp},
|
||||
\cref{subsubsec:mp/mpt/et/curry}.
|
||||
|
||||
De nombreux travaux ont proposé des modèles et implémentations de squelettes algorithmiques dans
|
||||
différents langages de programmation depuis l'introduction de ce concept.
|
||||
Ceux-ci proposent généralement des patrons classiques~\autocite{ref:campbell1996} : parmi ceux
|
||||
orientés vers la parallélisation de données, on trouve \en{map}, \en{zip}, \en{reduce} ; et parmi
|
||||
ceux travaillant sur la parallélisation de tâches, il existe \en{farm}, \en{pipeline}, \en{divide
|
||||
and conquer}~\autocite{ref:kuchen2002a}.
|
||||
|
||||
Cette section illustre certains patrons.
|
||||
Si l'on considère, dans un premier temps, le patron \en{fork-join} qui consiste simplement en
|
||||
l'exécution de deux tâches $T_0$ et $T_1$ en parallèle, on peut utiliser la représentation faite
|
||||
dans \acref{fig:alsk/relwork/forkjoin}.
|
||||
Dans celle-ci, les tâches exécutées sont représentées par des blocs et nommées $T_i$ où $i$ est un
|
||||
entier en l'absence duquel toutes les tâches $T$ effectuent la même chose.
|
||||
Les zones englobant plusieurs tâches indiquent une exécution parallèle de celles-ci.
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{relwork/forkjoin}
|
||||
{Patron d'exécution parallèle \en{fork-join}}
|
||||
\end{figure}
|
||||
|
||||
Le patron \en{map} a déjà été abordé dans l'introduction de ce chapitre et correspond à l'exécution
|
||||
de $n$ instances d'une tâche $T$ sur $n$ données, comme illustré par \acref{fig:alsk/relwork/map}.
|
||||
En remplaçant l'ensemble défini de données par un flux, un \en{map} devient un \en{farm}.
|
||||
|
||||
\begin{figure}[!hb]
|
||||
\inputfig{relwork/map}
|
||||
{Patron d'exécution parallèle \en{map}}
|
||||
\end{figure}
|
||||
|
||||
À nouveau comparable à \en{map}, la fonction d'ordre supérieure \en{zip} peut être définie ainsi :
|
||||
\begin{align*}
|
||||
zip : ((a, b) \to c) \to ([a], [b] \to [c]).
|
||||
\end{align*}
|
||||
|
||||
Cela correspond donc à l'application d'une fonction d'arité \num{2} sur chaque élément de deux
|
||||
vecteurs de données de même cardinalité ($\vert [a] \vert = \vert [b] \vert$) pour produire un
|
||||
unique vecteur.
|
||||
Il est possible de généraliser le principe à des arités quelconques.
|
||||
|
||||
L'application d'une fonction de projection (\texttt{min}, \texttt{sum}, ...) sur un ensemble de
|
||||
données pour le réduire à une seule est appelée réduction, et le patron associé \en{reduce} ou plus
|
||||
rarement \en{fold}.
|
||||
Il est très souvent appliqué après un \en{map}, ce qui correspond alors au patron
|
||||
\en{map-reduce}.% ref? illustré par \acref{fig:alsk/relwork/map}.
|
||||
|
||||
Le \en{pipeline} permet l'exécution parallèle de plusieurs tâches $T_0$, $T_1$, ... $T_n$ par
|
||||
lesquelles les données en entrée passent successivement (\cref{fig:alsk/relwork/pipeline}).
|
||||
Le principe de \og diviser pour régner \fg, en anglais \en{divide and conquer}, est de répartir le
|
||||
travail initial entre les travailleurs par séparation successives de l'ensemble de données en
|
||||
entrée.
|
||||
Après cette étape, les résultats sont fusionnés successivement jusqu'à obtenir un résultat final.
|
||||
Il est possible de diviser les données jusqu'à atteindre un niveau atomique (sans fixer le nombre de
|
||||
travailleurs) ou de définir la profondeur maximale (limitant le nombre de travailleurs).
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{relwork/pipeline}
|
||||
{Patron d'exécution parallèle \en{pipeline}}
|
||||
\end{figure}
|
||||
|
||||
Les structures de contrôle classiques (branches conditionnelles, boucles, ...) peuvent également
|
||||
être proposées comme squelette.
|
||||
Il existe d'autres patrons, mais ceux qui ont été présentés ci-dessus et les combinaisons
|
||||
concevables entre ceux-ci sont plus que suffisants pour le propos de cette thèse.
|
||||
|
||||
La bibliothèque C++ \gls{TBB} propose des fonctions correspondant à divers patrons parallèles tels
|
||||
que \cppinline{parallel_for}, \cppinline{parallel_reduce}, \cppinline{parallel_pipeline}, ...
|
||||
Ces fonctions sont conçues de manière similaire à la bibliothèque standard du langage (génériques
|
||||
par template, utilisation d'itérateurs).
|
||||
|
||||
L'exécution est parallélisée et équilibrée dynamiquement, et \gls{TBB} détecte l'utilisation
|
||||
imbriquée de plusieurs de ses fonctions.
|
||||
Cette fonctionnalité permet de distinguer cette bibliothèque d'un simple ensemble de fonctions et la
|
||||
rapproche des squelettes algorithmiques.
|
||||
|
||||
De manière similaire, le langage de programmation Cilk++ implémente des mots-clés pour faciliter
|
||||
l'exécution parallèle ainsi qu'une structure de contrôle utilisant la syntaxe de la boucle
|
||||
\cppinline{for} du C++, \cppinline{cilk_for}.
|
||||
Ainsi, bien que cela ne soit pas un outil dont la conception repose spécifiquement sur les
|
||||
squelettes algorithmiques (à l'instar de \gls{TBB}), les éléments proposés s'en rapprochent.
|
||||
|
||||
En revanche, \autocite{ref:rieger2019} propose un langage, Musket, fondamentalement basé sur le
|
||||
concept de squelettes algorithmiques.
|
||||
Celui-ci est un \gls{DSL}, dont la syntaxe est volontairement proche de celle du C++, l'objectif
|
||||
étant de permettre la génération de code C++ parallèle.
|
||||
Des types de données spécifiques, permettant la parallélisation, sont fournis (des types primitifs
|
||||
jusqu'aux matrices).
|
||||
Les motifs de parallélisation proposés sont \en{map}, \en{reduce}, \en{zip} et \en{shift partition}.
|
||||
|
||||
Les auteurs de Musket ont détaillé les raisons pour lesquelles ils ont choisi de développer un
|
||||
langage plutôt qu'une bibliothèque~\autocite{ref:wrede2020}.
|
||||
Celles-ci entraînent un surcoût en temps d'exécution par rapport à une implémentation manuelle ou
|
||||
une génération de code comme peut le faire le compilateur d'un langage.
|
||||
D'autre part, les bibliothèques étant contraintes à respecter la syntaxe du langage hôte, il est
|
||||
plus facile de proposer une meilleure lisibilité du code au sein d'un \gls{DSL}.
|
||||
Enfin, cette dernière contrainte apporte un autre argument au choix d'un langage dédié : cela permet
|
||||
davantage de flexibilité dans les transformations appliquées sur le code pour produire un programme
|
||||
parallèle.
|
||||
|
||||
De nombreuses bibliothèques de squelettes algorithmiques
|
||||
ont été proposées~\autocite{ref:aldinucci2009,ref:ciechanowicz2009,ref:leyton2010,ref:legaux2013,ref:ernstsson2018,ref:philippe2019}.
|
||||
\autocite{ref:striegnitz2000} a montré que le langage C++ permettait probablement l'implémentation
|
||||
de bibliothèques de squelettes algorithmiques.
|
||||
Plus tard, \autocite{ref:falcou2006a} l'a prouvé et a également montré que l'utilisation des
|
||||
templates permettait d'obtenir un moindre surcoût en temps d'exécution.
|
||||
La différence notable entre une bibliothèque \og classique \fg{} et ce que permettent les templates
|
||||
en C++ est la possibilité de réellement agir durant la compilation, les rendant \og actives
|
||||
\fg~\autocite{ref:veldhuizen1998a}.
|
||||
Enfin, il est possible de proposer un \gls{DSL} au sein de certains langages existants, comme c'est
|
||||
le cas du C++ : on parle alors d'un \gls{EDSL}~\autocite{ref:saidani2009}.
|
||||
Cela permet de mitiger la scission entre langage et bibliothèque en termes de performances et de
|
||||
flexibilité, au moins dans le cadre du C++.
|
||||
|
||||
Les travaux effectués durant cette thèse sur les squelettes algorithmiques ont ainsi été orientés
|
||||
vers le C++, et plus spécifiquement vers l'implémentation de bibliothèques faisant usage de la
|
||||
métaprogrammation template de ce langage.
|
||||
Les inconvénients des bibliothèques par rapport à la création d'un langage ou même par rapport à
|
||||
l'implémentation d'une extension pour un compilateur sont amoindris par l'utilisation de la
|
||||
métaprogrammation.
|
||||
En revanche, une bibliothèque apporte des avantages que nous avons jugé importants.
|
||||
Premièrement, elles s'inscrivent dans un cadre qui peut déjà être connu par le développeur, et dans
|
||||
le cas du langage C++, qui est très vastement utilisé, c'est particulièrement le cas.
|
||||
L'implémentation d'un nouveau langage nécessite également la mise en place des nombreuses
|
||||
optimisations déjà présentes et à venir sur les compilateurs de langages existants, alors qu'une
|
||||
bibliothèque profitera de celles-ci automatiquement.
|
||||
Certes, un nouveau langage peut, plutôt que d'être compilé directement vers de l'assembleur, générer
|
||||
du code dans un autre langage bénéficiant de ces optimisations~\autocite{ref:rieger2019}, cependant,
|
||||
cela requiert une maintenance parallèle des deux langages.
|
||||
Il existe également le cas des extensions pour un compilateur, mais celles-ci doivent alors être
|
||||
implémentées pour chaque compilateur, ou bien imposer aux utilisateurs de n'utiliser qu'un
|
||||
sous-ensemble des compilateurs disponibles.
|
||||
Une bibliothèque dont l'implémentation ne repose que sur le standard du langage ne crée aucune de
|
||||
ces contraintes.
|
227
src/alsk/2_app.tex
Normal file
227
src/alsk/2_app.tex
Normal file
@ -0,0 +1,227 @@
|
||||
\section{Application}
|
||||
|
||||
L'objectif de cette section est d'introduire les problèmes sur lesquels nous avons appliqué notre
|
||||
solution.
|
||||
Nous avons choisi de travailler sur la résolution de problèmes de \gls{RO}.
|
||||
Ceux-ci offrent plusieurs niveaux de parallélisation qui peuvent être entrelacés avec des niveaux
|
||||
non parallélisables, ce qui nous a intéressé pour valider notre représentation globale d'un
|
||||
algorithme.
|
||||
L'utilisation intensive de nombres pseudo-aléatoires dans ce domaine nous a également permis
|
||||
d'éprouver notre solution en ce qui concerne l'obtention de résultats répétables.
|
||||
|
||||
Le voyageur de commerce (\gls{TSP})~\autocite{ref:robinson1949} est un problème très classique de
|
||||
\gls{RO}.
|
||||
Une instance de ce problème consiste en un graphe $G = (V, A, c)$ où $V$ est un ensemble de sommets,
|
||||
$A$ un ensemble d'arêtes et $c$ une fonction de coût qui associe une distance minimale à un arc de
|
||||
$A$~\autocite{ref:dantzig1954}.
|
||||
Une solution peut être exprimée comme un vecteur $s$ de sommets contenant une fois chaque sommet de
|
||||
$V$, sa valeur $c_s$ étant alors donnée par \acref{eq:alsk/app/tspvalue}, où $(a, b)$ correspond à
|
||||
l'arête entre le sommet $a$ et le sommet $b$.
|
||||
|
||||
\begin{align}
|
||||
c_s = \sum_{i=2}^{\vert V \vert}{c((s[i-1], s[i]))}
|
||||
\label{eq:alsk/app/tspvalue}
|
||||
\end{align}
|
||||
|
||||
L'objectif est alors de trouver un cycle qui minimise $c_s$.
|
||||
\Acref{fig:alsk/app/tspinstance} est un exemple d'instance de \gls{TSP} avec \num{10} sommets pour
|
||||
lequel nous considérerons que les coûts sont les distances entre les deux sommets concernés
|
||||
(précisément la norme euclidienne).
|
||||
Deux solutions sont montrées dans \acref{fig:alsk/app/tspsolution}, celle de droite étant optimale.
|
||||
|
||||
Les algorithmes peuvent être évalués selon un critère de complexité, temporelle ou spatiale.
|
||||
Par extension, il est possible d'associer une complexité à un problème comme étant la meilleure de
|
||||
celles des algorithmes possibles permettant de le résoudre.
|
||||
Afin de catégoriser les problèmes en fonction de leur complexité, des classes de complexité ont été
|
||||
définies.
|
||||
Il existe par exemple la classe P dont les problèmes peuvent être résolus en temps
|
||||
polynomial, et sont donc considérés comme \og faciles \fg.
|
||||
En revanche, pour les problèmes de classe NP, ce n'est que la vérification d'une solution qui peut
|
||||
être faite en temps polynomial.
|
||||
Un problème NP-complet est un problème de classe NP qui est au moins aussi difficile que tous les
|
||||
autres problèmes de la classe NP et le \gls{TSP} est NP-complet : s'il est possible de vérifier une
|
||||
solution en temps polynomial, en trouver une est difficile.
|
||||
Cette catégorie de problèmes peut être traitée en \gls{RO} par des heuristiques et des
|
||||
métaheuristiques.
|
||||
|
||||
\newcommand*{\pointstotspstart}[2]{%
|
||||
\hypersetup{linkcolor=black}%
|
||||
\ocgmakeprefixes{#1}%
|
||||
\edef\prefixP{\ocgprefix-pointer}%
|
||||
\actionsocg{\prefixP}{}{}{#2}%
|
||||
\tikz[remember picture,baseline=-.5ex]{\coordinate(tsp start anchor);}%
|
||||
\begin{ocg}{\prefixP}{\prefixP}{0}%
|
||||
\foreach \tspstart in {0,...,9} {%
|
||||
\ifthenelse{\tspstart=0}{\def\state{1}}{\def\state{0}}%
|
||||
\ocgcase{\prefixI}{\prefixI-\tspstart}{\state}{\tikz[remember picture,overlay]{%
|
||||
\path[->,>=stealth,thick,dashed] (tsp start anchor) edge[bend right] (tsp node \tspstart);%
|
||||
}}%
|
||||
}%
|
||||
\end{ocg}%
|
||||
}
|
||||
\renewcommand*{\pointstotspstart}[2]{#2}%disabled
|
||||
|
||||
Le principe d'une heuristique est de trouver rapidement une solution au détriment de sa qualité.
|
||||
Un exemple d'heuristique est l'algorithme glouton (\cref{alg:alsk/app/greedy}).
|
||||
Appliqué au \gls{TSP}, celui-ci accepte en entrée une représentation du problème $P$ contenant
|
||||
notamment l'ensemble des sommets.
|
||||
Une solution est alors construite progressivement en lui ajoutant le sommet jugé optimal à chaque
|
||||
étape.
|
||||
\Acref{fig:alsk/app/tspgreedysolution} présente la solution obtenue par l'application de cet
|
||||
algorithme sur l'instance de la \acref{fig:alsk/app/tspinstance} en démarrant du
|
||||
\pointstotspstart{app/tspgreedysolution}{point grisé}.
|
||||
Il existe des variantes non déterministes, par exemple en considérant les $n > 1$ meilleurs ajouts
|
||||
possibles à chaque étape et en ajoutant l'un d'eux au hasard.
|
||||
|
||||
\begin{algorithm}
|
||||
\inputalg{app/greedy}
|
||||
{Algorithme glouton}
|
||||
\end{algorithm}
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{app/tspinstance}
|
||||
{Instance de \glsxtrshort{TSP}}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{app/tspsolution}
|
||||
{Solutions de l'instance de \glsxtrshort{TSP} de \acref{fig:alsk/app/tspinstance}}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\ocgfigRP{Solution TSP (glouton)}
|
||||
{app/tsptikzrp}{app/tspgreedysolution}
|
||||
{Solution d'une instance de \glsxtrshort{TSP} par un algorithme glouton}
|
||||
{\tspstart}{0/on,1/off,2/off,3/off,4/off,5/off,6/off,7/off,8/off,9/off}
|
||||
{circle,minimum size=5pt,inner sep=0pt}{tsp node \tspstart}
|
||||
{cliquer sur un sommet pour choisir le premier}
|
||||
\end{figure}
|
||||
|
||||
Une métaheuristique est une heuristique générique pouvant s'appliquer à différents problèmes sans
|
||||
changements importants de l'algorithme.
|
||||
Les exemples sont nombreux~\autocite{ref:toussaint2010} : recuit simulé, recherche tabou, recherche
|
||||
à voisinage variable, ...
|
||||
|
||||
Ceux qui vont nous intéresser particulièrement, étant utilisés comme exemples dans la suite de ce
|
||||
chapitre, sont :
|
||||
\begin{itemize}
|
||||
\item le \gls{GRASP} ;
|
||||
\item l'\gls{ILS} ;
|
||||
\item l'\gls{ELS}.
|
||||
\end{itemize}
|
||||
|
||||
Le \gls{GRASP}~\autocite{ref:feo1989} (\cref{alg:alsk/app/grasp}) consiste en la création de
|
||||
multiples solutions à différents endroits de l'espace des solutions (l'intérêt est amoindri si les
|
||||
solutions sont trop proches) suivie de l'amélioration par modifications successives (des
|
||||
déplacements \og locaux \fg dans l'espace des solutions).
|
||||
La création est accomplie par une heuristique constructive, par exemple un algorithme glouton non
|
||||
déterministe, et l'amélioration par une recherche locale.
|
||||
Une recherche locale consiste en l'exploration partielle ou complète du voisinage d'une solution
|
||||
dans l'espace des solutions.
|
||||
Le voisinage d'une solution est l'ensemble des solutions que l'on peut obtenir en appliquant une
|
||||
transformation sur celle-ci, aussi appelée mutation.
|
||||
% Une illustration commune de ceci est représentée dans \acref{fig:alsk/app/localmin}.
|
||||
% Dans celle-ci, la courbe est l'espace des solutions, et lorsque l'on cherche la solution dont la
|
||||
% valeur est minimale, une recherche locale sert à \og descendre \fg afin de trouver un minimum local,
|
||||
% voire un minimum global.
|
||||
|
||||
% \begin{figure}
|
||||
% \inputfig{app/localmin}
|
||||
% {Recherche locale au sein d'un espace de solutions quelconque}
|
||||
% \end{figure}
|
||||
|
||||
\begin{algorithm}
|
||||
\inputalg{app/grasp}
|
||||
{\Glsxtrshort{GRASP}}
|
||||
\end{algorithm}
|
||||
|
||||
Les transformations qu'il est possible de faire dépendent du problème : dans le cadre du \gls{TSP},
|
||||
il existe par exemple l'échange qui consiste en l'échange aléatoire de deux sommets dans la
|
||||
solution (voir \acref{fig:alsk/app/tspswap}).
|
||||
La descente est un exemple de recherche locale qui va remplacer la solution par son meilleur voisin
|
||||
jusqu'à ce qu'il n'existe pas de voisin au moins aussi intéressant.
|
||||
|
||||
\begin{figure}
|
||||
\ocgfigRP{Illustration d'échange de sommets d'une solution de TSP}
|
||||
{app/tsptikzrpii}{app/tspswap}
|
||||
{Échange de deux sommets d'une solution d'une instance de \glsxtrshort{TSP}}
|
||||
{\swapI}{0/off,1/off,2/off,3/off,4/on,5/off,6/off,7/off,8/off,9/off}
|
||||
{circle,minimum size=5pt,inner sep=0pt}{tsp node \swapI,tsp node \swapI'}
|
||||
{cliquer sur un sommet pour choisir un des sommets échangés}
|
||||
\end{figure}
|
||||
|
||||
Les différentes itérations de création (par heuristique constructive (HC)) et amélioration d'une
|
||||
solution (par recherche locale (RL)) sont indépendantes et peuvent donc être exécutées en parallèle.
|
||||
La sélection (S) de la solution doit en revanche être accomplie de manière séquentielle.
|
||||
|
||||
\Acref{fig:alsk/app/grasp} représente un \gls{GRASP} en tenant compte de cela.
|
||||
Les tâches à exécuter sont représentées par des cercles tandis que les triangles indiquent une
|
||||
section (ouverte par le triangle qui sépare le flot d'exécution, et fermée par le triangle qui les
|
||||
réunit) dont les flots d'exécutions peuvent être exécutés en parallèle.
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{app/grasp}
|
||||
{Schéma d'un \glsxtrshort{GRASP}}
|
||||
\end{figure}
|
||||
|
||||
L'\gls{ILS}~\autocite{ref:lourenco2003} (\cref{alg:alsk/app/ils}) améliore une solution $S$ plutôt
|
||||
que d'en créer une.
|
||||
Dans un premier temps, la solution $S$ donnée en paramètre est améliorée au moyen d'une recherche
|
||||
locale (initiale afin de la différencier de la recherche locale utilisée ensuite).
|
||||
L'amélioration de cette solution est ensuite effectuée en itérant $N$ fois l'amélioration par
|
||||
recherche locale d'une mutation de la solution courante $S$.
|
||||
À chaque itération, la solution courante est mise à jour pour prendre la nouvelle solution créée ou
|
||||
non en fonction d'un critère d'acceptation.
|
||||
Si cette solution est, par ailleurs, meilleure que la meilleure solution $S^{*}$ retenue
|
||||
jusqu'alors, elle la remplace.
|
||||
|
||||
\begin{algorithm}
|
||||
\inputalg{app/ils}
|
||||
{\Glsxtrshort{ILS}}
|
||||
\end{algorithm}
|
||||
|
||||
Chaque itération de cet algorithme dépendant du résultat de l'itération précédente, il n'est pas
|
||||
possible de le paralléliser.
|
||||
\Acref{fig:alsk/app/ils} représente cela par l'utilisation de carrés pour la boucle.
|
||||
Les tâches de mutation (M), de recherche locale (RL), de sélection (S) et de vérification du critère
|
||||
d'acceptation (A) sont ainsi exécutées séquentiellement à chaque itération, elles aussi exécutées en
|
||||
séquence.
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{app/ils}
|
||||
{Schéma d'un \glsxtrshort{ILS}}
|
||||
\end{figure}
|
||||
|
||||
Enfin, l'\gls{ELS}~\autocite{ref:wolf2007} (\cref{alg:alsk/app/els}) fonctionne de manière similaire
|
||||
à l'\gls{ILS}.
|
||||
On retrouve la recherche locale initiale et une boucle principale permettant d'améliorer une
|
||||
solution $S$ donnée en paramètre.
|
||||
À chaque itération, $M$ solutions sont générées par une mutation suivie d'une recherche locale et la
|
||||
meilleure, si elle vérifie le critère d'acceptation, est conservée pour l'itération suivante.
|
||||
|
||||
Cet algorithme est plus intéressant que le précédent quant à la parallélisation.
|
||||
Bien qu'il possède une boucle externe non parallélisable, la boucle interne peut l'être.
|
||||
\Acref{fig:alsk/app/els} présente ainsi une structure externe très semblable à
|
||||
\acref{fig:alsk/app/ils} dont la séquence \og mutation, recherche locale \fg{} est remplacée par une
|
||||
tâche plus complexe introduisant une boucle parallélisable.
|
||||
|
||||
\begin{figure}
|
||||
\inputfig{app/els}
|
||||
{Schéma d'un \glsxtrshort{ELS}}
|
||||
\end{figure}
|
||||
|
||||
Ces métaheuristiques peuvent également être combinées : \autocite{ref:prins2009a} a proposé
|
||||
\graspils{} et \graspels{}, des métaheuristiques \gls{GRASP} dont la recherche locale est,
|
||||
respectivement, \gls{ILS} et \gls{ELS}.
|
||||
C'est en particulier le \graspels{} qui va servir d'exemple dans ce chapitre pour illustrer
|
||||
l'utilisation des squelettes algorithmiques que nous proposons\footnote{Une bibliothèque
|
||||
implémentant des algorithmes de \gls{RO}, notamment le \graspels{}, fait partie des travaux
|
||||
effectués durant la thèse (\url{https://phd.pereda.fr/dev/rosa}).}.
|
||||
Sa structure générale possède deux niveaux de boucles parallélisables entrecoupés par un niveau de
|
||||
boucle devant être exécuté séquentiellement, ce qui en fait une application intéressante pour la
|
||||
validation de notre modèle.
|
||||
|
||||
\begin{algorithm}
|
||||
\inputalg{app/els}
|
||||
{\Glsxtrshort{ELS}}
|
||||
\end{algorithm}
|
7
src/alsk/3_concept.tex
Normal file
7
src/alsk/3_concept.tex
Normal file
@ -0,0 +1,7 @@
|
||||
\section{Conception}
|
||||
|
||||
\inputsrc{concept/0_intro}
|
||||
\inputsrc{concept/1_struct}
|
||||
\inputsrc{concept/2_links}
|
||||
\inputsrc{concept/3_inst}
|
||||
\inputsrc{concept/4_parheight}
|
8
src/alsk/4_exec.tex
Normal file
8
src/alsk/4_exec.tex
Normal file
@ -0,0 +1,8 @@
|
||||
\section{Politique d'exécution}
|
||||
\label{sec:alsk/exec}
|
||||
|
||||
\inputsrc{exec/0_intro}
|
||||
\inputsrc{exec/1_bones}
|
||||
\inputsrc{exec/2_ident}
|
||||
\inputsrc{exec/3_executor}
|
||||
\inputsrc{exec/4_impl}
|
7
src/alsk/5_repeat.tex
Normal file
7
src/alsk/5_repeat.tex
Normal file
@ -0,0 +1,7 @@
|
||||
\section{Répétabilité}
|
||||
\label{sec:alsk/repeatability}
|
||||
|
||||
\inputsrc{repeat/0_intro}
|
||||
\inputsrc{repeat/1_repeat}
|
||||
\inputsrc{repeat/2_opti}
|
||||
\inputsrc{repeat/3_results}
|
4
src/alsk/6_usage.tex
Normal file
4
src/alsk/6_usage.tex
Normal file
@ -0,0 +1,4 @@
|
||||
\section{Utilisation}
|
||||
|
||||
\inputsrc{usage/1_edsl}
|
||||
\inputsrc{usage/2_impl}
|
298
src/alsk/7_results.tex
Normal file
298
src/alsk/7_results.tex
Normal file
@ -0,0 +1,298 @@
|
||||
\section{Performances}
|
||||
|
||||
%{{{ Introduction "
|
||||
Cette section présente des mesures de temps d'exécution de programmes utilisant la bibliothèque
|
||||
présentée dans ce chapitre.
|
||||
Toutes les mesures ont été effectuées sur une machine dotée d'un Intel Xeon E7-8890 v3, cadencé à
|
||||
\SI{2.5}{\GHz} et ayant \num{72} cœurs physiques (\num{18} processeurs ayant chacun \num{4} cœurs
|
||||
physiques).
|
||||
Les programmes sont compilés en utilisant GCC (\texttt{g++}) 8.2.0 avec notamment le pack
|
||||
d'optimisations \texttt{O2}.
|
||||
Les valeurs données dans ce document sont obtenues par une moyenne sur \num{20} exécutions en
|
||||
utilisant des états initiaux différents pour les \gls{PRNG} (les mêmes \num{20} états sont utilisés
|
||||
à chaque fois).
|
||||
Lorsque cela est pertinent (notamment, suffisamment visible), l'intervalle de confiance à
|
||||
\SI{99}{\percent} est affiché.
|
||||
Pour ce qui est des exécutions, nous avons réglé l'affinité du processus de sorte que pour chaque
|
||||
processeur, au maximum un cœur soit utilisé.
|
||||
Cela limite donc à \num{18} cœurs pour protéger d'un biais de mesure potentiel dû à l'utilisation
|
||||
simultanée de plusieurs cœurs d'un même processeur.
|
||||
|
||||
Un objectif important que devait atteindre cette bibliothèque est d'être compétitive, en termes de
|
||||
temps d'exécution par rapport à une solution écrite directement par un développeur.
|
||||
En effet, une abstraction est moins intéressante si elle implique un fort surcoût.
|
||||
Pour cette raison, nous avons utilisé le langage C++ et la métaprogrammation template qui
|
||||
permettent, lorsqu'ils sont correctement utilisés, de s'approcher d'une implémentation manuelle en
|
||||
ce qui concerne le temps d'exécution.
|
||||
|
||||
Pour évaluer cela, nous avons comparé les temps d'exécution de programmes écrits en utilisant la
|
||||
bibliothèque (et en utilisant différentes politiques d'exécution) par rapport aux temps d'exécution
|
||||
de programmes équivalents écrits sans utiliser cette bibliothèque.
|
||||
Ces programmes implémentent un \graspels{} dans le but de résoudre des instances de \gls{TSP} de
|
||||
\num{38} sommets et de \num{194} sommets, ils utilisent donc des nombres pseudo-aléatoires.
|
||||
Afin de s'assurer de la pertinence des temps mesurés, nous avons donc fait en sorte de garantir la
|
||||
répétabilité des programmes écrits sans utiliser la bibliothèque.
|
||||
Pour les versions l'utilisant, la répétabilité est obtenue sans effort.
|
||||
|
||||
Dans cette section, nous utiliserons trois variables $N$, $O$ et $I$ qui correspondront
|
||||
respectivement au nombre d'itérations (parallélisables) du \gls{GRASP}, au nombre d'itérations (non
|
||||
parallélisables) de la boucle extérieure de l'\gls{ELS} et au nombre d'itérations (parallélisables)
|
||||
de la boucle intérieure de l'\gls{ELS}.
|
||||
|
||||
Toutes les mesures sont effectuées pour quatre politiques d'exécutions différentes lorsque la
|
||||
bibliothèque est utilisée :
|
||||
\begin{itemize}
|
||||
\item \og firstlevel \fg, qui ne parallélise que le premier niveau pouvant être exécuté en
|
||||
parallèle ;
|
||||
\item \og staticpool \fg, qui utilise un \en{thread pool} en associant à une tâche un
|
||||
\en{thread} en fonction de son identifiant et en équilibrant les multiples niveaux parallèles
|
||||
comme décrit dans \acref{sec:alsk/exec} ;
|
||||
\item \og dynamicpool \fg, qui utilise un \en{thread pool} utilisé de manière classique ;
|
||||
\item \og thread \fg, qui applique l'équilibrage des multiples niveaux parallèles de
|
||||
\acref{sec:alsk/exec} en créant des \en{threads} dynamiquement.
|
||||
\end{itemize}
|
||||
%}}}
|
||||
|
||||
%{{{ Sequential "
|
||||
Bien que l'objectif principal de cette bibliothèque soit d'aider à l'écriture de programmes
|
||||
parallèles, elle peut également être utilisée pour produire des programmes séquentiels en
|
||||
choisissant une politique d'exécution appropriée.
|
||||
Cela peut par exemple être utile à des fins de débugage, mais aussi pour effectuer des mesures de
|
||||
performance dans certains domaines scientifiques où les comparaisons sont généralement effectuées
|
||||
sur des programmes séquentiels.
|
||||
Nous avons donc dans un premier temps mesuré les temps d'exécution de programmes séquentiels.
|
||||
|
||||
\Acref{fig:alsk/results/rt_graspels_dj38_24_20_20_seq,fig:alsk/results/rt_graspels_qa194_24_20_20_seq}
|
||||
montrent les temps d'exécution de programmes séquentiels avec $N = 24$, $O = 20$ et $I = 20$.
|
||||
Les étiquettes préfixées de \og hw \fg{} correspondent aux programmes écrits sans utiliser la
|
||||
bibliothèque tandis que celles préfixées de \og sk \fg{} indiquent ceux l'utilisant.
|
||||
L'étiquette \og hw\_seq \fg{} est associée au programme écrit pour une exécution séquentielle.
|
||||
Quant à \og hw\_par \fg{}, il s'agit d'un programme écrit pour une exécution parallèle, bien que
|
||||
l'exécution sera effectivement séquentielle puisqu'un seul cœur est affecté.
|
||||
|
||||
Quelle que soit la politique d'exécutions utilisée pour les versions employant les squelettes
|
||||
algorithmiques, l'exécution sera également obligatoirement séquentielle en pratique puisqu'un seul
|
||||
cœur est affecté comme pour \og hw\_par \fg{}.
|
||||
|
||||
\Acref{fig:alsk/results/rt_graspels_dj38_24_20_20_seq} correspond aux temps d'exécution pour une
|
||||
instance de \gls{TSP} ayant \num{38} sommets et il s'agit d'une instance ayant \num{194} sommets
|
||||
pour \acref{fig:alsk/results/rt_graspels_qa194_24_20_20_seq}.
|
||||
Pour une petite instance (\num{38} sommets), on observe de légères variations, cependant la courte
|
||||
durée d'exécution ne permet pas de conclure clairement, sinon que l'utilisation de la bibliothèque
|
||||
n'engendre pas de surcoût significatif même pour des tâches courtes.
|
||||
|
||||
Les temps mesurés pour la seconde instance (\num{194} sommets) sont particulièrement proches pour
|
||||
les programmes écrits sans et avec la bibliothèque à l'exception des politiques d'exécution \og
|
||||
staticpool \fg{} et \og thread \fg.
|
||||
Ainsi, à nouveau, on observe que la politique d'exécution séquentielle permet d'obtenir des
|
||||
exécutions de durées quasiment identiques à ce que l'on peut atteindre sans utiliser la
|
||||
bibliothèque.
|
||||
À l'inverse, l'utilisation d'une autre politique d'exécution dans un contexte séquentiel (parce
|
||||
qu'un seul cœur est disponible) peut en revanche être coûteux.
|
||||
En effet, celles-ci peuvent avoir besoin de mettre en place des mécanismes, lesquels ne sont
|
||||
généralement pas optimisés pour le cas d'une exécution séquentielle.
|
||||
|
||||
Afin de garantir la répétabilité y compris lorsqu'un seul \en{thread} est possible, l'implémentation
|
||||
des politiques d'exécution doit dans ce cas également produire un comportement cohérent, privant
|
||||
celle-ci d'éventuelles optimisations.
|
||||
Cela explique par ailleurs pourquoi la bibliothèque n'utilise pas automatiquement la politique
|
||||
d'exécution séquentielle lorsque le nombre de cœurs alloués est de \num{1}.
|
||||
Néanmoins, dans le cas où la répétabilité n'a pas besoin d'être assurée au point d'avoir le même
|
||||
déroulement entre une exécution séquentielle et une exécution parallèle, alors il est avisé de la
|
||||
part du développeur d'utiliser la politique d'exécution séquentielle lorsqu'il n'y a qu'un cœur.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_dj38_24_20_20_seq.pdf}
|
||||
\caption{Temps d'exécution séquentielle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{38} sommets}
|
||||
\label{fig:alsk/results/rt_graspels_dj38_24_20_20_seq}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_24_20_20_seq.pdf}
|
||||
\caption{Temps d'exécution séquentielle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{194} sommets}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_24_20_20_seq}
|
||||
\end{figure}
|
||||
%}}}
|
||||
|
||||
%{{{ Parallel "
|
||||
%{{{ var cores "
|
||||
\Acref{fig:alsk/results/rt_graspels_dj38_24_20_20_par,fig:alsk/results/rt_graspels_qa194_24_20_20_par}
|
||||
présentent les temps d'exécution de programmes parallèles avec $N = 24$, $O = 20$ et $I = 20$.
|
||||
La première étiquette, \og hw\_par \fg, correspond au programme écrit sans utiliser la
|
||||
bibliothèque pour une exécution parallèle.
|
||||
Les étiquettes préfixées par \og sk \fg{} correspondent à des programmes écrits en utilisant la
|
||||
bibliothèque et en utilisant différentes politiques d'exécution.
|
||||
La seconde partie de chaque étiquette indique quelle politique d'exécution est utilisée.
|
||||
|
||||
Pour une instance de \gls{TSP} ayant \num{38} sommets, on obtient les résultats présentés par
|
||||
\acref{fig:alsk/results/rt_graspels_dj38_24_20_20_par}.
|
||||
On observe globalement des performances similaires et surtout une décroissance stable du temps
|
||||
d'exécution avec l'augmentation du nombre de cœurs.
|
||||
La politique d'exécution \og staticpool \fg{} semble particulièrement efficace.
|
||||
Cela se justifie par l'absence de sections critiques (contrairement à ce que l'on a avec \og
|
||||
dynamicpool \fg) et la réutilisation des \en{threads} créés (contrairement à ce que fait \og
|
||||
thread \fg).
|
||||
La répartition des tâches est également un peu meilleure que celle de \og firstlevel \fg{} pour les
|
||||
dernières itérations de la boucle principale du \gls{GRASP} lorsqu'il y a un reste à la division de
|
||||
$N$ par le nombre de cœurs disponibles.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_dj38_24_20_20_par.pdf}
|
||||
\caption{Temps d'exécution parallèle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{38} sommets}
|
||||
\label{fig:alsk/results/rt_graspels_dj38_24_20_20_par}
|
||||
\end{figure}
|
||||
|
||||
Lorsque l'on travaille sur une instance de \gls{TSP} avec \num{194} sommets, on observe les
|
||||
résultats présentés dans \acref{fig:alsk/results/rt_graspels_qa194_24_20_20_par}.
|
||||
Ils sont dans l'ensemble équivalents aux précédents, ce qui confirme une certaine indépendance des
|
||||
performances obtenues par rapport à la taille des données traitées.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_24_20_20_par.pdf}
|
||||
\caption{Temps d'exécution parallèle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{194} sommets}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_24_20_20_par}
|
||||
\end{figure}
|
||||
%}}}
|
||||
|
||||
%{{{ var grasp_n "
|
||||
En faisant varier $N$ de \num{4} à \num{20} par pas de \num{4}, on obtient les courbes de
|
||||
\acref{fig:alsk/results/rt_graspels_qa194_4:20_20_20_par}.
|
||||
En particulier pour $N=4$ (\cref{fig:alsk/results/rt_graspels_qa194_4_20_20_par}), $N=8$
|
||||
(\cref{fig:alsk/results/rt_graspels_qa194_8_20_20_par}) et $N=12$
|
||||
(\cref{fig:alsk/results/rt_graspels_qa194_12_20_20_par}) pour lesquels c'est très visible, on
|
||||
observe une limite dans l'accélération obtenue pour \og firstlevel \fg.
|
||||
Ce résultat est logique puisque la politique d'exécution utilisée dans ce cas ne parallélisant que
|
||||
le premier niveau possible, si celui-ci correspond à une boucle de $k$ itérations l'accélération
|
||||
maximale que l'on peut obtenir est de $k$.
|
||||
Les autres politiques d'exécution se comportent de la même manière, indépendamment du nombre
|
||||
d'itérations du \gls{GRASP}, ce qui est attendu puisque toutes les trois sont capables de
|
||||
paralléliser de multiples niveaux et donc de tirer profit des itérations parallélisables de
|
||||
l'\gls{ELS} (au nombre fixe de $I=20$).
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\foreach \n in {4,8,...,20} {
|
||||
\begin{subfigure}[b]{.49\textwidth}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_v\n_20_20_par.pdf}
|
||||
\caption{$N = \n$}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_\n_20_20_par}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
}
|
||||
\begin{subfigure}[b]{.49\textwidth}
|
||||
\centering
|
||||
\hspace{2em}
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_var_grasp_par_legend.pdf}
|
||||
\vspace{12ex}
|
||||
\end{subfigure}
|
||||
\caption{Temps d'exécution parallèle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{194} sommets selon
|
||||
le nombre d'itérations du \glsxtrshort{GRASP}}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_4:20_20_20_par}
|
||||
\end{figure}
|
||||
%}}}
|
||||
|
||||
%{{{ var els iter max "
|
||||
Nous avons voulu vérifier l'effet de la variation du nombre d'itérations de la boucle centrale non
|
||||
parallélisable (la boucle extérieure de l'\gls{ELS} dont le nombre d'itérations est $O$).
|
||||
Les courbes présentées dans \acref{fig:alsk/results/rt_graspels_qa194_4_1:50_20_par} correspondent à
|
||||
des mesures de temps d'exécution pour $N=4$ et $O$ variant entre $1$ et $50$.
|
||||
Ces courbes permettent d'observer que d'une manière globale, le comportement reste similaire.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\foreach \n in {1,4,8,40,50} {
|
||||
\begin{subfigure}[b]{.49\textwidth}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_4_v\n_20_par.pdf}
|
||||
\caption{$O = \n$}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_4_\n_20_par}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
}
|
||||
\begin{subfigure}[b]{.49\textwidth}
|
||||
\centering
|
||||
\hspace{2em}
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_var_els_iter_max_par_legend.pdf}
|
||||
\vspace{12ex}
|
||||
\end{subfigure}
|
||||
\caption{Temps d'exécution parallèle d'un \graspels{} pour une instance de \glsxtrshort{TSP} de \num{194} sommets selon
|
||||
le nombre d'itérations non parallélisables de l'\glsxtrshort{ELS}}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_4_1:50_20_par}
|
||||
\end{figure}
|
||||
%}}}
|
||||
|
||||
%{{{ speedup "
|
||||
Enfin, sur la base des données précédentes,
|
||||
\acref{fig:alsk/results/rt_graspels_qa194_4_20_20_speedup,fig:alsk/results/rt_graspels_qa194_20_20_20_speedup}
|
||||
présentent l'accélération obtenue pour les différentes politiques d'exécution (ainsi que pour une
|
||||
parallélisation sans utiliser la bibliothèque) en fonction du nombre de cœurs alloués.
|
||||
\Acref{fig:alsk/results/rt_graspels_qa194_4_20_20_speedup} correspond à l'exécution d'un \graspels{}
|
||||
pour lequel $N=4$, c'est-à-dire que la boucle principale du \gls{GRASP} effectue $4$ itérations qui
|
||||
peuvent être parallélisées.
|
||||
Les valeurs de $O$ et $I$ sont conservées à la valeur par défaut utilisée durant cette section, à
|
||||
savoir $20$ pour les deux.
|
||||
Lorsque $N=4$, on observe en particulier que la parallélisation en utilisant une politique
|
||||
d'exécution ne traitant qu'un niveau est limitée en accélération à la valeur atteinte lorsque le
|
||||
nombre de cœurs alloués égale $N$, ce qui n'est pas surprenant.
|
||||
Par ailleurs, l'accélération obtenue en utilisant la politique d'exécution par \en{thread pool} \og
|
||||
statique \fg{} semble être généralement meilleure que les autres.
|
||||
Dans tous les cas, on observe que l'accélération croît effectivement lorsque le nombre de cœurs
|
||||
alloués croît.
|
||||
|
||||
\begin{figure}
|
||||
\ocgfigIG{Accélération en fonction du nombre de coeurs alloués}
|
||||
{results/rt_graspels_qa194_4_20_20_speedup}{rt_graspels_qa194_}{_20_20_speedup.pdf}
|
||||
{Accélération en fonction du nombre de cœurs alloués (\graspels{} avec $N=4$, \glsxtrshort{TSP} de \num{194} sommets)}
|
||||
{$N$ :}{\N}{4/on,8/off,12/off,16/off}
|
||||
\end{figure}
|
||||
|
||||
\Acref{fig:alsk/results/rt_graspels_qa194_20_20_20_speedup} correspond quant à elle à l'exécution
|
||||
d'un \graspels{} avec $N=20$.
|
||||
Le comportement global est conservé et l'accélération obtenue est proportionnelle au nombre de cœurs
|
||||
alloués.
|
||||
Pour la politique d'exécution \og sk\_firstlevel \fg{}, l'accélération obtenue n'atteint logiquement
|
||||
plus un plafond puisque le nombre de cœurs alloués n'atteint pas, durant ces mesures, la valeur de
|
||||
$N$.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_20_20_20_speedup.pdf}
|
||||
\caption{Accélération en fonction du nombre de cœurs alloués (\graspels{} avec $N=20$,
|
||||
\glsxtrshort{TSP} de \num{194} sommets)}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_20_20_20_speedup}
|
||||
\end{figure}
|
||||
|
||||
\Acref{fig:alsk/results/rt_graspels_qa194_all_20_20_speedup_1,fig:alsk/results/rt_graspels_qa194_all_20_20_speedup_16}
|
||||
montrent l'accélération obtenue en fonction de la valeur de $N$ pour un nombre de cœurs alloués
|
||||
défini, respectivement \num{1} et \num{18}.
|
||||
Dans \acref{fig:alsk/results/rt_graspels_qa194_all_20_20_speedup_1}, on observe donc le comportement
|
||||
des politiques d'exécution lorsqu'elles sont utilisées pour une exécution séquentielle.
|
||||
Cela confirme les remarques précédentes à propos de la politique \og sk\_staticpool \fg{} qui
|
||||
apparaît comme étant la moins efficace dans ce contexte précis.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics{img/alsk/rt_graspels_qa194_all_20_20_speedup_1.pdf}
|
||||
\caption{Accélération en fonction de $N$ pour \num{1} cœur alloué (\graspels{}, \glsxtrshort{TSP} de \num{194} sommets)}
|
||||
\label{fig:alsk/results/rt_graspels_qa194_all_20_20_speedup_1}
|
||||
\end{figure}
|
||||
|
||||
En revanche, dans \acref{fig:alsk/results/rt_graspels_qa194_all_20_20_speedup_16} on vérifie que
|
||||
pour toute valeur de $N$ cette politique d'exécution est meilleure.
|
||||
Cela semble indiquer que le fait d'effectuer une partie du travail durant la compilation et de
|
||||
déterminer à l'avance à quel \en{thread} affecter chaque tâche affecte favorablement les
|
||||
performances du programme.
|
||||
|
||||
\begin{figure}
|
||||
\ocgfigIG{Accélération en fonction du nombre d'itérations}
|
||||
{results/rt_graspels_qa194_all_20_20_speedup_16}{rt_graspels_qa194_all_20_20_speedup_}{.pdf}
|
||||
{Accélération en fonction de $N$ pour \num{18} cœurs alloués (\graspels{}, \glsxtrshort{TSP} de \num{194} sommets)}
|
||||
{nombre de cœurs :}{\T}{2/off,4/off,6/off,8/off,10/off,12/off,14/off,16/off,18/on}
|
||||
\end{figure}
|
||||
%}}}
|
||||
%}}}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user