summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/hpl/package.py
blob: ad3cb43eb0b7f6f2a1d03dd06e131f2084fd95f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os
import platform

from spack.package import *


class Hpl(AutotoolsPackage):
    """HPL is a software package that solves a (random) dense linear system
    in double precision (64 bits) arithmetic on distributed-memory computers.
    It can thus be regarded as a portable as well as freely available
    implementation of the High Performance Computing Linpack Benchmark."""

    homepage = "https://www.netlib.org/benchmark/hpl/"
    url = "https://www.netlib.org/benchmark/hpl/hpl-2.2.tar.gz"

    # Note: HPL uses autotools starting with 2.3

    version("2.3", sha256="32c5c17d22330e6f2337b681aded51637fb6008d3f0eb7c277b163fadd612830")
    version("2.2", sha256="ac7534163a09e21a5fa763e4e16dfc119bc84043f6e6a807aba666518f8df440")

    variant("openmp", default=False, description="Enable OpenMP support")

    depends_on("mpi@1.1:")
    depends_on("blas")

    # 2.3 adds support for openmpi 4
    conflicts("^openmpi@4.0.0:", when="@:2.2")

    parallel = False

    arch = "{0}-{1}".format(platform.system(), platform.processor())
    build_targets = ["arch={0}".format(arch)]

    @when("@:2.2")
    def autoreconf(self, spec, prefix):
        # Prevent sanity check from killing the build
        touch("configure")

    @when("@:2.2")
    def configure(self, spec, prefix):
        # List of configuration options
        # Order is important
        config = []

        # OpenMP support
        if "+openmp" in spec:
            config.append("OMP_DEFS     = {0}".format(self.compiler.openmp_flag))

        config.extend(
            [
                # Shell
                "SHELL        = /bin/sh",
                "CD           = cd",
                "CP           = cp",
                "LN_S         = ln -fs",
                "MKDIR        = mkdir -p",
                "RM           = /bin/rm -f",
                "TOUCH        = touch",
                # Platform identifier
                "ARCH         = {0}".format(self.arch),
                # HPL Directory Structure / HPL library
                "TOPdir       = {0}".format(os.getcwd()),
                "INCdir       = $(TOPdir)/include",
                "BINdir       = $(TOPdir)/bin/$(ARCH)",
                "LIBdir       = $(TOPdir)/lib/$(ARCH)",
                "HPLlib       = $(LIBdir)/libhpl.a",
                # Message Passing library (MPI)
                "MPinc        = {0}".format(spec["mpi"].prefix.include),
                "MPlib        = -L{0}".format(spec["mpi"].prefix.lib),
                # Linear Algebra library (BLAS or VSIPL)
                "LAinc        = {0}".format(spec["blas"].prefix.include),
                "LAlib        = {0}".format(spec["blas"].libs.joined()),
                # F77 / C interface
                "F2CDEFS      = -DAdd_ -DF77_INTEGER=int -DStringSunStyle",
                # HPL includes / libraries / specifics
                "HPL_INCLUDES = -I$(INCdir) -I$(INCdir)/$(ARCH) " + "-I$(LAinc) -I$(MPinc)",
                "HPL_LIBS     = $(HPLlib) $(LAlib) $(MPlib)",
                "HPL_OPTS     = -DHPL_DETAILED_TIMING -DHPL_PROGRESS_REPORT",
                "HPL_DEFS     = $(F2CDEFS) $(HPL_OPTS) $(HPL_INCLUDES)",
                # Compilers / linkers - Optimization flags
                "CC           = {0}".format(spec["mpi"].mpicc),
                "CCNOOPT      = $(HPL_DEFS)",
                "CCFLAGS      = $(HPL_DEFS) -O3",
                "LINKER       = $(CC)",
                "LINKFLAGS    = $(CCFLAGS) $(OMP_DEFS)",
                "ARCHIVER     = ar",
                "ARFLAGS      = r",
                "RANLIB       = echo",
            ]
        )

        # Write configuration options to include file
        with open("Make.{0}".format(self.arch), "w") as makefile:
            for var in config:
                makefile.write("{0}\n".format(var))

    @when("@2.3:")
    def configure_args(self):
        filter_file(r"^libs10=.*", "libs10=%s" % self.spec["blas"].libs.ld_flags, "configure")

        if "+openmp" in self.spec:
            config = ["CFLAGS=-O3 " + self.compiler.openmp_flag]
        else:
            config = ["CFLAGS=-O3"]

        if (
            self.spec.satisfies("^intel-mkl")
            or self.spec.satisfies("^intel-oneapi-mkl")
            or self.spec.satisfies("^intel-parallel-studio+mkl")
        ):
            config.append("LDFLAGS={0}".format(self.spec["blas"].libs.ld_flags))

        if "%aocc" in self.spec:
            amd_ldflags = " "
            if "%aocc@3:" in self.spec:
                amd_ldflags += "-lamdlibm -lm "
            if "%aocc@4:" in self.spec:
                amd_ldflags += "-lamdalloc "
            config.append("LDFLAGS=" + amd_ldflags)

        return config

    @when("@:2.2")
    def install(self, spec, prefix):
        # Manual installation
        install_tree(join_path("bin", self.arch), prefix.bin)
        install_tree(join_path("lib", self.arch), prefix.lib)
        install_tree(join_path("include", self.arch), prefix.include)
        install_tree("man", prefix.man)

    @run_after("install")
    def copy_dat(self):
        if self.spec.satisfies("@2.3:"):
            # The pre-2.3 makefile would include a default HPL.dat config
            # file in the bin directory
            install("./testing/ptest/HPL.dat", join_path(self.prefix.bin, "HPL.dat"))