QMCPACK package: update blas/lapack detection (#6753)

* Fix detection of blas and lapack: provide libraries/includes as
  arguments to CMake rather than using CMake's auto-detection.
  This includes a patch to QMCPACK's CMake files to refer to
  Spack-built blas/lapack implementations. This also includes
  special-case logic for the intel-mkl implementation of blas/lapack

* Break up unit tests and short tests. Only hard failure if the unit
  tests fail, if short tests fail issue a warning only.

* Add QMCPACK 3.3.0, get rid of 3.0.0
This commit is contained in:
Nichols A. Romero 2017-12-22 18:47:49 -06:00 committed by scheibelp
parent 0c1f4a7997
commit 24743b7e5a
2 changed files with 125 additions and 37 deletions

View File

@ -0,0 +1,55 @@
diff --git a/CMake/FindMKL.cmake b/CMake/FindMKL.cmake
index a457eaba0..66dc43ce6 100644
--- a/CMake/FindMKL.cmake
+++ b/CMake/FindMKL.cmake
@@ -7,21 +7,21 @@ FILE( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl.cxx"
"#include <iostream>\n #include <mkl.h>\n int main() { return 0; }\n" )
try_compile(HAVE_MKL ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl.cxx
- CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" )
+ CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" "-DINCLUDE_DIRECTORIES=${LAPACK_INCLUDE_DIRS}")
# Check for mkl_vml_functions.h
FILE( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl_vml.cxx"
"#include <iostream>\n #include <mkl_vml_functions.h>\n int main() { return 0; }\n" )
try_compile(HAVE_MKL_VML ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl_vml.cxx
- CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" )
+ CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" "-DINCLUDE_DIRECTORIES=${LAPACK_INCLUDE_DIRS}")
# Check for fftw3
FILE( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl_fftw3.cxx"
"#include <iostream>\n #include <fftw/fftw3.h>\n int main() { return 0; }\n" )
try_compile(HAVE_MKL_FFTW3 ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl_fftw3.cxx
- CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" )
+ CMAKE_FLAGS "${CMAKE_CXX_FLAGS} -mkl" "-DINCLUDE_DIRECTORIES=${LAPACK_INCLUDE_DIRS}")
IF ( HAVE_MKL )
SET( MKL_FOUND 1 )
diff --git a/CMake/FindVectorMath.cmake b/CMake/FindVectorMath.cmake
index c0c919746..f5c511253 100644
--- a/CMake/FindVectorMath.cmake
+++ b/CMake/FindVectorMath.cmake
@@ -19,7 +19,7 @@ IF ( NOT HAVE_VECTOR_MATH )
"#include <iostream>\n #include <mkl_vml_functions.h>\n int main() { return 0; }\n" )
try_compile(HAVE_MKL_VML ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src_mkl_vml.cxx
- CMAKE_FLAGS "${CMAKE_CXX_FLAGS}" )
+ CMAKE_FLAGS "${CMAKE_CXX_FLAGS}" "-DINCLUDE_DIRECTORIES=${LAPACK_INCLUDE_DIRS}")
IF (HAVE_MKL_VML)
# enable VML only when MKL libraries have been picked up
IF (MKL_FOUND)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 570d8a01f..56d939786 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -464,6 +464,8 @@ ELSE(CMAKE_TOOLCHAIN_FILE)
MESSAGE(STATUS "LAPACK libraries: ${LAPACK_LIBRARIES}")
MESSAGE(STATUS "LAPACK linker flags: ${LAPACK_LINKER_FLAGS}")
SET(LAPACK_LIBRARY ${LAPACK_LIBRARIES} ${LAPACK_LINKER_FLAGS})
+ MESSAGE(STATUS "LAPACK_INCLUDE_DIRS: ${LAPACK_INCLUDE_DIRS}")
+ INCLUDE_DIRECTORIES(${LAPACK_INCLUDE_DIRS})
ELSE()
MESSAGE(FATAL_ERROR "Could not find required libraries LAPACK &/or BLAS")
ENDIF()

View File

@ -23,6 +23,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
from spack import * from spack import *
import llnl.util.tty as tty
class Qmcpack(CMakePackage): class Qmcpack(CMakePackage):
@ -33,13 +34,14 @@ class Qmcpack(CMakePackage):
homepage = "http://www.qmcpack.org/" homepage = "http://www.qmcpack.org/"
url = "https://github.com/QMCPACK/qmcpack.git" url = "https://github.com/QMCPACK/qmcpack.git"
# This download method is untrusted, and is not recommended # This download method is untrusted, and is not recommended by the
# by the Spack manual. However, it is easier to maintain # Spack manual. However, it is easier to maintain because github hashes
# because github hashes can occasionally change # can occasionally change.
# NOTE: 12/19/2017 QMCPACK 3.0.0 does not build properly with Spack.
version('3.3.0', git=url, tag='v3.3.0')
version('3.2.0', git=url, tag='v3.2.0') version('3.2.0', git=url, tag='v3.2.0')
version('3.1.1', git=url, tag='v3.1.1') version('3.1.1', git=url, tag='v3.1.1')
version('3.1.0', git=url, tag='v3.1.0') version('3.1.0', git=url, tag='v3.1.0')
version('3.0.0', git=url, tag='v3.0.0')
version('develop', git=url) version('develop', git=url)
# These defaults match those in the QMCPACK manual # These defaults match those in the QMCPACK manual
@ -72,7 +74,9 @@ class Qmcpack(CMakePackage):
conflicts('^openblas+ilp64') conflicts('^openblas+ilp64')
conflicts('^intel-mkl+ilp64') conflicts('^intel-mkl+ilp64')
# Dependencies match those in the QMCPACK manual # Dependencies match those in the QMCPACK manual.
# FIXME: once concretizer can unite unconditional and conditional
# dependencies the some of the '~mpi' will not be necessary.
depends_on('cmake@3.4.3:', type='build') depends_on('cmake@3.4.3:', type='build')
depends_on('mpi', when='+mpi') depends_on('mpi', when='+mpi')
depends_on('libxml2') depends_on('libxml2')
@ -92,7 +96,7 @@ class Qmcpack(CMakePackage):
# blas and lapack patching fails often and so are disabled at this time # blas and lapack patching fails often and so are disabled at this time
depends_on('py-numpy~blas~lapack', type='run', when='+da') depends_on('py-numpy~blas~lapack', type='run', when='+da')
# GUI is optional fpr data anlysis # GUI is optional for data anlysis
# py-matplotlib leads to a long complex DAG for dependencies # py-matplotlib leads to a long complex DAG for dependencies
depends_on('py-matplotlib', type='run', when='+gui') depends_on('py-matplotlib', type='run', when='+gui')
@ -108,6 +112,10 @@ class Qmcpack(CMakePackage):
patches=patch(patch_url, sha256=patch_checksum), patches=patch(patch_url, sha256=patch_checksum),
when='~mpi') when='~mpi')
# This is Spack specific patch, we may need to enhance QMCPACK's CMake
# in the near future.
patch('cmake.diff')
def patch(self): def patch(self):
# FindLibxml2QMC.cmake doesn't check the environment by default # FindLibxml2QMC.cmake doesn't check the environment by default
# for libxml2, so we fix that. # for libxml2, so we fix that.
@ -116,22 +124,23 @@ def patch(self):
'CMake/FindLibxml2QMC.cmake') 'CMake/FindLibxml2QMC.cmake')
def cmake_args(self): def cmake_args(self):
spec = self.spec
args = [] args = []
if '+mpi' in self.spec: if '+mpi' in spec:
mpi = self.spec['mpi'] mpi = spec['mpi']
args.append('-DCMAKE_C_COMPILER={0}'.format(mpi.mpicc)) args.append('-DCMAKE_C_COMPILER={0}'.format(mpi.mpicc))
args.append('-DCMAKE_CXX_COMPILER={0}'.format(mpi.mpicxx)) args.append('-DCMAKE_CXX_COMPILER={0}'.format(mpi.mpicxx))
args.append('-DMPI_BASE_DIR:PATH={0}'.format(mpi.prefix)) args.append('-DMPI_BASE_DIR:PATH={0}'.format(mpi.prefix))
# Currently FFTW_HOME and LIBXML2_HOME are used by CMake. # Currently FFTW_HOME and LIBXML2_HOME are used by CMake.
# Any CMake warnings about other variables are benign. # Any CMake warnings about other variables are benign.
xml2_prefix = self.spec['libxml2'].prefix xml2_prefix = spec['libxml2'].prefix
args.append('-DLIBXML2_HOME={0}'.format(xml2_prefix)) args.append('-DLIBXML2_HOME={0}'.format(xml2_prefix))
args.append('-DLibxml2_INCLUDE_DIRS={0}'.format(xml2_prefix.include)) args.append('-DLibxml2_INCLUDE_DIRS={0}'.format(xml2_prefix.include))
args.append('-DLibxml2_LIBRARY_DIRS={0}'.format(xml2_prefix.lib)) args.append('-DLibxml2_LIBRARY_DIRS={0}'.format(xml2_prefix.lib))
fftw_prefix = self.spec['fftw'].prefix fftw_prefix = spec['fftw'].prefix
args.append('-DFFTW_HOME={0}'.format(fftw_prefix)) args.append('-DFFTW_HOME={0}'.format(fftw_prefix))
args.append('-DFFTW_INCLUDE_DIRS={0}'.format(fftw_prefix.include)) args.append('-DFFTW_INCLUDE_DIRS={0}'.format(fftw_prefix.include))
args.append('-DFFTW_LIBRARY_DIRS={0}'.format(fftw_prefix.lib)) args.append('-DFFTW_LIBRARY_DIRS={0}'.format(fftw_prefix.lib))
@ -140,15 +149,15 @@ def cmake_args(self):
args.append('-DHDF5_ROOT={0}'.format(self.spec['hdf5'].prefix)) args.append('-DHDF5_ROOT={0}'.format(self.spec['hdf5'].prefix))
# Default is MPI, serial version is convenient for cases, e.g. laptops # Default is MPI, serial version is convenient for cases, e.g. laptops
if '+mpi' in self.spec: if '+mpi' in spec:
args.append('-DQMC_MPI=1') args.append('-DQMC_MPI=1')
elif '~mpi' in self.spec: elif '~mpi' in spec:
args.append('-DQMC_MPI=0') args.append('-DQMC_MPI=0')
# Default is real-valued single particle orbitals # Default is real-valued single particle orbitals
if '+complex' in self.spec: if '+complex' in spec:
args.append('-DQMC_COMPLEX=1') args.append('-DQMC_COMPLEX=1')
elif '~complex' in self.spec: elif '~complex' in spec:
args.append('-DQMC_COMPLEX=0') args.append('-DQMC_COMPLEX=0')
# When '-DQMC_CUDA=1', CMake automatically sets: # When '-DQMC_CUDA=1', CMake automatically sets:
@ -157,44 +166,56 @@ def cmake_args(self):
# There is a double-precision CUDA path, but it is not as well # There is a double-precision CUDA path, but it is not as well
# tested. # tested.
if '+cuda' in self.spec: if '+cuda' in spec:
args.append('-DQMC_CUDA=1') args.append('-DQMC_CUDA=1')
elif '~cuda' in self.spec: elif '~cuda' in spec:
args.append('-DQMC_CUDA=0') args.append('-DQMC_CUDA=0')
# Mixed-precision versues double-precision CPU and GPU code # Mixed-precision versues double-precision CPU and GPU code
if '+mixed' in self.spec: if '+mixed' in spec:
args.append('-DQMC_MIXED_PRECISION=1') args.append('-DQMC_MIXED_PRECISION=1')
elif '~mixed' in self.spec: elif '~mixed' in spec:
args.append('-DQMC_MIXED_PRECISION=0') args.append('-DQMC_MIXED_PRECISION=0')
# New Structure-of-Array (SOA) code, much faster than default # New Structure-of-Array (SOA) code, much faster than default
# Array-of-Structure (AOS) code. # Array-of-Structure (AOS) code.
# No support for local atomic orbital basis. # No support for local atomic orbital basis.
if '+soa' in self.spec: if '+soa' in spec:
args.append('-DENABLE_SOA=1') args.append('-DENABLE_SOA=1')
elif '~soa' in self.spec: elif '~soa' in spec:
args.append('-DENABLE_SOA=0') args.append('-DENABLE_SOA=0')
# Manual Timers # Manual Timers
if '+timers' in self.spec: if '+timers' in spec:
args.append('-DENABLE_TIMERS=1') args.append('-DENABLE_TIMERS=1')
elif '~timers' in self.spec: elif '~timers' in spec:
args.append('-DENABLE_TIMERS=0') args.append('-DENABLE_TIMERS=0')
# # Proper MKL detection not working. # Proper detection of optimized BLAS and LAPACK.
# # Include MKL flags # Based on the code from the deal II Spack package:
# if 'intel-mkl' in self.spec: # https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/dealii/package.py
# args.append('-DBLA_VENDOR=Intel10_64lp_seq') #
# args.append('-DQMC_INCLUDE={0}'.format(join_path(env['MKLROOT'],'include'))) # Basically, we override CMake's auto-detection mechanism
return args # and use the Spack's interface instead
lapack_blas = spec['lapack'].libs + spec['blas'].libs
args.extend([
'-DLAPACK_FOUND=true',
'-DLAPACK_LIBRARIES=%s' % lapack_blas.joined(';')
])
# def setup_environment(self, spack_env, run_env): # Additionally, we need to pass the BLAS+LAPACK include directory for
# # Add MKLROOT/lib to the CMAKE_PREFIX_PATH to enable CMake to find # header files. Intel MKL requires special case due to differences in
# # MKL libraries. MKLROOT environment variable must be defined for # Darwin vs. Linux $MKLROOT naming schemes
# # this to work properly. if 'intel-mkl' in self.spec:
# if 'intel-mkl' in self.spec: args.append(
# spack_env.append_path('CMAKE_PREFIX_PATH',format(join_path(env['MKLROOT'],'lib'))) '-DLAPACK_INCLUDE_DIRS=%s' %
format(join_path(env['MKLROOT'], 'include')))
else:
args.append(
'-DLAPACK_INCLUDE_DIRS=%s;%s' % (
self.spec['lapack'].prefix.include,
self.spec['blas'].prefix.include))
return args
def install(self, spec, prefix): def install(self, spec, prefix):
"""Make the install targets""" """Make the install targets"""
@ -228,7 +249,19 @@ def install(self, spec, prefix):
def check(self): def check(self):
"""Run ctest after building binary. """Run ctest after building binary.
It can take over 24 hours to run all the regression tests, here we It can take over 24 hours to run all the regression tests, here we
only run the unit tests and short tests.""" only run the unit tests and short tests. If the unit tests fail,
the QMCPACK installation aborts. On the other hand, the short tests
are too strict and often fail, but are still useful to run. In the
future, the short tests will be more reasonable in terms of quality
assurance (i.e. they will not be so strict), but will be sufficient to
validate QMCPACK in production."""
with working_dir(self.build_directory): with working_dir(self.build_directory):
ctest('-L', 'unit') ctest('-L', 'unit')
try:
ctest('-R', 'short') ctest('-R', 'short')
except ProcessError:
warn = 'Unit tests passed, but short tests have failed.\n'
warn += 'Please review failed tests before proceeding\n'
warn += 'with production calculations.\n'
tty.msg(warn)