\documentclass{beamer}

\usetheme[headernav]{TACC} %%Drop the 'headernav' if you don't like
                           %%the stuff at the top of your slide

\usepackage{amsmath,amssymb,amsthm}
\usepackage{alltt}
\usepackage{graphicx}

\title{Lmod Tutorial}


\author{Robert McLay}
\institute{The Texas Advanced Computing Center}

\date{June 12, 2014}  %% Use this if you want to fix the date in
                      %% stone rather than use \today

\newcommand{\bfnabla}{\mbox{\boldmath$\nabla$}}
\newcommand{\laplacian}[1]{\bfnabla^2 #1}
\newcommand{\grad}[1]{\bfnabla #1}
\newcommand{\tgrad}[1]{\bfnabla^T #1}
\newcommand{\dvg}[1]{\bfnabla \cdot #1}
\newcommand{\curl}[1]{\bfnabla \times #1}
\newcommand{\lap}[1]{\bfnabla^2 #1}

\begin{document}

\begin{frame}
  \titlepage
\end{frame}

\section{Introduction}

\begin{frame}{Introduction}
  \begin{itemize}
    \item Fundamental Issues
    \item Environment Modules
    \item Software Hierarchy
    \item Lmod
    \item Conclusions
  \end{itemize}
\end{frame}


\begin{frame}{Fundamental Issues}
  \begin{itemize}
    \item Software Packages are created and updated all the time.
    \item Some Users need new versions for new features and bug fixes.
    \item Other Users need older versions for stability and continuity.
    \item No system can support all versions of all packages.
    \item User programs using pre-built C++ \& Fortran libraries must
      link with the same compiler.
    \item Similarly, MPI Applications must build and link with same
      MPI/Compiler pairing when using prebuilt MPI libraries.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Example of Lmod: Environment Modules (I)}
    {\tiny
\begin{alltt}
\$ {\color{blue} module avail}
------------------ /opt/apps/modulefiles/MPI/intel/12.0/mpich2/1.4 ------------------
  petsc/3.1 (default)    petsc/3.1-debug    pmetis/4.0    tau/2.20.3

------------------- /opt/apps/modulefiles/Compiler/intel/12.0 -----------------------
  boost/1.45.0              gotoblas2/1.13          openmpi/1.4.3
  boost/1.46.0              mpich2/1.3.2            openmpi/1.5.1
  boost/1.46.1 (default)    mpich2/1.4 (default)    openmpi/1.5.3 (default)

-------------------------- /opt/apps/modulefiles/Core -------------------------------
  PrgEnv               intel/11.1               papi/4.1.4
  admin/admin-1.0      intel/12.0 (default)     scite/2.28
  ddt/ddt              lmod/lmod                tex/2010
  dmalloc/dmalloc      local/local (default)    unix/unix (default)
  fdepend/1.2          mkl/mkl                  visit/visit
  gcc/4.4              noweb/2.11b
  gcc/4.5 (default)
\end{alltt}
    }
\end{frame}

\begin{frame}[fragile]
    \frametitle{Example of Lmod: Environment Modules (II)}
    {\tiny
\begin{alltt}
{\color{blue}\$ module list}
Currently Loaded Modules:
  1) PrgEnv  2) gcc/4.5  3) mpich2/1.4  4) petsc/3.1
{\color{blue}\$ module unload gcc}
Inactive Modules:
  1) mpich2  2) petsc
{\color{blue}\$ module list}
Currently Loaded Modules:
  1) PrgEnv
Inactive Modules:
  1) mpich2  2) petsc
{\color{blue}\$ module load intel}
Activating Modules:
  1) mpich2  2) petsc
{\color{blue}\$ module swap intel gcc}
Due to MODULEPATH changes the follow modules have been reloaded:
  1) mpich2  2) petsc
\end{alltt}
    }
\end{frame}


\begin{frame}{Benefits of Modules}
  \begin{itemize}
    \item Users do not need to know where software is installed
    \item Environment Variables to interface package can be set:
      \begin{itemize}
        \item TACC\_{\color{blue}\emph{PACKAGE}}\_LIB
        \item TACC\_{\color{blue}\emph{PACKAGE}}\_INC
        \item User do not need to set hardcoded paths.
      \end{itemize}
    \item Package required variables such as \texttt{LICENSE\_PATH}
      can be set automatically.
  \end{itemize}
\end{frame}


\begin{frame}{Benefits of Lmod vs. TCL/C modules}

  \begin{itemize}
    \item Lmod provides all the functionality that TCL/C Modules does.
    \item Directly support for Software Hierarchy.
    \item It reads both TCL and Lua based modulefiles.
      \begin{itemize}
        \item Lua module files have ``\texttt{.lua}'' extension.
        \item TCL module files don't.
      \end{itemize}
    \item Users can find all modules available via {\color{blue}module spider}.
    \item Users can set their default set of modules via
      {\color{blue}module  save}.
  \end{itemize}
\end{frame}

\begin{frame}{Environment Modules}
  \begin{itemize}
    \item The ``module'' command ``loads'' a package.
    \item It adds directories to \texttt{PATH} or \texttt{LD\_LIBRARY\_PATH} and
      sets other  Variables.
    \item ``\texttt{module unload} \emph{package}'' removes all packages
      changes: \texttt{PATH}, \texttt{LD\_LIBRARY\_PATH}, unset vars.
    \item A module file is a text file containing shell-independent commands:
      \begin{itemize}
        \item \texttt{prepend\_path("PATH","/opt/apps/git/1.8/bin")}
        \item \texttt{setenv("TACC\_GIT\_DIR","/opt/apps/git/1.8")}
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Modules and Versions}
  \begin{itemize}
    \item Modules are typically named: \emph{package/version}
    \item For example: \texttt{git/1.8}
    \item There is a default version so:
      \begin{itemize}
        \item ``\texttt{module load git}'' load the default version.
        \item ``\texttt{module load git/1.8}'' load the 1.8 version.
      \end{itemize}
    \item Typically a module name is a directory name and the version
      is a file.
  \end{itemize}
\end{frame}

\begin{frame}{Sys-admin Vs. User Control of software}
  \begin{itemize}
    \item Sys-admins control what versions are default.
    \item Users can load newer/older versions instead of the default.
    \item When compilers are updated, users can switch between
      versions, allowing for testing.
    \item This is the key to a flexible system.
    \item Users can create their own modules for personal software.
  \end{itemize}
\end{frame}

