From c342491666628ef17f4777f387efba3916a47631 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Keck <Jean-Baptiste.Keck@imag.fr> Date: Sat, 18 Apr 2020 11:26:55 +0200 Subject: [PATCH] lexicographical topological sort --- CMakeLists.txt | 4 +- ci/docker_images/ubuntu/bionic/Dockerfile | 320 ++++++++-------------- hysop/core/graph/graph.py | 14 +- hysop/core/graph/graph_builder.py | 9 +- hysop/core/graph/tests/test_graph.py | 8 +- hysop/numerics/fft/_mkl_fft.py | 3 +- requirements.txt | 1 + 7 files changed, 140 insertions(+), 219 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3274ee31f..dbdad4951 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,10 +147,12 @@ find_python_module(tee REQUIRED) find_python_module(colors REQUIRED) # ansicolor package find_python_module(argparse_color_formatter REQUIRED) find_python_module(primefac REQUIRED) -find_python_module(graph_tool REQUIRED) +find_python_module(networkx REQUIRED) find_python_module(pyfftw REQUIRED) find_python_module(backports.weakref REQUIRED) # python-backports.weakref #find_python_module(backports.functools-lru-cache REQUIRED) # python-backports.functools-lru-cache +find_python_module(matplotlib OPTIONAL) +find_python_module(pyvis OPTIONAL) find_package( OpenCL ) if(${OpenCL_LIBRARY}) # Some opencl related python package fails to import on non OpenCL machines (cluster's frontend for instance) diff --git a/ci/docker_images/ubuntu/bionic/Dockerfile b/ci/docker_images/ubuntu/bionic/Dockerfile index 9f1153b4d..28363a675 100644 --- a/ci/docker_images/ubuntu/bionic/Dockerfile +++ b/ci/docker_images/ubuntu/bionic/Dockerfile @@ -2,247 +2,153 @@ FROM ubuntu:bionic MAINTAINER Jean-Baptiste.Keck@imag.fr +# parallel builds +ARG NTHREADS +ENV MAKEFLAGS "-j${NTHREADS}" + # upgrade initial image ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get full-upgrade -y # get build tools and required libraries -RUN apt-get install -y expat -RUN apt-get install -y unzip -RUN apt-get install -y xz-utils -RUN apt-get install -y automake -RUN apt-get install -y libtool -RUN apt-get install -y pkg-config -RUN apt-get install -y cmake -RUN apt-get install -y git -RUN apt-get install -y vim -RUN apt-get install -y ssh -RUN apt-get install -y clang -RUN apt-get install -y gcc -RUN apt-get install -y gfortran -RUN apt-get install -y cython -RUN apt-get install -y swig -RUN apt-get install -y lsb-core -RUN apt-get install -y cpio -RUN apt-get install -y libnuma1 -RUN apt-get install -y libpciaccess0 -RUN apt-get install -y libreadline-dev -RUN apt-get install -y libboost-all-dev -RUN apt-get install -y libblas-dev -RUN apt-get install -y liblapack-dev -RUN apt-get install -y libcgal-dev -RUN apt-get install -y libatlas-base-dev -RUN apt-get install -y libopenblas-dev -RUN apt-get install -y libgfortran3 -RUN apt-get install -y libgcc1 -RUN apt-get install -y libopenmpi-dev -RUN apt-get install -y libhdf5-openmpi-dev -RUN apt-get install -y libfftw3-dev -RUN apt-get install -y libfftw3-mpi-dev -RUN apt-get install -y libgmp-dev -RUN apt-get install -y libmpfr-dev -RUN apt-get install -y libmpc-dev -RUN apt-get install -y libsparsehash-dev -RUN apt-get install -y libcairo-dev -RUN apt-get install -y libcairomm-1.0-dev -RUN apt-get install -y python -RUN apt-get install -y python-dev -RUN apt-get install -y python-pip -RUN apt-get install -y python-tk -RUN apt-get install -y opencl-headers -RUN apt-get install -y ocl-icd-libopencl1 -RUN apt-get install -y clinfo - -# python packages +RUN apt-get install -y expat unzip xz-utils automake libtool pkg-config cmake git vim ssh clang gcc gfortran cython swig lsb-core cpio libnuma1 libpciaccess0 libreadline-dev libboost-all-dev libblas-dev liblapack-dev libcgal-dev libatlas-base-dev libopenblas-dev libgfortran3 libgcc1 libopenmpi-dev libhdf5-openmpi-dev libfftw3-dev libfftw3-mpi-dev libgmp-dev libmpfr-dev libmpc-dev libsparsehash-dev libcairo-dev libcairomm-1.0-dev python python-dev python-pip python-tk opencl-headers ocl-icd-libopencl1 clinfo + +# python packages using pip RUN pip install --upgrade pip -RUN pip install --upgrade setuptools -RUN pip install --upgrade backports.weakref -RUN pip install --upgrade backports.tempfile -RUN pip install --upgrade cffi -RUN pip install --upgrade wheel -RUN pip install --upgrade pytest -RUN pip install --upgrade numpy -RUN pip install --upgrade scipy -RUN pip install --upgrade sympy -RUN pip install --upgrade matplotlib -RUN pip install --upgrade mpi4py +RUN pip install --upgrade numpy setuptools cffi wheel pytest +RUN pip install --upgrade backports.weakref backports.tempfile scipy sympy matplotlib mpi4py gmpy2 psutil py-cpuinfo Mako subprocess32 editdistance portalocker colors.py tee primefac pycairo weave argparse_color_formatter networkx pyvis RUN CC=mpicc HDF5_MPI="ON" pip install --upgrade --no-binary=h5py h5py -RUN pip install --upgrade gmpy2 -RUN pip install --upgrade psutil -RUN pip install --upgrade py-cpuinfo -RUN pip install --upgrade Mako -RUN pip install --upgrade subprocess32 -RUN pip install --upgrade editdistance -RUN pip install --upgrade portalocker -RUN pip install --upgrade colors.py -RUN pip install --upgrade tee -RUN pip install --upgrade primefac -RUN pip install --upgrade pycairo -RUN pip install --upgrade weave -RUN pip install --upgrade argparse_color_formatter -RUN pip install --upgrade numba -RUN pip install --upgrade poetry # For documentation -# RUN pip install --upgrade sphinx -# RUN pip install --upgrade sphinxcontrib-bibtex -# RUN pip install --upgrade sphinx_bootstrap_theme -# RUN pip install --upgrade strip-hints -# RUN cd /tmp && git clone https://github.com/sphinx-contrib/doxylink.git && cd doxylink/sphinxcontrib/doxylink \ -# && mv doxylink.py doxylink.py3 && strip-hints doxylink.py3 > doxylink.py && rm doxylink.py3 \ -# && mv parsing.py parsing.py3 && strip-hints parsing.py3 > parsing.py && rm parsing.py3 \ -# && cd ../.. && python setup.py install - - -# scitools (python-scitools does not exist on ubuntu:bionic) -RUN cd /tmp \ - && git clone https://github.com/hplgit/scitools \ - && cd scitools \ - && pip install . \ - && cd - \ - && rm -Rf /tmp/scitools +# RUN pip install --upgrade sphinx sphinxcontrib-bibtex sphinx_bootstrap_theme strip-hints +# RUN cd /tmp git clone https://github.com/sphinx-contrib/doxylink.git cd doxylink/sphinxcontrib/doxylink && \ +# mv doxylink.py doxylink.py3 strip-hints doxylink.py3 > doxylink.py rm doxylink.py3 && \ +# mv parsing.py parsing.py3 strip-hints parsing.py3 > parsing.py rm parsing.py3 && \ +# cd ../.. python setup.py install + +# llvm + numba + llvmlite (llvmlite 0.32 has a bug with llvm8) +RUN apt-get install -y llvm-8-dev libclang-8-dev clang-8 +ENV LLVM_CONFIG=llvm-config-8 +RUN pip install --upgrade numba llvmlite==0.31.0 # patchelf -RUN cd /tmp \ - && git clone https://github.com/NixOS/patchelf \ - && cd patchelf \ - && ./bootstrap.sh \ - && ./configure \ - && make \ - && make install \ - && cd - \ - && rm -Rf /tmp/patchelf - -RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \ - && echo 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' >> /etc/apt/sources.list \ - && echo 'deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main' >> /etc/apt/sources.list \ - && apt-get update \ - && apt-get install --assume-yes llvm-3.9 clang-3.9 libllvm3.9 libclang-3.9-dev +RUN cd /tmp && \ + git clone https://github.com/NixOS/patchelf && \ + cd patchelf && \ + ./bootstrap.sh && \ + ./configure && \ + make && \ + make install && \ + cd - && \ + rm -Rf /tmp/patchelf # Intel OpenCl -RUN cd /tmp \ -&& mkdir intel \ -&& cd intel \ -&& wget http://registrationcenter-download.intel.com/akdlm/irc_nas/12556/opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz \ -&& tar -xvzf opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz \ -&& cd opencl_runtime_16.1.2_x64_rh_6.4.0.37 \ -&& ls -la \ -&& sed -i "s/ACCEPT_EULA=decline/ACCEPT_EULA=accept/g" "silent.cfg" \ -&& ./install.sh --silent ./silent.cfg \ -&& cd /tmp \ -&& rm -Rf /tmp/intel +RUN cd /tmp && \ + mkdir intel && \ + cd intel && \ + wget http://registrationcenter-download.intel.com/akdlm/irc_nas/12556/opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz && \ + tar -xvzf opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz && \ + cd opencl_runtime_16.1.2_x64_rh_6.4.0.37 && \ + ls -la && \ + sed -i "s/ACCEPT_EULA=decline/ACCEPT_EULA=accept/g" "silent.cfg" && \ + ./install.sh --silent ./silent.cfg && \ + cd /tmp && \ + rm -Rf /tmp/intel # Fix OpenCl ICD RUN ln -s /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /usr/lib/x86_64-linux-gnu/libOpenCL.so RUN ldconfig # pyopencl -RUN cd /tmp \ -&& pip install pybind11 \ -&& git clone https://github.com/inducer/pyopencl \ -&& cd pyopencl \ -&& git submodule update --init \ -&& ./configure.py \ -&& make \ -&& pip install --upgrade . \ -&& cd - \ -&& rm -Rf /tmp/pyopencl +RUN cd /tmp && \ + pip install pybind11 && \ + git clone https://github.com/inducer/pyopencl && \ + cd pyopencl && \ + git submodule update --init && \ + ./configure.py && \ + make && \ + pip install --upgrade . && \ + cd - && \ + rm -Rf /tmp/pyopencl # oclgrind -RUN apt-get install --assume-yes --allow-unauthenticated llvm-6.0 clang-6.0 libllvm6.0 libclang-6.0-dev -RUN cd /tmp \ - && git clone https://github.com/jrprice/Oclgrind \ - && cd Oclgrind \ - && mkdir build \ - && cd build \ - && cmake -DCMAKE_BUILD_TYPE=Release .. \ - && make \ - && make install \ - && cd - \ - && rm -Rf /tmp/Oclgrind +RUN cd /tmp && \ + git clone https://github.com/jrprice/Oclgrind && \ + cd Oclgrind && \ + mkdir build && \ + cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release .. && \ + make && \ + make install && \ + cd - && \ + rm -Rf /tmp/Oclgrind # clpeak -RUN cd /tmp \ - && git clone https://github.com/krrishnarraj/clpeak \ - && cd clpeak/ \ - && mkdir build \ - && cd build/ \ - && cmake .. \ - && make \ - && mv clpeak /usr/local/bin/ \ - && cd - \ - && rm -Rf /tmp/clpeak +RUN cd /tmp && \ + git clone https://github.com/krrishnarraj/clpeak && \ + cd clpeak/ && \ + mkdir build && \ + cd build/ && \ + cmake .. && \ + make && \ + mv clpeak /usr/local/bin/ && \ + cd - && \ + rm -Rf /tmp/clpeak # clFFT -RUN cd /tmp \ - && ln -s /usr/local/lib /usr/local/lib64 \ - && git clone https://github.com/clMathLibraries/clFFT \ - && cd clFFT \ - && cd src \ - && mkdir build \ - && cd build \ - && cmake -DCMAKE_BUILD_TYPE=Release .. \ - && make \ - && make install \ - && cd - \ - && rm -Rf /tmp/clFFT +RUN cd /tmp && \ + ln -s /usr/local/lib /usr/local/lib64 && \ + git clone https://github.com/clMathLibraries/clFFT && \ + cd clFFT && \ + cd src && \ + mkdir build && \ + cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release .. && \ + make && \ + make install && \ + cd - && \ + rm -Rf /tmp/clFFT # gpyFFT -RUN cd /tmp \ - && git clone https://github.com/geggo/gpyfft \ - && cd gpyfft \ - && pip install . \ - && cd - \ - && rm -Rf /tmp/gpyfft - -# python graphtools -RUN cd /tmp \ - && wget https://downloads.skewed.de/graph-tool/graph-tool-2.26.tar.bz2 \ - && tar -xvjf graph-tool-2.26.tar.bz2 \ - && cd graph-tool-2.26 \ - && ./autogen.sh \ - && mkdir pycairo   \ - && find /usr/ -name 'pycairo.h' -exec cp {} ./pycairo/pycairo.h \; \ - && CPPFLAGS=-I. ./configure \ - && CPPFLAGS=-I. make -j16 \ - && make install \ - && cd - \ - && rm -Rf /tmp/graph-tool-2.26 +RUN cd /tmp && \ + git clone https://github.com/geggo/gpyfft && \ + cd gpyfft && \ + pip install . && \ + cd - && \ + rm -Rf /tmp/gpyfft # pyfftw (with R2R transforms - experimental branch) -RUN cd /tmp \ - && git clone https://github.com/drwells/pyFFTW \ - && cd pyFFTW \ - && git checkout r2r-try-two \ - && sed -i 's/\(fftw3[fl]\?_\)threads/\1omp/g' setup.py \ - && pip install . \ - && cd - \ - && rm -Rf /tmp/pyFFTW +RUN cd /tmp && \ + git clone https://github.com/drwells/pyFFTW && \ + cd pyFFTW && \ + git checkout r2r-try-two && \ + sed -i 's/\(fftw3[fl]\?_\)threads/\1omp/g' setup.py && \ + pip install . && \ + cd - && \ + rm -Rf /tmp/pyFFTW # HPTT (CPU tensor permutation library) -RUN cd /tmp - && git clone https://gitlab.com/keckj/hptt \ - && cd hptt \ - && mkdir build \ - && cd build \ - && cmake -DCMAKE_BUILD_TYPE=Release .. \ - && make -j8 \ - && make install \ - && cd ../pythonAPI \ - && pip install --upgrade . \ - && cd /tmp \ - && rm -Rf /tmp/hptt +RUN cd /tmp && \ + git clone https://gitlab.com/keckj/hptt && \ + cd hptt && \ + mkdir build && \ + cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release .. && \ + make && \ + make install && \ + cd ../pythonAPI && \ + pip install --upgrade . && \ + cd /tmp && \ + rm -Rf /tmp/hptt # fork of memory_tempfile for python 2.7 -RUN cd /tmp - && git clone https://gitlab.com/keckj/memory-tempfile \ - && cd memory-tempfile \ - && poetry install \ - && poetry build \ - && pip install ./dist/memory-tempfile-*.tar.gz \ - && cd /tmp \ - && rm -Rf /tmp/memory-tempfile +RUN cd /tmp && \ + git clone https://gitlab.com/keckj/memory-tempfile && \ + cd memory-tempfile && \ + pip install . && \ + cd /tmp && \ + rm -Rf /tmp/memory-tempfile # ensure all libraries are known by the runtime linker RUN ldconfig diff --git a/hysop/core/graph/graph.py b/hysop/core/graph/graph.py index 21466bd2d..e7bcfbe2d 100644 --- a/hysop/core/graph/graph.py +++ b/hysop/core/graph/graph.py @@ -4,11 +4,13 @@ from hysop.constants import MemoryOrdering from hysop.tools.types import check_instance, first_not_None from hysop.tools.decorators import not_implemented, debug, wraps, profile -is_directed_acyclic_graph = networkx.algorithms.dag.is_directed_acyclic_graph +def is_directed_acyclic_graph(graph): + return networkx.algorithms.dag.is_directed_acyclic_graph(graph) def transitive_reduction(graph): reduced_graph = networkx.algorithms.dag.transitive_reduction(graph) - # copy back edge attributes + # copy back edge attributes (node data is automatically transferred + # because nodes are the data (VertexAttributes)) for node in reduced_graph: for out_node in reduced_graph[node]: for (k,v) in graph[node][out_node].items(): @@ -18,8 +20,12 @@ def transitive_reduction(graph): def all_simple_paths(graph, src, dst): return tuple(networkx.algorithms.simple_paths.all_simple_paths(graph, src, dst)) -def topological_sort(graph): - return tuple(networkx.algorithms.dag.topological_sort(graph)) +def lexicographical_topological_sort(graph): + # Lexicographical sort ensures a unique permutations of nodes + # such that they are in the same topological order on each + # MPI process. Else operators will not be executed in the same + # order and everything deadlocks on MPI synchronization. + return tuple(networkx.algorithms.dag.lexicographical_topological_sort(graph)) def new_directed_graph(): return networkx.DiGraph() diff --git a/hysop/core/graph/graph_builder.py b/hysop/core/graph/graph_builder.py index d0351a65b..e1614af36 100644 --- a/hysop/core/graph/graph_builder.py +++ b/hysop/core/graph/graph_builder.py @@ -12,7 +12,7 @@ from hysop.topology.cartesian_topology import CartesianTopologyState from hysop.core.graph.graph import (new_directed_graph, new_vertex, new_edge, is_directed_acyclic_graph, transitive_reduction, - topological_sort, all_simple_paths) + lexicographical_topological_sort, all_simple_paths) from hysop.core.graph.computational_graph import ComputationalGraph from hysop.core.graph.computational_node import ComputationalGraphNode from hysop.core.graph.computational_operator import ComputationalGraphOperator @@ -433,9 +433,10 @@ class GraphBuilder(object): # ie. remove useless redondant dependencies reduced_graph = transitive_reduction(graph) - # Topological sort - # ie. find out operator order for execution purposes - sorted_nodes = topological_sort(reduced_graph) + # Lexicographical topological sort + # => find out operator order for execution purposes + # => have to be exactly the same on each MPI process. + sorted_nodes = lexicographical_topological_sort(reduced_graph) for (i, node) in enumerate(sorted_nodes): node.op_ordering = i diff --git a/hysop/core/graph/tests/test_graph.py b/hysop/core/graph/tests/test_graph.py index a142a4a75..52b0b754e 100644 --- a/hysop/core/graph/tests/test_graph.py +++ b/hysop/core/graph/tests/test_graph.py @@ -1,4 +1,5 @@ -from hysop.domain.box import Box +import tempfile +from hysop.domain.box import Box from hysop.topology.cartesian_topology import CartesianTopology from hysop.tools.parameters import CartesianDiscretization from hysop.fields.continuous_field import Field @@ -97,10 +98,13 @@ class TestGraph(object): g.discretize() g.setup(None) g.apply() + + with tempfile.NamedTemporaryFile(suffix='.html') as f: + g.to_html(f.name) if display: g.display() if __name__ == '__main__': test = TestGraph() - test.test_graph_build(display=True) + test.test_graph_build(display=False) diff --git a/hysop/numerics/fft/_mkl_fft.py b/hysop/numerics/fft/_mkl_fft.py index 94c329dce..a095dfa05 100644 --- a/hysop/numerics/fft/_mkl_fft.py +++ b/hysop/numerics/fft/_mkl_fft.py @@ -4,7 +4,8 @@ FFT interface for fast Fourier Transforms using Intel MKL (numpy interface). :class:`~hysop.numerics.MklFFTPlan` /!\ -- OPENMP CONFLICT WITH GRAPHTOOLS -- -/!\ Only works if MKL_THREADING_LAYER is set to OMP because graph_tools is compiled against GNU OpenMP. +/!\ Only works if MKL_THREADING_LAYER is set to OMP if some + dependencies are compiled against GNU OpenMP. /!\ May also work with MKL_THREADING_LAYER=TBB and SEQUENCIAL but not INTEL. Required version of mkl_fft is: https://gitlab.com/keckj/mkl_fft diff --git a/requirements.txt b/requirements.txt index f99a62727..6728ee0a5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,3 +22,4 @@ numba configparser backports.tempfile backports.weakref +networkx -- GitLab