From 8dd4818612f93a32fd161e616ba07bd51e2336d6 Mon Sep 17 00:00:00 2001 From: bibek Date: Wed, 4 Sep 2024 15:34:55 +0200 Subject: [PATCH] This is the cp2k.py(Easyblock) that i have written being based on (2918) --- easybuild/easyblocks/c/cp2k.py | 164 +++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 60 deletions(-) diff --git a/easybuild/easyblocks/c/cp2k.py b/easybuild/easyblocks/c/cp2k.py index 1a0f109878..73842437a0 100644 --- a/easybuild/easyblocks/c/cp2k.py +++ b/easybuild/easyblocks/c/cp2k.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2024 Ghent University +# Copyright 2009-2023 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -35,6 +35,7 @@ @author: Damian Alvarez (Forschungszentrum Juelich GmbH) @author: Alan O'Cais (Forschungszentrum Juelich GmbH) @author: Balazs Hajgato (Free University Brussels (VUB)) +@author: O. Baris Malcioglu (Middle East Technical University) """ import fileinput @@ -42,7 +43,7 @@ import re import os import sys -from easybuild.tools import LooseVersion +from distutils.version import LooseVersion import easybuild.tools.toolchain as toolchain from easybuild.framework.easyblock import EasyBlock @@ -80,6 +81,7 @@ def __init__(self, *args, **kwargs): # used for both libsmm and libxsmm self.libsmm = '' + self.libsmm_path = '' self.modincpath = '' self.openmp = '' @@ -103,6 +105,8 @@ def extra_options(): 'plumed': [None, "Enable PLUMED support", CUSTOM], 'type': ['popt', "Type of build ('popt' or 'psmp')", CUSTOM], 'typeopt': [True, "Enable optimization", CUSTOM], + 'v2024': [False, "2024 version of CP2K", CUSTOM], + 'gpuver': ['H100', "CUDA gpu version", CUSTOM], } return EasyBlock.extra_options(extra_vars) @@ -110,7 +114,7 @@ def _generate_makefile(self, options): """Generate Makefile based on options dictionary and optional make instructions""" text = "# Makefile generated by CP2K easyblock in EasyBuild\n" - for key, value in sorted(options.items()): + for key, value in options.items(): text += "%s = %s\n" % (key, value) return text + self.make_instructions @@ -124,6 +128,10 @@ def configure_step(self): if self.cfg['type'] not in known_types: raise EasyBuildError("Unknown build type specified: '%s', known types are %s", self.cfg['type'], known_types) + if self.cfg['v2024'] and self.cfg['type'] == 'popt': + self.cfg['type'] = 'psmp' + setvar('OMP_NUM_THREADS', '1') + self.log.debug('In 2023 version popt is psmp with OMP_NUM_THREADS set to 1') # correct start dir, if needed # recent CP2K versions have a 'cp2k' dir in the unpacked 'cp2k' dir @@ -154,6 +162,7 @@ def configure_step(self): if libxsmm: self.cfg.update('extradflags', '-D__LIBXSMM') self.libsmm = '-lxsmm -lxsmmf' + self.libsmm_path = libxsmm self.log.debug('Using libxsmm %s' % libxsmm) elif libsmm: libsmms = glob.glob(os.path.join(libsmm, 'lib', 'libsmm_*nn.a')) @@ -161,6 +170,7 @@ def configure_step(self): moredflags = ' ' + ' '.join(dfs) self.cfg.update('extradflags', moredflags) self.libsmm = ' '.join(libsmms) + self.libsmm_path = libsmm self.log.debug('Using libsmm %s (extradflags %s)' % (self.libsmm, moredflags)) # obtain list of modinc's to use @@ -219,22 +229,39 @@ def configure_step(self): if elpa: options['LIBS'] += ' -lelpa' elpa_inc_dir = os.path.join(elpa, 'include', 'elpa-%s' % get_software_version('ELPA'), 'modules') - options['FCFLAGSOPT'] += ' -I%s ' % elpa_inc_dir + if self.cfg['v2024']: + options['INCS'] += ' -I%s ' % elpa_inc_dir + else: + options['FCFLAGSOPT'] += ' -I%s ' % elpa_inc_dir if LooseVersion(self.version) >= LooseVersion('6.1'): elpa_ver = ''.join(get_software_version('ELPA').split('.')[:2]) options['DFLAGS'] += ' -D__ELPA=%s' % elpa_ver elpa_inc_dir = os.path.join(elpa, 'include', 'elpa-%s' % get_software_version('ELPA'), 'elpa') - options['FCFLAGSOPT'] += ' -I%s ' % elpa_inc_dir + if self.cfg['v2024']: + options['INCS'] += ' -I%s ' % elpa_inc_dir + else: + options['FCFLAGSOPT'] += ' -I%s ' % elpa_inc_dir else: options['DFLAGS'] += ' -D__ELPA3' # CUDA cuda = get_software_root('CUDA') if cuda: - options['DFLAGS'] += ' -D__ACC -D__DBCSR_ACC' - options['LIBS'] += ' -lcudart -lcublas -lcufft -lrt' - options['NVCC'] = ' nvcc' - + if self.cfg['v2024']: + options['DFLAGS'] += ' -D__OFFLOAD_CUDA -D__DBCSR_ACC ' + options['LIBS'] += ' -lcufft -lcudart -lnvrtc -lcuda -lcublas' + options['OFFLOAD_CC'] = 'nvcc' + options['OFFLOAD_FLAGS'] = "-O3 -g -w --std=c++11 $(DFLAGS) -Xcompiler='-fopenmp -Wall -Wextra -Werror'" + options['OFFLOAD_TARGET'] = 'cuda' + options['GPUVER'] = self.cfg['gpuver'] + options['CXX'] = 'mpicxx' + options['CXXFLAGS'] = '-O3 -fopenmp -g -w --std=c++14 -fPIC $(DFLAGS) $(INCS)' + else: + options['DFLAGS'] += ' -D__ACC -D__DBCSR_ACC' + options['LIBS'] += ' -lcudart -lcublas -lcufft -lrt' + options['NVCC'] = ' nvcc' + # reset typearch + self.typearch = "Linux-x86-64-%s-cuda" % self.toolchain.name # avoid group nesting options['LIBS'] = options['LIBS'].replace('-Wl,--start-group', '').replace('-Wl,--end-group', '') @@ -302,7 +329,7 @@ def configure_common(self): # openmp introduces 2 major differences # -automatic is default: -noautomatic -auto-scalar # some mem-bandwidth optimisation - if self.cfg['type'] == 'psmp': + if self.cfg['type'] == 'psmp' or self.cfg['v2024']: self.openmp = self.toolchain.get_flag('openmp') # determine which opt flags to use @@ -342,28 +369,29 @@ def configure_common(self): cflags = os.getenv('CFLAGS') fflags = os.getenv('FFLAGS') fflags_lowopt = re.sub('-O[0-9]', '-O1', fflags) + options = { 'CC': os.getenv('MPICC'), - 'CPP': '', + 'AR': 'ar -r', 'FC': '%s %s' % (os.getenv('MPIF90'), self.openmp), 'LD': '%s %s' % (os.getenv('MPIF90'), self.openmp), - 'AR': 'ar -r', - 'CPPFLAGS': '', - 'FPIC': self.fpic, + 'DFLAGS': ' -D__parallel -D__BLACS -D__SCALAPACK -D__FFTSG %s' % self.cfg['extradflags'], + 'INCS': '', + 'CFLAGS': '-O3 -fopenmp -ftree-vectorize -march=native -fno-math-errno -fopenmp -std=c11 $(FPIC) $(DEBUG) ' + '$(INCS) $(DFLAGS) %s ' % + self.cfg['extracflags'], 'DEBUG': self.debug, - - 'FCFLAGS': '$(FCFLAGS%s)' % optflags, + 'FREE': '', + 'FCFLAGS': '$(FCFLAGS%s) $(INCS)' % optflags, 'FCFLAGS2': '$(FCFLAGS%s)' % regflags, - - 'CFLAGS': ' %s %s %s $(FPIC) $(DEBUG) %s ' % (cflags, cppflags, ldflags, self.cfg['extracflags']), - 'DFLAGS': ' -D__parallel -D__BLACS -D__SCALAPACK -D__FFTSG %s' % self.cfg['extradflags'], - - 'LIBS': os.getenv('LIBS', ''), - 'FCFLAGSNOOPT': '$(DFLAGS) $(CFLAGS) -O0 $(FREE) $(FPIC) $(DEBUG)', 'FCFLAGSOPT': '%s $(FREE) $(SAFE) $(FPIC) $(DEBUG)' % fflags, 'FCFLAGSOPT2': '%s $(FREE) $(SAFE) $(FPIC) $(DEBUG)' % fflags_lowopt, + + 'LDFLAGS': '$(FCFLAGS) %s ' % ldflags, + 'LIBS': os.getenv('LIBS', ''), + } libint = get_software_root('LibInt') @@ -410,7 +438,10 @@ def configure_common(self): options['LIBS'] += ' %s -lstdc++ %s' % (libint_libs, libint_wrapper) # add Libint include dir to $FCFLAGS - options['FCFLAGS'] += ' -I' + os.path.join(libint, 'include') + if self.cfg['v2024']: + options['INCS'] += ' -I' + os.path.join(libint, 'include') + else: + options['FCFLAGS'] += ' -I' + os.path.join(libint, 'include') else: # throw a warning, since CP2K without Libint doesn't make much sense @@ -436,20 +467,14 @@ def configure_common(self): options['LIBS'] += ' -L%s/lib -lxcf90 -lxc' % libxc else: options['LIBS'] += ' -L%s/lib -lxc' % libxc + + if self.cfg['v2024']: + options['INCS'] += ' -I%s/include ' % libxc + self.log.info("Using Libxc-%s" % cur_libxc_version) else: self.log.info("libxc module not loaded, so building without libxc support") - libvori = get_software_root('libvori') - if libvori: - if LooseVersion(self.version) >= LooseVersion('8.1'): - options['LIBS'] += ' -lvori' - options['DFLAGS'] += ' -D__LIBVORI' - else: - raise EasyBuildError("This version of CP2K does not suppport libvori") - else: - self.log.info("libvori module not loaded, so building without support for Voronoi integration") - return options def configure_intel_based(self): @@ -498,7 +523,7 @@ def configure_intel_based(self): # Required due to memory leak that occurs if high optimizations are used (from CP2K 7.1 intel-popt-makefile) if ifortver >= LooseVersion("2018.5"): self.make_instructions += "mp2_optimize_ri_basis.o: mp2_optimize_ri_basis.F\n" \ - "\t$(FC) -c $(subst O2,O0,$(FCFLAGSOPT)) $<\n" + "\t$(FC) -c $(subst O2,O0,$(FCFLAGSOPT)) $<\n" self.log.info("Optimization level of mp2_optimize_ri_basis.F was decreased to '-O0'") # RHEL8 intel/2020a lots of CPASSERT failed (due to high optimization in cholesky decomposition) @@ -544,20 +569,26 @@ def configure_intel_based(self): def configure_GCC_based(self): """Configure for GCC based toolchains""" options = self.configure_common() - - options.update({ - # need this to prevent "Unterminated character constant beginning" errors - 'FREE': '-ffree-form -ffree-line-length-none', - - 'LDFLAGS': '$(FCFLAGS)', - 'OBJECTS_ARCHITECTURE': 'machine_gfortran.o', - }) + if self.cfg['v2024']: + options.update({ + # need this to prevent "Unterminated character constant beginning" errors + 'FREE': '-ffree-form -ffree-line-length-none -std=f2008', + }) + options[ + 'FCFLAGSOPT'] = '-O3 -ftree-vectorize -march=native -fno-math-errno -fopenmp -fPIC $(FREE) $(DFLAGS) ' \ + '-fmax-stack-var-size=32768' + else: + options.update({ + # need this to prevent "Unterminated character constant beginning" errors + 'FREE': '-ffree-form -ffree-line-length-none ', + 'LDFLAGS': '$(FCFLAGS) ', + 'OBJECTS_ARCHITECTURE': 'machine_gfortran.o', + }) + options['FCFLAGSOPT'] += ' $(DFLAGS) $(CFLAGS) -fmax-stack-var-size=32768' + options['FCFLAGSOPT2'] += ' $(DFLAGS) $(CFLAGS)' options['DFLAGS'] += ' -D__GFORTRAN' - options['FCFLAGSOPT'] += ' $(DFLAGS) $(CFLAGS) -fmax-stack-var-size=32768' - options['FCFLAGSOPT2'] += ' $(DFLAGS) $(CFLAGS)' - gcc_version = get_software_version('GCCcore') or get_software_version('GCC') if LooseVersion(gcc_version) >= LooseVersion('10.0') and LooseVersion(self.version) <= LooseVersion('7.1'): # -fallow-argument-mismatch is required for CP2K 7.1 (and older) when compiling with GCC 10.x & more recent, @@ -583,12 +614,18 @@ def configure_ACML(self, options): blas = os.getenv('LIBBLAS', '') blas = blas.replace('gfortran64', 'gfortran64%s' % openmp_suffix) options['LIBS'] += ' %s %s %s' % (self.libsmm, os.getenv('LIBSCALAPACK', ''), blas) + if self.cfg['v2024']: + options['LDFLAGS'] += ' -L%s/lib ' % self.libsmm_path + options['INCS'] += ' -I%s/include ' % self.libsmm_path return options def configure_BLAS_lib(self, options): """Configure for BLAS library.""" options['LIBS'] += ' %s %s' % (self.libsmm, os.getenv('LIBBLAS', '')) + if self.cfg['v2024']: + options['LDFLAGS'] += ' -L%s/lib ' % self.libsmm_path + options['INCS'] += ' -I%s/include ' % self.libsmm_path return options def configure_MKL(self, options): @@ -624,24 +661,31 @@ def configure_MKL(self, options): options['INTEL_INCF'] = '$(INTEL_INC)/fftw' options['LIBS'] = '%s %s' % (os.getenv('LIBFFT', ''), options['LIBS']) + if self.cfg['v2024']: + options['LDFLAGS'] += ' %s ' % self.libsmm + return options def configure_FFTW3(self, options): """Configure for FFTW3""" - - options.update({ - 'FFTW_INC': os.getenv('FFT_INC_DIR', ''), # GCC - 'FFTW3INC': os.getenv('FFT_INC_DIR', ''), # Intel - 'FFTW3LIB': os.getenv('FFT_LIB_DIR', ''), # Intel - }) - - options['DFLAGS'] += ' -D__FFTW3' - if self.cfg['type'] == 'psmp': + if self.cfg['v2024']: libfft = os.getenv('LIBFFT_MT', '') + options['LIBS'] += ' -lfftw3_omp -lfftw3' + options['LDFLAGS'] += ' -L%s ' % os.getenv('FFT_LIB_DIR', '') + options['INCS'] += ' -I%s ' % os.getenv('FFT_INC_DIR', '') else: - libfft = os.getenv('LIBFFT', '') - options['LIBS'] += ' -L%s %s' % (os.getenv('FFT_LIB_DIR', '.'), libfft) + options.update({ + 'FFTW_INC': os.getenv('FFT_INC_DIR', ''), # GCC + 'FFTW3INC': os.getenv('FFT_INC_DIR', ''), # Intel + 'FFTW3LIB': os.getenv('FFT_LIB_DIR', ''), # Intel + }) + if self.cfg['type'] == 'psmp': + libfft = os.getenv('LIBFFT_MT', '') + else: + libfft = os.getenv('LIBFFT', '') + options['LIBS'] += ' -L%s %s' % (os.getenv('FFT_LIB_DIR', '.'), libfft) + options['DFLAGS'] += ' -D__FFTW3' return options def configure_LAPACK(self, options): @@ -729,15 +773,15 @@ def test_step(self): # location of do_regtest script cfg_fn = 'cp2k_regtest.cfg' - regtest_script = os.path.join(self.cfg['start_dir'], 'tools', 'regtesting', 'do_regtest') - regtest_cmd = [regtest_script, '-nobuild', '-config', cfg_fn] + regtest_script = os.path.join(self.cfg['start_dir'], 'tests', 'do_regtest.py') + regtest_cmd = [regtest_script, self.typearch, self.cfg['type']] if LooseVersion(self.version) < LooseVersion('7.1'): # -nosvn option was removed in CP2K 7.1 regtest_cmd.insert(1, '-nosvn') # older version of CP2K if not os.path.exists(regtest_script): - regtest_script = os.path.join(self.cfg['start_dir'], 'tools', 'do_regtest') + regtest_script = os.path.join(self.cfg['start_dir'], 'tests', 'do_regtest.py') regtest_cmd = [regtest_script, '-nocvs', '-quick', '-nocompile', '-config', cfg_fn] regtest_cmd = ' '.join(regtest_cmd) @@ -781,7 +825,7 @@ def test_step(self): 'cp2k_dir': os.path.basename(os.path.normpath(self.cfg['start_dir'])), 'maxtasks': self.cfg['maxtasks'], 'mpicmd_prefix': self.toolchain.mpi_cmd_for('', test_core_cnt), - } + } write_file(cfg_fn, cfg_txt) self.log.debug("Contents of %s: %s" % (cfg_fn, cfg_txt))