\begin{frame}{Environment Modules History}
  \begin{itemize}
    \item Paper described modules in 1991 (Furlani).
    \item Cray used modules on Unicos mid-1990's.
    \item TACC has been using modules since our 1st Cray T3E in the
      late 90's.
  \end{itemize}
\end{frame}

\begin{frame}{Environment Modules History (II)}
  \begin{itemize}
    \item At some point Environment Modules was rewritten in a TCL/C combination.
    \item Another module system called CMOD:
      www.lysator.liu.se/cmod/ (1997-1998)
    \item www.modules.org: TCL/C Module files written in TCL (Late '90s - now)
    \item A pure TCL based module system: www.modules.org (? - now)
    \item Lmod: Lua Based Environment Module System (2008 - now) (lmod.sf.net)
  \end{itemize}
\end{frame}

\begin{frame}{How could modules possibly work?}
  \begin{itemize}
    \item Child processes inherit the parents environment.
    \item Not the other way around.
    \item So how does this work?
  \end{itemize}
\end{frame}

\begin{frame}{The Trick}
  \begin{itemize}
    \item The module command {\color{blue}\texttt{\$LMOD\_CMD}} reads module files
    \item The program outputs shell dependent text.
    \item Second step: evaluate shell dependent text.
    \item In bash:
      \begin{itemize}
          \item {\color{blue}\texttt{module () \{ eval \$(\$LMOD\_CMD bash "\$@")\}}}
      \end{itemize}
    \item In csh \texttt{module} is an alias:
      \begin{itemize}
        \item {\color{blue}\texttt{alias module eval `\$LMOD\_CMD csh $\backslash$!*`}}
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{The Trick (II)}
    Text output of the module command:
    \begin{itemize}
      \item modulefile ``foo/1.0.lua'':
    {
\begin{verbatim}
          setenv("FOO_VERSION","1.0")
\end{verbatim}
    }
     \item Output for bash:
\begin{verbatim}
          export FOO_VERSION="1.0"
\end{verbatim}
     \item Output for csh:
\begin{verbatim}
          setenv FOO_VERSION "1.0"
\end{verbatim}
    \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Interactive Playtime: Shell Startup Debug}
  \begin{itemize}
    \item This is to test your VM installs
    \item Use VM lmod-test, login \emph{mclay}, password: \emph{mclay}
    {\small
\begin{verbatim}
  $ cat "export SHELL_STARTUP_DEBUG=1" > $HOME/.init.sh
  $ bash -l
\end{verbatim}
}
    \item This is a great help in installing Lmod and tracking startup bugs.
  \end{itemize}
\end{frame}




\section{Software Hierarchy}

\begin{frame}{Software Hierarchy}
  \begin{itemize}
    \item TACC used modules from www.modules.org (TCL/C) modules
    \item Life was good at TACC until ...
    \item Multiple Compilers and Multiple MPI implementations.
    \item Pre-built C++ \& Fortran libraries must link with the same compiler
    \item Similarly MPI Applications must build and link with same
      MPI/Compiler pairing when using prebuilt MPI libraries.
  \end{itemize}
\end{frame}

\begin{frame}{Modulefile Choices}
  \begin{itemize}
    \item Flat Naming Scheme
    \item Hierarchical Naming Scheme
  \end{itemize}
\end{frame}

\begin{frame}{Flat Naming Scheme: PETSc}
  PETSc is a parallel iterative solver package:
  \begin{itemize}
    \item Compilers: GCC 4.5, Intel 11.1
    \item MPI Implementations: MVAPICH 1.2, Openmpi 1.5
    \item MPI Solver package: PETSc 4.1
    \item 4 versions of PETSc: 2 Compilers $\times$ 2 MPI
  \end{itemize}
\end{frame}

\begin{frame}{Flat: PETSc }
  \begin{enumerate}
  \item \texttt{PETSc-4.1-mvapich-1.2-gcc-4.5}
  \item \texttt{PETSc-4.1-mvapich-1.2-intel-11.1}
  \item \texttt{PETSc-4.1-openmpi-1.5-gcc-4.5}
  \item \texttt{PETSc-4.1-openmpi-1.5-intel-11.1}
  \end{enumerate}
\end{frame}

\begin{frame}{Problems w/ Flat naming scheme}
  \begin{itemize}
    \item Users have to load modules:
      \begin{itemize}
        \item ``intel/11.1''
        \item ``mvapich/1.2-intel-11.1''
        \item ``PETSc/4.1-mvapich-1.2-intel-11.1''
        \item Changing compilers means unloading all three modules
        \item Reloading new compiler, MPI, PETSc modules.
        \item Not loading correct modules $\Rightarrow$ Mysterious Failures!
        \item Onus of package compatibility on users!
      \end{itemize}
  \end{itemize}
\end{frame}


\begin{frame}{Hierarchical Naming Schemes}
  \begin{itemize}
    \item Store modules under one tree: \texttt{/opt/apps/modulefiles}
    \item One strategy is to use sub-directories:
      \begin{itemize}
        \item Core: Regular packages: apps, compilers, git
        \item Compiler: Packages that depend on compiler: boost, MPI
        \item MPI: Packages that depend on MPI/Compiler: PETSc, TAU
      \end{itemize}

  \end{itemize}
\end{frame}

\begin{frame}{\texttt{MODULEPATH}}
  \begin{itemize}
    \item \texttt{MODULEPATH} is a colon separated list of directories
      containing directories and module files.
    \item No modulefiles loaded $\Rightarrow$ users can only load core modules.
    \item Loading a compiler module adds to the \texttt{MODULEPATH}:
      \begin{itemize}
        \item Users can load compiler dependent modules.
        \item This includes MPI implementations modules.
      \end{itemize}
    \item Loading an MPI module adds to the \texttt{MODULEPATH}:
      \begin{itemize}
        \item Users can load MPI libraries that match the MPI/compiler pairing.
      \end{itemize}
  \end{itemize}
\end{frame}


\begin{frame}{Hierarchical Examples: Core}
  \begin{itemize}
    \item Generic:
      \begin{itemize}
        \item Package: \texttt{/opt/apps/}\emph{package/version}
        \item M: {\color{blue}/opt/apps/modulefiles}
        \item Modulefile: \texttt{{\color{blue}\$M}/Core/}\emph{package/version}
      \end{itemize}
    \item Git 1.8
      \begin{itemize}
        \item Package: \texttt{/opt/apps/git/1.8}
        \item Modulefile: \texttt{{\color{blue}\$M}/Core/git/1.8}
      \end{itemize}
    \item Intel compilers 11.1
      \begin{itemize}
        \item Package: \texttt{/opt/apps/intel/11.1}
        \item Modulefile: \texttt{{\color{blue}\$M}/Core/intel/11.1}
        \item Modulefile adds \texttt{{\color{blue}\$M}/Compiler/intel/11.1} to \texttt{MODULEPATH}
      \end{itemize}
  \end{itemize}
