From f5f98ca941b785a904b9a13dad9a55538d3f08d0 Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 17 Feb 2020 11:16:05 +0100 Subject: [PATCH 01/10] Added lammps easyblock; added .idea to gitignore --- .gitignore | 1 + easybuild/easyblocks/l/lammps.py | 357 +++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 easybuild/easyblocks/l/lammps.py diff --git a/.gitignore b/.gitignore index 4b67ea8dfa..a45816047f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea .pydevproject .project LICENSE_HEADER diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py new file mode 100644 index 0000000000..5cde3d3b41 --- /dev/null +++ b/easybuild/easyblocks/l/lammps.py @@ -0,0 +1,357 @@ +## +# Copyright 2009-2020 Ghent University +# +# This file is part of EasyBuild, +# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), +# with support of Ghent University (http://ugent.be/hpc), +# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en), +# the Hercules foundation (http://www.herculesstichting.be/in_English) +# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en). +# +# https://github.com/easybuilders/easybuild +# +# EasyBuild is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation v2. +# +# EasyBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with EasyBuild. If not, see . +## +""" +@author: Pavel Grochal (INUITS) +""" + +import glob +import os +import shutil +import sys + +from easybuild.easyblocks.generic.cmakemake import CMakeMake +from easybuild.framework.easyconfig import CUSTOM, MANDATORY +from easybuild.tools import toolchain +from easybuild.tools.build_log import EasyBuildError, print_warning +from easybuild.tools.config import build_option +from easybuild.tools.modules import get_software_root, get_software_version +from easybuild.tools.run import run_cmd +from easybuild.tools.systemtools import get_cpu_features, get_shared_lib_ext + + +KOKKOS_CPU_ARCH_LIST = [ + 'ARMv80', # ARMv8.0 Compatible CPU + 'ARMv81', # ARMv8.1 Compatible CPU + 'ARMv8-ThunderX', # ARMv8 Cavium ThunderX CPU + 'BGQ', # IBM Blue Gene/Q CPUs + 'Power8', # IBM POWER8 CPUs + 'Power9', # IBM POWER9 CPUs + 'SNB', # Intel Sandy/Ivy Bridge CPUs + 'HSW', # Intel Haswell CPUs + 'BDW', # Intel Broadwell Xeon E-class CPUs + 'SKX', # Intel Sky Lake Xeon E-class HPC CPUs (AVX512) + 'KNC', # Intel Knights Corner Xeon Phi + 'KNL', # Intel Knights Landing Xeon Phi +] + + +KOKKOS_GPU_ARCH_TABLE = { + "3.0": "Kepler30", # NVIDIA Kepler generation CC 3.0 + "3.2": "Kepler32", # NVIDIA Kepler generation CC 3.2 + "3.5": "Kepler35", # NVIDIA Kepler generation CC 3.5 + "3.7": "Kepler37", # NVIDIA Kepler generation CC 3.7 + "5.0": "Maxwell50", # NVIDIA Maxwell generation CC 5.0 + "5.2": "Maxwell52", # NVIDIA Maxwell generation CC 5.2 + "5.3": "Maxwell53", # NVIDIA Maxwell generation CC 5.3 + "6.0": "Pascal60", # NVIDIA Pascal generation CC 6.0 + "6.1": "Pascal61", # NVIDIA Pascal generation CC 6.1 + "7.0": "Volta70", # NVIDIA Volta generation CC 7.0 + "7.2": "Volta72", # NVIDIA Volta generation CC 7.2 + "7.5": "Turing75", # NVIDIA Turing generation CC 7.5 +} + + +class EB_LAMMPS(CMakeMake): + """ + Support for building and installing LAMMPS + """ + + @staticmethod + def extra_options(): + """Custom easyconfig parameters for LAMMPS""" + + extra_vars = { + # see https://developer.nvidia.com/cuda-gpus + 'cuda_compute_capabilities': [[], "List of CUDA compute capabilities to build with", CUSTOM], + 'general_packages': [None, "List of general packages without `PKG_` prefix.", MANDATORY], + 'kokkos': [True, "Enable kokkos build. (enabled by default)", CUSTOM], + 'kokkos_arch': [None, "Set kokkos processor arch to specific value, if auto-detection doesn't work.", CUSTOM], + 'user_packages': [None, "List user packages without `PKG_USER-` prefix.", MANDATORY], + } + return CMakeMake.extra_options(extra_vars) + + def configure_step(self): + """Custom configuration procedure for LAMMPS.""" + + cuda = get_software_root('CUDA') + # list of CUDA compute capabilities to use can be specifed in two ways (where (2) overrules (1)): + # (1) in the easyconfig file, via the custom cuda_compute_capabilities; + # (2) in the EasyBuild configuration, via --cuda-compute-capabilities configuration option; + ec_cuda_cc = self.cfg['cuda_compute_capabilities'] + cfg_cuda_cc = build_option('cuda_compute_capabilities') + cuda_cc = cfg_cuda_cc or ec_cuda_cc or [] + + # cmake has its own folder + self.cfg['srcdir'] = os.path.join(self.start_dir, 'cmake') + + # verbose CMake + if '-DCMAKE_VERBOSE_MAKEFILE=' not in self.cfg['configopts']: + self.cfg.update('configopts','-DCMAKE_VERBOSE_MAKEFILE=yes') + + # Enable following packages, if not configured in easycofig + default_options = [ + 'BUILD_DOC', 'BUILD_EXE', 'BUILD_LIB', + 'BUILD_SHARED_LIBS', 'BUILD_TOOLS', + ] + for option in default_options: + if "-D%s=" % option not in self.cfg['configopts']: + self.cfg.update('configopts','-D%s=on' % option) + + # Is there a gzip + if '-DWITH_GZIP=' not in self.cfg['configopts']: + if get_software_root('gzip'): + self.cfg.update('configopts','-DWITH_GZIP=yes') + else: + self.cfg.update('configopts','-DWITH_GZIP=no') + + # Is there a libpng + if '-DWITH_PNG=' not in self.cfg['configopts']: + if get_software_root('libpng'): + self.cfg.update('configopts','-DWITH_PNG=yes') + else: + self.cfg.update('configopts','-DWITH_PNG=no') + + # Is there a libjpeg-turbo + if '-DWITH_JPEG=' not in self.cfg['configopts']: + if get_software_root('libjpeg-turbo'): + self.cfg.update('configopts','-DWITH_JPEG=yes') + else: + self.cfg.update('configopts','-DWITH_JPEG=no') + + # With Eigen dependency: + if '-DDOWNLOAD_EIGEN3=' not in self.cfg['configopts']: + self.cfg.update('configopts','-DDOWNLOAD_EIGEN3=no') + # Compiler complains about 'Eigen3_DIR' not beeing set, but acutally it needs + # 'EIGEN3_INCLUDE_DIR'. + # see: https://github.com/lammps/lammps/issues/1110 + if '-DEIGEN3_INCLUDE_DIR=' not in self.cfg['configopts']: + if get_software_root('Eigen'): + self.cfg.update('configopts','-DEIGEN3_INCLUDE_DIR=%s/include/Eigen' % get_software_root('Eigen')) + + if '-DEigen3_DIR=' not in self.cfg['configopts']: + if get_software_root('Eigen'): + self.cfg.update('configopts','-DEigen3_DIR=%s/share/eigen3/cmake/' % get_software_root('Eigen')) + + # LAMMPS Configuration Options + # https://github.com/lammps/lammps/blob/master/cmake/README.md#lammps-configuration-options + if self.cfg['general_packages']: + for package in self.cfg['general_packages']: + self.cfg.update('configopts', '-DPKG_%s=on' % package) + + if self.cfg['user_packages']: + for package in self.cfg['user_packages']: + self.cfg.update('configopts', '-DPKG_USER-%s=on' % package) + + # Optimization settings + if '-DPKG_OPT=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DPKG_OPT=on') + + if '-DPKG_USR-INTEL=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DPKG_USER-INTEL=on') + + # MPI/OpenMP + if self.toolchain.options.get('usempi', None): + self.cfg.update('configopts', '-DBUILD_MPI=yes') + if self.toolchain.options.get('openmp', None): + self.cfg.update('configopts', '-DBUILD_OMP=yes') + self.cfg.update('configopts', '-DPKG_USER-OMP=on') + + # FFT + if '-DFFT=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DFFT=FFTW3') + if '-DFFT_PACK=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DFFT_PACK=array') + + # https://lammps.sandia.gov/doc/Build_extras.html + # KOKKOS + if self.cfg['kokkos']: + + if self.toolchain.options.get('openmp', None): + self.cfg.update('configopts', '-DKOKKOS_ENABLE_OPENMP=yes') + + self.cfg.update('configopts', '-DPKG_KOKKOS=on') + self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_gpu_arch(cuda_cc) ) + + # if KOKKOS and CUDA + if cuda: + self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) + nvcc_wrapper_path = os.path.join(self.start_dir, "lib","kokkos", "bin", "nvcc_wrapper") + # nvcc_wrapper can't find OpenMP for some reason, need to specify OpenMP flags. + # https://software.intel.com/en-us/forums/intel-oneapi-base-toolkit/topic/842470 + self.cfg.update('configopts', '-DOpenMP_CXX_FLAGS="-qopenmp"') + self.cfg.update('configopts', '-DOpenMP_CXX_LIB_NAMES="libiomp5"') + self.cfg.update('configopts', '-DOpenMP_libiomp5_LIBRARY=$EBROOTICC/lib/intel64_lin/libiomp5.so') + + self.cfg.update('configopts', '-DKOKKOS_ENABLE_CUDA=yes') + self.cfg.update('configopts', '-DCMAKE_CXX_COMPILER="%s"' % nvcc_wrapper_path) + self.cfg.update('configopts', '-DCMAKE_CXX_FLAGS="-ccbin $CXX $CXXFLAGS"') + + # CUDA only + elif cuda: + self.cfg.update('configopts', '-DPKG_GPU=on') + self.cfg.update('configopts', '-DGPU_API=cuda') + + self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) + self.cfg.update('configopts', '-DGPU_ARCH=%s' % self.get_cuda_gpu_arch(cuda_cc)) + + return super(EB_LAMMPS, self).configure_step() + + # This might be needed - keep it as reference + # def build_step(self): + # if self.cfg['kokkos'] and get_software_root('CUDA'): + # self.cfg.update('prebuildopts', 'export NVCC_WRAPPER_DEFAULT_COMPILER=$MPICXX &&') + # return super(EB_LAMMPS, self).build_step() + + def sanity_check_step(self, *args, **kwargs): + check_files = [ + 'atm', 'balance', 'colloid', 'crack', 'dipole', 'friction', + 'hugoniostat', 'indent', 'melt', 'message', 'min', 'msst', + 'nemd', 'obstacle', 'pour', 'voronoi', + ] + + custom_commands = [ + # LAMMPS test - you need to call specific test file on path + """python -c 'from lammps import lammps; l=lammps(); l.file("%s")'""" % + # The path is joined by "build_dir" (start_dir)/examples/filename/in.filename + os.path.join(self.start_dir, "examples", "%s" % check_file, "in.%s" % check_file) + # And this should be done for every file specified above + for check_file in check_files + ] + + pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) + pythonpath = os.path.join('lib','python%s' % pyshortver,'site-packages') + shlib_ext = get_shared_lib_ext() + custom_paths = { + 'files': [ + 'bin/lmp', + 'include/lammps/library.h', + 'lib64/liblammps.%s' % shlib_ext, + ], + 'dirs': [pythonpath], + } + + return super(EB_LAMMPS, self).sanity_check_step( + custom_commands=custom_commands, + custom_paths=custom_paths + ) + + def make_module_extra(self): + """Add install path to PYTHONPATH""" + + txt = super(EB_LAMMPS, self).make_module_extra() + + pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) + pythonpath = os.path.join('lib','python%s' % pyshortver,'site-packages') + + txt += self.module_generator.prepend_paths('PYTHONPATH', [pythonpath, "lib64"]) + txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', ["lib64"]) + + return txt + + def get_cuda_gpu_arch(self, cuda_cc): + cuda_cc.sort(reverse=True) + return 'sm_%' % str(cuda_cc[0]).replace(".", "") + + def get_kokkos_gpu_arch(self, cuda_cc): + # see: https://lammps.sandia.gov/doc/Build_extras.html#kokkos + cuda = get_software_root('CUDA') + processor_arch = None + + if self.cfg['kokkos_arch']: + if self.cfg['kokkos_arch'] not in KOKKOS_CPU_ARCH_LIST: + warning_msg = "Specified CPU ARCH (%s) " % self.cfg['kokkos_arch'] + warning_msg += "was not found in listed options [%s]." % KOKKOS_CPU_ARCH_LIST + warning_msg += "Still might work though." + print_warning(warning_msg) + processor_arch = self.cfg['kokkos_arch'] + + else: + warning_msg = "kokkos_arch not set. Trying to auto-detect CPU arch." + print_warning(warning_msg) + + cpu_arch = self.get_cpu_arch() + + if cpu_arch == "sandybridge" or cpu_arch == "ivybridge": + processor_arch = 'SNB' + elif cpu_arch == "haswell": + processor_arch = 'HSW' + elif cpu_arch == "broadwell": + processor_arch = 'BDW' + elif cpu_arch == "skylake": + processor_arch = 'SKX' + elif cpu_arch == "knights-landing": + processor_arch = 'KNL' + else: + error_msg = "Couldn't determine CPU architecture, you need to set 'kokkos_arch' manually." + raise EasyBuildError(error_msg) + exit(1) + print("Determined cpu arch: %s" % processor_arch) + + if not cuda: + return processor_arch + + # CUDA below + cuda_cc.sort(reverse=True) + gpu_arch = None + for cc in cuda_cc: + gpu_arch = KOKKOS_GPU_ARCH_TABLE.get(str(cc)) + if gpu_arch: + break + else: + warning_msg = "(%s) GPU ARCH was not found in listed options." % cc + print_warning(warning_msg) + + if not gpu_arch: + error_msg = "Specified GPU ARCH (%s) " % cuda_cc + error_msg += "was not found in listed options [%s]." % KOKKOS_GPU_ARCH_TABLE + raise EasyBuildError(error_msg) + return "%s;%s" % (processor_arch, gpu_arch) + + def check_cuda_compute_capabilities(self, cfg_cuda_cc, ec_cuda_cc, cuda_cc): + cuda = get_software_root('CUDA') + + if cuda: + if cfg_cuda_cc and ec_cuda_cc: + warning_msg = "cuda_compute_capabilities specified in easyconfig (%s) are overruled by " % self.ec_cuda_cc + warning_msg += "--cuda-compute-capabilities configuration option (%s)" % self.cfg_cuda_cc + print_warning(warning_msg) + elif not cuda_cc: + error_msg = "No CUDA compute capabilities specified.\nTo build LAMMPS with Cuda you need to use" + error_msg += "the --cuda-compute-capabilities configuration option or the cuda_compute_capabilities " + error_msg += "easyconfig parameter to specify a list of CUDA compute capabilities to compile with." + raise EasyBuildError(error_msg) + + elif cuda_cc: + warning_msg = "Missing CUDA package (in dependencies), but 'cuda_compute_capabilities' option was specified." + print_warning(warning_msg) + + return cuda_cc + + def get_cpu_arch(self): + out, ec = run_cmd("python -c 'from archspec.cpu import host; print(host())'", simple=False) + if ec: + raise EasyBuildError("Failed to determine CPU architecture: %s", out) + # transform: 'skylake_avx512\n' => 'skylake' + return out.strip().split("_")[0] From e8b3649ba3d62fb6c3e200e4101f07df1e37933c Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 17 Feb 2020 11:32:49 +0100 Subject: [PATCH 02/10] Fixed PEP errors --- easybuild/easyblocks/l/lammps.py | 67 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 5cde3d3b41..942689ba5f 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -33,27 +33,26 @@ from easybuild.easyblocks.generic.cmakemake import CMakeMake from easybuild.framework.easyconfig import CUSTOM, MANDATORY -from easybuild.tools import toolchain from easybuild.tools.build_log import EasyBuildError, print_warning from easybuild.tools.config import build_option from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import get_cpu_features, get_shared_lib_ext +from easybuild.tools.systemtools import get_shared_lib_ext KOKKOS_CPU_ARCH_LIST = [ - 'ARMv80', # ARMv8.0 Compatible CPU - 'ARMv81', # ARMv8.1 Compatible CPU - 'ARMv8-ThunderX', # ARMv8 Cavium ThunderX CPU - 'BGQ', # IBM Blue Gene/Q CPUs - 'Power8', # IBM POWER8 CPUs - 'Power9', # IBM POWER9 CPUs - 'SNB', # Intel Sandy/Ivy Bridge CPUs - 'HSW', # Intel Haswell CPUs - 'BDW', # Intel Broadwell Xeon E-class CPUs - 'SKX', # Intel Sky Lake Xeon E-class HPC CPUs (AVX512) - 'KNC', # Intel Knights Corner Xeon Phi - 'KNL', # Intel Knights Landing Xeon Phi + 'ARMv80', # ARMv8.0 Compatible CPU + 'ARMv81', # ARMv8.1 Compatible CPU + 'ARMv8-ThunderX', # ARMv8 Cavium ThunderX CPU + 'BGQ', # IBM Blue Gene/Q CPUs + 'Power8', # IBM POWER8 CPUs + 'Power9', # IBM POWER9 CPUs + 'SNB', # Intel Sandy/Ivy Bridge CPUs + 'HSW', # Intel Haswell CPUs + 'BDW', # Intel Broadwell Xeon E-class CPUs + 'SKX', # Intel Sky Lake Xeon E-class HPC CPUs (AVX512) + 'KNC', # Intel Knights Corner Xeon Phi + 'KNL', # Intel Knights Landing Xeon Phi ] @@ -87,7 +86,7 @@ def extra_options(): 'cuda_compute_capabilities': [[], "List of CUDA compute capabilities to build with", CUSTOM], 'general_packages': [None, "List of general packages without `PKG_` prefix.", MANDATORY], 'kokkos': [True, "Enable kokkos build. (enabled by default)", CUSTOM], - 'kokkos_arch': [None, "Set kokkos processor arch to specific value, if auto-detection doesn't work.", CUSTOM], + 'kokkos_arch': [None, "Set kokkos processor arch manually, if auto-detection doesn't work.", CUSTOM], 'user_packages': [None, "List user packages without `PKG_USER-` prefix.", MANDATORY], } return CMakeMake.extra_options(extra_vars) @@ -108,7 +107,7 @@ def configure_step(self): # verbose CMake if '-DCMAKE_VERBOSE_MAKEFILE=' not in self.cfg['configopts']: - self.cfg.update('configopts','-DCMAKE_VERBOSE_MAKEFILE=yes') + self.cfg.update('configopts', '-DCMAKE_VERBOSE_MAKEFILE=yes') # Enable following packages, if not configured in easycofig default_options = [ @@ -117,42 +116,42 @@ def configure_step(self): ] for option in default_options: if "-D%s=" % option not in self.cfg['configopts']: - self.cfg.update('configopts','-D%s=on' % option) + self.cfg.update('configopts', '-D%s=on' % option) # Is there a gzip if '-DWITH_GZIP=' not in self.cfg['configopts']: if get_software_root('gzip'): - self.cfg.update('configopts','-DWITH_GZIP=yes') + self.cfg.update('configopts', '-DWITH_GZIP=yes') else: - self.cfg.update('configopts','-DWITH_GZIP=no') + self.cfg.update('configopts', '-DWITH_GZIP=no') # Is there a libpng if '-DWITH_PNG=' not in self.cfg['configopts']: if get_software_root('libpng'): - self.cfg.update('configopts','-DWITH_PNG=yes') + self.cfg.update('configopts', '-DWITH_PNG=yes') else: - self.cfg.update('configopts','-DWITH_PNG=no') + self.cfg.update('configopts', '-DWITH_PNG=no') # Is there a libjpeg-turbo if '-DWITH_JPEG=' not in self.cfg['configopts']: if get_software_root('libjpeg-turbo'): - self.cfg.update('configopts','-DWITH_JPEG=yes') + self.cfg.update('configopts', '-DWITH_JPEG=yes') else: - self.cfg.update('configopts','-DWITH_JPEG=no') + self.cfg.update('configopts', '-DWITH_JPEG=no') # With Eigen dependency: if '-DDOWNLOAD_EIGEN3=' not in self.cfg['configopts']: - self.cfg.update('configopts','-DDOWNLOAD_EIGEN3=no') + self.cfg.update('configopts', '-DDOWNLOAD_EIGEN3=no') # Compiler complains about 'Eigen3_DIR' not beeing set, but acutally it needs # 'EIGEN3_INCLUDE_DIR'. # see: https://github.com/lammps/lammps/issues/1110 if '-DEIGEN3_INCLUDE_DIR=' not in self.cfg['configopts']: if get_software_root('Eigen'): - self.cfg.update('configopts','-DEIGEN3_INCLUDE_DIR=%s/include/Eigen' % get_software_root('Eigen')) + self.cfg.update('configopts', '-DEIGEN3_INCLUDE_DIR=%s/include/Eigen' % get_software_root('Eigen')) if '-DEigen3_DIR=' not in self.cfg['configopts']: if get_software_root('Eigen'): - self.cfg.update('configopts','-DEigen3_DIR=%s/share/eigen3/cmake/' % get_software_root('Eigen')) + self.cfg.update('configopts', '-DEigen3_DIR=%s/share/eigen3/cmake/' % get_software_root('Eigen')) # LAMMPS Configuration Options # https://github.com/lammps/lammps/blob/master/cmake/README.md#lammps-configuration-options @@ -192,12 +191,12 @@ def configure_step(self): self.cfg.update('configopts', '-DKOKKOS_ENABLE_OPENMP=yes') self.cfg.update('configopts', '-DPKG_KOKKOS=on') - self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_gpu_arch(cuda_cc) ) + self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_gpu_arch(cuda_cc)) # if KOKKOS and CUDA if cuda: self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) - nvcc_wrapper_path = os.path.join(self.start_dir, "lib","kokkos", "bin", "nvcc_wrapper") + nvcc_wrapper_path = os.path.join(self.start_dir, "lib", "kokkos", "bin", "nvcc_wrapper") # nvcc_wrapper can't find OpenMP for some reason, need to specify OpenMP flags. # https://software.intel.com/en-us/forums/intel-oneapi-base-toolkit/topic/842470 self.cfg.update('configopts', '-DOpenMP_CXX_FLAGS="-qopenmp"') @@ -241,7 +240,7 @@ def sanity_check_step(self, *args, **kwargs): ] pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) - pythonpath = os.path.join('lib','python%s' % pyshortver,'site-packages') + pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') shlib_ext = get_shared_lib_ext() custom_paths = { 'files': [ @@ -254,7 +253,7 @@ def sanity_check_step(self, *args, **kwargs): return super(EB_LAMMPS, self).sanity_check_step( custom_commands=custom_commands, - custom_paths=custom_paths + custom_paths=custom_paths, ) def make_module_extra(self): @@ -263,7 +262,7 @@ def make_module_extra(self): txt = super(EB_LAMMPS, self).make_module_extra() pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) - pythonpath = os.path.join('lib','python%s' % pyshortver,'site-packages') + pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') txt += self.module_generator.prepend_paths('PYTHONPATH', [pythonpath, "lib64"]) txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', ["lib64"]) @@ -334,7 +333,8 @@ def check_cuda_compute_capabilities(self, cfg_cuda_cc, ec_cuda_cc, cuda_cc): if cuda: if cfg_cuda_cc and ec_cuda_cc: - warning_msg = "cuda_compute_capabilities specified in easyconfig (%s) are overruled by " % self.ec_cuda_cc + warning_msg = "cuda_compute_capabilities specified in easyconfig (%s)" % self.ec_cuda_cc + warning_msg += " are overruled by " warning_msg += "--cuda-compute-capabilities configuration option (%s)" % self.cfg_cuda_cc print_warning(warning_msg) elif not cuda_cc: @@ -344,7 +344,8 @@ def check_cuda_compute_capabilities(self, cfg_cuda_cc, ec_cuda_cc, cuda_cc): raise EasyBuildError(error_msg) elif cuda_cc: - warning_msg = "Missing CUDA package (in dependencies), but 'cuda_compute_capabilities' option was specified." + warning_msg = "Missing CUDA package (in dependencies), " + warning_msg += "but 'cuda_compute_capabilities' option was specified." print_warning(warning_msg) return cuda_cc From 5ca564bcb112fb7a8dd3374616a78ecf3ab9d19c Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 17 Feb 2020 11:37:46 +0100 Subject: [PATCH 03/10] fixed import --- easybuild/easyblocks/l/lammps.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 942689ba5f..455559e309 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -26,10 +26,7 @@ @author: Pavel Grochal (INUITS) """ -import glob import os -import shutil -import sys from easybuild.easyblocks.generic.cmakemake import CMakeMake from easybuild.framework.easyconfig import CUSTOM, MANDATORY From 4af5aed699b26c1c3c4d9046a176caf9e896e108 Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 17 Feb 2020 11:57:36 +0100 Subject: [PATCH 04/10] Fixed python path errors --- easybuild/easyblocks/l/lammps.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 455559e309..743d40ed0e 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -236,8 +236,6 @@ def sanity_check_step(self, *args, **kwargs): for check_file in check_files ] - pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) - pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') shlib_ext = get_shared_lib_ext() custom_paths = { 'files': [ @@ -245,9 +243,15 @@ def sanity_check_step(self, *args, **kwargs): 'include/lammps/library.h', 'lib64/liblammps.%s' % shlib_ext, ], - 'dirs': [pythonpath], + 'dirs': [], } + python = get_software_version('Python') + if python: + pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) + pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') + custom_paths['dirs'].append(pythonpath) + return super(EB_LAMMPS, self).sanity_check_step( custom_commands=custom_commands, custom_paths=custom_paths, @@ -258,10 +262,13 @@ def make_module_extra(self): txt = super(EB_LAMMPS, self).make_module_extra() - pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) - pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') + python = get_software_version('Python') + if python: + pyshortver = '.'.join(get_software_version('Python').split('.')[:2]) + pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') + txt += self.module_generator.prepend_paths('PYTHONPATH', [pythonpath]) - txt += self.module_generator.prepend_paths('PYTHONPATH', [pythonpath, "lib64"]) + txt += self.module_generator.prepend_paths('PYTHONPATH', ["lib64"]) txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', ["lib64"]) return txt From 176efd0bfde4689c4346d197cae7ca800a4a7750 Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 17 Feb 2020 13:43:41 +0100 Subject: [PATCH 05/10] Fixed remarks --- easybuild/easyblocks/l/lammps.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 743d40ed0e..4d08ebde69 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -30,6 +30,7 @@ from easybuild.easyblocks.generic.cmakemake import CMakeMake from easybuild.framework.easyconfig import CUSTOM, MANDATORY +from easybuild.tools import toolchain from easybuild.tools.build_log import EasyBuildError, print_warning from easybuild.tools.config import build_option from easybuild.tools.modules import get_software_root, get_software_version @@ -164,6 +165,8 @@ def configure_step(self): if '-DPKG_OPT=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DPKG_OPT=on') + # If this is intel compiler and -DPKG_USR-INTEL= is not specified + # This should work with GCC as well. if '-DPKG_USR-INTEL=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DPKG_USER-INTEL=on') @@ -194,12 +197,6 @@ def configure_step(self): if cuda: self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) nvcc_wrapper_path = os.path.join(self.start_dir, "lib", "kokkos", "bin", "nvcc_wrapper") - # nvcc_wrapper can't find OpenMP for some reason, need to specify OpenMP flags. - # https://software.intel.com/en-us/forums/intel-oneapi-base-toolkit/topic/842470 - self.cfg.update('configopts', '-DOpenMP_CXX_FLAGS="-qopenmp"') - self.cfg.update('configopts', '-DOpenMP_CXX_LIB_NAMES="libiomp5"') - self.cfg.update('configopts', '-DOpenMP_libiomp5_LIBRARY=$EBROOTICC/lib/intel64_lin/libiomp5.so') - self.cfg.update('configopts', '-DKOKKOS_ENABLE_CUDA=yes') self.cfg.update('configopts', '-DCMAKE_CXX_COMPILER="%s"' % nvcc_wrapper_path) self.cfg.update('configopts', '-DCMAKE_CXX_FLAGS="-ccbin $CXX $CXXFLAGS"') @@ -214,12 +211,6 @@ def configure_step(self): return super(EB_LAMMPS, self).configure_step() - # This might be needed - keep it as reference - # def build_step(self): - # if self.cfg['kokkos'] and get_software_root('CUDA'): - # self.cfg.update('prebuildopts', 'export NVCC_WRAPPER_DEFAULT_COMPILER=$MPICXX &&') - # return super(EB_LAMMPS, self).build_step() - def sanity_check_step(self, *args, **kwargs): check_files = [ 'atm', 'balance', 'colloid', 'crack', 'dipole', 'friction', From 17e005027b3e12ce954216da8bbdc82d24f77ea8 Mon Sep 17 00:00:00 2001 From: darkless Date: Fri, 21 Feb 2020 11:24:28 +0100 Subject: [PATCH 06/10] Fixed remarks --- easybuild/easyblocks/l/lammps.py | 196 ++++++++++++++++--------------- 1 file changed, 101 insertions(+), 95 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 4d08ebde69..de1aa49629 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -24,19 +24,24 @@ ## """ @author: Pavel Grochal (INUITS) +@author: Kenneth Hoste (Ghent University) +@author: Alan O'Cais + +Based on work of Alan O'Cais (https://github.com/ocaisa) +https://github.com/easybuilders/easybuild-easyconfigs/blob/0c7fa07b9b7a855df6d14b971bd9eb1a25f51dd8/easybuild/easyconfigs/l/LAMMPS/LAMMPS-24Oct2018-intel-2018b.eb """ import os -from easybuild.easyblocks.generic.cmakemake import CMakeMake +import easybuild.tools.toolchain as toolchain from easybuild.framework.easyconfig import CUSTOM, MANDATORY -from easybuild.tools import toolchain -from easybuild.tools.build_log import EasyBuildError, print_warning +from easybuild.tools.build_log import EasyBuildError, print_warning, print_msg from easybuild.tools.config import build_option from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_shared_lib_ext +from easybuild.easyblocks.generic.cmakemake import CMakeMake KOKKOS_CPU_ARCH_LIST = [ 'ARMv80', # ARMv8.0 Compatible CPU @@ -53,6 +58,15 @@ 'KNL', # Intel Knights Landing Xeon Phi ] +KOKKOS_CPU_MAPPING = { + 'sandybridge': 'SNB', + 'ivybridge': 'SNB', + 'haswell': 'HSW', + 'broadwell': 'BDW', + 'skylake_avx512': 'SKX', + 'knights-landing': 'KNL', +} + KOKKOS_GPU_ARCH_TABLE = { "3.0": "Kepler30", # NVIDIA Kepler generation CC 3.0 @@ -76,20 +90,27 @@ class EB_LAMMPS(CMakeMake): """ @staticmethod - def extra_options(): + def extra_options(**kwargs): """Custom easyconfig parameters for LAMMPS""" extra_vars = { # see https://developer.nvidia.com/cuda-gpus 'cuda_compute_capabilities': [[], "List of CUDA compute capabilities to build with", CUSTOM], 'general_packages': [None, "List of general packages without `PKG_` prefix.", MANDATORY], - 'kokkos': [True, "Enable kokkos build. (enabled by default)", CUSTOM], + 'kokkos': [True, "Enable kokkos build.", CUSTOM], 'kokkos_arch': [None, "Set kokkos processor arch manually, if auto-detection doesn't work.", CUSTOM], 'user_packages': [None, "List user packages without `PKG_USER-` prefix.", MANDATORY], } return CMakeMake.extra_options(extra_vars) - def configure_step(self): + def prepare_step(self): + super(EB_LAMMPS, self).prepare_step() + + # Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise + if self.cfg['kokkos'] and get_software_root('CUDA'): + run_cmd("unset LIBS") + + def configure_step(self, **kwargs): """Custom configuration procedure for LAMMPS.""" cuda = get_software_root('CUDA') @@ -101,12 +122,9 @@ def configure_step(self): cuda_cc = cfg_cuda_cc or ec_cuda_cc or [] # cmake has its own folder + self.cfg['separate_build_dir'] = True self.cfg['srcdir'] = os.path.join(self.start_dir, 'cmake') - # verbose CMake - if '-DCMAKE_VERBOSE_MAKEFILE=' not in self.cfg['configopts']: - self.cfg.update('configopts', '-DCMAKE_VERBOSE_MAKEFILE=yes') - # Enable following packages, if not configured in easycofig default_options = [ 'BUILD_DOC', 'BUILD_EXE', 'BUILD_LIB', @@ -116,39 +134,32 @@ def configure_step(self): if "-D%s=" % option not in self.cfg['configopts']: self.cfg.update('configopts', '-D%s=on' % option) - # Is there a gzip - if '-DWITH_GZIP=' not in self.cfg['configopts']: - if get_software_root('gzip'): - self.cfg.update('configopts', '-DWITH_GZIP=yes') - else: - self.cfg.update('configopts', '-DWITH_GZIP=no') - - # Is there a libpng - if '-DWITH_PNG=' not in self.cfg['configopts']: - if get_software_root('libpng'): - self.cfg.update('configopts', '-DWITH_PNG=yes') - else: - self.cfg.update('configopts', '-DWITH_PNG=no') - - # Is there a libjpeg-turbo - if '-DWITH_JPEG=' not in self.cfg['configopts']: - if get_software_root('libjpeg-turbo'): - self.cfg.update('configopts', '-DWITH_JPEG=yes') - else: - self.cfg.update('configopts', '-DWITH_JPEG=no') - - # With Eigen dependency: + # Enable gzip, libpng and libjpeg-turbo support when its included as dependency + deps = [ + ('gzip', 'GZIP'), + ('libpng', 'PNG'), + ('libjpeg-turbo', 'JPEG'), + ] + for dep_name, with_name in deps: + with_opt = '-DWITH_%s=' % with_name + if with_opt not in self.cfg['configopts']: + if get_software_root(dep_name): + self.cfg.update('configopts', with_opt + 'yes') + else: + self.cfg.update('configopts', with_opt + 'no') + + # Disable auto-downloading/building Eigen dependency: if '-DDOWNLOAD_EIGEN3=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DDOWNLOAD_EIGEN3=no') - # Compiler complains about 'Eigen3_DIR' not beeing set, but acutally it needs - # 'EIGEN3_INCLUDE_DIR'. + + # Compiler complains about 'Eigen3_DIR' not beeing set, but acutally it needs 'EIGEN3_INCLUDE_DIR'. # see: https://github.com/lammps/lammps/issues/1110 - if '-DEIGEN3_INCLUDE_DIR=' not in self.cfg['configopts']: - if get_software_root('Eigen'): + # Enable Eigen when its included as dependency dependency: + eigen_root = get_software_root('Eigen') + if eigen_root: + if '-DEIGEN3_INCLUDE_DIR=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DEIGEN3_INCLUDE_DIR=%s/include/Eigen' % get_software_root('Eigen')) - - if '-DEigen3_DIR=' not in self.cfg['configopts']: - if get_software_root('Eigen'): + if '-DEigen3_DIR=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DEigen3_DIR=%s/share/eigen3/cmake/' % get_software_root('Eigen')) # LAMMPS Configuration Options @@ -165,10 +176,10 @@ def configure_step(self): if '-DPKG_OPT=' not in self.cfg['configopts']: self.cfg.update('configopts', '-DPKG_OPT=on') - # If this is intel compiler and -DPKG_USR-INTEL= is not specified - # This should work with GCC as well. + # USR-INTEL enables optimizations on Intel processors. GCC has also partial support for some of them. if '-DPKG_USR-INTEL=' not in self.cfg['configopts']: - self.cfg.update('configopts', '-DPKG_USER-INTEL=on') + if self.toolchain.comp_family() in [toolchain.GCC, toolchain.INTELCOMP]: + self.cfg.update('configopts', '-DPKG_USER-INTEL=on') # MPI/OpenMP if self.toolchain.options.get('usempi', None): @@ -177,11 +188,12 @@ def configure_step(self): self.cfg.update('configopts', '-DBUILD_OMP=yes') self.cfg.update('configopts', '-DPKG_USER-OMP=on') - # FFT - if '-DFFT=' not in self.cfg['configopts']: - self.cfg.update('configopts', '-DFFT=FFTW3') - if '-DFFT_PACK=' not in self.cfg['configopts']: - self.cfg.update('configopts', '-DFFT_PACK=array') + # FFTW + if get_software_root('FFTW'): + if '-DFFT=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DFFT=FFTW3') + if '-DFFT_PACK=' not in self.cfg['configopts']: + self.cfg.update('configopts', '-DFFT_PACK=array') # https://lammps.sandia.gov/doc/Build_extras.html # KOKKOS @@ -191,7 +203,7 @@ def configure_step(self): self.cfg.update('configopts', '-DKOKKOS_ENABLE_OPENMP=yes') self.cfg.update('configopts', '-DPKG_KOKKOS=on') - self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_gpu_arch(cuda_cc)) + self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_arch(cuda_cc)) # if KOKKOS and CUDA if cuda: @@ -230,9 +242,9 @@ def sanity_check_step(self, *args, **kwargs): shlib_ext = get_shared_lib_ext() custom_paths = { 'files': [ - 'bin/lmp', - 'include/lammps/library.h', - 'lib64/liblammps.%s' % shlib_ext, + os.path.join('bin', 'lmp'), + os.path.join('include', 'lammps', 'library.h'), + os.path.join('lib64', 'liblammps.%s' % shlib_ext), ], 'dirs': [], } @@ -243,10 +255,7 @@ def sanity_check_step(self, *args, **kwargs): pythonpath = os.path.join('lib', 'python%s' % pyshortver, 'site-packages') custom_paths['dirs'].append(pythonpath) - return super(EB_LAMMPS, self).sanity_check_step( - custom_commands=custom_commands, - custom_paths=custom_paths, - ) + return super(EB_LAMMPS, self).sanity_check_step(custom_commands=custom_commands, custom_paths=custom_paths) def make_module_extra(self): """Add install path to PYTHONPATH""" @@ -265,11 +274,16 @@ def make_module_extra(self): return txt def get_cuda_gpu_arch(self, cuda_cc): - cuda_cc.sort(reverse=True) - return 'sm_%' % str(cuda_cc[0]).replace(".", "") + """Return CUDA gpu ARCH in LAMMPS required format (eg. sm_32)""" + # Get largest cuda supported + return 'sm_%s' % str(cuda_cc.sorted(reverse=True)[0]).replace(".", "") - def get_kokkos_gpu_arch(self, cuda_cc): - # see: https://lammps.sandia.gov/doc/Build_extras.html#kokkos + def get_kokkos_arch(self, cuda_cc): + """ + Return KOKKOS ARCH in LAMMPS required format + + see: https://lammps.sandia.gov/doc/Build_extras.html#kokkos + """ cuda = get_software_root('CUDA') processor_arch = None @@ -285,43 +299,36 @@ def get_kokkos_gpu_arch(self, cuda_cc): warning_msg = "kokkos_arch not set. Trying to auto-detect CPU arch." print_warning(warning_msg) - cpu_arch = self.get_cpu_arch() - - if cpu_arch == "sandybridge" or cpu_arch == "ivybridge": - processor_arch = 'SNB' - elif cpu_arch == "haswell": - processor_arch = 'HSW' - elif cpu_arch == "broadwell": - processor_arch = 'BDW' - elif cpu_arch == "skylake": - processor_arch = 'SKX' - elif cpu_arch == "knights-landing": - processor_arch = 'KNL' - else: + processor_arch = KOKKOS_CPU_MAPPING.get(self.get_cpu_arch()) + + if not processor_arch: error_msg = "Couldn't determine CPU architecture, you need to set 'kokkos_arch' manually." raise EasyBuildError(error_msg) - exit(1) - print("Determined cpu arch: %s" % processor_arch) - - if not cuda: - return processor_arch - - # CUDA below - cuda_cc.sort(reverse=True) - gpu_arch = None - for cc in cuda_cc: - gpu_arch = KOKKOS_GPU_ARCH_TABLE.get(str(cc)) - if gpu_arch: - break - else: - warning_msg = "(%s) GPU ARCH was not found in listed options." % cc - print_warning(warning_msg) - if not gpu_arch: - error_msg = "Specified GPU ARCH (%s) " % cuda_cc - error_msg += "was not found in listed options [%s]." % KOKKOS_GPU_ARCH_TABLE - raise EasyBuildError(error_msg) - return "%s;%s" % (processor_arch, gpu_arch) + print_msg("Determined cpu arch: %s" % processor_arch) + + if cuda: + # CUDA below + gpu_arch = None + for cc in cuda_cc.sorted(reverse=True): + gpu_arch = KOKKOS_GPU_ARCH_TABLE.get(str(cc)) + if gpu_arch: + break + else: + warning_msg = "(%s) GPU ARCH was not found in listed options." % cc + print_warning(warning_msg) + + if not gpu_arch: + error_msg = "Specified GPU ARCH (%s) " % cuda_cc + error_msg += "was not found in listed options [%s]." % KOKKOS_GPU_ARCH_TABLE + raise EasyBuildError(error_msg) + + kokkos_arch = "%s;%s" % (processor_arch, gpu_arch) + + else: + kokkos_arch = processor_arch + + return kokkos_arch def check_cuda_compute_capabilities(self, cfg_cuda_cc, ec_cuda_cc, cuda_cc): cuda = get_software_root('CUDA') @@ -349,5 +356,4 @@ def get_cpu_arch(self): out, ec = run_cmd("python -c 'from archspec.cpu import host; print(host())'", simple=False) if ec: raise EasyBuildError("Failed to determine CPU architecture: %s", out) - # transform: 'skylake_avx512\n' => 'skylake' - return out.strip().split("_")[0] + return out.strip() From 0ce5c8728c0fd371b226403edd6bb53be96a40c3 Mon Sep 17 00:00:00 2001 From: darkless Date: Fri, 21 Feb 2020 14:24:16 +0100 Subject: [PATCH 07/10] Fixed errors --- easybuild/easyblocks/l/lammps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index de1aa49629..cc7954630b 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -103,8 +103,8 @@ def extra_options(**kwargs): } return CMakeMake.extra_options(extra_vars) - def prepare_step(self): - super(EB_LAMMPS, self).prepare_step() + def prepare_step(self, *args, **kwargs): + super(EB_LAMMPS, self).prepare_step(*args, **kwargs) # Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise if self.cfg['kokkos'] and get_software_root('CUDA'): From d4990c600a94e52890ba8cf5f327a2508251e5f9 Mon Sep 17 00:00:00 2001 From: darkless Date: Fri, 21 Feb 2020 14:29:28 +0100 Subject: [PATCH 08/10] Updated unset_env_vars --- easybuild/easyblocks/l/lammps.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index cc7954630b..dbab8dad9f 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -37,6 +37,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError, print_warning, print_msg from easybuild.tools.config import build_option +from easybuild.tools.environment import unset_env_vars from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_shared_lib_ext @@ -108,7 +109,7 @@ def prepare_step(self, *args, **kwargs): # Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise if self.cfg['kokkos'] and get_software_root('CUDA'): - run_cmd("unset LIBS") + unset_env_vars(['LIBS']) def configure_step(self, **kwargs): """Custom configuration procedure for LAMMPS.""" From 51d5e0692de9f9c196048b39e383f45e4d470ea1 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 22 Feb 2020 16:16:35 +0100 Subject: [PATCH 09/10] set $XDG_CACHE_HOME to avoid that pip (ab)uses /Users/kehoste/.cache/pip --- easybuild/easyblocks/l/lammps.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index dbab8dad9f..3f9c522a88 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -32,12 +32,13 @@ """ import os +import tempfile +import easybuild.tools.environment as env import easybuild.tools.toolchain as toolchain from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError, print_warning, print_msg from easybuild.tools.config import build_option -from easybuild.tools.environment import unset_env_vars from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_shared_lib_ext @@ -109,7 +110,7 @@ def prepare_step(self, *args, **kwargs): # Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise if self.cfg['kokkos'] and get_software_root('CUDA'): - unset_env_vars(['LIBS']) + env.unset_env_vars(['LIBS']) def configure_step(self, **kwargs): """Custom configuration procedure for LAMMPS.""" @@ -222,6 +223,11 @@ def configure_step(self, **kwargs): self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) self.cfg.update('configopts', '-DGPU_ARCH=%s' % self.get_cuda_gpu_arch(cuda_cc)) + # avoid that pip (ab)uses $HOME/.cache/pip + # cfr. https://pip.pypa.io/en/stable/reference/pip_install/#caching + env.setvar('XDG_CACHE_HOME', tempfile.gettempdir()) + self.log.info("Using %s as pip cache directory", os.environ['XDG_CACHE_HOME']) + return super(EB_LAMMPS, self).configure_step() def sanity_check_step(self, *args, **kwargs): From 8bbd477bd71b7fd1a2e48ce0df31bcdffb33faa3 Mon Sep 17 00:00:00 2001 From: darkless Date: Mon, 24 Feb 2020 10:22:44 +0100 Subject: [PATCH 10/10] Fixed remarks. --- easybuild/easyblocks/l/lammps.py | 194 +++++++++++++++++-------------- 1 file changed, 106 insertions(+), 88 deletions(-) diff --git a/easybuild/easyblocks/l/lammps.py b/easybuild/easyblocks/l/lammps.py index 3f9c522a88..63c2f20e71 100644 --- a/easybuild/easyblocks/l/lammps.py +++ b/easybuild/easyblocks/l/lammps.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ## # Copyright 2009-2020 Ghent University # @@ -25,10 +26,7 @@ """ @author: Pavel Grochal (INUITS) @author: Kenneth Hoste (Ghent University) -@author: Alan O'Cais - -Based on work of Alan O'Cais (https://github.com/ocaisa) -https://github.com/easybuilders/easybuild-easyconfigs/blob/0c7fa07b9b7a855df6d14b971bd9eb1a25f51dd8/easybuild/easyconfigs/l/LAMMPS/LAMMPS-24Oct2018-intel-2018b.eb +@author: Alan O'Cais (Juelich Supercomputing Centre) """ import os @@ -71,18 +69,18 @@ KOKKOS_GPU_ARCH_TABLE = { - "3.0": "Kepler30", # NVIDIA Kepler generation CC 3.0 - "3.2": "Kepler32", # NVIDIA Kepler generation CC 3.2 - "3.5": "Kepler35", # NVIDIA Kepler generation CC 3.5 - "3.7": "Kepler37", # NVIDIA Kepler generation CC 3.7 - "5.0": "Maxwell50", # NVIDIA Maxwell generation CC 5.0 - "5.2": "Maxwell52", # NVIDIA Maxwell generation CC 5.2 - "5.3": "Maxwell53", # NVIDIA Maxwell generation CC 5.3 - "6.0": "Pascal60", # NVIDIA Pascal generation CC 6.0 - "6.1": "Pascal61", # NVIDIA Pascal generation CC 6.1 - "7.0": "Volta70", # NVIDIA Volta generation CC 7.0 - "7.2": "Volta72", # NVIDIA Volta generation CC 7.2 - "7.5": "Turing75", # NVIDIA Turing generation CC 7.5 + '3.0': 'Kepler30', # NVIDIA Kepler generation CC 3.0 + '3.2': 'Kepler32', # NVIDIA Kepler generation CC 3.2 + '3.5': 'Kepler35', # NVIDIA Kepler generation CC 3.5 + '3.7': 'Kepler37', # NVIDIA Kepler generation CC 3.7 + '5.0': 'Maxwell50', # NVIDIA Maxwell generation CC 5.0 + '5.2': 'Maxwell52', # NVIDIA Maxwell generation CC 5.2 + '5.3': 'Maxwell53', # NVIDIA Maxwell generation CC 5.3 + '6.0': 'Pascal60', # NVIDIA Pascal generation CC 6.0 + '6.1': 'Pascal61', # NVIDIA Pascal generation CC 6.1 + '7.0': 'Volta70', # NVIDIA Volta generation CC 7.0 + '7.2': 'Volta72', # NVIDIA Volta generation CC 7.2 + '7.5': 'Turing75', # NVIDIA Turing generation CC 7.5 } @@ -106,6 +104,7 @@ def extra_options(**kwargs): return CMakeMake.extra_options(extra_vars) def prepare_step(self, *args, **kwargs): + """Custom prepare step for LAMMPS.""" super(EB_LAMMPS, self).prepare_step(*args, **kwargs) # Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise @@ -121,7 +120,7 @@ def configure_step(self, **kwargs): # (2) in the EasyBuild configuration, via --cuda-compute-capabilities configuration option; ec_cuda_cc = self.cfg['cuda_compute_capabilities'] cfg_cuda_cc = build_option('cuda_compute_capabilities') - cuda_cc = cfg_cuda_cc or ec_cuda_cc or [] + cuda_cc = check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc) # cmake has its own folder self.cfg['separate_build_dir'] = True @@ -205,11 +204,10 @@ def configure_step(self, **kwargs): self.cfg.update('configopts', '-DKOKKOS_ENABLE_OPENMP=yes') self.cfg.update('configopts', '-DPKG_KOKKOS=on') - self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % self.get_kokkos_arch(cuda_cc)) + self.cfg.update('configopts', '-DKOKKOS_ARCH="%s"' % get_kokkos_arch(cuda_cc, self.cfg['kokkos_arch'])) # if KOKKOS and CUDA if cuda: - self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) nvcc_wrapper_path = os.path.join(self.start_dir, "lib", "kokkos", "bin", "nvcc_wrapper") self.cfg.update('configopts', '-DKOKKOS_ENABLE_CUDA=yes') self.cfg.update('configopts', '-DCMAKE_CXX_COMPILER="%s"' % nvcc_wrapper_path) @@ -219,9 +217,7 @@ def configure_step(self, **kwargs): elif cuda: self.cfg.update('configopts', '-DPKG_GPU=on') self.cfg.update('configopts', '-DGPU_API=cuda') - - self.check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc, cuda_cc) - self.cfg.update('configopts', '-DGPU_ARCH=%s' % self.get_cuda_gpu_arch(cuda_cc)) + self.cfg.update('configopts', '-DGPU_ARCH=%s' % get_cuda_gpu_arch(cuda_cc)) # avoid that pip (ab)uses $HOME/.cache/pip # cfr. https://pip.pypa.io/en/stable/reference/pip_install/#caching @@ -231,6 +227,7 @@ def configure_step(self, **kwargs): return super(EB_LAMMPS, self).configure_step() def sanity_check_step(self, *args, **kwargs): + """Run custom sanity checks for LAMMPS files, dirs and commands.""" check_files = [ 'atm', 'balance', 'colloid', 'crack', 'dipole', 'friction', 'hugoniostat', 'indent', 'melt', 'message', 'min', 'msst', @@ -280,87 +277,108 @@ def make_module_extra(self): return txt - def get_cuda_gpu_arch(self, cuda_cc): - """Return CUDA gpu ARCH in LAMMPS required format (eg. sm_32)""" - # Get largest cuda supported - return 'sm_%s' % str(cuda_cc.sorted(reverse=True)[0]).replace(".", "") - def get_kokkos_arch(self, cuda_cc): - """ - Return KOKKOS ARCH in LAMMPS required format +def get_cuda_gpu_arch(cuda_cc): + """Return CUDA gpu ARCH in LAMMPS required format. Example: 'sm_32' """ + # Get largest cuda supported + return 'sm_%s' % str(cuda_cc.sorted(reverse=True)[0]).replace(".", "") - see: https://lammps.sandia.gov/doc/Build_extras.html#kokkos - """ - cuda = get_software_root('CUDA') - processor_arch = None - if self.cfg['kokkos_arch']: - if self.cfg['kokkos_arch'] not in KOKKOS_CPU_ARCH_LIST: - warning_msg = "Specified CPU ARCH (%s) " % self.cfg['kokkos_arch'] - warning_msg += "was not found in listed options [%s]." % KOKKOS_CPU_ARCH_LIST - warning_msg += "Still might work though." - print_warning(warning_msg) - processor_arch = self.cfg['kokkos_arch'] +def get_kokkos_arch(cuda_cc, kokkos_arch): + """ + Return KOKKOS ARCH in LAMMPS required format, which is either 'CPU_ARCH' or 'CPU_ARCH;GPU_ARCH'. - else: - warning_msg = "kokkos_arch not set. Trying to auto-detect CPU arch." + see: https://lammps.sandia.gov/doc/Build_extras.html#kokkos + """ + cuda = get_software_root('CUDA') + processor_arch = None + + if kokkos_arch: + if kokkos_arch not in KOKKOS_CPU_ARCH_LIST: + warning_msg = "Specified CPU ARCH (%s) " % kokkos_arch + warning_msg += "was not found in listed options [%s]." % KOKKOS_CPU_ARCH_LIST + warning_msg += "Still might work though." print_warning(warning_msg) + processor_arch = kokkos_arch - processor_arch = KOKKOS_CPU_MAPPING.get(self.get_cpu_arch()) + else: + warning_msg = "kokkos_arch not set. Trying to auto-detect CPU arch." + print_warning(warning_msg) - if not processor_arch: - error_msg = "Couldn't determine CPU architecture, you need to set 'kokkos_arch' manually." - raise EasyBuildError(error_msg) + processor_arch = KOKKOS_CPU_MAPPING.get(get_cpu_arch()) - print_msg("Determined cpu arch: %s" % processor_arch) + if not processor_arch: + error_msg = "Couldn't determine CPU architecture, you need to set 'kokkos_arch' manually." + raise EasyBuildError(error_msg) - if cuda: - # CUDA below - gpu_arch = None - for cc in cuda_cc.sorted(reverse=True): - gpu_arch = KOKKOS_GPU_ARCH_TABLE.get(str(cc)) - if gpu_arch: - break - else: - warning_msg = "(%s) GPU ARCH was not found in listed options." % cc - print_warning(warning_msg) + print_msg("Determined cpu arch: %s" % processor_arch) - if not gpu_arch: - error_msg = "Specified GPU ARCH (%s) " % cuda_cc - error_msg += "was not found in listed options [%s]." % KOKKOS_GPU_ARCH_TABLE - raise EasyBuildError(error_msg) + if cuda: + # CUDA below + gpu_arch = None + for cc in cuda_cc.sorted(reverse=True): + gpu_arch = KOKKOS_GPU_ARCH_TABLE.get(str(cc)) + if gpu_arch: + break + else: + warning_msg = "(%s) GPU ARCH was not found in listed options." % cc + print_warning(warning_msg) - kokkos_arch = "%s;%s" % (processor_arch, gpu_arch) + if not gpu_arch: + error_msg = "Specified GPU ARCH (%s) " % cuda_cc + error_msg += "was not found in listed options [%s]." % KOKKOS_GPU_ARCH_TABLE + raise EasyBuildError(error_msg) - else: - kokkos_arch = processor_arch + kokkos_arch = "%s;%s" % (processor_arch, gpu_arch) - return kokkos_arch + else: + kokkos_arch = processor_arch - def check_cuda_compute_capabilities(self, cfg_cuda_cc, ec_cuda_cc, cuda_cc): - cuda = get_software_root('CUDA') + return kokkos_arch - if cuda: - if cfg_cuda_cc and ec_cuda_cc: - warning_msg = "cuda_compute_capabilities specified in easyconfig (%s)" % self.ec_cuda_cc - warning_msg += " are overruled by " - warning_msg += "--cuda-compute-capabilities configuration option (%s)" % self.cfg_cuda_cc - print_warning(warning_msg) - elif not cuda_cc: - error_msg = "No CUDA compute capabilities specified.\nTo build LAMMPS with Cuda you need to use" - error_msg += "the --cuda-compute-capabilities configuration option or the cuda_compute_capabilities " - error_msg += "easyconfig parameter to specify a list of CUDA compute capabilities to compile with." - raise EasyBuildError(error_msg) - - elif cuda_cc: - warning_msg = "Missing CUDA package (in dependencies), " - warning_msg += "but 'cuda_compute_capabilities' option was specified." + +def check_cuda_compute_capabilities(cfg_cuda_cc, ec_cuda_cc): + """ + Checks if cuda-compute-capabilities is set and prints warning if it gets declared on multiple places. + + :param cfg_cuda_cc: cuda-compute-capabilities from cli config + :param ec_cuda_cc: cuda-compute-capabilities from easyconfig + :return: returns preferred cuda-compute-capabilities + """ + + cuda = get_software_root('CUDA') + cuda_cc = cfg_cuda_cc or ec_cuda_cc or [] + + if cuda: + if cfg_cuda_cc and ec_cuda_cc: + warning_msg = "cuda_compute_capabilities specified in easyconfig (%s)" % ec_cuda_cc + warning_msg += " are overruled by " + warning_msg += "--cuda-compute-capabilities configuration option (%s)" % cfg_cuda_cc print_warning(warning_msg) + elif not cuda_cc: + error_msg = "No CUDA compute capabilities specified.\nTo build LAMMPS with Cuda you need to use" + error_msg += "the --cuda-compute-capabilities configuration option or the cuda_compute_capabilities " + error_msg += "easyconfig parameter to specify a list of CUDA compute capabilities to compile with." + raise EasyBuildError(error_msg) - return cuda_cc + elif cuda_cc: + warning_msg = "Missing CUDA package (in dependencies), " + warning_msg += "but 'cuda_compute_capabilities' option was specified." + print_warning(warning_msg) - def get_cpu_arch(self): - out, ec = run_cmd("python -c 'from archspec.cpu import host; print(host())'", simple=False) - if ec: - raise EasyBuildError("Failed to determine CPU architecture: %s", out) - return out.strip() + return cuda_cc + + +def get_cpu_arch(): + """ + Checks for CPU architecture via archspec library. + https://github.com/archspec/archspec + Archspec should be bundled as build-dependency to determine CPU arch. + It can't be called directly in code because it gets available only after prepare_step. + + :return: returns detected cpu architecture + """ + out, ec = run_cmd("python -c 'from archspec.cpu import host; print(host())'", simple=False) + if ec: + raise EasyBuildError("Failed to determine CPU architecture: %s", out) + return out.strip()