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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
# Copyright 2013-2024 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
import re
from spack.package import *
class Hpcc(MakefilePackage):
"""HPC Challenge is a benchmark suite that measures a range memory access
patterns.
The HPC Challenge benchmark consists of basically 7 tests:
1) HPL - the Linpack TPP benchmark which measures the floating point
rate of execution for solving a linear system of equations.
2) DGEMM - measures the floating point rate of execution of double
precision real matrix-matrix multiplication.
3) STREAM - a simple synthetic benchmark program that measures
sustainable memory bandwidth (in GB/s) and
the corresponding computation rate for simple vector kernel.
4) PTRANS (parallel matrix transpose) - exercises the communications
where pairs of processors communicate
with each other simultaneously. It is a useful test of the total
communications capacity of the network.
5) RandomAccess - measures the rate of integer random updates of memory
(GUPS).
6) FFT - measures the floating point rate of execution of double
precision complex one-dimensional Discrete Fourier Transform (DFT).
7) Communication bandwidth and latency - a set of tests to measure
latency and bandwidth of a number of simultaneous communication
patterns; based on b_eff (effective bandwidth benchmark)."""
homepage = "https://icl.cs.utk.edu/hpcc"
url = "https://icl.cs.utk.edu/projectsfiles/hpcc/download/hpcc-1.5.0.tar.gz"
git = "https://github.com/icl-utk-edu/hpcc.git"
version("develop", branch="main")
version("1.5.0", sha256="0a6fef7ab9f3347e549fed65ebb98234feea9ee18aea0c8f59baefbe3cf7ffb8")
variant(
"fft",
default="internal",
description="FFT library to use",
values=("internal", "fftw2", "mkl"),
multi=False,
)
depends_on("gmake", type="build")
depends_on("mpi@1.1:")
depends_on("blas")
depends_on("fftw@2+mpi", when="fft=fftw2")
depends_on("mkl", when="fft=mkl")
arch = "{0}-{1}".format(platform.system(), platform.processor())
config = {
"@SHELL@": "/bin/sh",
"@CD@": "cd",
"@CP@": "cp",
"@LN_S@": "ln -s",
"@MKDIR@": "mkdir",
"@RM@": "/bin/rm -f",
"@TOUCH@": "touch",
"@ARCHIVER@": "ar",
"@ARFLAGS@": "r",
"@RANLIB@": "echo",
"@ARCH@": arch,
"@MPDIR@": "",
"@MPINC@": "",
"@MPLIB@": "",
"@F2CDEFS@": "-DAdd_ -DF77_INTEGER=int -DStringSunStyle",
"@LADIR@": "",
"@LAINC@": "",
"@LALIB@": "",
"@CC@": None,
"@CCNOOPT@": "",
"@CCFLAGS@": "-O3",
"@LINKER@": "$(CC)",
"@LINKFLAGS@": "",
}
def patch(self):
if "fftw" in self.spec:
# spack's fftw2 prefix headers with floating point type
filter_file(r"^\s*#include <fftw.h>", "#include <sfftw.h>", "FFT/wrapfftw.h")
filter_file(
r"^\s*#include <fftw_mpi.h>", "#include <sfftw_mpi.h>", "FFT/wrapmpifftw.h"
)
def _write_make_arch(self, spec, prefix):
"""write make.arch file"""
with working_dir("hpl"):
# copy template make.arch file
make_arch_filename = "Make.{0}".format(self.arch)
copy(join_path("setup", "Make.UNKNOWN.in"), make_arch_filename)
# fill template with values
make_arch = FileFilter(make_arch_filename)
for k, v in self.config.items():
make_arch.filter(k, v)
def edit(self, spec, prefix):
# Message Passing library (MPI)
self.config["@MPINC@"] = spec["mpi"].headers.include_flags
self.config["@MPLIB@"] = spec["mpi"].libs.search_flags
lin_alg_libs = []
# FFT
if self.spec.variants["fft"].value in ("fftw2", "mkl"):
self.config["@LAINC@"] += " -DUSING_FFTW"
if self.spec.variants["fft"].value == "fftw2":
self.config["@LAINC@"] += spec["fftw-api"].headers.include_flags
# fftw does not set up libs for version 2
lin_alg_libs.append(join_path(spec["fftw-api"].prefix.lib, "libsfftw_mpi.so"))
lin_alg_libs.append(join_path(spec["fftw-api"].prefix.lib, "libsfftw.so"))
elif (
self.spec.variants["fft"].value == "mkl"
and spec["fftw-api"].name in INTEL_MATH_LIBRARIES
):
mklroot = env["MKLROOT"]
self.config["@LAINC@"] += " -I{0}".format(join_path(mklroot, "include/fftw"))
libfftw2x_cdft = join_path(
mklroot, "lib", "intel64", "libfftw2x_cdft_DOUBLE_ilp64.a"
)
libfftw2xc = join_path(mklroot, "lib", "intel64", "libfftw2xc_double_intel.a")
if not (os.path.exists(libfftw2x_cdft) and os.path.exists(libfftw2xc)):
raise InstallError(
"HPCC need fftw2 interface, "
"here are brief notes how to make one:\n"
"# make fftw2x_cdft interface to mkl\n"
"cd $MKLROOT/interfaces/fftw2x_cdft\n"
"make libintel64 PRECISION=MKL_DOUBLE "
"interface=ilp64 MKLROOT=$MKLROOT\n"
"\n"
"# make FFTW C wrapper library\n"
"cd $MKLROOT/interfaces/fftw2xc\n"
"make libintel64 PRECISION=MKL_DOUBLE "
"MKLROOT=$MKLROOT\n"
)
lin_alg_libs.append(libfftw2xc)
lin_alg_libs.append(libfftw2x_cdft)
# Linear Algebra library (BLAS or VSIPL)
self.config["@LAINC@"] = spec["blas"].headers.include_flags
lin_alg_libs = lin_alg_libs + [lib for lib in spec["blas"].libs if lib not in lin_alg_libs]
# pack all LA/FFT libraries
self.config["@LALIB@"] = " ".join(lin_alg_libs)
# Compilers / linkers - Optimization flags
self.config["@CC@"] = "{0}".format(spec["mpi"].mpicc)
# Compiler flags for CPU architecture optimizations
if spec.satisfies("%intel"):
# with intel-parallel-studio+mpi the '-march' arguments
# are not passed to icc
arch_opt = spec.target.optimization_flags(spec.compiler.name, spec.compiler.version)
self.config["@CCFLAGS@"] = "-O3 -restrict -ansi-alias -ip {0}".format(arch_opt)
self.config["@CCNOOPT@"] = "-restrict"
self._write_make_arch(spec, prefix)
def build(self, spec, prefix):
make("arch={0}".format(self.arch))
def check(self):
"""Simple check that compiled binary is working:
launch with 4 MPI processes and check that test finished."""
# copy input
copy("_hpccinf.txt", "hpccinf.txt")
# run test
run = Executable(join_path(os.path.dirname(self.spec["mpi"].mpicc), "mpirun"))
run("-np", "4", "./hpcc")
# check output
hpccoutf = open("hpccoutf.txt", "rt").read()
if not re.search("End of HPC Challenge tests", hpccoutf):
raise Exception("Test run was not successfull!")
def installcheck(self):
"""Same as check but within prefix location"""
with working_dir(self.prefix.share.hpcc):
# run test
run = Executable(join_path(os.path.dirname(self.spec["mpi"].mpicc), "mpirun"))
run("-np", "4", self.prefix.bin.hpcc)
# check output
hpccoutf = open("hpccoutf.txt", "rt").read()
if not re.search("End of HPC Challenge tests", hpccoutf):
raise Exception("Test run was not successfull!")
def install(self, spec, prefix):
# copy executable
mkdirp(self.prefix.bin)
install("hpcc", prefix.bin)
# copy input example
mkdirp(self.prefix.share.hpcc)
install("_hpccinf.txt", join_path(self.prefix.share.hpcc, "hpccinf.txt"))
# copy documentation
mkdirp(self.prefix.doc.hpcc)
install("README.html", self.prefix.doc.hpcc)
install("README.txt", self.prefix.doc.hpcc)
def flag_handler(self, name, flags):
# old GCC defaults to -std=c90 but C99 is required for "restrict"
if self.spec.satisfies("%gcc@:5.1") and name == "cflags":
flags.append(self.compiler.c99_flag)
return (flags, None, None)
|