\end{frame}



\begin{frame}{Hierarchical Examples: Compiler Dependent}
  \begin{itemize}
    \item Generic:
      \begin{itemize}
        \item Package: /opt/apps/\emph{compiler-version/package/version}
        \item M: {\color{blue}/opt/apps/modulefiles}
        \item Modulefile: \texttt{{\color{blue}\$M}/Compiler/}\emph{compiler/version/package/version}
      \end{itemize}
    \item Openmpi 1.5 with gcc 4.5
      \begin{itemize}
        \item Package: \texttt{/opt/apps/gcc-4\_5/openmpi/1.5}
        \item Modulefile: \texttt{{\color{blue}\$M}/Compiler/gcc/4.5/openmpi/1.5}
        \item Modulefile adds \texttt{{\color{blue}\$M}/MPI/gcc/4.5/openmpi/1.5}
          to \texttt{MODULEPATH} \\
      \end{itemize}
    \item Openmpi 1.5 with intel 11.1
      \begin{itemize}
        \item Package: \texttt{/opt/apps/intel-11\_1/openmpi/1.5}
        \item Modulefile: \texttt{{\color{blue}\$M}/Compiler/intel/11.1/openmpi/1.5}
        \item Modulefile adds \texttt{\$M/MPI/intel/11.1/openmpi/1.5}
          to \texttt{MODULEPATH}

      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Hierarchical Examples: MPI/Compiler Dependent}
  \begin{itemize}
    \item PETSc 4.1 (1)
      \begin{itemize}
        \item Package: \texttt{/opt/apps/intel-11\_1/openmpi-1\_5/petsc/4.1}
        \item Modulefile: \texttt{{\color{blue}\$M}/MPI/intel/11.1/openmpi/1.5/petsc/4.1}
      \end{itemize}
    \item PETSc 4.1 (2)
      \begin{itemize}
        \item Package: \texttt{/opt/apps/gcc-4\_5/mvapich-1\_2/petsc/4.1}
        \item Modulefile: \texttt{{\color{blue}\$M}/MPI/gcc/4.5/mvapich/1.2/petsc/4.1}
      \end{itemize}
  \end{itemize}
\end{frame}


\begin{frame}{Loading the correct module}
  \begin{itemize}
    \item User loads ``\texttt{intel/11.1}'' module
    \item Can only see/load compiler dependent packages that are built with
      intel 11.1 compiler.
    \item Can not see/load package built with other versions or other compilers.
    \item Similar loading ``\texttt{openmpi/1.5}'' module.
    \item User can only load package that are built w/ intel 11.1 and openmpi 1.5 and no others.
  \end{itemize}
\end{frame}


\section{Lmod}

\begin{frame}{Better but ...}
  \begin{itemize}
    \item Using TCL/C modules, Users can load correct modules by using
      the Software Hierarchy.
    \item But swapping compilers or MPI stack $\Rightarrow$ complicated!
    \item For Parallel libraries like PETSc:
      \begin{itemize}
        \item Users must unload PETSc, MPI, compiler
        \item Reload compiler, MPI, PETSc
        \item Nobody got this right!
      \end{itemize}
    \item Solution: Yet another Environment Module System: \texttt{Lmod}
  \end{itemize}
\end{frame}

\begin{frame}{Lmod}
  \begin{itemize}
    \item Complete Rewrite of the Environment Modules System.
    \item Reads TCL or Lua modulefiles.
    \item Based on the Lua scripting language.
    \item Simple yet powerful with:
      \begin{itemize}
        \item Functions are first class objects.
        \item Simplifies loading/unloading of modules.
        \item Tables combine array and hash seamlessly.
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Key Insight (I): \texttt{MODULEPATH}}
  \begin{itemize}
    \item Lmod remembers the current state of \texttt{MODULEPATH}.
    \item If it changes then it unloads any modules not in current
      search path $\Rightarrow$ inactive.
    \item It tries to activate any inactive modules.
    \item It remembers inactive modules.
    \item It continues to attempt to activate any inactive modules on
      future invocations.
  \end{itemize}
\end{frame}

\begin{frame}{Key Insight (II): \texttt{MODULEPATH}}
  \begin{itemize}
    \item Loading \texttt{gcc/4.5} and \texttt{boost/1.47.1}
    \item M=\texttt{{\color{blue}/opt/apps/modulefiles}}
      \begin{itemize}
        \item Adds \texttt{{\color{blue}\$M}/Compiler/gcc/4.5} to
          \texttt{MODULEPATH}.
        \item Boost: \texttt{{\color{blue}\$M}/Compiler/gcc/4.5/boost/1.47.1}
      \end{itemize}
    \item Unloading gcc/4.5
      \begin{itemize}
        \item Removes \texttt{{\color{blue}\$M}/Compiler/gcc/4.5}
          from \texttt{MODULEPATH}.
        \item Inactivates boost/1.47.1
      \end{itemize}
    \item Loading intel/11.1
      \begin{itemize}
        \item Adds \texttt{{\color{blue}\$M}/Compiler/intel/11.1} to
          \texttt{MODULEPATH}.
        \item Activates Boost: \texttt{{\color{blue}\$M}/Compiler/intel/11.1/boost/1.47.1}
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Other Safety Features of Lmod (I)}
  \begin{itemize}
    \item Users can only load one version of a package.
    \item ``\texttt{module load xyz/2.1}'' loads xyz version 2.1
    \item ``\texttt{module load xyz/2.2}'' unloads 2.1, loads 2.2
  \end{itemize}
\end{frame}

\begin{frame}{Other Safety Features of Lmod (II)}
  \begin{itemize}
    \item Lmod adds a new command in modulefiles: \texttt{family("}\emph{name}\texttt{")}
    \item All of our compiler modules have \texttt{family("compiler")}
    \item All of our MPI modules have \texttt{family("MPI")}
    \item Users can only load one compiler or MPI at a time
    \item Powers users can get around this restriction.
  \end{itemize}
\end{frame}

