def sanity_check_step(self): """Custom sanity check for Boost.""" shlib_ext = get_shared_lib_ext() custom_paths = {'files': [], 'dirs': ['include/boost']} if self.cfg['tagged_layout']: lib_mt_suffix = '-mt' # Architecture tags introduced in 1.69.0 if LooseVersion(self.version) >= LooseVersion("1.69.0"): if get_cpu_architecture() == AARCH64: lib_mt_suffix += '-a64' elif get_cpu_architecture() == POWER: lib_mt_suffix += '-p64' else: lib_mt_suffix += '-x64' if self.cfg['only_python_bindings']: for pyver in self.pyvers: pymajorver, pyminorver = pyver.split('.')[:2] if LooseVersion(self.version) >= LooseVersion("1.67.0"): suffix = '%s%s' % (pymajorver, pyminorver) elif int(pymajorver) >= 3: suffix = pymajorver else: suffix = '' custom_paths['files'].append( os.path.join('lib', 'libboost_python%s.%s' % (suffix, shlib_ext))) if self.cfg['tagged_layout']: custom_paths['files'].append( os.path.join( 'lib', 'libboost_python%s%s.%s' % (suffix, lib_mt_suffix, shlib_ext))) else: custom_paths['files'].append( os.path.join('lib', 'libboost_system.%s' % shlib_ext)) if self.cfg['tagged_layout']: custom_paths['files'].append( os.path.join( 'lib', 'libboost_system%s.%s' % (lib_mt_suffix, shlib_ext))) custom_paths['files'].append( os.path.join( 'lib', 'libboost_thread%s.%s' % (lib_mt_suffix, shlib_ext))) if self.cfg['boost_mpi']: custom_paths['files'].append( os.path.join('lib', 'libboost_mpi.%s' % shlib_ext)) if self.cfg['tagged_layout']: custom_paths['files'].append( os.path.join( 'lib', 'libboost_mpi%s.%s' % (lib_mt_suffix, shlib_ext))) super(EB_Boost, self).sanity_check_step(custom_paths=custom_paths)
def __init__(self, *args, **kwargs): """Constructor for custom Mesa easyblock: figure out which values to pass to swr-arches configuration option.""" super(EB_Mesa, self).__init__(*args, **kwargs) self.gallium_configopts = [] # Mesa fails to build with libunwind on aarch64 # See https://github.com/easybuilders/easybuild-easyblocks/issues/2150 if get_cpu_architecture() == AARCH64: given_config_opts = self.cfg.get('configopts') if "-Dlibunwind=true" in given_config_opts: self.log.warning('libunwind not supported on aarch64, stripping from configopts!') configopts_libunwind_stripped = given_config_opts.replace('-Dlibunwind=true', '-Dlibunwind=false') self.cfg.set_keys({'configopts': configopts_libunwind_stripped}) self.log.warning('New configopts after stripping: ' + self.cfg.get('configopts')) # Check user-defined Gallium drivers gallium_drivers = self.get_configopt_value('gallium-drivers') if not gallium_drivers: # Add appropriate Gallium drivers for current architecture arch = get_cpu_architecture() arch_gallium_drivers = { X86_64: ['swrast', 'swr'], POWER: ['swrast'], AARCH64: ['swrast'], } if arch in arch_gallium_drivers: gallium_drivers = arch_gallium_drivers[arch] # Add configopt for additional Gallium drivers self.gallium_configopts.append('-Dgallium-drivers=' + ','.join(gallium_drivers)) self.log.debug('Gallium driver(s) included in the installation: %s' % ', '.join(gallium_drivers)) self.swr_arches = [] if 'swr' in gallium_drivers: # Check user-defined SWR arches self.swr_arches = self.get_configopt_value('swr-arches') if not self.swr_arches: # Set cpu features of SWR for current micro-architecture feat_to_swrarch = { 'avx': 'avx', 'avx1.0': 'avx', # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' 'avx2': 'avx2', 'avx512f': 'skx', # AVX-512 Foundation - introduced in Skylake 'avx512er': 'knl', # AVX-512 Exponential and Reciprocal Instructions implemented in Knights Landing } # Determine list of values to pass to swr-arches configuration option cpu_features = get_cpu_features() self.swr_arches = sorted([swrarch for feat, swrarch in feat_to_swrarch.items() if feat in cpu_features]) # Add configopt for additional SWR arches self.gallium_configopts.append('-Dswr-arches=' + ','.join(self.swr_arches)) self.log.debug('SWR Gallium driver will support: %s' % ', '.join(self.swr_arches))
def sanity_check_step(self): """Custom sanity check for Boost.""" shlib_ext = get_shared_lib_ext() custom_paths = {'files': [], 'dirs': ['include/boost']} if not self.cfg['only_python_bindings']: custom_paths['files'].append( os.path.join('lib', 'libboost_system.%s' % shlib_ext)) if self.cfg['boost_mpi']: custom_paths['files'].append( os.path.join('lib', 'libboost_mpi.%s' % shlib_ext)) for pyver in self.pyvers: pymajorver = pyver.split('.')[0] pyminorver = pyver.split('.')[1] if LooseVersion(self.version) >= LooseVersion("1.67.0"): suffix = '%s%s' % (pymajorver, pyminorver) elif int(pymajorver) >= 3: suffix = pymajorver else: suffix = '' custom_paths['files'].append( os.path.join('lib', 'libboost_python%s.%s' % (suffix, shlib_ext))) lib_mt_suffix = '-mt' # MT libraries gained an extra suffix from v1.69.0 onwards if LooseVersion(self.version) >= LooseVersion("1.69.0"): if get_cpu_architecture() == AARCH64: lib_mt_suffix += '-a64' elif get_cpu_architecture() == POWER: lib_mt_suffix += '-p64' else: lib_mt_suffix += '-x64' if self.cfg['boost_multi_thread']: custom_paths['files'].append( os.path.join( 'lib', 'libboost_thread%s.%s' % (lib_mt_suffix, shlib_ext))) if self.cfg['boost_mpi'] and self.cfg['boost_multi_thread']: custom_paths['files'].append( os.path.join('lib', 'libboost_mpi%s.%s' % (lib_mt_suffix, shlib_ext))) super(EB_Boost, self).sanity_check_step(custom_paths=custom_paths)
def prepare_step(self, *args, **kwargs): """Prepare environment for installing OpenCV.""" super(EB_OpenCV, self).prepare_step(*args, **kwargs) self.pylibdir = det_pylibdir() if get_cpu_architecture() == X86_64: # IPP are Intel's Integrated Performance Primitives - so only make sense on X86_64 ippicv_tgz = glob.glob(os.path.join(self.builddir, 'ippicv*.tgz')) if ippicv_tgz: if len(ippicv_tgz) == 1: # copy ippicv tarball in the right place # expected location is 3rdparty/ippicv/downloads/linux-<md5sum>/ ippicv_tgz = ippicv_tgz[0] ippicv_tgz_md5 = compute_checksum(ippicv_tgz, checksum_type='md5') target_subdir = os.path.join('3rdparty', 'ippicv', 'downloads', 'linux-%s' % ippicv_tgz_md5) copy([ippicv_tgz], os.path.join(self.cfg['start_dir'], target_subdir)) self.cfg.update('configopts', '-DWITH_IPP=ON') # for recent OpenCV 3.x versions (and newer), we must also specify the download location # to prevent that the ippicv tarball is re-downloaded if LooseVersion(self.version) >= LooseVersion('3.4.4'): self.cfg.update( 'configopts', '-DOPENCV_DOWNLOAD_PATH=%s' % self.builddir) else: raise EasyBuildError( "Found multiple ippicv*.tgz source tarballs in %s: %s", self.builddir, ippicv_tgz)
def __init__(self, *args, **kwargs): """Initialisation of custom class variables for tbb""" super(EB_tbb, self).__init__(*args, **kwargs) platform_name = get_platform_name() myarch = get_cpu_architecture() if platform_name.startswith('x86_64'): self.arch = "intel64" elif platform_name.startswith('i386') or platform_name.startswith( 'i686'): self.arch = 'ia32' elif myarch == POWER: self.arch = 'ppc64' else: raise EasyBuildError( "Failed to determine system architecture based on %s", platform_name) if not self.toolchain.is_system_toolchain(): # open-source TBB version self.build_in_installdir = True self.cfg['requires_runtime_license'] = False if self.toolchain.is_system_toolchain(): self.tbb_subdir = 'tbb' else: self.tbb_subdir = ''
def __init__(self, *args, **kwargs): """ Init the cuDNN easyblock adding a new cudnnarch template var """ # Need to call super's init first, so we can use self.version super(EB_cuDNN, self).__init__(*args, **kwargs) # Generate cudnnarch template value for this system cudnnarch = False myarch = get_cpu_architecture() if LooseVersion(self.version) < LooseVersion('8.3.3'): if myarch == AARCH64: cudnnarch = 'aarch64sbsa' elif myarch == POWER: cudnnarch = 'ppc64le' elif myarch == X86_64: cudnnarch = 'x64' else: if myarch == AARCH64: cudnnarch = 'sbsa' elif myarch == POWER: cudnnarch = 'ppc64le' elif myarch == X86_64: cudnnarch = 'x86_64' if not cudnnarch: raise EasyBuildError("The cuDNN easyblock does not currently support architecture %s", myarch) self.cfg['keepsymlinks'] = True self.cfg.template_values['cudnnarch'] = cudnnarch self.cfg.generate_template_values()
def extra_options(): # We only want to install mkl-dnn by default on x86_64 systems with_mkl_dnn_default = get_cpu_architecture() == X86_64 extra_vars = { # see https://developer.nvidia.com/cuda-gpus 'cuda_compute_capabilities': [[], "List of CUDA compute capabilities to build with", CUSTOM], 'path_filter': [[], "List of patterns to be filtered out in paths in $CPATH and $LIBRARY_PATH", CUSTOM], 'with_jemalloc': [ None, "Make TensorFlow use jemalloc (usually enabled by default)", CUSTOM ], 'with_mkl_dnn': [ with_mkl_dnn_default, "Make TensorFlow use Intel MKL-DNN", CUSTOM ], 'test_script': [None, "Script to test TensorFlow installation with", CUSTOM], } return PythonPackage.extra_options(extra_vars)
def det_psubdir(self): """Determine the platform-specific installation directory for OpenFOAM.""" # OpenFOAM >= 3.0.0 can use 64 bit integers # same goes for OpenFOAM-Extend >= 4.1 if 'extend' in self.name.lower(): set_int_size = self.looseversion >= LooseVersion('4.1') else: set_int_size = self.looseversion >= LooseVersion('3.0') if set_int_size: if self.toolchain.options['i8']: int_size = 'Int64' else: int_size = 'Int32' else: int_size = '' archpart = '64' arch = get_cpu_architecture() if arch == AARCH64: # Variants have different abbreviations for ARM64... if self.looseversion < LooseVersion("100"): archpart = 'Arm64' else: archpart = 'ARM64' elif arch == POWER: archpart = 'PPC64le' psubdir = "linux%s%sDP%s%s" % (archpart, self.wm_compiler, int_size, self.build_type) return psubdir
def __init__(self, *args, **kwargs): """Initialize custom class variables for Clang.""" super(EB_Clang, self).__init__(*args, **kwargs) self.llvm_src_dir = None self.llvm_obj_dir_stage1 = None self.llvm_obj_dir_stage2 = None self.llvm_obj_dir_stage3 = None self.make_parallel_opts = "" build_targets = self.cfg['build_targets'] if build_targets is None: arch = get_cpu_architecture() default_targets = DEFAULT_TARGETS_MAP.get(arch, None) if default_targets: self.cfg['build_targets'] = build_targets = default_targets self.log.debug("Using %s as default build targets for CPU architecture %s.", default_targets, arch) else: raise EasyBuildError("No default build targets defined for CPU architecture %s.", arch) unknown_targets = [target for target in build_targets if target not in CLANG_TARGETS] if unknown_targets: raise EasyBuildError("Some of the chosen build targets (%s) are not in %s.", ', '.join(unknown_targets), ', '.join(CLANG_TARGETS)) if LooseVersion(self.version) < LooseVersion('3.4') and "R600" in build_targets: raise EasyBuildError("Build target R600 not supported in < Clang-3.4") if LooseVersion(self.version) > LooseVersion('3.3') and "MBlaze" in build_targets: raise EasyBuildError("Build target MBlaze is not supported anymore in > Clang-3.3")
def configure_step(self): """ set up some options - but no configure command to run""" default_opts = { 'BINARY': '64', 'CC': os.getenv('CC'), 'FC': os.getenv('FC'), 'USE_OPENMP': '1', 'USE_THREAD': '1', } if '%s=' % TARGET in self.cfg['buildopts']: # Add any TARGET in buildopts to default_opts, so it is passed to testopts and installopts for buildopt in self.cfg['buildopts'].split(): optpair = buildopt.split('=') if optpair[0] == TARGET: default_opts[optpair[0]] = optpair[1] elif LooseVersion(self.version) < LooseVersion( '0.3.6') and get_cpu_architecture() == POWER: # There doesn't seem to be a POWER9 option yet, but POWER8 should work. print_warning( "OpenBLAS 0.3.5 and lower have known issues on POWER systems") default_opts[TARGET] = 'POWER8' for key in sorted(default_opts.keys()): for opts_key in ['buildopts', 'testopts', 'installopts']: if '%s=' % key not in self.cfg[opts_key]: self.cfg.update(opts_key, "%s='%s'" % (key, default_opts[key])) self.cfg.update('installopts', 'PREFIX=%s' % self.installdir)
def prepare_step(self, *args, **kwargs): """Prepare build environment.""" super(EB_Clang, self).prepare_step(*args, **kwargs) build_targets = self.cfg['build_targets'] if build_targets is None: arch = get_cpu_architecture() try: default_targets = DEFAULT_TARGETS_MAP[arch][:] # If CUDA is included as a dep, add NVPTX as a target (could also support AMDGPU if we knew how) if get_software_root("CUDA"): default_targets += ["NVPTX"] self.cfg['build_targets'] = build_targets = default_targets self.log.debug("Using %s as default build targets for CPU/GPU architecture %s.", default_targets, arch) except KeyError: raise EasyBuildError("No default build targets defined for CPU architecture %s.", arch) # carry on with empty list from this point forward if no build targets are specified if build_targets is None: self.cfg['build_targets'] = build_targets = [] unknown_targets = [target for target in build_targets if target not in CLANG_TARGETS] if unknown_targets: raise EasyBuildError("Some of the chosen build targets (%s) are not in %s.", ', '.join(unknown_targets), ', '.join(CLANG_TARGETS)) if LooseVersion(self.version) < LooseVersion('3.4') and "R600" in build_targets: raise EasyBuildError("Build target R600 not supported in < Clang-3.4") if LooseVersion(self.version) > LooseVersion('3.3') and "MBlaze" in build_targets: raise EasyBuildError("Build target MBlaze is not supported anymore in > Clang-3.3")
def sanity_check_step(self): """Custom sanity check for Qt.""" shlib_ext = get_shared_lib_ext() if LooseVersion(self.version) >= LooseVersion('4'): libversion = '' if LooseVersion(self.version) >= LooseVersion('5'): libversion = self.version.split('.')[0] libfile = os.path.join('lib', 'libQt%sCore.%s' % (libversion, shlib_ext)) else: libfile = os.path.join('lib', 'libqt.%s' % shlib_ext) custom_paths = { 'files': ['bin/moc', 'bin/qmake', libfile], 'dirs': ['include', 'plugins'], } if self.cfg['check_qtwebengine']: glibc_version = get_glibc_version() myarch = get_cpu_architecture() if LooseVersion(glibc_version) <= LooseVersion("2.16"): self.log.debug("Skipping check for qtwebengine, since it requires a more recent glibc.") elif myarch == POWER: self.log.debug("Skipping check for qtwebengine, since it is not supported on POWER.") else: qtwebengine_libs = ['libQt%s%s.%s' % (libversion, x, shlib_ext) for x in ['WebEngine', 'WebEngineCore']] custom_paths['files'].extend([os.path.join('lib', lib) for lib in qtwebengine_libs]) if LooseVersion(self.version) >= LooseVersion('4'): custom_paths['files'].append('bin/xmlpatterns') super(EB_Qt, self).sanity_check_step(custom_paths=custom_paths)
def __init__(self, *args, **kwargs): """Compiler constructor.""" Toolchain.base_init(self) self.arch = systemtools.get_cpu_architecture() self.cpu_family = systemtools.get_cpu_family() # list of compiler prefixes self.prefixes = [] super(Compiler, self).__init__(*args, **kwargs)
def get_gromacs_arch(self): """Determine value of GMX_SIMD CMake flag based on optarch string. Refs: [0] http://manual.gromacs.org/documentation/2016.3/install-guide/index.html#typical-installation [1] http://manual.gromacs.org/documentation/2016.3/install-guide/index.html#simd-support [2] http://www.gromacs.org/Documentation/Acceleration_and_parallelization """ # default: fall back on autodetection res = None optarch = build_option('optarch') or '' # take into account that optarch value is a dictionary if it is specified by compiler family if isinstance(optarch, dict): comp_fam = self.toolchain.comp_family() optarch = optarch.get(comp_fam, '') optarch = optarch.upper() # The list of GMX_SIMD options can be found # http://manual.gromacs.org/documentation/2018/install-guide/index.html#simd-support if 'MIC-AVX512' in optarch and LooseVersion( self.version) >= LooseVersion('2016'): res = 'AVX_512_KNL' elif 'AVX512' in optarch and LooseVersion( self.version) >= LooseVersion('2016'): res = 'AVX_512' elif 'AVX2' in optarch and LooseVersion( self.version) >= LooseVersion('5.0'): res = 'AVX2_256' elif 'AVX' in optarch: res = 'AVX_256' elif 'SSE3' in optarch or 'SSE2' in optarch or 'MARCH=NOCONA' in optarch: # Gromacs doesn't have any GMX_SIMD=SSE3 but only SSE2 and SSE4.1 [1]. # According to [2] the performance difference between SSE2 and SSE4.1 is minor on x86 # and SSE4.1 is not supported by AMD Magny-Cours[1]. res = 'SSE2' elif optarch == OPTARCH_GENERIC: cpu_arch = get_cpu_architecture() if cpu_arch == X86_64: res = 'SSE2' else: res = 'None' elif optarch: warn_msg = "--optarch configuration setting set to %s but not taken into account; " % optarch warn_msg += "compiling GROMACS for the current host architecture (i.e. the default behavior)" self.log.warning(warn_msg) print_warning(warn_msg) if res: self.log.info( "Target architecture based on optarch configuration option ('%s'): %s", optarch, res) else: self.log.info( "No target architecture specified based on optarch configuration option ('%s')", optarch) return res
def __init__(self, *args, **kwargs): """Initialisation of custom class variables for FFTW.""" super(EB_FFTW, self).__init__(*args, **kwargs) # do not enable MPI if the toolchain does not support it if not self.toolchain.mpi_family(): self.log.info("Disabling MPI support because the toolchain used does not support it.") self.cfg['with_mpi'] = False for flag in FFTW_CPU_FEATURE_FLAGS: # fail-safe: make sure we're not overwriting an existing attribute (could lead to weird bugs if we do) if hasattr(self, flag): raise EasyBuildError("EasyBlock attribute '%s' already exists") setattr(self, flag, self.cfg['use_%s' % flag]) # backwards compatibility: use use_fma setting if use_fma4 is not set if flag == 'fma4' and self.cfg['use_fma4'] is None and self.cfg['use_fma'] is not None: self.log.deprecated("Use 'use_fma4' instead of 'use_fma' easyconfig parameter", '4.0') self.fma4 = self.cfg['use_fma'] # auto-detect CPU features that can be used and are not enabled/disabled explicitly, # but only if --optarch=GENERIC is not being used cpu_arch = get_cpu_architecture() if self.cfg['auto_detect_cpu_features']: # if --optarch=GENERIC is used, limit which CPU features we consider for auto-detection if build_option('optarch') == OPTARCH_GENERIC: if cpu_arch == X86_64: # SSE(2) is supported on all x86_64 architectures cpu_features = ['sse', 'sse2'] elif cpu_arch == AARCH64: # NEON is supported on all AARCH64 architectures (indicated with 'asimd') cpu_features = ['asimd'] else: cpu_features = [] else: cpu_features = FFTW_CPU_FEATURE_FLAGS self.log.info("CPU features considered for auto-detection: %s", cpu_features) # get list of available CPU features, so we can check which ones to retain avail_cpu_features = get_cpu_features() # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' if 'avx1.0' in avail_cpu_features: avail_cpu_features.append('avx') self.log.info("List of available CPU features: %s", avail_cpu_features) for flag in cpu_features: # only enable use of a particular CPU feature if it's still undecided (i.e. None) if getattr(self, flag) is None and flag in avail_cpu_features: self.log.info("Enabling use of %s (should be supported based on CPU features)", flag.upper()) setattr(self, flag, True) # Auto-disable quad-precision on ARM and POWER, as it is unsupported if self.cfg['with_quad_prec'] and cpu_arch in [AARCH32, AARCH64, POWER]: self.cfg['with_quad_prec'] = False self.log.debug("Quad-precision automatically disabled; not supported on %s.", cpu_arch)
def sanity_check_step(self): """Custom sanity check for AOMP""" shlib_ext = get_shared_lib_ext() arch = get_cpu_architecture() # Check architecture explicitly since Clang uses potentially # different names arch_map = { X86_64: 'x86_64', POWER: 'ppc64', AARCH64: 'aarch64', } if arch in arch_map: arch = arch_map[arch] else: print_warning( "Unknown CPU architecture (%s) for OpenMP offloading!" % arch) custom_paths = { 'files': [ "amdgcn/bitcode/hip.bc", "amdgcn/bitcode/opencl.bc", "bin/aompcc", "bin/aompversion", "bin/clang", "bin/flang", "bin/ld.lld", "bin/llvm-config", "bin/mygpu", "bin/opt", "bin/rocminfo", "include/amd_comgr.h", "include/hsa/amd_hsa_common.h", "include/hsa/hsa.h", "include/omp.h", "include/omp_lib.h", "lib/libclang.%s" % shlib_ext, "lib/libflang.%s" % shlib_ext, "lib/libomp.%s" % shlib_ext, "lib/libomptarget.rtl.amdgpu.%s" % shlib_ext, "lib/libomptarget.rtl.%s.%s" % (arch, shlib_ext), "lib/libomptarget.%s" % shlib_ext, ], 'dirs': ["amdgcn", "include/clang", "include/hsa", "include/llvm"], } # If we are building with CUDA support we need to check if it was built properly if get_software_root('CUDA') or get_software_root('CUDAcore'): custom_paths['files'].append("lib/libomptarget.rtl.cuda.%s" % shlib_ext) custom_commands = [ 'aompcc --help', 'clang --help', 'clang++ --help', 'flang --help', 'llvm-config --cxxflags', ] super(EB_AOMP, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)
def test_step(self): """Run unit tests""" # Make PyTorch tests not use the user home env.setvar('XDG_CACHE_HOME', os.path.join(self.tmpdir, '.cache')) # Pretend to be on FB CI which disables some tests, especially those which download stuff env.setvar('SANDCASTLE', '1') # Skip this test(s) which is very flaky env.setvar('SKIP_TEST_BOTTLENECK', '1') # Parse excluded_tests and flatten into space separated string excluded_tests = [] for arch, tests in self.cfg['excluded_tests'].items(): if not arch or arch == get_cpu_architecture(): excluded_tests.extend(tests) # -x should not be used if there are no excluded tests if excluded_tests: excluded_tests = ['-x'] + excluded_tests self.cfg.template_values.update({ 'python': self.python_cmd, 'excluded_tests': ' '.join(excluded_tests) }) (tests_out, tests_ec) = super(EB_PyTorch, self).test_step(return_output_ec=True) ran_tests_hits = re.findall(r"^Ran (?P<test_cnt>[0-9]+) tests in", tests_out, re.M) test_cnt = 0 for hit in ran_tests_hits: test_cnt += int(hit) failed_tests = nub(re.findall(r"^(?P<failed_test_name>.*) failed!\s*$", tests_out, re.M)) failed_test_cnt = len(failed_tests) if failed_test_cnt: max_failed_tests = self.cfg['max_failed_tests'] test_or_tests = 'tests' if failed_test_cnt > 1 else 'test' msg = "%d %s (out of %d) failed:\n" % (failed_test_cnt, test_or_tests, test_cnt) msg += '\n'.join('* %s' % t for t in sorted(failed_tests)) if max_failed_tests == 0: raise EasyBuildError(msg) else: msg += '\n\n' + ' '.join([ "The PyTorch test suite is known to include some flaky tests,", "which may fail depending on the specifics of the system or the context in which they are run.", "For this PyTorch installation, EasyBuild allows up to %d tests to fail." % max_failed_tests, "We recommend to double check that the failing tests listed above ", "are known to be flaky, or do not affect your intended usage of PyTorch.", "In case of doubt, reach out to the EasyBuild community (via GitHub, Slack, or mailing list).", ]) print_warning(msg) if failed_test_cnt > max_failed_tests: raise EasyBuildError("Too many failed tests (%d), maximum allowed is %d", failed_test_cnt, max_failed_tests) elif tests_ec: raise EasyBuildError("Test command had non-zero exit code (%s), but no failed tests found?!", tests_ec)
def __init__(self, *args, **kwargs): """Constructor for custom Mesa easyblock: figure out which values to pass to swr-arches configuration option.""" super(EB_Mesa, self).__init__(*args, **kwargs) self.gallium_configopts = [] # Check user-defined Gallium drivers gallium_drivers = self.get_configopt_value('gallium-drivers') if not gallium_drivers: # Add appropriate Gallium drivers for current architecture arch = get_cpu_architecture() arch_gallium_drivers = { 'x86_64': ['swrast', 'swr'], 'POWER': ['swrast'], } if arch in arch_gallium_drivers: gallium_drivers = arch_gallium_drivers[arch] # Add configopt for additional Gallium drivers self.gallium_configopts.append('-Dgallium-drivers=' + ','.join(gallium_drivers)) self.log.debug('Gallium driver(s) included in the installation: %s' % ', '.join(gallium_drivers)) self.swr_arches = [] if 'swr' in gallium_drivers: # Check user-defined SWR arches self.swr_arches = self.get_configopt_value('swr-arches') if not self.swr_arches: # Set cpu features of SWR for current micro-architecture feat_to_swrarch = { 'avx': 'avx', 'avx1.0': 'avx', # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' 'avx2': 'avx2', 'avx512f': 'skx', # AVX-512 Foundation - introduced in Skylake 'avx512er': 'knl', # AVX-512 Exponential and Reciprocal Instructions implemented in Knights Landing } # Determine list of values to pass to swr-arches configuration option cpu_features = get_cpu_features() self.swr_arches = sorted([ swrarch for feat, swrarch in feat_to_swrarch.items() if feat in cpu_features ]) # Add configopt for additional SWR arches self.gallium_configopts.append('-Dswr-arches=' + ','.join(self.swr_arches)) self.log.debug('SWR Gallium driver will support: %s' % ', '.join(self.swr_arches))
def get_gromacs_arch(self): """Determine value of GMX_SIMD CMake flag based on optarch string. Refs: [0] http://manual.gromacs.org/documentation/2016.3/install-guide/index.html#typical-installation [1] http://manual.gromacs.org/documentation/2016.3/install-guide/index.html#simd-support [2] http://www.gromacs.org/Documentation/Acceleration_and_parallelization """ # default: fall back on autodetection res = None optarch = build_option('optarch') or '' # take into account that optarch value is a dictionary if it is specified by compiler family if isinstance(optarch, dict): comp_fam = self.toolchain.comp_family() optarch = optarch.get(comp_fam, '') optarch = optarch.upper() # The list of GMX_SIMD options can be found # http://manual.gromacs.org/documentation/2018/install-guide/index.html#simd-support if 'MIC-AVX512' in optarch and LooseVersion(self.version) >= LooseVersion('2016'): res = 'AVX_512_KNL' elif 'AVX512' in optarch and LooseVersion(self.version) >= LooseVersion('2016'): res = 'AVX_512' elif 'AVX2' in optarch and LooseVersion(self.version) >= LooseVersion('5.0'): res = 'AVX2_256' elif 'AVX' in optarch: res = 'AVX_256' elif 'SSE3' in optarch or 'SSE2' in optarch or 'MARCH=NOCONA' in optarch: # Gromacs doesn't have any GMX_SIMD=SSE3 but only SSE2 and SSE4.1 [1]. # According to [2] the performance difference between SSE2 and SSE4.1 is minor on x86 # and SSE4.1 is not supported by AMD Magny-Cours[1]. res = 'SSE2' elif optarch == OPTARCH_GENERIC: cpu_arch = get_cpu_architecture() if cpu_arch == X86_64: res = 'SSE2' else: res = 'None' elif optarch: warn_msg = "--optarch configuration setting set to %s but not taken into account; " % optarch warn_msg += "compiling GROMACS for the current host architecture (i.e. the default behavior)" self.log.warning(warn_msg) print_warning(warn_msg) if res: self.log.info("Target architecture based on optarch configuration option ('%s'): %s", optarch, res) else: self.log.info("No target architecture specified based on optarch configuration option ('%s')", optarch) return res
def sanity_check_step(self): """Custom sanity check for libdrm""" shlib_ext = get_shared_lib_ext() custom_paths = { 'files': ['include/xf86drm.h', 'include/xf86drmMode.h', 'lib/libdrm_radeon.%s' % shlib_ext, 'lib/libdrm.%s' % shlib_ext, 'lib/libkms.%s' % shlib_ext], 'dirs': ['include/libdrm', 'include/libkms', 'lib/pkgconfig'], } arch = get_cpu_architecture() if arch == X86_64: custom_paths['files'].append('lib/libdrm_intel.%s' % shlib_ext) super(EB_libdrm, self).sanity_check_step(custom_paths=custom_paths)
def sanity_check_step(self): """Custom sanity check for Clang.""" shlib_ext = get_shared_lib_ext() custom_paths = { 'files': [ "bin/clang", "bin/clang++", "bin/llvm-ar", "bin/llvm-nm", "bin/llvm-as", "bin/opt", "bin/llvm-link", "bin/llvm-config", "bin/llvm-symbolizer", "include/llvm-c/Core.h", "include/clang-c/Index.h", "lib/libclang.%s" % shlib_ext, "lib/clang/%s/include/stddef.h" % self.version, ], 'dirs': ["include/clang", "include/llvm", "lib/clang/%s/lib" % self.version], } if self.cfg['static_analyzer']: custom_paths['files'].extend(["bin/scan-build", "bin/scan-view"]) if self.cfg['build_extra_clang_tools'] and LooseVersion(self.version) >= LooseVersion('3.4'): custom_paths['files'].extend(["bin/clang-tidy"]) if self.cfg["usepolly"]: custom_paths['files'].extend(["lib/LLVMPolly.%s" % shlib_ext]) custom_paths['dirs'].extend(["include/polly"]) if self.cfg["build_lld"]: custom_paths['files'].extend(["bin/lld"]) if self.cfg["libcxx"]: custom_paths['files'].extend(["lib/libc++.%s" % shlib_ext]) custom_paths['files'].extend(["lib/libc++abi.%s" % shlib_ext]) if LooseVersion(self.version) >= LooseVersion('3.8'): custom_paths['files'].extend(["lib/libomp.%s" % shlib_ext, "lib/clang/%s/include/omp.h" % self.version]) if 'NVPTX' in self.cfg['build_targets']: arch = get_cpu_architecture() # Check architecture explicitly since Clang uses potentially # different names if arch == X86_64: arch = 'x86_64' elif arch == POWER: arch = 'ppc64' elif arch == AARCH64: arch = 'aarch64' else: print_warning("Unknown CPU architecture (%s) for OpenMP offloading!" % arch) custom_paths['files'].extend(["lib/libomptarget.%s" % shlib_ext, "lib/libomptarget-nvptx.a", "lib/libomptarget.rtl.cuda.%s" % shlib_ext, "lib/libomptarget.rtl.%s.%s" % (arch, shlib_ext)]) custom_commands = ['clang --help', 'clang++ --help', 'llvm-config --cxxflags'] super(EB_Clang, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)
def get_user_depot_path(self): user_depot_path = '' hostname = socket.gethostname() hostname_short = ''.join(c for c in hostname if not c.isdigit()) optarch = build_option('optarch') or None if optarch: user_depot_path = os.path.join('~', '.julia', self.version, self.get_environment_folder()) else: arch = systemtools.get_cpu_architecture() cpu_family = systemtools.get_cpu_family() user_depot_path = os.path.join('~', '.julia', self.version, self.get_environment_folder()) return user_depot_path
def __init__(self, *args, **kwargs): """ Init the easyblock adding a new mapped_arch template var """ myarch = get_cpu_architecture() if myarch == X86_64: self.mapped_arch = 'amd64' elif myarch == AARCH64: self.mapped_arch = 'arm64' else: raise EasyBuildError("Architecture %s is not supported for code-server on EasyBuild", myarch) super(EB_code_minus_server, self).__init__(*args, **kwargs) self.cfg.template_values['mapped_arch'] = self.mapped_arch self.cfg.generate_template_values()
def __init__(self, *args, **kwargs): """ Init the Java easyblock adding a new jdkarch template var """ myarch = get_cpu_architecture() if myarch == AARCH64: jdkarch = 'aarch64' elif myarch == POWER: jdkarch = 'ppc64le' elif myarch == X86_64: jdkarch = 'x64' else: raise EasyBuildError("Architecture %s is not supported for Java on EasyBuild", myarch) super(EB_Java, self).__init__(*args, **kwargs) self.cfg.template_values['jdkarch'] = jdkarch self.cfg.generate_template_values()
def __init__(self, *args, **kwargs): """ Init the cuda easyblock adding a new cudaarch template var """ myarch = get_cpu_architecture() if myarch == X86_64: cudaarch = '' elif myarch == POWER: cudaarch = '_ppc64le' else: raise EasyBuildError( "Architecture %s is not supported for CUDA on EasyBuild", myarch) super(EB_CUDA, self).__init__(*args, **kwargs) self.cfg.template_values['cudaarch'] = cudaarch self.cfg.generate_template_values()
def prepare_step(self, *args, **kwargs): """Prepare build environment.""" super(EB_NAMD, self).prepare_step(*args, **kwargs) if self.cfg['namd_basearch'] is None: self.log.info("namd_basearch not specified, so determining it based a CPU arch...") arch = get_cpu_architecture() if arch == X86_64: basearch = 'Linux-x86_64' elif arch == POWER: basearch = 'Linux-POWER' self.cfg['namd_basearch'] = basearch self.log.info("Derived value for 'namd_basearch': %s", self.cfg['namd_basearch'])
def __init__(self, *args, **kwargs): """Initialisation of custom class variables for FFTW.""" super(EB_FFTW, self).__init__(*args, **kwargs) for flag in FFTW_CPU_FEATURE_FLAGS: # fail-safe: make sure we're not overwriting an existing attribute (could lead to weird bugs if we do) if hasattr(self, flag): raise EasyBuildError("EasyBlock attribute '%s' already exists") setattr(self, flag, self.cfg['use_%s' % flag]) # auto-detect CPU features that can be used and are not enabled/disabled explicitly, # but only if --optarch=GENERIC is not being used if self.cfg['auto_detect_cpu_features']: # if --optarch=GENERIC is used, limit which CPU features we consider for auto-detection if build_option('optarch') == OPTARCH_GENERIC: cpu_arch = get_cpu_architecture() if cpu_arch == X86_64: # SSE(2) is supported on all x86_64 architectures cpu_features = ['sse', 'sse2'] elif cpu_arch == AARCH64: # NEON is supported on all AARCH64 architectures (indicated with 'asimd') cpu_features = ['asimd'] else: cpu_features = [] else: cpu_features = FFTW_CPU_FEATURE_FLAGS self.log.info("CPU features considered for auto-detection: %s", cpu_features) # get list of available CPU features, so we can check which ones to retain avail_cpu_features = get_cpu_features() # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' if 'avx1.0' in avail_cpu_features: avail_cpu_features.append('avx') self.log.info("List of available CPU features: %s", avail_cpu_features) for flag in cpu_features: # only enable use of a particular CPU feature if it's still undecided (i.e. None) if getattr(self, flag) is None and flag in avail_cpu_features: self.log.info( "Enabling use of %s (should be supported based on CPU features)", flag.upper()) setattr(self, flag, True)
def configure_step(self): """ Install extra tools in bin/; enable zlib if it is a dep; optionally enable rtti; and set the build target """ if LooseVersion(self.version) >= LooseVersion('14'): self.cfg.update('configopts', '-DLLVM_INCLUDE_BENCHMARKS=OFF') if self.build_shared: self.cfg.update( 'configopts', '-DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON') self.cfg.update('configopts', '-DLLVM_INSTALL_UTILS=ON') if get_software_root('zlib'): self.cfg.update('configopts', '-DLLVM_ENABLE_ZLIB=ON') if self.cfg["enable_rtti"]: self.cfg.update('configopts', '-DLLVM_ENABLE_RTTI=ON') build_targets = self.cfg['build_targets'] if build_targets is None: arch = get_cpu_architecture() try: default_targets = DEFAULT_TARGETS_MAP[arch][:] self.cfg['build_targets'] = build_targets = default_targets self.log.debug( "Using %s as default build targets for CPU architecture %s.", default_targets, arch) except KeyError: raise EasyBuildError( "No default build targets defined for CPU architecture %s.", arch) unknown_targets = [ target for target in build_targets if target not in CLANG_TARGETS ] if unknown_targets: raise EasyBuildError( "Some of the chosen build targets (%s) are not in %s.", ', '.join(unknown_targets), ', '.join(CLANG_TARGETS)) self.cfg.update( 'configopts', '-DLLVM_TARGETS_TO_BUILD="%s"' % ';'.join(build_targets)) super(EB_LLVM, self).configure_step()
def test_cpu_architecture(self): """Test getting the CPU architecture (mocked).""" st.platform.uname = mocked_uname global MACHINE_NAME machine_names = { 'aarch64': AARCH64, 'aarch64_be': AARCH64, 'armv7l': AARCH32, 'ppc64': POWER, 'ppc64le': POWER, 'x86_64': X86_64, 'some_fancy_arch': UNKNOWN, } for name in machine_names: MACHINE_NAME = name self.assertEqual(get_cpu_architecture(), machine_names[name])
def __init__(self, *args, **kwargs): """Init and validate easyconfig parameters and system architecture""" super(EB_ORCA, self).__init__(*args, **kwargs) # If user overwrites 'files_to_copy', custom 'sanity_check_paths' must be present if self.cfg['files_to_copy'] and not self.cfg['sanity_check_paths']: raise EasyBuildError("Found 'files_to_copy' option in easyconfig without 'sanity_check_paths'") # Add orcaarch template for supported architectures myarch = get_cpu_architecture() if myarch == X86_64: orcaarch = 'x86-64' else: raise EasyBuildError("Architecture %s is not supported by ORCA on EasyBuild", myarch) self.cfg.template_values['orcaarch'] = orcaarch self.cfg.generate_template_values()
def test_step(self): """Run unit tests""" # Make PyTorch tests not use the user home env.setvar('XDG_CACHE_HOME', os.path.join(self.tmpdir, '.cache')) # Parse excluded_tests and flatten into space separated string excluded_tests = [] for arch, tests in self.cfg['excluded_tests'].items(): if not arch or arch == get_cpu_architecture(): excluded_tests.extend(tests) # -x should not be used if there are no excluded tests if excluded_tests: excluded_tests = ['-x'] + excluded_tests self.cfg.template_values.update({ 'python': self.python_cmd, 'excluded_tests': ' '.join(excluded_tests) }) super(EB_PyTorch, self).test_step()
def run_all_steps(self, *args, **kwargs): """ Put configure options in place for different precisions (single, double, long double, quad). """ # keep track of configopts specified in easyconfig file, so we can include them in each iteration later common_config_opts = self.cfg['configopts'] self.cfg['configopts'] = [] for prec in FFTW_PRECISION_FLAGS: if self.cfg[EB_FFTW._prec_param(prec)]: prec_configopts = [] # double precison is the default, no configure flag needed (there is no '--enable-double') if prec != 'double': prec_configopts.append('--enable-%s' % prec) # MPI is not supported for quad precision if prec != 'quad-precision' and self.cfg['with_mpi']: prec_configopts.append('--enable-mpi') if self.toolchain.options['pic']: prec_configopts.append('--with-pic') for libtype in ['openmp', 'shared', 'threads']: if self.cfg['with_%s' % libtype]: prec_configopts.append('--enable-%s' % libtype) # SSE2, AVX* only supported for single/double precision if prec in ['single', 'double']: for flag in FFTW_CPU_FEATURE_FLAGS_SINGLE_DOUBLE: if getattr(self, flag): if flag == 'fma4': prec_configopts.append('--enable-avx-128-fma') else: prec_configopts.append('--enable-%s' % flag) # Altivec (POWER) and SSE only for single precision for flag in ['altivec', 'sse']: if prec == 'single' and getattr(self, flag): prec_configopts.append('--enable-%s' % flag) # NEON (ARM) only for single precision and double precision (on AARCH64) if (prec == 'single' and (self.asimd or self.neon)) or (prec == 'double' and self.asimd): prec_configopts.append('--enable-neon') # For POWER with GCC 5/6/7 and FFTW/3.3.6 we need to disable some settings for tests to pass # (we do it last so as not to affect previous logic) cpu_arch = get_cpu_architecture() comp_fam = self.toolchain.comp_family() fftw_ver = LooseVersion(self.version) if cpu_arch == POWER and comp_fam == TC_CONSTANT_GCC and fftw_ver <= LooseVersion('3.3.8'): # See https://github.com/FFTW/fftw3/issues/59 which applies to GCC 5/6/7 if prec == 'single': self.log.info("Disabling altivec for single precision on POWER with GCC for FFTW/%s" % self.version) prec_configopts.append('--disable-altivec') if prec == 'double': self.log.info("Disabling vsx for double precision on POWER with GCC for FFTW/%s" % self.version) prec_configopts.append('--disable-vsx') # append additional configure options (may be empty string, but that's OK) self.cfg.update('configopts', [' '.join(prec_configopts) + ' ' + common_config_opts]) self.log.debug("List of configure options to iterate over: %s", self.cfg['configopts']) return super(EB_FFTW, self).run_all_steps(*args, **kwargs)
def test_cpu_architecture_native(self): """Test getting the CPU architecture.""" arch = get_cpu_architecture() self.assertTrue(arch in CPU_ARCHITECTURES)