From 1242f10d1110c24a2da6f5674a518580c7d32023 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Fri, 21 May 2021 02:19:21 -0400 Subject: [PATCH] Update the GASNet package (#23796) The previous `gasnet` spack package was not vetted/approved by the GASNet library maintainers. This one is. Notably adds build-time testing and smoke-testing. Convert network variants into a multi-valued `conduits` variant has the minor advantage of enabling a concise `conduits=none` spec, but the major drawback that it degrades the `spack info gasnet` output. --- .../repos/builtin/packages/gasnet/package.py | 194 +++++++++++------- .../repos/builtin/packages/upcxx/package.py | 17 +- 2 files changed, 131 insertions(+), 80 deletions(-) diff --git a/var/spack/repos/builtin/packages/gasnet/package.py b/var/spack/repos/builtin/packages/gasnet/package.py index 77db379981..d76a104a35 100644 --- a/var/spack/repos/builtin/packages/gasnet/package.py +++ b/var/spack/repos/builtin/packages/gasnet/package.py @@ -4,100 +4,138 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) from spack import * +import os -class Gasnet(AutotoolsPackage): - """GASNet is a language-independent, low-level networking layer - that provides network-independent, high-performance communication - primitives tailored for implementing parallel global address space - SPMD languages and libraries such as UPC, Co-Array Fortran, SHMEM, - Cray Chapel, and Titanium. +class Gasnet(Package): + """GASNet is a language-independent, networking middleware layer that + provides network-independent, high-performance communication primitives + including Remote Memory Access (RMA) and Active Messages (AM). It has been + used to implement parallel programming models and libraries such as UPC, + UPC++, Co-Array Fortran, Legion, Chapel, and many others. The interface is + primarily intended as a compilation target and for use by runtime library + writers (as opposed to end users), and the primary goals are high + performance, interface portability, and expressiveness. + + ***NOTICE***: The GASNet library built by this Spack package is ONLY intended for + unit-testing purposes, and is generally UNSUITABLE FOR PRODUCTION USE. + The RECOMMENDED way to build GASNet is as an embedded library as configured + by the higher-level client runtime package (UPC++, Legion, etc), including + system-specific configuration. """ homepage = "https://gasnet.lbl.gov" - url = "https://gasnet.lbl.gov/EX/GASNet-2020.3.0.tar.gz" + url = "https://gasnet.lbl.gov/EX/GASNet-2021.3.0.tar.gz" + git = "https://bitbucket.org/berkeleylab/gasnet.git" maintainers = ['PHHargrove', 'bonachea'] - version('2020.3.0', sha256='019eb2d2284856e6fabe6c8c0061c874f10e95fa0265245f227fd3497f1bb274') - version('2019.9.0', sha256='117f5fdb16e53d0fa8a47a1e28cccab1d8020ed4f6e50163d985dc90226aaa2c') - version('2019.6.0', sha256='839ba115bfb48083c66b4c1c27703d73063b75d2f1e0501d5eab2ad7f0f776c8') - version('2019.3.2', sha256='9e2175047879f1e8c7c4b0a9db3c2cd20c978371cd7f209cf669d402119b6fdb') - version('2019.3.0', sha256='97fe19bb5ab32d14a96d2dd19d0f03048f68bb20ca83abe0c00cdab40e86eba5') - version('1.32.0', sha256='42e4774b3bbc7c142f77c41b6ce86b594f579073f46c31f47f424c7e31ee1511') - version('1.30.0', sha256='b5d8c98c53174a98a41efb4ec9dedb62c0a9e8fa111bb6460cd4493beb80d497') - version('1.28.2', sha256='7903fd8ebdd03bcda20a66e3fcedef2f8b384324591aa91b8370f3360f6384eb') - version('1.28.0', sha256='a7999fbaa1f220c2eb9657279c7e7cccd1b21865d5383c9a5685cfe05a0702bc') - version('1.24.0', sha256='76b4d897d5e2261ef83d0885c192e8ac039e32cb2464f11eb64eb3f9f2df38c0') + version('develop', branch='develop') + version('main', branch='stable') + version('master', branch='master') - variant('mpi', default=True, description="Support MPI") - variant('ibv', default=False, description="Support InfiniBand") - variant('udp', default=False, description="Support UDP") - variant('aligned-segments', default=False, - description="Requirement to achieve aligned VM segments") - variant('pshm', default=True, - description="Support inter-process shared memory support") - variant('segment-mmap-max', default='16GB', - description="Upper bound for mmap-based GASNet segments") + version('2021.3.0', sha256='8a40fb3fa8bacc3922cd4d45217816fcb60100357ab97fb622a245567ea31747') + version('2020.10.0', sha256='ed17baf7fce90499b539857ee37b3eea961aa475cffbde77e4c607a34ece06a0') + version('2020.3.0', sha256='019eb2d2284856e6fabe6c8c0061c874f10e95fa0265245f227fd3497f1bb274') + version('2019.9.0', sha256='117f5fdb16e53d0fa8a47a1e28cccab1d8020ed4f6e50163d985dc90226aaa2c') + # Do NOT add older versions here. + # GASNet-EX releases over 2 years old are not supported. - conflicts('+aligned-segments', when='+pshm') + # The optional network backends: + variant('conduits', + values=any_combination_of('smp', 'mpi', 'ibv', 'udp').with_default('smp'), + description="The hardware-dependent network backends to enable.\n" + + "(smp) = SMP conduit for single-node operation ;\n" + + "(ibv) = Native InfiniBand verbs conduit ;\n" + + "(udp) = Portable UDP conduit, for Ethernet networks ;\n" + + "(mpi) = Low-performance/portable MPI conduit ;\n" + + "For detailed recommendations, consult https://gasnet.lbl.gov") - depends_on('mpi', when='+mpi') + variant('debug', default=False, description="Enable library debugging mode") - def url_for_version(self, version): - url = "https://gasnet.lbl.gov/" - if version >= Version('2019'): - url += "EX/GASNet-{0}.tar.gz".format(version) - else: - url += "download/GASNet-{0}.tar.gz".format(version) + depends_on('mpi', when='conduits=mpi') - return url + depends_on('autoconf@2.69', type='build', when='@master:') + depends_on('automake@1.16:', type='build', when='@master:') - def configure_args(self): - args = [ - # TODO: factor IB suport out into architecture description. - '--enable-par', - '--enable-mpi-compat', - '--enable-segment-fast', - '--disable-parsync', - '--with-segment-mmap-max=%s ' - % (self.spec.variants['segment-mmap-max'].value), - # for consumers with shared libs - "CC=%s %s" % (spack_cc, self.compiler.cc_pic_flag), - "CXX=%s %s" % (spack_cxx, self.compiler.cxx_pic_flag), - ] + def install(self, spec, prefix): + if spec.satisfies('@master:'): + bootstrapsh = Executable("./Bootstrap") + bootstrapsh() - if '+aligned-segments' in self.spec: - args.append('--enable-aligned-segments') - else: - args.append('--disable-aligned-segments') + # The GASNet-EX library has a highly multi-dimensional configure space, + # to accomodate the varying behavioral requirements of each client runtime. + # The library's ABI/link compatibility is strongly dependent on these + # client-specific build-time settings, and that variability is deliberately NOT + # encoded in the variants of this package. The recommended way to build/deploy + # GASNet is as an EMBEDDED library within the build of the client package + # (eg. Berkeley UPC, UPC++, Legion, etc), some of which provide build-time + # selection of the GASNet library sources. This spack package provides + # the GASNet-EX sources, for use by appropriate client packages. + install_tree('.', prefix + "/src") - if '+pshm' in self.spec: - args.append('--enable-pshm') - else: - args.append('--disable-pshm') + # Library build is provided for unit-testing purposes only (see notice above) + if 'conduits=none' not in spec: + options = ["--prefix=%s" % prefix] - if '+mpi' in self.spec: - args.extend(['--enable-mpi', - '--disable-udp', - '--disable-ibv', - '--disable-seq', - 'MPI_CC=%s %s' - % (self.spec['mpi'].mpicc, self.compiler.cc_pic_flag)]) + if '+debug' in spec: + options.append("--enable-debug") - if '+ibv' in self.spec: - args.extend(['--enable-ibv', - '--with-ibv-max-hcas=1', - '--enable-pthreads', - '--disable-udp', - '--disable-mpi', - '--disable-seq', - '--disable-smp', - '--disable-portals']) + if 'conduits=mpi' in spec: + options.append("--enable-mpi-compat") + else: + options.append("--disable-mpi-compat") - if '+udp' in self.spec: - args.extend(['--enable-udp', - '--disable-ibv', - '--disable-mpi', - '--disable-seq']) + options.append("--disable-auto-conduit-detect") + for c in spec.variants['conduits'].value: + options.append("--enable-" + c) - return args + configure(*options) + make() + make('install') + + for c in spec.variants['conduits'].value: + testdir = join_path(self.prefix.tests, c) + mkdirp(testdir) + make('-C', c + '-conduit', 'testgasnet-par') + install(c + "-conduit/testgasnet", testdir) + make('-C', c + '-conduit', 'testtools-par') + install(c + "-conduit/testtools", self.prefix.tests) + + @run_after('install') + @on_package_attributes(run_tests=True) + def test_install(self): + if 'conduits=smp' in self.spec: + make('-C', 'smp-conduit', 'run-tests') + if 'conduits=none' not in self.spec: + self.run_test(join_path(self.prefix.tests, 'testtools'), + expected=['Done.'], status=0, + installed=True, purpose="Running testtools") + + def test(self): + if 'conduits=none' in self.spec: + spack.main.send_warning_to_tty("No conduit libraries built -- SKIPPED") + return + + ranks = '4' + spawner = { + 'smp': ['env', 'GASNET_PSHM_NODES=' + ranks], + 'mpi': [join_path(self.prefix.bin, 'gasnetrun_mpi'), '-n', ranks], + 'ibv': [join_path(self.prefix.bin, 'gasnetrun_ibv'), '-n', ranks], + 'udp': [join_path(self.prefix.bin, 'amudprun'), '-spawn', 'L', '-np', ranks] + } + + os.environ['GASNET_VERBOSEENV'] = '1' # include diagnostic info + if 'GASNET_SSH_SERVERS' not in os.environ: + os.environ['GASNET_SSH_SERVERS'] = "localhost " * 4 + + self.run_test(join_path(self.prefix.tests, 'testtools'), + expected=['Done.'], status=0, + installed=True, purpose="Running testtools") + + for c in self.spec.variants['conduits'].value: + os.environ['GASNET_SUPERNODE_MAXSIZE'] = '0' if (c == 'smp') else '1' + test = join_path(self.prefix.tests, c, 'testgasnet') + self.run_test(spawner[c][0], spawner[c][1:] + [test], + expected=['done.'], status=0, + installed=(c != 'smp'), + purpose="Running %s-conduit/testgasnet" % c) diff --git a/var/spack/repos/builtin/packages/upcxx/package.py b/var/spack/repos/builtin/packages/upcxx/package.py index 47ad7defca..d613581258 100644 --- a/var/spack/repos/builtin/packages/upcxx/package.py +++ b/var/spack/repos/builtin/packages/upcxx/package.py @@ -50,6 +50,13 @@ class Upcxx(Package): msg='cross=none is unacceptable on Cray.' + 'Please specify an appropriate "cross" value') + # UPC++ always relies on GASNet-EX. + # The default (and recommendation) is to use the implicit, embedded version. + # This variant allows overriding with a particular version of GASNet-EX sources. + variant('gasnet', default=False, + description="Override embedded GASNet-EX version") + depends_on('gasnet conduits=none', when='+gasnet') + depends_on('mpi', when='+mpi') depends_on('cuda', when='+cuda') # Require Python2 2.7.5+ up to v2019.9.0 @@ -120,6 +127,8 @@ def install(self, spec, prefix): env['CXX'] = spec['mpi'].mpicxx else: env['CXX'] = self.compiler.cxx + if '+gasnet' in self.spec: + env['GASNET'] = spec['gasnet'].prefix.src installsh = Executable("./install") installsh(prefix) else: @@ -150,8 +159,12 @@ def install(self, spec, prefix): env['CC'] = real_cc env['CXX'] = real_cxx - installsh = Executable("./configure") - installsh('--prefix=' + prefix) + options = ["--prefix=%s" % prefix] + + if '+gasnet' in self.spec: + options.append('--with-gasnet=' + spec['gasnet'].prefix.src) + + configure(*options) make()