\begin{frame}{Save/Restore}
  \begin{itemize}
    \item User can setup their own initially loaded modules.
      \begin{itemize}
        \item Users simply load, unload and/or swap until happy.
        \item {\color{blue}\texttt{module save}} saves state in ``default''
        \item Our login scripts do: {\color{blue}\texttt{module restore}}
          which loads the user's default.
      \end{itemize}
    \item Users can create other collections by:
      \begin{itemize}
        \item {\color{blue}\texttt{module save}
            {\color{violet}name}} to save it.
        \item {\color{blue}\texttt{module restore}
            {\color{violet}name}} to retrieve it.
      \end{itemize}
    \item This used to known as setdefault/getdefault.
  \end{itemize}
\end{frame}

\begin{frame}{Lmod Module Layout}
  \begin{itemize}
    \item Supports Flat layouts
    \item Supports Hierarchical layouts
    \item Naming Schemes:
      \begin{itemize}
        \item Name/Version (e.g. \texttt{bowtie/2.3})
        \item Category/Name/version (e.g. \texttt{bio/bowtie/2.3})
        \item Category/Sub/Name/version (e.g. \texttt{bio/genomics/bowtie/2.3})
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{For those who can't type: ``\texttt{ml}''}
  \begin{itemize}
    \item \texttt{ml} is a wrapper:
      \begin{itemize}
        \item With no argument: \texttt{ml} means \texttt{module list}
        \item With a module name: \texttt{ml foo} means \texttt{module
            load foo}.
        \item With a module command: \texttt{ml spider} means
          \texttt{module spider}.
      \end{itemize}
    \item See \texttt{ml --help} for more documentation.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Interactive Playtime: Lmod example}
  \begin{itemize}
    \item Use VM lmod-test, login \emph{mclay}, password: \emph{mclay}
    {\small
\begin{verbatim}
    $ module load gcc mpich parmetis
    $ module list
    $ module avail
    $ module swap gcc clang
    $ module spider
    $ module spider parmetis/4.0.3
\end{verbatim}
}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Interactive Playtime: Lmod example (II)}
    {\small
\begin{verbatim}
    $ ml purge
    $ ml gcc mpich parmetis
    $ ml
    $ ml -gcc clang
    $ ml spider
    $ ml spider parmetis/4.0.3
\end{verbatim}
}
\end{frame}

\subsection{Searching for Modules}
\label{sec:search}


\begin{frame}{Searching for Modules}
  \begin{itemize}
    \item Three ways to search for modules:
      \begin{itemize}
        \item ``\texttt{module avail}''
        \item ``\texttt{module spider}''
        \item ``\texttt{module keyword}''
      \end{itemize}
    \item The ``\texttt{avail}''  command reports all ``loadable'' modules.
    \item The ``\texttt{spider}'' command reports all ``possible'' modules.
    \item The ``\texttt{keyword}'' command reports all ``possible''
      modules that match keywords.
    \item What is the difference?
  \end{itemize}
\end{frame}

\begin{frame}{Module avail}
  \begin{itemize}
    \item ``avail'' only reports modules that are loadable w/ current
      MPI/Compiler pairing.
    \item A parallel library may not be built for all possible pairings.
    \item Won't always show with avail.
    \item Not all package can be build or work with all compiler/MPI suites.
  \end{itemize}
\end{frame}

\begin{frame}{Module spider}
  \begin{itemize}
    \item Reports all modules for given \texttt{MODULEPATH}.
    \item It recursively searches the tree to find all branches.
    \item Large systems of modules save a cache file that is saved for
      a day.
    \item Three modes:
      \begin{itemize}
        \item module spider - all possible modules no detail.
        \item module spider petsc - all versions of petsc, no detail.
        \item module spider petsc/3.1 - details.
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Module keyword key1 key2 ...}
    \begin{itemize}
      \item
    Modules can have a ``whatis'' description:
    {\tiny
\begin{alltt}
whatis("Name: Abyss")
whatis("Version: 1.2.7")
whatis("Category: computational biology, genomics")
whatis("Keywords: compbio, genomics")
whatis("URL:http://www.bcgsc.ca/platform/bioinfo/software/abyss")
whatis("Description: Assembly By Short Sequences.")
\end{alltt}
    }
  \item {\color{blue}module keyword key1 ...} will report all modules
    with any of the {\color{blue}key}'s.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Generic Modulefile support}
  \begin{itemize}
    \item Lmod support several functions to help with generic modulefiles:
      \begin{itemize}
        \item \texttt{myModuleName()}  $\Rightarrow$ boost, bio/bowtie
        \item \texttt{myModuleVersion()}  $\Rightarrow$ 1.47.0
        \item \texttt{myModuleFullName()}  $\Rightarrow$ boost/1.47.0
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Generic Modulefile support: hierarchyA()}
  \begin{itemize}
    \item Extracting the hierarchy based on location: mpich/3.1.lua
    {\small
\begin{verbatim}
local pkgName  = myModuleFullName()
local hierA    = hierarchyA(pkgName,1)
local comp     = hierA[1]
local compDir  = comp:gsub("/","-"):gsub("%.","_")
local base     = pathJoin("/opt/apps", compDir, pkgName)
prepend_path("PATH", pathJoin(base,"bin"))
\end{verbatim}
}
    \item If you use a different layout, you can provide similar
      functions in ``SitePackage.lua''
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Interactive Playtime: Generic Modulefiles}
  \begin{itemize}
    \item Lets look at one way to support Generic Modulefiles:
    {\small
\begin{verbatim}
$ cd /opt/apps/modulefiles/Core; more gcc/4.8.lua
$ cd ../Compiler/
$ ls -R *
$ cd .base/mpich/
$ look at 3.1.lua
$ cd ../../MPI/.base/parmetis
$ look at 4.0.3.lua
\end{verbatim}
}
  \end{itemize}
\end{frame}



\subsection{Installing Lmod}
\label{sec:installing}

\begin{frame}{Installation Overview}
  \begin{itemize}
    \item Chose a place for module tree: ``\texttt{/opt/apps/modulefiles}''
    \item Use configure to override default.
    \item Install lua and Lmod applications.
    \item Place module command in system shell startup.
    \item Possibly modify bash's startup procedure.
    \item Design a default set of modules for your users.
  \end{itemize}
\end{frame}


\begin{frame}{Installing Lmod (I)}
  \begin{itemize}
    \item Download files from lmod.sf.net
      \begin{itemize}
        \item lua-x.y.z.tar.gz
        \item lmod-x.y.z.tar.gz
      \end{itemize}
    \item Assume all ``optional'' packages are in ``\texttt{/opt/apps/}''
    \item Install lua in ``\texttt{/opt/apps/lua/}\emph{x.y.z}''
    \item ``\texttt{\$ ln -s }\emph{x.y.z} \texttt{/opt/apps/lua/lua}''
    \item This way ``\texttt{/opt/apps/lua/lua/bin/lua}'' always points to
      lua independent of version.
  \end{itemize}
