diff --git a/docs/index.rst b/docs/index.rst index 055cb039d..961a7df52 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,6 +26,7 @@ Contents :maxdepth: 1 intro + install tutorial examples changelog diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 000000000..54b0f2cfb --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,247 @@ +Installation +============ + +Nutils requires a working installation of Python 3.5 or higher. Many different +installers exist and there are no known issues with any of them. When in doubt +about which to use, a safe option is to go with the `official installer +`_. From there on Nutils can be installed +following the steps below. + +Depending on your system the Python executable may be installed as either +``python`` or ``python3``, or both, not to mention alternative implementations +such as ``pypy`` or ``pyston``. In the following instructions, ``python`` +is to be replaced with the relevant executable name. + + +Installing Nutils +----------------- + +Nutils is installed via Python's `Pip `_ +package installer, which most Python distributions install by default. In the +following instructions we add the flag ``--user`` for a local installation that +does not require system privileges, which is recommended but not required. + +The following command installs the stable version of Nutils from the package +archive, along with its dependencies `Numpy `_, `Treelog +`_ and `Stringly +`_:: + + python -m pip install --user nutils + +To install the most recent development version we use Github's ability to +generate zip balls:: + + python -m pip install --user --force-reinstall \ + https://github.com/evalf/nutils/archive/refs/heads/master.zip + +Alternatively, if the `Git `_ version control system is +installed, we can use pip's ability to interact with it directly to install the +same version as follows:: + + python -m pip install --user --force-reinstall \ + git+https://github.com/evalf/nutils.git@master + +This notation has the advantage that even a specific commit (rather than a +branch) can be installed directly by specifying it after the ``@``. + +Finally, if we do desire a checkout of Nutils' source code, for instance to +make changes to it, then we can instruct pip to install directly from the +location on disk:: + + git clone https://github.com/evalf/nutils.git + cd nutils + python -m pip install --user . + +In this scenario it is possible to add the ``--editable`` flag to install +Nutils by reference, rather than by making a copy, which is useful in +situations of active development. Note, however, that pip requires manual +intervention to revert back to a subsequent installation by copy. + + +Installing a matrix backend +--------------------------- + +Nutils currently supports three matrix backends: Numpy, Scipy and MKL. Since +Numpy is a primary dependency this backend is always available. Unfortunately +it is also the least performant of the three because of its inability to +exploit sparsity. It is therefore strongly recommended to install one of the +other two backends via the instructions below. + +By default, Nutils automatically activates the best available matrix backend: +MKL, Scipy or Numpy, in that order. A consequence of this is that a faulty +installation may easily go unnoticed as Nutils will silently fall back on a +lesser backend. As such, to make sure that the installation was successful it +is recommended to force the backend at least once by setting the +``NUTILS_MATRIX`` environment variable. In Linux:: + + NUTILS_MATRIX=MKL python myscript.py + +Scipy +~~~~~ + +The Scipy matrix backend becomes available when `Scipy +`_ is installed, either using the platform's package +manager or via pip:: + + python -m pip install --user scipy + +In addition to a sparse direct solver, the Scipy backend provides many +iterative solvers such as CG, CGS and GMRES, as well as preconditioners. The +direct solver can optionally be made more performant by additionally installing +the ``scikit-umfpack`` module. + +MKL +~~~ + +Intel's oneAPI Math Kernel Library provides the Pardiso sparse direct solver, +which is easily the most powerful direct solver that is currently supported. +It is installed via the `official instructions +`_, or, if applicable, by any of the +steps below. + +On a Debian based Linux system (such as Ubuntu) the libraries can be directly +installed via the package manager:: + + sudo apt install libmkl-rt + +For Fedora or Centos Linux, Intel maintains its own repository that can be +added with the following steps:: + + sudo dnf config-manager --add-repo https://yum.repos.intel.com/mkl/setup/intel-mkl.repo + sudo rpm --import https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB + sudo dnf install intel-mkl + sudo tee /etc/ld.so.conf.d/mkl.conf << EOF > /dev/null + /opt/intel/lib/intel64/ + /opt/intel/mkl/lib/intel64/ + EOF + sudo ldconfig -v + + +Improving performance +--------------------- + +While Nutils is not (yet) the fastest tool in its class, with some effort it is +possible to achieve sufficient performance to allow simulations of over a +million degrees of freedom. The matrix backend is the most important thing to +get right, but there are a few other factors that are worth considering. + +Enable parallel processing +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On multi-core architectures, the most straightforward acceleration path +available is to use parallel assembly, activated using the ``NUTILS_NPROCS`` +environment variable. Both Linux and OS X both are supported. Unfortunately, +the feature is currently disabled on Windows as it does not support the +``fork`` system call that is used by the current implementation. + +On Windows, the easiest way to enjoy parallel speedup is to make use of the new +Windows Subsystem for Linux (WSL2), which is complete Linux environment running +on top of Windows. To install it simply select one of the many Linux +distributions from the Windows store, such as `Ubuntu 20.04 LTS +`_ or `Debian GNU/Linux +`_. + +Disable threads +~~~~~~~~~~~~~~~ + +Many Numpy installations default to using the openBLAS library to provide its +linear algebra routines, which supports multi-threading using the openMP +parallelization standard. While this is useful in general, it is in fact +detrimental in case Nutils is using parallel assembly, in which case the +numerical operations are best performed sequentially. This can be achieved by +setting the ``OMP_NUM_THREADS`` environment variable. + +In Linux this can be done permanently by adding the following line to the +shell's configuration file. In Linux this is typically ``~/.bashrc``:: + + export OMP_NUM_THREADS=1 + +The downside to this approach is that multithreading is disabled for all +applications that use openBLAS, not just Nutils. Alternatively in Linux the +setting can be specified one-off in the form of a prefix:: + + OMP_NUM_THREADS=1 NUTILS_NPROCS=8 python myscript.py + +Consider a faster interpretor +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The most commonly used Python interpretor is without doubt the `CPython +`_ reference implementation, but it is not +the only option. Before taking an application in production it may be worth +testing if `other implementations +`_ have useful performance +benefits. + +One interpretor of note is `Pyston `_, which brings +just-in-time compilation enhancements that in a typical application can yield a +20% speed improvement. After Pyston is installed, Nutils and dependencies can +be installed as before simply replacing ``python`` by ``pyston3``. As packages +will be installed from source some development libraries may need to be +installed, but what is missing can usually be inferred from the error messages. + + +Using Docker, Podman +-------------------- + +As an alternative to installing Nutils, it is possible to download a +preinstalled system image with all the above considerations taken care of. +Nutils provides `OCI `_ compatible containers for +all releases, as well as the current developement version, which can be run +using tools such as `Docker `_ or `Podman +`_. The images are hosted in `Github's container repository +`_. + +The container images include all the :ref:`examples`. To run one, add the name +of the example and any additional arguments to the command line. For example, +you can run example ``laplace`` using the latest version of Nutils with:: + + docker run --rm -it ghcr.io/evalf/nutils:latest laplace + +HTML log files are generated in the ``/log`` directory of the container. If you +want to store the log files in ``/path/to/log`` on the host, add ``-v +/path/to/log:/log`` to the command line before the name of the image. Extending +the previous example:: + + docker run --rm -it -v /path/to/log:/log ghcr.io/evalf/nutils:latest laplace + +To run a Python script in this container, bind mount the directory containing +the script, including all files necessary to run the script, to ``/app`` in the +container and add the relative path to the script and any arguments to the +command line. For example, you can run ``/path/to/myscript.py`` with Docker +using:: + + docker run --rm -it -v /path/to:/app:ro ghcr.io/evalf/nutils:latest myscript.py + + +Remote Computing +---------------- + +Computations beyond a certain size are usually moved to a remote computing +facility, typically accessed using tools such as `Secure Shell +`_ or `Mosh `_, +combined with a terminal multiplexer such as `GNU Screen +`_ or `Tmux +`_. In this scenario it is useful to install +a webserver for remote viewing of the html logs. + +The standard ``~/public_html`` output directory is configured with the scenario +in mind, as the `Apache `_ webserver uses this as +the default `user directory +`_. As this is +disabled by default, the module needs to be enabled by editing the relevant +configuration file or, in Debian Linux, by using the ``a2enmod`` utility:: + + sudo a2enmod userdir + +Similar behaviour can be achieved with the `Nginx `_ by +configuring a location pattern in the appropriate server block:: + + location ~ ^/~(.+?)(/.*)?$ { + alias /home/$1/public_html$2; + } + +Finally, the terminal output can be made to show the http address rather than +the local uri by adding the following line to the ``~/.nutilsrc`` configuration +file:: + + outrooturi = 'https://mydomain.tld/~myusername/'