diff options
Diffstat (limited to 'var')
-rw-r--r-- | var/spack/repos/builtin/packages/hpcc/package.py | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/var/spack/repos/builtin/packages/hpcc/package.py b/var/spack/repos/builtin/packages/hpcc/package.py new file mode 100644 index 0000000000..9ca9b31dbe --- /dev/null +++ b/var/spack/repos/builtin/packages/hpcc/package.py @@ -0,0 +1,207 @@ +# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +from spack import * +import os +import re +import platform + + +class Hpcc(MakefilePackage): + """HPC Challenge is a benchmark suite that measures a range memory access + patterns. + The HPC Challenge benchmark consists of basically 7 tests: + 1) HPL - the Linpack TPP benchmark which measures the floating point + rate of execution for solving a linear system of equations. + 2) DGEMM - measures the floating point rate of execution of double + precision real matrix-matrix multiplication. + 3) STREAM - a simple synthetic benchmark program that measures + sustainable memory bandwidth (in GB/s) and + the corresponding computation rate for simple vector kernel. + 4) PTRANS (parallel matrix transpose) - exercises the communications + where pairs of processors communicate + with each other simultaneously. It is a useful test of the total + communications capacity of the network. + 5) RandomAccess - measures the rate of integer random updates of memory + (GUPS). + 6) FFT - measures the floating point rate of execution of double + precision complex one-dimensional Discrete Fourier Transform (DFT). + 7) Communication bandwidth and latency - a set of tests to measure + latency and bandwidth of a number of simultaneous communication + patterns; based on b_eff (effective bandwidth benchmark).""" + + homepage = "http://icl.cs.utk.edu/hpcc" + url = "http://icl.cs.utk.edu/projectsfiles/hpcc/download/hpcc-1.5.0.tar.gz" + git = "https://github.com/icl-utk-edu/hpcc.git" + + version('develop', branch='main') + version('1.5.0', sha256='0a6fef7ab9f3347e549fed65ebb98234feea9ee18aea0c8f59baefbe3cf7ffb8') + + variant( + 'fft', default='internal', description='FFT library to use', + values=('internal', 'fftw2', 'mkl'), multi=False + ) + + depends_on('gmake', type='build') + depends_on('mpi@1.1:') + depends_on('blas') + depends_on('fftw-api@2+mpi', when='fft=fftw2') + depends_on('mkl', when='fft=mkl') + + arch = '{0}-{1}'.format(platform.system(), platform.processor()) + + config = { + '@SHELL@': '/bin/sh', + '@CD@': 'cd', + '@CP@': 'cp', + '@LN_S@': 'ln -s', + '@MKDIR@': 'mkdir', + '@RM@': '/bin/rm -f', + '@TOUCH@': 'touch', + '@ARCHIVER@': 'ar', + '@ARFLAGS@': 'r', + '@RANLIB@': 'echo', + '@ARCH@': arch, + '@MPDIR@': '', + '@MPINC@': '', + '@MPLIB@': '', + '@F2CDEFS@': '-DAdd_ -DF77_INTEGER=int -DStringSunStyle', + '@LADIR@': '', + '@LAINC@': '', + '@LALIB@': '', + '@CC@': None, + '@CCNOOPT@': '', + '@CCFLAGS@': '-O3', + '@LINKER@': '$(CC)', + '@LINKFLAGS@': '' + } + + def patch(self): + if 'fftw' in self.spec: + # spack's fftw2 prefix headers with floating point type + filter_file(r"^\s*#include <fftw.h>", "#include <sfftw.h>", + "FFT/wrapfftw.h") + filter_file(r"^\s*#include <fftw_mpi.h>", "#include <sfftw_mpi.h>", + "FFT/wrapmpifftw.h") + + def _write_make_arch(self, spec, prefix): + """write make.arch file""" + with working_dir('hpl'): + # copy template make.arch file + make_arch_filename = 'Make.{0}'.format(self.arch) + copy(join_path('setup', 'Make.UNKNOWN.in'), make_arch_filename) + + # fill template with values + make_arch = FileFilter(make_arch_filename) + for k, v in self.config.items(): + make_arch.filter(k, v) + + def edit(self, spec, prefix): + # Message Passing library (MPI) + self.config['@MPINC@'] = spec['mpi'].headers.include_flags + self.config['@MPLIB@'] = spec['mpi'].libs.search_flags + + lin_alg_libs = [] + # FFT + if self.spec.variants['fft'].value in ('fftw2', 'mkl'): + self.config['@LAINC@'] += ' -DUSING_FFTW' + + if self.spec.variants['fft'].value == 'fftw2': + self.config['@LAINC@'] += \ + spec['fftw-api'].headers.include_flags + # fftw does not set up libs for version 2 + lin_alg_libs.append( + join_path(spec['fftw-api'].prefix.lib, 'libsfftw_mpi.so')) + lin_alg_libs.append( + join_path(spec['fftw-api'].prefix.lib, 'libsfftw.so')) + + elif self.spec.variants['fft'].value == 'mkl' and '^mkl' in spec: + mklroot = env['MKLROOT'] + self.config['@LAINC@'] += \ + ' -I{0}'.format(join_path(mklroot, 'include/fftw')) + libfftw2x_cdft = join_path( + mklroot, 'lib', 'intel64', 'libfftw2x_cdft_DOUBLE_ilp64.a') + libfftw2xc = join_path( + mklroot, 'lib', 'intel64', 'libfftw2xc_double_intel.a') + if not (os.path.exists(libfftw2x_cdft) and + os.path.exists(libfftw2xc)): + raise InstallError( + "HPCC need fftw2 interface, " + "here are brief notes how to make one:\n" + "# make fftw2x_cdft interface to mkl\n" + "cd $MKLROOT/interfaces/fftw2x_cdft\n" + "make libintel64 PRECISION=MKL_DOUBLE " + "interface=ilp64 MKLROOT=$MKLROOT\n" + "\n" + "# make FFTW C wrapper library\n" + "cd $MKLROOT/interfaces/fftw2xc\n" + "make libintel64 PRECISION=MKL_DOUBLE " + "MKLROOT=$MKLROOT\n") + lin_alg_libs.append(libfftw2xc) + lin_alg_libs.append(libfftw2x_cdft) + + # Linear Algebra library (BLAS or VSIPL) + self.config['@LAINC@'] = spec['blas'].headers.include_flags + lin_alg_libs = lin_alg_libs + [ + lib for lib in spec['blas'].libs if lib not in lin_alg_libs] + + # pack all LA/FFT libraries + self.config['@LALIB@'] = ' '.join(lin_alg_libs) + + # Compilers / linkers - Optimization flags + self.config['@CC@'] = '{0}'.format(spec['mpi'].mpicc) + + # Compiler flags for CPU architecture optimizations + if spec.satisfies('%intel'): + # with intel-parallel-studio+mpi the '-march' arguments + # are not passed to icc + arch_opt = spec.target.optimization_flags( + spec.compiler.name, spec.compiler.version) + self.config['@CCFLAGS@'] = \ + '-O3 -restrict -ansi-alias -ip {0}'.format(arch_opt) + self.config['@CCNOOPT@'] = '-restrict' + self._write_make_arch(spec, prefix) + + def build(self, spec, prefix): + make('arch={0}'.format(self.arch)) + + def check(self): + """Simple check that compiled binary is working: + launch with 4 MPI processes and check that test finished.""" + # copy input + copy('_hpccinf.txt', 'hpccinf.txt') + # run test + run = Executable( + join_path(os.path.dirname(self.spec['mpi'].mpicc), 'mpirun')) + run('-np', '4', './hpcc') + # check output + hpccoutf = open('hpccoutf.txt', 'rt').read() + if not re.search("End of HPC Challenge tests", hpccoutf): + raise Exception("Test run was not successfull!") + + def installcheck(self): + """Same as check but within prefix location""" + with working_dir(self.prefix.share.hpcc): + # run test + run = Executable( + join_path(os.path.dirname(self.spec['mpi'].mpicc), 'mpirun')) + run('-np', '4', self.prefix.bin.hpcc) + # check output + hpccoutf = open('hpccoutf.txt', 'rt').read() + if not re.search("End of HPC Challenge tests", hpccoutf): + raise Exception("Test run was not successfull!") + + def install(self, spec, prefix): + # copy executable + mkdirp(self.prefix.bin) + install('hpcc', prefix.bin) + # copy input example + mkdirp(self.prefix.share.hpcc) + install('_hpccinf.txt', + join_path(self.prefix.share.hpcc, 'hpccinf.txt')) + # copy documentation + mkdirp(self.prefix.doc.hpcc) + install('README.html', self.prefix.doc.hpcc) + install('README.txt', self.prefix.doc.hpcc) |