\end{frame}

\begin{frame}{Installing Lmod (II)}
  \begin{itemize}
    \item Install Lmod in ``\texttt{/opt/apps/lmod/}\emph{x.y.z}''
    \item ``\texttt{make install}'' creates a symlink from
      ``\emph{x.y.z}'' to lmod.
    \item This way ``\texttt{/opt/apps/lmod/lmod/...}'' always points
      to the latest lmod.
  \end{itemize}
\end{frame}

\begin{frame}{Integrating Lmod into User's Shell (I)}
    We must add the module alias for all user's shells by either link
    or copy:
    \begin{itemize}
      \item \texttt{\$ ln -s /opt/apps/lmod/lmod/init/profile /etc/profile.d/z00\_lmod.sh}
      \item \texttt{\$ ln -s /opt/apps/lmod/lmod/init/cshrc   /etc/profile.d/z00\_lmod.csh}
      \item You may have to create ``\texttt{/etc/profile.d}'' first.
  \end{itemize}
\end{frame}

\begin{frame}{Bash Shell startup files}
    \begin{tabular}{|l|l|l|}
        \hline
        ~           & System       & User \\\hline\hline
        login       & /etc/profile & $\sim$/.bash\_profile $\parallel$ $\sim$/.profile, ...\\\hline
        interactive & {\color{red}/etc/bashrc}$^\star$  & $\sim$/.bashrc\\\hline
        non-interactive & \$BASH\_ENV  & ~\\\hline
    \end{tabular}
    ~\\
    ~\\
    $^\star$ Not always built-in!\\
    \$BASH\_ENV points to a file which is run on  non-interactive shells.
\end{frame}

\begin{frame}{Csh Shell startup files}
{\small
    \begin{tabular}{|l|l|l|}
        \hline
        ~           & System       & User \\\hline\hline
        login       & /etc/csh.cshrc \& /etc/csh.login &  $\sim$/.cshrc  \& $\sim$/.login\\\hline
        interactive & /etc/csh.cshrc  & $\sim$/.cshrc\\\hline
        non-interactive & /etc/csh.cshrc & $\sim$/.cshrc~\\\hline
    \end{tabular}
}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Linux /etc/profile}
    {
\begin{verbatim}
if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
fi
\end{verbatim}
    }
\end{frame}


