Spack in a nutshell
A 10 minutes introduction to the tool
Spack is a package manager
- Tracks metadata for installed software
- Multiple configurations of the same software
- Support for supercomputers, linux and MacOS
- Builds from sources, supports binary packaging
- Can be used for deployment, development or QA
https://spack.io
Who can profit from Spack?
- End users of HPC software
- HPC application teams
- Package developers
- User support teams at HPC centers
Spack is open source
- Started by Todd Gamblin (LLNL, Lead Developer)
- Very active and engaging community
- Dual license Apache-2.0 or MIT
- Switched from LGPL to be company friendly
- Want to get buy-in and PRs by HPC vendors
https://github.com/spack/spack
Contributions to Spack
Spack is committed to be open source
Clone it and you're ready to go!
$ git clone https://github.com/spack/spack.git
$ . spack/share/spack/setup-env.sh
$ spack install hdf5
Packages are Python classes
class Kripke(Package):
"""Kripke is a simple, scalable, 3D Sn
deterministic particle transport mini app.
"""
homepage = "https://codesign.llnl.gov/kripke.php"
url = "https://codesign.llnl.gov/kripke-1.1.tar.gz"
version('1.1', '7fe6f2b26ed983a6ce5495ab701f85bf')
version('1.0', 'f4247dde07952a5ff866b24e45b5cdd1')
variant('mpi', default=True, description='Build with MPI.')
depends_on('mpi', when="+mpi")
Easy to work with packages
$ # Create a new package in the built-in repository
$ spack create <url>
$ # Modify an existing package
$ export EDITOR='emacs -nw'
$ spack edit <package-name>
$ # Scrape for versions of an existing package
$ spack versions <package-name>
Spack fights combinatorics with combinatorics!
Complexity of a typical HPC ecosystem
Software must be easy to use in any configuration
The spec syntax describes user's needs
$ # Install a specific version by appending @
$ spack install hdf5@1.10.1
$ # Specify a compiler (and optional version), with %
$ spack install hdf5@1.10.1 %gcc@4.7.3
$ # Add special boolean compile-time options with +
$ spack install hdf5@1.10.1 +szip
$ # Add custom compiler flags
$ spack install hdf5@1.10.1 cppflags="-O3 -floop-block"
$ # Cross-compile on a Cray or Blue Gene/Q
$ spack install hdf5@1.10.1 target=backend
Directives model allowed configurations
class Openblas(MakefilePackage):
"""OpenBLAS: An optimized BLAS library"""
homepage = 'http://www.openblas.net'
url = 'http://github.com/OpenBLAS/v0.2.19.tar.gz'
version('0.3.4', sha256='4b4b4453251')
version('0.3.3', sha256='49d88f4494a')
variant('shared', default=True,
description='Build shared libraries')
variant('ilp64', default=False,
description='64 bit integers')
conflicts('%intel@16', when='@0.2.15:0.2.19')
The concretizer fills in missing details
The abstract spec is turned into a concrete configuration
that can be installed
Each configuration is installed in its own prefix
All the software is installed in the Spack's store
The results of concretization can be queried
$ spack spec -Il hdf5+mpi ^mpich
Input spec
--------------------------------
- hdf5+mpi
- ^mpich
Concretized
--------------------------------
- wqoi56r hdf5@1.10.4%gcc@8.2.0~cxx~debug~fortran~hl+mpi+pic+shared~szip~threadsafe arch=linux-ubuntu18.04-x86_64
- k2mhs2k ^mpich@3.3%gcc@8.2.0 device=ch3 +hydra netmod=tcp +pmi+romio~verbs arch=linux-ubuntu18.04-x86_64
- rwrp443 ^findutils@4.6.0%gcc@8.2.0 patches=84b916c0bf8c51b7e7b28417692f0ad3e7030d1f3c248ba77c42ede5c1c5d11e,bd9e4e5cc280f9753ae14956c4e4aa17fe7a210f55dd6c84aa60b12d106d47a2 arch=linux-ubuntu18.04-x86_64
- vsawnwb ^autoconf@2.69%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- i3zd457 ^m4@1.4.18%gcc@8.2.0 patches=3877ab548f88597ab2327a2230ee048d2d07ace1062efe81fc92e91b7f39cd00,c0a408fbffb7255fcc75e26bd8edab116fc81d216bfd18b473668b7739a4158e,fc9b61654a3ba1a8d6cd78ce087e7c96366c290bc8d2c299f09828d793b853c8 +sigsegv arch=linux-ubuntu18.04-x86_64
- bd227q2 ^libsigsegv@2.11%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- 5pyk3t3 ^perl@5.26.2%gcc@8.2.0+cpanm patches=0eac10ed90aeb0459ad8851f88081d439a4e41978e586ec743069e8b059370ac +shared+threads arch=linux-ubuntu18.04-x86_64
- gota243 ^gdbm@1.18.1%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- ltrvf62 ^readline@7.0%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- 6mbvq7i ^ncurses@6.1%gcc@8.2.0~symlinks~termlib arch=linux-ubuntu18.04-x86_64
- zaevtj5 ^pkgconf@1.5.4%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- tcf52hq ^automake@1.16.1%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- rcuvdn3 ^libtool@2.4.6%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
- 3iz4m52 ^texinfo@6.5%gcc@8.2.0 arch=linux-ubuntu18.04-x86_64
[+] ivqu252 ^zlib@1.2.11%gcc@8.2.0+optimize+pic+shared arch=linux-ubuntu18.04-x86_64
Spack keeps the metadata of the software it installed!
Installed configurations are stored in a JSON file
{
"database": {
"installs": {
"ivqu252fvh7r5iar6zwx4fmeoxiykln7": {
"explicit": true,
"installation_time": 1548272929.178339,
"ref_count": 0,
"installed": true,
"path": "/home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-8.2.0/zlib-1.2.11-ivqu252fvh7r5iar6zwx4fmeoxiykln7",
"spec": {
"zlib": {
"version": "1.2.11",
"arch": {
"platform": "linux",
"platform_os": "ubuntu18.04",
"target": "x86_64"
},
"compiler": {
"name": "gcc",
"version": "8.2.0"
},
"namespace": "builtin",
"parameters": {
"optimize": true,
"pic": true,
"shared": true,
"cflags": [],
"cppflags": [],
"cxxflags": [],
"fflags": [],
"ldflags": [],
"ldlibs": []
}
}
}
}
},
"version": "0.9.3"
}
}
opt/spack/.spack-db/index.json
Provenance is preserved for each configuration
$ tree $(spack location -i hdf5)/.spack
<prefix>/.spack
├── archived-files
│ └── config.log
├── build.env
├── build.out
├── repos
│ └── builtin
│ ├── packages
│ │ ├── hdf5
│ │ │ └── package.py
│ │ └── zlib
│ │ └── package.py
│ └── repo.yaml
└── spec.yaml
6 directories, 7 files
The JSON database can be regenerated based on this information
Tools are then built over the data in the DB
- Query commands
- Uninstallation procedures
- Module file generation
- Python modules activation
- ...
Query what's installed from the command line
$ spack find zlib
==> 1 installed package
-- linux-ubuntu18.04-x86_64 / gcc@8.2.0 ----
zlib@1.2.11
$ spack find --start-date 'a month ago'
==> 3 installed packages
-- linux-ubuntu18.04-x86_64 / gcc@8.2.0 ----
hdf5@1.10.4 openblas@0.3.5 zlib@1.2.11
Uninstall anything in an easy and safe way
$ spack find zlib
==> 2 installed packages
-- linux-ubuntu18.04-x86_64 / gcc@8.2.0 ----
zlib@1.2.8 zlib@1.2.11
$ spack uninstall zlib@1.2.8
==> The following packages will be uninstalled:
-- linux-ubuntu18.04-x86_64 / gcc@8.2.0 ----
yxoie27 zlib@1.2.8%gcc+optimize+pic+shared
==> Do you want to proceed? [y/N] y
==> Successfully uninstalled zlib@1.2.8%gcc@8.2.0 [...] /yxoie27
Generate module files for HPC sites
- Output highly customizable using YAML files
- By default generated via post-install hooks
- Can be managed via command line afterwards
- Everything is powered by Jinja2 templates
- Support for both TCL and Lua modules
Tutorial: Spack 101 - module files
Generate module files for HPC sites
modules:
lmod:
core_compilers:
- gcc@4.8.5
hierarchy:
- mpi
- lapack
hash_length: 0
all:
suffixes:
+mpi: mpi
+openmp: openmp
...
Tutorial: Spack 101 - module files
Activate python modules on a fine-grained base
$ spack install python py-scipy py-numpy
[...]
$ # Activate only py-numpy
$ $ spack activate py-numpy
==> Activating extension py-numpy@1.15.2%gcc@8.2.0+blas+lapack arch=linux-ubuntu18.04-x86_64 /o626ufb for python@2.7.15%gcc@8.2.0+dbm~optimizations patches=123082ab3483ded78e86d7c809e98a804b3465b4683c96bd79a2fd799f572244 +pic+pythoncmd+shared~tk~ucs4 arch=linux-ubuntu18.04-x86_64 /nft4nfs
$ $(spack location -i python)/bin/python
Python 2.7.15 (default, Jan 25 2019, 09:14:19)
[GCC 8.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> import scipy
[...]
ImportError: No module named scipy
Activated modules look like they are site installed
Scrape build logs of installed configurations
$ spack log-parse $(spack location -i hdf5)/.spack/build.out
0 errors
$ spack log-parse --show=errors,warnings $(spack location -i hdf5)/.spack/build.out
0 errors
741 warnings
534 CC H5dbg.lo
535 CC H5system.lo
536 H5system.c: In function 'HDfprintf':
>> 537 H5system.c:276:45: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
538 n = fprintf(stream, format_templ, x);
539 ^~~~~~~~~~~~
[...]
Permits to investigate issues reported on
software that has already been deployed
Spack Environments
The cool new feature!
Spack's store might be inconvenient at times
$ spack find
==> 70 installed packages
-- linux-ubuntu16.04-x86_64 / clang@3.8.0-2ubuntu4 ----
tcl@8.6.8 zlib@1.2.8 zlib@1.2.11
-- linux-ubuntu16.04-x86_64 / gcc@4.7 ----
zlib@1.2.11
-- linux-ubuntu16.04-x86_64 / gcc@5.4.0 ----
adept-utils@1.0.1 hdf5@1.10.4 mpc@1.1.0
autoconf@2.69 hdf5@1.10.4 mpfr@3.1.6
automake@1.16.1 hdf5@1.10.4 mpich@3.2.1
boost@1.68.0 hwloc@1.11.9 mpileaks@1.0
bzip2@1.0.6 hypre@2.15.1 mumps@5.1.1
...
It would be nice to have a terser view without throwing away what's already installed
Spack environments to the rescue!
$ spack env create my-project
==> Created environment 'my-project' in [...]/my-project
$ spack env activate my-project
$ spack env status
==> In environment my-project
$ spack find
==> In environment my-project
==> No root specs
==> 0 installed packages
An environment is a virtualized Spack instance that can be used for a specific purpose
Environments use what's available in the store
$ spack find
==> In environment my-project
==> No root specs
==> 0 installed packages
$ spack install zlib hdf5~mpi
==> zlib is already installed in [...]
==> Installing hdf5
[...]
==> Successfully installed hdf5
Fetch: 0.06s. Build: 1m 14.67s. Total: 1m 14.73s.
[+] /home/.../hdf5-1.10.4-xucyflhbo2p47n46smfsqo7p2y3hijmd
zlib
has been reused, hdf5
has been installed
in the Spack's store and then added
Users can set-up groups of packages at once
$ spack add hdf5~mpi python
==> Adding hdf5~mpi to environment my-project
==> Adding python to environment my-project
==> Adding mpich to environment my-project
$ spack find -v
==> In environment my-project
==> Root specs
hdf5~mpi mpich python
==> 0 installed packages
$ spack install
[...]
"spack install
" concretizes the root specs and builds what's missing
Each detail can be finely tuned
$ spack config get
# This is a Spack Environment file.
#
# It describes a set of packages to be installed, along with
# configuration settings.
spack:
# add package specs to the `specs` list
specs: [hdf5~mpi, python, mpich]
mirrors: {}
modules:
enable: []
repos: []
packages: {}
config: {}
Use "spack config edit
" to edit the file and add custom configurations
Abstract user requests are stored in spack.yaml
- It's the configuration file we have seen before
- Does not have to live inside Spack tree
- Can be bundled with anything
- Can be manipulated directly if it is in the
pwd
- Use
spack.yaml
to distribute an environment
Fully concretized specs are in spack.lock
{
"concrete_specs": {
"teneqii2xv5u6zl5r6qi3pwurc6pmypz": {
"xz": {
"version": "5.2.4",
"arch": {
"platform": "linux",
"platform_os": "ubuntu16.04",
"target": "x86_64"
},
...
Using either spack.yaml
or spack.lock
you can recreate an environment
Coming soon in Spack environments...
Associate a view with an environment
spack:
specs:
- hdf5+mpi
- bzip2
view: True
|
$ ls .spack-env/view/bin
h5clear h5diff ... h5unjam
h5copy h5dump ... ph5diff
h5debug ... ...
$ ls .spack-env/view/include
H5ACpublic.h ... hdf5.h
H5Apublic.h ... zconf.h
H5Cpublic.h ... zlib.h
|
Views are projections of the Spack combinatorial space into a single prefix