\begin{frame}[fragile]
    \frametitle{Linux /etc/bashrc}
    {
\begin{verbatim}
if ! shopt -q login_shell; then
  if [ -d /etc/profile.d ]; then
    for i in /etc/profile.d/*.sh; do
      if [ -r $i ]; then
        . $i
      fi
    done
  fi
fi
\end{verbatim}
    }
\end{frame}

\begin{frame}[fragile]
    \frametitle{Linux /etc/csh.cshrc}
    {
\begin{verbatim}
if ( -d /etc/profile.d ) then
  set nonomatch
  foreach i ( /etc/profile.d/*.csh )
     if ( -r $i ) then
       if ($?prompt) then
         source $i
       else
         source $i >& /dev/null
       endif
    endif
  end
endif
\end{verbatim}
    }
\end{frame}

\begin{frame}{Rebuilding Bash to use /etc/bashrc on non-login shells}
  \begin{itemize}
    \item By default bash does not read /etc/bashrc (or similar)
    \item Debian and Ubuntu read /etc/bash.bashrc on interactive
      non-login shells.
    \item Red Hat, Centos,  Mac OS X, don't read /etc/bashrc
    \item At TACC, we rebuilt bash so that it does read /etc/bashrc
    \item You must patch config-top.h to change bash's behavior.
  \end{itemize}
\end{frame}

\begin{frame}{Rebuilding Bash Benefits}
  \begin{itemize}
    \item We want bash interactive non-login shells to behave the same
      as login shells.
    \item Fortran 90 program typically need ``\texttt{ulimit -s unlimited}''
    \item MPI invokes an interactive non-login, non-prompt shell on
      every node.
    \item bash users were not getting ``\texttt{ulimit -s unlimited}''
      from system /etc/profile.d/*.sh
    \item By rebuilding Bash we guarantee that MPI jobs source \texttt{/etc/profile.d/*.sh}
    \item We control what goes into \texttt{/etc/tacc/\{profile,bashrc\}}
  \end{itemize}
\end{frame}

\begin{frame}{Loading Default Modules}
  \begin{itemize}
    \item At TACC, all users get a default set of module loaded at startup.
    \item In ``\texttt{/etc/profile.d/z96\_login\_modules.sh}:'' \\
      {\color{blue}\texttt{export LMOD\_SYSTEM\_DEFAULT\_MODULES=TACC}}\\
      {\color{blue}\texttt{module --initial\_load restore}}
    \item Most users get the ``TACC'' set of modules
    \item We load standard tools, a compiler, and an MPI implementation.
    \item Users can replace the default via ``{\color{blue}\texttt{module save}}''
  \end{itemize}
\end{frame}

\begin{frame}{Modules and Package Management at TACC}
  \begin{itemize}
    \item All of the ``optional'' software: compilers, MPI Stacks,
      Libraries, and Applications are installed via the RPM package manager.
    \item We create our optional RPMs with both the software and the
      module files.
    \item Uninstalling a package removes both the software and the
      module that access it.
    \item We use a single parameterized RPM spec file to build all
      compiler/MPI pairings.
  \end{itemize}
\end{frame}

\begin{frame}{Management of Modules}
  \begin{itemize}
    \item Encourage users to use modules with their own software.
    \item Check modulefile syntax errors by running:
       {\color{blue}module spider}
    \item Use {\color{violet}\texttt{prereq("foo","bar")}} instead of
      {\color{violet}\texttt{load("foo","bar")}}
    \item Use  {\color{violet}\texttt{family("compiler")}} and similar
      in your compiler and MPI module files.
  \end{itemize}
\end{frame}

\subsection{Deploying Lmod}
\label{sec:deploying_lmod}

\begin{frame}{Deploying Lmod}
  \begin{itemize}
    \item Lmod can be tested even though your site runs TCL/C modules.
    \item Make sure that Lua and lua-posix and lua-filesytem are installed
    \item Otherwise install lua-5.1.4.8.tar.gz from lmod.sf.net
    \item Install Lua, Install Lmod in your account.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Deploying Lmod: Personal startup}
    {\small
\begin{verbatim}
if [ -z "$LMOD_CMD" ]; then
  CURRENT_MPATH=$MODULEPATH
  module purge 2> /dev/null             # purge using old cmd

  LMOD_PKG=$HOME/pkg/lmod/lmod
  LMOD_CMD=$LMOD_PKG/libexec/lmod
  export BASH_ENV=$LMOD_PKG/init/bash
  . $BASH_ENV                           # redefine module cmd
  export LMOD_SYSTEM_DEFAULT_MODULES=...
  MODULEPATH=$CURRENT_MPATH
  module  --initial_load restore
fi
\end{verbatim}
}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Opt-in Testing}
  \begin{itemize}
    \item You and others can then opt-in
    {\small
\begin{verbatim}
    if [ -d $HOME/.lmod.d ]; then
      # Use Lmod for Modules
      ...
    else
      # Use TCL/C modules
      ...
    fi
\end{verbatim}
}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Opt-out deployment}
  \begin{itemize}
    \item When read to deploy to users do:
    {\small
\begin{verbatim}
    if [ ! -f $HOME/.no.lmod ]; then
      # Use Lmod for Modules
      ...
    else
      # Use TCL/C modules
      ...
    fi

\end{verbatim}
}
  \end{itemize}
\end{frame}


\subsection{HPC issues}

\begin{frame}{Module usage}
  \begin{itemize}
    \item It is possible to record module usage:
      \begin{itemize}
        \item Record modules loaded at logout time and/or job submission.
        \item Find out what modules are not or under used.
          $\Rightarrow$ removal or upgrade.
        \item Suggest to users of one module to consider using another module.
      \end{itemize}
    \item Use ``\texttt{load}'' hook to record every loaded module via SitePackage.lua
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
    \frametitle{HPC issues: Root}
  \begin{itemize}
    \item Root should not define the module command or load a default
      set of modules during shell startup.
    \item No non-local path should automatically ever be in root's path.
    \item What if \texttt{/opt/apps/} is unavailable?
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{HPC issues: Startup Files and Compute nodes}
  \begin{itemize}
    \item At TACC: the environment variable: ENVIRONMENT is ``BATCH'' when on a compute node.
    \item When in BATCH mode:
      \begin{itemize}
        \item The module command is defined.
        \item The TACC module is NOT loaded.
        \item The user's environment is passed to all processes.
        \item Mvapich2: mpirun\_rsh ... {\color{blue}Var1}={\color{blue}V1} {\color{blue}Var2}={\color{blue}V2} ...
        \item Where {\color{blue}Var1} ... are env. vars such as
          \$HOME, \$PATH ...
      \end{itemize}
    \item This prevents every node from a users parallel job from
      doing ``opendir("/opt/apps/modulefile/Core")''
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{HPC issues: Users}
  \begin{itemize}
    \item Users can overwork the parallel file system.
    \item Encourage your users to use {\color{blue}module save}
    \item Or users should load their modules via $\sim$/.bashrc or
      $\sim$/.cshrc but wrap them:
    {\small
\begin{verbatim}
    if [ -z “$_READ” -a -z “$ENVIRONMENT” ]; then
      export _READ=1 # Put any module commands here:
      module load git
    fi
\end{verbatim}
}
\item Otherwise each node of a user's 8192 process job will try to
  load modules $\Rightarrow$ Parallel file system metadata servers can hang.
  \end{itemize}
\end{frame}


\section{User Inspired Features to Lmod}
\label{sec:inspired}

\subsection{Version Sorting}
\label{sec:sorting}

\begin{frame}[fragile]
    \frametitle{Version Sorting}
  \begin{itemize}
    \item TCL/C module and older Lmod sorted alphabetically:
    \item intel/9.0 ``was'' newer than intel/10.0 $\Rightarrow$ Yuck!
    \item Python has a clever scheme.  I've re-implemented it in Lua.
    \item Lmod 4.1+ uses version sorting:
    {\small
\begin{verbatim}
   2.4dev1: 00002.00004.*@.00001.*zfinal
     2.4a1: 00002.00004.*a.00001.*zfinal
    2.4rc1: 00002.00004.*c.00001.*zfinal
       2.4: 00002.00004.*zfinal
     2.4-1: 00002.00004.*zfinal-.00001.*zfinal
     2.4.1: 00002.00004.00001.*zfinal
3.2-static: 00003.00002.*static.*zfinal
       3.2: 00003.00002.*zfinal
\end{verbatim}
}
  \end{itemize}
\end{frame}

\subsection{New Lmod Commands}
\label{sec:cmds}

\begin{frame}[fragile]
    \frametitle{Load/Prereq modify functions}
  \begin{itemize}
    \item In Lua modulefiles you can now do:
    {\small
\begin{verbatim}
   load(atleast("FOO","2.3"))
   load(between("BAR","7.1","10.1"))
   load(latest("BAZ"))
   prereq(atleast("boost","1.47.0"))
\end{verbatim}
}
    \item I'm thinking about similar modify functions for conflict()
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Module Proprieties (I)}
  \begin{itemize}
    \item Modules can have properties
    \item At TACC, we have MIC, and GPU accelerators.
    \item Some libraries are MIC aware.
    {\small
\begin{verbatim}
    add_property("arch","mic")
\end{verbatim}
}
    \item This is controlled by the table in lmodrc.lua
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Module Properties (II)}
  \begin{itemize}
    \item Some modules will be ``MIC'' aware: mkl, fftw3, phdf5, ...
    \item Lmod will decorate these modules:
  {\tiny
    \begin{alltt}
  1) unix/unix     3) ddt/ddt       5) mpich2/1.5    7) {\color{blue}phdf5/1.8.9 (m)}
  2) intel/13.0    4) {\color{red}mkl/mkl (*)}   6) petsc/3.2     8) PrgEnv

  Where:
   {\color{blue}(m)}:  module is build natively for MIC
   {\color{red}(*)}:  module is build natively for MIC and offload to the MIC

   ------
   add_property("arch","mic")              -- > phdf5
   add_property("arch","mic:offload")      -- > mkl
    \end{alltt}
}
  \item What properties would you like to support?
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Module Properties (III): Sticky}
  \begin{itemize}
    \item A module can be sticky.
    \item It requires ``\texttt{--force}'' to unload or purge.
    {\small
\begin{verbatim}
    add_property("lmod","sticky")
\end{verbatim}
}
  \end{itemize}
\end{frame}





\begin{frame}[fragile]
    \frametitle{pushenv}
  \begin{itemize}
    \item Suppose you'd like to set \texttt{CC} in the environment.
    \item \texttt{setenv} won't work.
    \item \texttt{pushenv} will!
    {\small
\begin{verbatim}
  $ module load   gcc;   # -> CC=gcc       CC=gcc
  $ module load   mpich; # -> CC=mpicc     CC=mpicc
  $ module unload mpich; # -> CC is unset  CC=gcc
  $ module unload gcc;   # -> CC is unset  CC is unset
\end{verbatim}
}
    \item \texttt{pushenv} keeps an private env vars: \texttt{\_\_LMOD\_STACK\_}\emph{NAME}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{always\_load and always\_unload}
  \begin{itemize}
    \item The \texttt{load()} function is reversed on unload.
    \item The \texttt{always\_load()} function is a no-op on unload.
    \item Still you may want:
    {\small
\begin{verbatim}
  if (not isloaded("FOO")) then always_load("FOO") end
\end{verbatim}
}
    \item Which is only slightly better than:
    {\small
\begin{verbatim}
  if (not isloaded("FOO") and mode()== "load") then
     load("FOO")
  end
\end{verbatim}
}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{prepend\_path() takes priorities}
  \begin{itemize}
    \item When you need to push a path to the front of the line do:
    {\small
\begin{verbatim}
   prepend_path{"PATH","/usr/local/first",
                             priority=1000}  -- Lua
   prepend-path PATH /usr/local/first 1000   # tcl
\end{verbatim}
}
    \item This is great for wrapper scripts:
    \item ``Do not use mpirun on login nodes''
    \item Works for \texttt{append\_path()} as well.
    \item Drives paths to be last.
  \end{itemize}
\end{frame}

\subsection{SitePackage.lua}
\label{sec:sitePackage}

\begin{frame}[fragile]
    \frametitle{SitePackage.lua: Customize Behavior for your Site}
  \begin{itemize}
    \item Use \texttt{StandardPackage.lua} as a guide for your \texttt{SitePackage.lua}
    \item Many examples of SitePackage.lua in contrib/* directories
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Load hook}
    {\small
\begin{verbatim}
local hook   = require("Hook")
function load_hook(t)
   if (mode() ~= "load") then return end
   local user  = os.getenv("USER")
   local jobid = os.getenv("PBS_JOBID") or "unknown"
   local msg   = string.format("user=%s,module=%s,job=%s",
                          user, t.modFullName, jobid)
   os.execute("logger -t lmod -p local0.info " .. msg)
   dbg.fini()
end
hook.register("load",load_hook)
\end{verbatim}
}
\end{frame}

\subsection{Settarg}
\label{sec:sitePackage}

\begin{frame}[fragile]
    \frametitle {settarg}
    \begin{itemize}
      \item Provides safety, flexibility and repeatability in a dynamic environment.
      \item Dynamically updates the state when modules change:
        {\small
          \begin{alltt}
    \$ {\color{red} env | grep '^TARG'}
    {\color{blue}TARG_BUILD_SCENARIO=dbg
    TARG=OBJ/_x86_64_dbg_gcc-4.6_mpich-3.0
    TARG_MPI_FAMILY=mpich
    TARG_MPI=mpich-3.0}
    \${\color{red} module swap mpich openmpi; opt; env | grep '^TARG'}
    {\color{blue}TARG_BUILD_SCENARIO=opt
    TARG=OBJ/_x86_64_opt_gcc-4.6_openmpi-1.6
    TARG_MPI=openmpi-1.6
    TARG_MPI_FAMILY=openmpi}
          \end{alltt}
          }
      \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle {settarg (II)}
    \begin{itemize}
      \item Typically TARG is OBJ/\$ARCH\_\$SCENARIO\_\$CMPLR\_\$MPI
      \item \texttt{TARG=OBJ/\_x86\_64\_dbg\_gcc-4.6\_mpich-3.0}
      \item User can extend this with user level or directory level
        specialization.
      \item \texttt{OBJ/\_x86\_64\_dbg\_intel-14.0\_mpich-3.0\_petsc-3.4}
      \item A makefile can modified to write generated file into \$TARG.
      \item Never need to ``\texttt{make clobber}'' when switching
        scenario, compiler, etc.
      \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Interactive Playtime: settarg}
    {\small
\begin{verbatim}
$ ml
$ cd ~/w/hello
$ ml clang mpich
$ make; mpirun -n 2 hello
$ ml -clang gcc
$ make; mpirun -n 2 hello
$ dbg
$ make; mpirun -n 2 hello
$ opt
$ make; mpirun -n 2 hello
$ cd OBJ
\end{verbatim}
}
\end{frame}

\subsection{Spider Cache}
\label{sec:cache}

\begin{frame}{Spider Cache Advantages}
  \begin{itemize}
    \item The spider cache speeds up avail and spider greatly.
    \item All system modulefiles have been read, properties determined.
    \item Lua is quite fast and reading and interpreting a single file.
    \item This is preferable to walking the directory tree and reading
      every module.
    \item Why is every module file read: properties.
  \end{itemize}
\end{frame}

\begin{frame}{Spider Cache Disadvantages}
  \begin{itemize}
    \item There is only one: Keeping it up-to-date.
    \item If Lmod sees a valid cache file it assumes it is correct.
    \item Otherwise what's the point.
    \item Currently loads bypass cache but avail and spider depend on it.
    \item Personal modules are not effected by system cache foo.
  \end{itemize}
\end{frame}

\begin{frame}{Spider Cache Implementation}
  \begin{itemize}
    \item There is a cache directory
    \item A time stamp file that marks the last update date.
    \item You can have 1 or more of these pairs.
  \end{itemize}
\end{frame}

\begin{frame}{Spider Cache Building Strategies}
  \begin{itemize}
    \item Common tool to install (like losf)
      \begin{itemize}
        \item Use it to rebuild the cache when necessary
      \end{itemize}
    \item Using rpm or dpkg or similar to install software:
      \begin{itemize}
        \item Wrap rpm or dpkg to update the time-stamp file
        \item A cron job to rebuild the cache when necessary
      \end{itemize}
    \item Others?
  \end{itemize}
\end{frame}

\begin{frame}{Inherit}
  \begin{itemize}
    \item Imagine you are developer of a parallel library
    \item You are on a system deploying a software hierarchy
    \item How to take advantage of the system supplied layout?
  \end{itemize}
\end{frame}

\begin{frame}{Inherit (II)}
  \begin{itemize}
    \item Create a personal hierarchy for each compiler and MPI stack
      you want to test against.
    \item Then copy each system compiler and MPI modulefile into your
      personal hierarchy.
    \item Then add a \texttt{prepend\_path("MODULEPATH",...)} at the
      end.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Inherit Compiler Module }
  \begin{itemize}
    \item Or you can ``inherit'' the same named module in the hierarchy.
    \item For a compiler modulefile it can be:
    {\small
\begin{verbatim}
inherit()
local MyMRoot = os.getenv("MY_MODULE_ROOT")
local compN   = myModuleName()
local compV   = myModuleVersion():match("(%d+%.%d+)%.?")
prepend_path("MODULEPATH", pathJoin(myMRoot,
                                   "Compiler",compN,compV)
\end{verbatim}
}
    \item Using \texttt{\$MY\_MODULE\_ROOT/Compiler/C/CV}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Inherit MPI Module }
  \begin{itemize}
    \item Or you can ``inherit'' the same named module in the hierarchy.
    \item For a compiler modulefile it can be:
    {\small
\begin{verbatim}
inherit()
local MyMRoot  = os.getenv("MY_MODULE_ROOT")
local pkgName  = myModuleName()
local pkgV     = myModuleVersion():match("(%d+%.%d+)%.?")
local hierA    = hierarchyA(pkgName,1)
local comp     = hierA[1]
prepend_path("MODULEPATH", pathJoin(myMRoot,
                          "Compiler",comp, pkgName, pkgV)
\end{verbatim}
}
    \item Using \texttt{\$MY\_MODULE\_ROOT/Compiler/C/CV/M/MV}
  \end{itemize}
\end{frame}

\section{Lessons learned and Conclusions}

\begin{frame}{Lessons Learned}
  \begin{itemize}
    \item A very small percentage of Lmod users join the mailing list.
    \item Able support many requests for features but not all.
    \item Hardening:
      \begin{itemize}
        \item sandbox for evaluating modulefiles
        \item Checking argument types
        \item checkModuleSyntax script
      \end{itemize}
    \item Users sometimes ask the right question.
    \item Lmod is much better product because of its wider use.
  \end{itemize}
\end{frame}

\begin{frame}{Lessons Learned (II)}
  \begin{itemize}
    \item It is hard work developing a users' communities trust.
    \item Some site will be managed in a way that I have never dreamed of.
    \item I struggle with mistakes in design that I have to live with:
      \begin{itemize}
        \item is\_spider $\Rightarrow$ mode()
        \item set\_default, get\_default $\Rightarrow$ save, restore
        \item duplicate paths
      \end{itemize}
    \item Deprecating features is difficult with Lmod.
    \item Users would get deprecated feature reports that sys-admins
      must fix.
  \end{itemize}
\end{frame}


\begin{frame}{Regression Testing of Lmod}
  \begin{itemize}
    \item A suite of 60+ tests each with many steps.
    \item No release without passing all those tests.
    \item These tests make Lmod re-factoring much easier.
    \item The github repo is generally safe.
  \end{itemize}
\end{frame}

\begin{frame}{Remote Debugging}
  \begin{itemize}
    \item No software over ten lines is bug free.
    \item Lmod is no exception.
    \item Bug reports are as easy as:
      \begin{itemize}
        \item \texttt{module --config  2> config.log}
        \item \texttt{module -D avail  2> avail.log}
      \end{itemize}
    \item Sometimes I'll create test versions with more debugging for
      you to test.
  \end{itemize}
\end{frame}

\begin{frame}{Recommendations for Good Site Management}
  \begin{itemize}
    \item A module purge should not break things.
    \item Set \texttt{LMOD\_SYSTEM\_DEFAULT\_MODULES} so that module
      restore works.
    \item Encourage the use of "module save" so that users can have a
      default set of modules.
    \item Use the family directive to protect users.
    \item Consider the use of "checkModuleSyntax" before installing new modules.
  \end{itemize}
\end{frame}

\begin{frame}{Follow on projects from Lmod: Lariat}
  \begin{itemize}
    \item At TACC, we want to know what packages and libraries are
      user use.
    \item All parallel jobs at TACC use the script ``ibrun''.
    \item Lariat adds two tools to ibrun.
      \begin{itemize}
        \item checkExec
        \item parseLDD
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{CheckExec}
  \begin{itemize}
    \item At TACC, your build environment and your submit environment
      must match.
    \item checkExec does an ldd of your executable looking for particular MPI libraries.
    \item It then uses the ``reverse map'' to map MPI library to MPI
      module and compiler module.
    \item It also extract your current environment to see if they match.
    \item It generates a warning if they don't.
  \end{itemize}
\end{frame}

\begin{frame}{ParseLDD}
  \begin{itemize}
    \item The program parseLDD also does an ldd of your executable.
    \item It checks to see if the executable or the any of the shared
      libraries are TACC built modules.
    \item It records information for later analysis.
  \end{itemize}
\end{frame}

\begin{frame}{Lariat + ALTD $\Rightarrow$ XALT}
  \begin{itemize}
    \item Mark Fahey developed ALTD which records similar information.
    \item Mark and I won an NSF Grant to create XALT.
    \item Alpha users soon, Beta users summer of 2014.
  \end{itemize}
\end{frame}
\begin{frame}{Future Plans}
  \begin{itemize}
    \item Make Lmod available as rpm and debian packages.
    \item How to deal with libraries and applications that do not fit
      neatly into the hierarchy.
    \item \texttt{libmesh} http://libmesh.sourceforge.net/
      \begin{itemize}
        \item is a framework for solving 1D, 2D, 3D grid
          in parallel with support for AMR.
        \item It depends on boost, petsc, trilinos, grvy, ...
        \item If you are a developer how do you test it against
          multiple version of boost, petsc, etc.
        \item I'm still thinking about how to handle this ``Matrix'' dependency.
      \end{itemize}
    \item
  \end{itemize}
\end{frame}

\begin{frame}{Conclusions}
  \begin{itemize}
    \item Download source from: lmod.sourceforge.net (lmod.sf.net)
    \item GitHub repo: https://github.com/TACC/lmod.git
    \item Documentation: www.tacc.utexas.edu/tacc-projects/lmod
    \item Mailing list: lmod-users@lists.sourceforge.net
  \end{itemize}
\end{frame}


\begin{frame}{Projects to work on here}
  \begin{itemize}
    \item Install lua-5.1.4.8.tgz in the mclay account.
    \item Install Lmod in mclay account
    \item Use your personal version of Lmod.
    \item Create Personal modules.
    \item Generic Module file discussion.
    \item Talk about Software install issues at your site.
  \end{itemize}
\end{frame}

\end{document}
