├── .gitignore ├── AUTHORS ├── INSTALL ├── LICENSE ├── Makefile.am ├── NEWS ├── README.md ├── autogen.sh ├── configure.ac ├── docs └── ates_icpp19.pdf ├── m4 ├── ax_cache_size.m4 ├── ax_count_cpus.m4 ├── ax_cpu_vendor.m4 ├── ax_cxx_compile_stdcxx.m4 └── ax_gcc_x86_cpuid.m4 └── src ├── anomalies.h ├── cachecopy.c ├── cpuoccupy.c ├── iobandwidth ├── iometadata.c ├── main.c ├── membw.c ├── memeater.c ├── memleak.c ├── netoccupy.c ├── utils.c └── utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # http://www.gnu.org/software/automake 35 | 36 | Makefile.in 37 | /ar-lib 38 | /mdate-sh 39 | /py-compile 40 | /test-driver 41 | /ylwrap 42 | 43 | # http://www.gnu.org/software/autoconf 44 | 45 | autom4te.cache 46 | /autoscan.log 47 | /autoscan-*.log 48 | /aclocal.m4 49 | /compile 50 | /config.guess 51 | /config.h.in 52 | /config.log 53 | /config.status 54 | /config.sub 55 | /configure 56 | /configure.scan 57 | /depcomp 58 | /install-sh 59 | /missing 60 | /stamp-h1 61 | 62 | # https://www.gnu.org/software/libtool/ 63 | 64 | /ltmain.sh 65 | 66 | # http://www.gnu.org/software/texinfo 67 | 68 | /texinfo.tex 69 | 70 | # http://www.gnu.org/software/m4/ 71 | 72 | m4/libtool.m4 73 | m4/ltoptions.m4 74 | m4/ltsugar.m4 75 | m4/ltversion.m4 76 | m4/lt~obsolete.m4 77 | 78 | # Manually added 79 | build-aux/ 80 | .deps/ 81 | .dirstamp 82 | *~ 83 | Makefile 84 | hpas 85 | hpas-*.tar.gz 86 | config.h 87 | bin 88 | .idea/ 89 | 90 | #Output files 91 | *.out 92 | CoMD*.yaml 93 | results.yaml 94 | clover.in.tmp 95 | *.log 96 | __pycache__/ 97 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Emre Ates 2 | Burak Aksar 3 | Yijia Zhang 4 | Ata Turk 5 | Vitus J. Leung 6 | Jim Brandt 7 | Manuel Egele 8 | Ayse K. Coskun 9 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software 5 | Foundation, Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell command './configure && make && make install' 16 | should configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the 'README' file for 18 | instructions specific to this package. Some packages provide this 19 | 'INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The 'configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a 'Makefile' in each directory of the package. 27 | It may also create one or more '.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script 'config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file 'config.log' containing compiler output (useful mainly for 31 | debugging 'configure'). 32 | 33 | It can also use an optional file (typically called 'config.cache' and 34 | enabled with '--cache-file=config.cache' or simply '-C') that saves the 35 | results of its tests to speed up reconfiguring. Caching is disabled by 36 | default to prevent problems with accidental use of stale cache files. 37 | 38 | If you need to do unusual things to compile the package, please try 39 | to figure out how 'configure' could check whether to do them, and mail 40 | diffs or instructions to the address given in the 'README' so they can 41 | be considered for the next release. If you are using the cache, and at 42 | some point 'config.cache' contains results you don't want to keep, you 43 | may remove or edit it. 44 | 45 | The file 'configure.ac' (or 'configure.in') is used to create 46 | 'configure' by a program called 'autoconf'. You need 'configure.ac' if 47 | you want to change it or regenerate 'configure' using a newer version of 48 | 'autoconf'. 49 | 50 | The simplest way to compile this package is: 51 | 52 | 1. 'cd' to the directory containing the package's source code and type 53 | './configure' to configure the package for your system. 54 | 55 | Running 'configure' might take a while. While running, it prints 56 | some messages telling which features it is checking for. 57 | 58 | 2. Type 'make' to compile the package. 59 | 60 | 3. Optionally, type 'make check' to run any self-tests that come with 61 | the package, generally using the just-built uninstalled binaries. 62 | 63 | 4. Type 'make install' to install the programs and any data files and 64 | documentation. When installing into a prefix owned by root, it is 65 | recommended that the package be configured and built as a regular 66 | user, and only the 'make install' phase executed with root 67 | privileges. 68 | 69 | 5. Optionally, type 'make installcheck' to repeat any self-tests, but 70 | this time using the binaries in their final installed location. 71 | This target does not install anything. Running this target as a 72 | regular user, particularly if the prior 'make install' required 73 | root privileges, verifies that the installation completed 74 | correctly. 75 | 76 | 6. You can remove the program binaries and object files from the 77 | source code directory by typing 'make clean'. To also remove the 78 | files that 'configure' created (so you can compile the package for 79 | a different kind of computer), type 'make distclean'. There is 80 | also a 'make maintainer-clean' target, but that is intended mainly 81 | for the package's developers. If you use it, you may have to get 82 | all sorts of other programs in order to regenerate files that came 83 | with the distribution. 84 | 85 | 7. Often, you can also type 'make uninstall' to remove the installed 86 | files again. In practice, not all packages have tested that 87 | uninstallation works correctly, even though it is required by the 88 | GNU Coding Standards. 89 | 90 | 8. Some packages, particularly those that use Automake, provide 'make 91 | distcheck', which can by used by developers to test that all other 92 | targets like 'make install' and 'make uninstall' work correctly. 93 | This target is generally not run by end users. 94 | 95 | Compilers and Options 96 | ===================== 97 | 98 | Some systems require unusual options for compilation or linking that 99 | the 'configure' script does not know about. Run './configure --help' 100 | for details on some of the pertinent environment variables. 101 | 102 | You can give 'configure' initial values for configuration parameters 103 | by setting variables in the command line or in the environment. Here is 104 | an example: 105 | 106 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 107 | 108 | *Note Defining Variables::, for more details. 109 | 110 | Compiling For Multiple Architectures 111 | ==================================== 112 | 113 | You can compile the package for more than one kind of computer at the 114 | same time, by placing the object files for each architecture in their 115 | own directory. To do this, you can use GNU 'make'. 'cd' to the 116 | directory where you want the object files and executables to go and run 117 | the 'configure' script. 'configure' automatically checks for the source 118 | code in the directory that 'configure' is in and in '..'. This is known 119 | as a "VPATH" build. 120 | 121 | With a non-GNU 'make', it is safer to compile the package for one 122 | architecture at a time in the source code directory. After you have 123 | installed the package for one architecture, use 'make distclean' before 124 | reconfiguring for another architecture. 125 | 126 | On MacOS X 10.5 and later systems, you can create libraries and 127 | executables that work on multiple system types--known as "fat" or 128 | "universal" binaries--by specifying multiple '-arch' options to the 129 | compiler but only a single '-arch' option to the preprocessor. Like 130 | this: 131 | 132 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 133 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CPP="gcc -E" CXXCPP="g++ -E" 135 | 136 | This is not guaranteed to produce working output in all cases, you 137 | may have to build one architecture at a time and combine the results 138 | using the 'lipo' tool if you have problems. 139 | 140 | Installation Names 141 | ================== 142 | 143 | By default, 'make install' installs the package's commands under 144 | '/usr/local/bin', include files under '/usr/local/include', etc. You 145 | can specify an installation prefix other than '/usr/local' by giving 146 | 'configure' the option '--prefix=PREFIX', where PREFIX must be an 147 | absolute file name. 148 | 149 | You can specify separate installation prefixes for 150 | architecture-specific files and architecture-independent files. If you 151 | pass the option '--exec-prefix=PREFIX' to 'configure', the package uses 152 | PREFIX as the prefix for installing programs and libraries. 153 | Documentation and other data files still use the regular prefix. 154 | 155 | In addition, if you use an unusual directory layout you can give 156 | options like '--bindir=DIR' to specify different values for particular 157 | kinds of files. Run 'configure --help' for a list of the directories 158 | you can set and what kinds of files go in them. In general, the default 159 | for these options is expressed in terms of '${prefix}', so that 160 | specifying just '--prefix' will affect all of the other directory 161 | specifications that were not explicitly provided. 162 | 163 | The most portable way to affect installation locations is to pass the 164 | correct locations to 'configure'; however, many packages provide one or 165 | both of the following shortcuts of passing variable assignments to the 166 | 'make install' command line to change installation locations without 167 | having to reconfigure or recompile. 168 | 169 | The first method involves providing an override variable for each 170 | affected directory. For example, 'make install 171 | prefix=/alternate/directory' will choose an alternate location for all 172 | directory configuration variables that were expressed in terms of 173 | '${prefix}'. Any directories that were specified during 'configure', 174 | but not in terms of '${prefix}', must each be overridden at install time 175 | for the entire installation to be relocated. The approach of makefile 176 | variable overrides for each directory variable is required by the GNU 177 | Coding Standards, and ideally causes no recompilation. However, some 178 | platforms have known limitations with the semantics of shared libraries 179 | that end up requiring recompilation when using this method, particularly 180 | noticeable in packages that use GNU Libtool. 181 | 182 | The second method involves providing the 'DESTDIR' variable. For 183 | example, 'make install DESTDIR=/alternate/directory' will prepend 184 | '/alternate/directory' before all installation names. The approach of 185 | 'DESTDIR' overrides is not required by the GNU Coding Standards, and 186 | does not work on platforms that have drive letters. On the other hand, 187 | it does better at avoiding recompilation issues, and works well even 188 | when some directory options were not specified in terms of '${prefix}' 189 | at 'configure' time. 190 | 191 | Optional Features 192 | ================= 193 | 194 | If the package supports it, you can cause programs to be installed 195 | with an extra prefix or suffix on their names by giving 'configure' the 196 | option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. 197 | 198 | Some packages pay attention to '--enable-FEATURE' options to 199 | 'configure', where FEATURE indicates an optional part of the package. 200 | They may also pay attention to '--with-PACKAGE' options, where PACKAGE 201 | is something like 'gnu-as' or 'x' (for the X Window System). The 202 | 'README' should mention any '--enable-' and '--with-' options that the 203 | package recognizes. 204 | 205 | For packages that use the X Window System, 'configure' can usually 206 | find the X include and library files automatically, but if it doesn't, 207 | you can use the 'configure' options '--x-includes=DIR' and 208 | '--x-libraries=DIR' to specify their locations. 209 | 210 | Some packages offer the ability to configure how verbose the 211 | execution of 'make' will be. For these packages, running './configure 212 | --enable-silent-rules' sets the default to minimal output, which can be 213 | overridden with 'make V=1'; while running './configure 214 | --disable-silent-rules' sets the default to verbose, which can be 215 | overridden with 'make V=0'. 216 | 217 | Particular systems 218 | ================== 219 | 220 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC 221 | is not installed, it is recommended to use the following options in 222 | order to use an ANSI C compiler: 223 | 224 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 225 | 226 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 227 | 228 | HP-UX 'make' updates targets which have the same time stamps as their 229 | prerequisites, which makes it generally unusable when shipped generated 230 | files such as 'configure' are involved. Use GNU 'make' instead. 231 | 232 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 233 | parse its '' header file. The option '-nodtk' can be used as a 234 | workaround. If GNU CC is not installed, it is therefore recommended to 235 | try 236 | 237 | ./configure CC="cc" 238 | 239 | and if that doesn't work, try 240 | 241 | ./configure CC="cc -nodtk" 242 | 243 | On Solaris, don't put '/usr/ucb' early in your 'PATH'. This 244 | directory contains several dysfunctional programs; working variants of 245 | these programs are available in '/usr/bin'. So, if you need '/usr/ucb' 246 | in your 'PATH', put it _after_ '/usr/bin'. 247 | 248 | On Haiku, software installed for all users goes in '/boot/common', 249 | not '/usr/local'. It is recommended to use the following options: 250 | 251 | ./configure --prefix=/boot/common 252 | 253 | Specifying the System Type 254 | ========================== 255 | 256 | There may be some features 'configure' cannot figure out 257 | automatically, but needs to determine by the type of machine the package 258 | will run on. Usually, assuming the package is built to be run on the 259 | _same_ architectures, 'configure' can figure that out, but if it prints 260 | a message saying it cannot guess the machine type, give it the 261 | '--build=TYPE' option. TYPE can either be a short name for the system 262 | type, such as 'sun4', or a canonical name which has the form: 263 | 264 | CPU-COMPANY-SYSTEM 265 | 266 | where SYSTEM can have one of these forms: 267 | 268 | OS 269 | KERNEL-OS 270 | 271 | See the file 'config.sub' for the possible values of each field. If 272 | 'config.sub' isn't included in this package, then this package doesn't 273 | need to know the machine type. 274 | 275 | If you are _building_ compiler tools for cross-compiling, you should 276 | use the option '--target=TYPE' to select the type of system they will 277 | produce code for. 278 | 279 | If you want to _use_ a cross compiler, that generates code for a 280 | platform different from the build platform, you should specify the 281 | "host" platform (i.e., that on which the generated programs will 282 | eventually be run) with '--host=TYPE'. 283 | 284 | Sharing Defaults 285 | ================ 286 | 287 | If you want to set default values for 'configure' scripts to share, 288 | you can create a site shell script called 'config.site' that gives 289 | default values for variables like 'CC', 'cache_file', and 'prefix'. 290 | 'configure' looks for 'PREFIX/share/config.site' if it exists, then 291 | 'PREFIX/etc/config.site' if it exists. Or, you can set the 292 | 'CONFIG_SITE' environment variable to the location of the site script. 293 | A warning: not all 'configure' scripts look for a site script. 294 | 295 | Defining Variables 296 | ================== 297 | 298 | Variables not defined in a site shell script can be set in the 299 | environment passed to 'configure'. However, some packages may run 300 | configure again during the build, and the customized values of these 301 | variables may be lost. In order to avoid this problem, you should set 302 | them in the 'configure' command line, using 'VAR=value'. For example: 303 | 304 | ./configure CC=/usr/local2/bin/gcc 305 | 306 | causes the specified 'gcc' to be used as the C compiler (unless it is 307 | overridden in the site shell script). 308 | 309 | Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an 310 | Autoconf limitation. Until the limitation is lifted, you can use this 311 | workaround: 312 | 313 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 314 | 315 | 'configure' Invocation 316 | ====================== 317 | 318 | 'configure' recognizes the following options to control how it 319 | operates. 320 | 321 | '--help' 322 | '-h' 323 | Print a summary of all of the options to 'configure', and exit. 324 | 325 | '--help=short' 326 | '--help=recursive' 327 | Print a summary of the options unique to this package's 328 | 'configure', and exit. The 'short' variant lists options used only 329 | in the top level, while the 'recursive' variant lists options also 330 | present in any nested packages. 331 | 332 | '--version' 333 | '-V' 334 | Print the version of Autoconf used to generate the 'configure' 335 | script, and exit. 336 | 337 | '--cache-file=FILE' 338 | Enable the cache: use and save the results of the tests in FILE, 339 | traditionally 'config.cache'. FILE defaults to '/dev/null' to 340 | disable caching. 341 | 342 | '--config-cache' 343 | '-C' 344 | Alias for '--cache-file=config.cache'. 345 | 346 | '--quiet' 347 | '--silent' 348 | '-q' 349 | Do not print messages saying which checks are being made. To 350 | suppress all normal output, redirect it to '/dev/null' (any error 351 | messages will still be shown). 352 | 353 | '--srcdir=DIR' 354 | Look for the package's source code in directory DIR. Usually 355 | 'configure' can determine that directory automatically. 356 | 357 | '--prefix=DIR' 358 | Use DIR as the installation prefix. *note Installation Names:: for 359 | more details, including other options available for fine-tuning the 360 | installation locations. 361 | 362 | '--no-create' 363 | '-n' 364 | Run the configure checks, but stop before creating any output 365 | files. 366 | 367 | 'configure' also accepts some other, not widely useful, options. Run 368 | 'configure --help' for more details. 369 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Emre Ates 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | ACLOCAL_AMFLAGS = -I m4 --install 3 | AM_CFLAGS = -DBINDIR='"$(bindir)"' 4 | 5 | dist_bin_SCRIPTS = src/iobandwidth 6 | bin_PROGRAMS = hpas 7 | 8 | hpas_SOURCES = src/cachecopy.c src/cpuoccupy.c src/iometadata.c src/main.c src/memeater.c src/memleak.c src/utils.c src/utils.h src/anomalies.h 9 | if HAVE_SHMEM 10 | hpas_SOURCES += src/netoccupy.c 11 | endif 12 | if HAVE_XMM 13 | hpas_SOURCES += src/membw.c 14 | endif 15 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peaclab/HPAS/e4050abbf4a7525cef5a1694c736632341d7fecf/NEWS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HPC Performance Anomaly Suite (HPAS) 2 | ==================================== 3 | 4 | This repository holds the anomaly suite presented in the paper "[HPAS: An HPC Performance Anomaly Suite for Reproducing Performance Variations](https://github.com/peaclab/HPAS/blob/master/docs/ates_icpp19.pdf)"[1]. It consists of a set of synthetic anomalies that reproduce common root causes of performance variations in supercomputers: 5 | 6 | * CPU contention 7 | * Cache evictions 8 | * Memory bandwidth interference 9 | * Memory intensive processes 10 | * Memory leaks 11 | * Network contention 12 | * I/O metadata server contention 13 | * I/O storage server contention 14 | 15 | These anomalies use processes that run in user space; thus do not require any hardware or kernel modification. For installation details please see below. 16 | 17 | An earlier subset of the anomalies were used as part of the papers *Tuncer et al., "Online Diagnosis of Performance Variation in HPC Systems Using Machine Learning"*[2] and *Tuncer et al., "Diagnosing Performance Variations in HPC Applications Using Machine Learning"*[3]. 18 | 19 | Installation 20 | ------------ 21 | A brief intro is here, but check INSTALL for more details. 22 | 1. Install C/C++ compilers, GNU autotools 23 | 1. Install shmem if you wish to use netoccupy anomaly. OpenMPI typically 24 | includes a shmem compiler. 25 | 2. If checking out from git, generate the configure script by running the 26 | command `./autogen.sh`. For the latest release tarball, see the releases. 27 | 3. `./configure` 28 | 1. Configure has some options that can be explored, such as prefix 29 | directory, see `./configure --help` 30 | 2. The cache anomalies measure the cache size during this step, so it's 31 | important to run configure on the node that the anomaly is going to 32 | execute on. 33 | 3. `LD_LIBRARY_PATH` and `CFLAGS` should indicate the location of `shmem.h` and 34 | relevant libraries. If using OpenMPI, use `oshcc` to compile (add 35 | `CC=oshcc` to `configure` arguments) and oshrun to run. 36 | 4. `make` 37 | 5. `make install` 38 | 39 | More Details on Anomalies 40 | ------------------------- 41 | 42 | The time units are specified in double precision floats, in seconds. Up to 43 | microsecond granularity can be used. Each anomaly has a `--help` option, which 44 | prints detailed information about command line arguments. 45 | 46 | For detailed evaluation of anomalies, refer to our paper at ICPP'19, a copy is 47 | included in `docs/ates_icpp19.pdf`. 48 | 49 | #### Note for `netoccupy` 50 | The `netoccupy` anomaly assumes that each node has a hostname of the form e.g., 51 | `nid00020`, such that each node name is `nid` followed by a unique integer. The 52 | relevant line within `src/netoccupy.c` should be changed to support different 53 | node naming conventions. 54 | 55 | ### Comparison with anomalies from [2] and [3] 56 | In the 2017 ISC paper [3], and the 2019 TPDS paper [2] an earlier version of the anomaly suite was used. 57 | The following table describes how each anomaly corresponds to the ones in the suite. 58 | 59 | | Subsystem | HPAS Anomaly | Anomaly from [2] | Anomaly from [3] | 60 | | --------- | ------------ | ---------------- | -----------------| 61 | | CPU | cpuoccupy | dial | dial | 62 | | Cache | cachecopy | dcopy | dcopy, ddot | 63 | | Memory | memleak | leak | leak | 64 | | Memory | memeater | memeater | memeater | 65 | | Memory | membw | N/A | N/A | 66 | | Network | netoccupy | N/A | N/A | 67 | | Network | N/A | linkclog | N/A | 68 | | I/O | iobandwidth | N/A | N/A | 69 | | I/O | iometadata | N/A | N/A | 70 | 71 | In [2], `linkclog` was using wrappers around MPI calls to emulate network contention, whereas `netoccupy` 72 | creates actual network contention by sending/receiving many messages, so they are not equivalent. 73 | 74 | Usage of Anomalies 75 | ------------------ 76 | 77 | For SLURM systems, the anomalies can be injected into the application with the 78 | following example line (with necessary modifications) in the job submission script: 79 | 80 | ``` 81 | srun --nodelist=$ANOMALOUS_NODE -N 1 -n 1 $PREFIX/bin/hpas cpuoccupy [--options] & 82 | anomaly_pid=$! 83 | ``` 84 | 85 | For anomalies that stress a shared resource between nodes (I/O and network), 86 | `$ANOMALOUS_NODE` should be different from application nodes, and it should be 87 | one of the application nodes if the anomaly is a CPU, cache or memory anomaly. 88 | The I/O anomalies can be executed with higher `-N` (nodes) and `-n` (ranks) 89 | values for more interference, and the network anomaly has to be executed 90 | with `-N 2`. 91 | 92 | 93 | Contributing 94 | ------------ 95 | 96 | This anomaly suite is not an exhaustive list of anomaly generators for HPC 97 | systems. Therefore, we are open to additions of new anomalies. If you have an 98 | anomaly generator you would like to contribute, please open a pull request/issue 99 | at GitHub, and we can work together to include the anomalies. 100 | 101 | For any bugs/problems, please open a pull request if you have a fix, issue 102 | otherwise. 103 | 104 | Using HPAS 105 | ---------- 106 | 107 | If you use this anomaly suite for a publication, please cite [1]. 108 | 109 | Bibtex entry: 110 | ``` 111 | @inproceedings{ates:2019, 112 | author = {Emre Ates and Yijia Zhang and Burak Aksar and Jim Brandt and 113 | Vitus J. Leung and Manuel Egele and Ayse K. Coskun}, 114 | title = {{HPAS}: An {HPC} Performance Anomaly Suite for Reproducing 115 | Performance Variations}, 116 | booktitle = {48th International Conference on Parallel Processing 117 | (ICPP 2019)}, 118 | year = {2019}, 119 | } 120 | ``` 121 | 122 | License 123 | ------- 124 | 125 | HPAS is licensed under the [BSD 3-Clause license](https://github.com/peaclab/HPAS/blob/master/LICENSE). 126 | 127 | References 128 | ---------- 129 | 130 | [1] Emre Ates, Yijia Zhang, Burak Aksar, Jim Brandt, Vitus J. Leung, Manuel Egele, and Ayse K. Coskun. HPAS: An HPC Performance Anomaly Suite for Reproducing Performance Variations. In International Conference on Parallel Processing (ICPP), Aug. 2019 131 | 132 | [2] Ozan Tuncer, Emre Ates, Yijia Zhang, Ata Turk, Jim Brandt, Vitus J. Leung, Manuel Egele, and Ayse K. Coskun. Online Diagnosis of Performance Variation in HPC Systems Using Machine Learning, in IEEE Transactions on Parallel and Distributed Systems (TPDS), vol. 30, no. 4, pp. 883-896, April 2019. 133 | 134 | [3] Ozan Tuncer, Emre Ates, Yijia Zhang, Ata Turk, Jim Brandt, Vitus Leung, Manuel Egele, and Ayse K. Coskun. Diagnosing Performance Variations in HPC Applications using Machine Learning. In International Supercomputing Conference, ISC-HPC 2017., pp. 355-373, June 2017. Gauss Award. 135 | 136 | 137 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Used to build the suite completely 4 | # Aimed at developers, users should just use configure and make 5 | 6 | autoreconf -ivf 7 | ./configure --prefix=$PWD 8 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([HPCAnomalySuite], [0.9], [ates@bu.edu], [hpas], [www.bu.edu/peaclab]) 2 | AC_CONFIG_SRCDIR([src]) 3 | AC_CONFIG_AUX_DIR([build-aux]) 4 | AC_CONFIG_MACRO_DIR([m4]) 5 | m4_include([m4/ax_cache_size.m4]) 6 | 7 | ## Determine the compiler's vendor. 8 | 9 | AC_PROG_GREP 10 | COMPILER_VERSION=`"$CC" --version 2>/dev/null` 11 | IS_CRAY_COMPILER=`echo $COMPILER_VERSION | $GREP 'Cray'` 12 | if test ! -z "$IS_CRAY_COMPILER" 13 | then 14 | # Otherwise cray compiler cannot find libuuid 15 | LDFLAGS+=' -dynamic ' 16 | fi 17 | 18 | have_shmem_h=no 19 | AC_CHECK_HEADERS([shmem.h], [have_shmem_h=yes], 20 | [AC_MSG_WARN(["shmem.h not found"])]) 21 | have_shmem_lib=no 22 | AC_SEARCH_LIBS([shmem_init], [shmem], [have_shmem_lib=yes], 23 | [AC_MSG_WARN(["shmem_init not found"])]) 24 | 25 | AM_CONDITIONAL([HAVE_SHMEM], [test "$have_shmem_h" = "yes" && test "$have_shmem_lib" = "yes"]) 26 | AC_DEFINE([HAVE_SHMEM], [], ["Have SHMEM"]) 27 | AS_IF([test "$have_shmem_h" = "yes" && test "$have_shmem_lib" = "yes"], 28 | [AC_DEFINE([HAVE_SHMEM], [1])], 29 | [AC_DEFINE([HAVE_SHMEM], [0]) 30 | AC_MSG_WARN(["not compiling netoccupy"])]) 31 | 32 | have_xmm=no 33 | AC_CHECK_HEADERS([xmmintrin.h], [have_xmm=yes], 34 | [AC_MSG_WARN(["xmmintrin.h not found, not compiling membw"])]) 35 | AM_CONDITIONAL([HAVE_XMM], [test "$have_xmm" = "yes"]) 36 | 37 | AX_CACHE_SIZE 38 | AM_INIT_AUTOMAKE([1.11 subdir-objects -Wall -Werror]) 39 | AC_CONFIG_FILES([Makefile]) 40 | AC_CONFIG_HEADERS([config.h]) 41 | AC_PROG_CC 42 | AM_PROG_CC_C_O 43 | AC_OUTPUT 44 | -------------------------------------------------------------------------------- /docs/ates_icpp19.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peaclab/HPAS/e4050abbf4a7525cef5a1694c736632341d7fecf/docs/ates_icpp19.pdf -------------------------------------------------------------------------------- /m4/ax_cache_size.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_cache_size.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CACHE_SIZE 8 | # 9 | # DESCRIPTION 10 | # 11 | # Find L1, L2 and L3 caches size by reading the corresponding file on UNIX or 12 | # by requesting cpuid. The results are available in the defines 13 | # CPU_L1_CACHE, CPU_L2_CACHE and CPU_L3_CACHE. 14 | # 15 | # This macro depends on AX_GCC_X86_CPUID, AC_PROG_SED, AX_COUNT_CPUS, and 16 | # AX_CPU_VENDOR. 17 | # 18 | # LICENSE 19 | # 20 | # Copyright (c) 2008 Christophe Tournayre 21 | # 22 | # Edited by Emre Ates, 2018 23 | # 24 | # Copying and distribution of this file, with or without modification, are 25 | # permitted in any medium without royalty provided the copyright notice 26 | # and this notice are preserved. This file is offered as-is, without any 27 | # warranty. 28 | 29 | #serial 8 30 | 31 | AC_DEFUN([AX_CACHE_SIZE], 32 | [ 33 | AC_REQUIRE([AC_PROG_SED]) 34 | AC_REQUIRE([AX_COUNT_CPUS]) 35 | AC_REQUIRE([AX_GCC_X86_CPUID]) 36 | AC_REQUIRE([AX_CPU_VENDOR]) 37 | 38 | AX_COUNT_CPUS 39 | AX_CPU_VENDOR 40 | 41 | ax_l1_size=unknown 42 | ax_l2_size=unknown 43 | ax_l3_size=unknown 44 | 45 | #Check if the variable is present 46 | if test -e /sys/devices/system/cpu/cpu0/cache/index0/size; then 47 | for ncpu in `seq 0 $(($CPU_COUNT-1))`; do 48 | for idx in `seq 0 3`; do 49 | if test -e /sys/devices/system/cpu/cpu$ncpu/cache/index$idx/size ; then 50 | level=`cat /sys/devices/system/cpu/cpu$ncpu/cache/index$idx/level` 51 | size=`cat /sys/devices/system/cpu/cpu$ncpu/cache/index$idx/size` 52 | eval CPU$ncpu\_L$level\_CACHE="$size" 53 | fi 54 | done 55 | done 56 | 57 | # This part can (must !!!) be optimized, because we know all caches per proc but 58 | # we only take care about the first proc 59 | ax_l1_size=$CPU0_L1_CACHE 60 | ax_l2_size=$CPU0_L2_CACHE 61 | ax_l3_size=$CPU0_L3_CACHE 62 | 63 | else 64 | AC_MSG_WARN(Using values hard-coded in m4/ax_cache_size.m4) 65 | ax_l1_size=512K 66 | ax_l2_size=1024K 67 | ax_l3_size=8192K 68 | fi 69 | 70 | # Keep only digits if there is a unit (ie 1024K -> 1024) and convert in Bytes 71 | AC_MSG_CHECKING(the L1 cache size) 72 | ax_l1_size=`echo $ax_l1_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` 73 | ax_l1_size=$(($ax_l1_size*1024)) 74 | AC_MSG_RESULT( $ax_l1_size Bytes) 75 | 76 | AC_MSG_CHECKING(the L2 cache size) 77 | ax_l2_size=`echo $ax_l2_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` 78 | ax_l2_size=$(($ax_l2_size*1024)) 79 | AC_MSG_RESULT( $ax_l2_size Bytes) 80 | 81 | AC_MSG_CHECKING(the L3 cache size) 82 | ax_l3_size=`echo $ax_l3_size | $SED 's/\([[0-9]]\)[[A-Za-z]]$/\1/g'` 83 | ax_l3_size=$(($ax_l3_size*1024)) 84 | AC_MSG_RESULT( $ax_l3_size Bytes) 85 | 86 | AC_DEFINE_UNQUOTED([CPU_L1_CACHE], ${ax_l1_size}, [L1 cache size (in Bytes)]) 87 | AC_DEFINE_UNQUOTED([CPU_L2_CACHE], ${ax_l2_size}, [L2 cache size (in Bytes)]) 88 | AC_DEFINE_UNQUOTED([CPU_L3_CACHE], ${ax_l3_size}, [L3 cache size (in Bytes)]) 89 | ]) 90 | 91 | -------------------------------------------------------------------------------- /m4/ax_count_cpus.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_COUNT_CPUS([ACTION-IF-DETECTED],[ACTION-IF-NOT-DETECTED]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Attempt to count the number of logical processor cores (including 12 | # virtual and HT cores) currently available to use on the machine and 13 | # place detected value in CPU_COUNT variable. 14 | # 15 | # On successful detection, ACTION-IF-DETECTED is executed if present. If 16 | # the detection fails, then ACTION-IF-NOT-DETECTED is triggered. The 17 | # default ACTION-IF-NOT-DETECTED is to set CPU_COUNT to 1. 18 | # 19 | # LICENSE 20 | # 21 | # Copyright (c) 2014,2016 Karlson2k (Evgeny Grin) 22 | # Copyright (c) 2012 Brian Aker 23 | # Copyright (c) 2008 Michael Paul Bailey 24 | # Copyright (c) 2008 Christophe Tournayre 25 | # 26 | # Copying and distribution of this file, with or without modification, are 27 | # permitted in any medium without royalty provided the copyright notice 28 | # and this notice are preserved. This file is offered as-is, without any 29 | # warranty. 30 | 31 | #serial 22 32 | 33 | AC_DEFUN([AX_COUNT_CPUS],[dnl 34 | AC_REQUIRE([AC_CANONICAL_HOST])dnl 35 | AC_REQUIRE([AC_PROG_EGREP])dnl 36 | AC_MSG_CHECKING([the number of available CPUs]) 37 | CPU_COUNT="0" 38 | 39 | # Try generic methods 40 | 41 | # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and 42 | # 'NPROCESSORS_ONLN' are platform-specific 43 | command -v getconf >/dev/null 2>&1 && \ 44 | CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0" 45 | AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1]],[[: # empty]],[dnl 46 | # 'nproc' is part of GNU Coreutils and is widely available 47 | CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0" 48 | ])dnl 49 | 50 | AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl 51 | # Try platform-specific preferred methods 52 | AS_CASE([[$host_os]],dnl 53 | [[*linux*]],[[CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+,' -c` || CPU_COUNT="0"]],dnl 54 | [[*darwin*]],[[CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0"]],dnl 55 | [[freebsd*]],[[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0"]],dnl 56 | [[netbsd*]], [[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0"]],dnl 57 | [[solaris*]],[[command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^@<:@0-9@:>@.*on-line' -c 2>/dev/null` || CPU_COUNT="0"]],dnl 58 | [[mingw*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl 59 | [[msys*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl 60 | [[cygwin*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]]dnl 61 | )dnl 62 | ])dnl 63 | 64 | AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1]],[[: # empty]],[dnl 65 | # Try less preferred generic method 66 | # 'hw.ncpu' exist on many platforms, but not on GNU/Linux 67 | CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0" 68 | ])dnl 69 | 70 | AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl 71 | # Try platform-specific fallback methods 72 | # They can be less accurate and slower then preferred methods 73 | AS_CASE([[$host_os]],dnl 74 | [[*linux*]],[[CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0"]],dnl 75 | [[*darwin*]],[[CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0"]],dnl 76 | [[freebsd*]],[[CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl 77 | [[netbsd*]], [[CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^@<:@0-9@:>@+ .* online ' -c` || \ 78 | CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl 79 | [[solaris*]],[[command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \ 80 | CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0"]],dnl 81 | [[mingw*]],[AS_IF([[CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\@<:@0-9@:>@+$' -c`]],dnl 82 | [[: # empty]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]])],dnl 83 | [[msys*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]],dnl 84 | [[cygwin*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]]dnl 85 | )dnl 86 | ])dnl 87 | 88 | AS_IF([[test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null]],[dnl 89 | AC_MSG_RESULT([[$CPU_COUNT]]) 90 | m4_ifvaln([$1],[$1],)dnl 91 | ],[dnl 92 | m4_ifval([$2],[dnl 93 | AS_UNSET([[CPU_COUNT]]) 94 | AC_MSG_RESULT([[unable to detect]]) 95 | $2 96 | ], [dnl 97 | CPU_COUNT="1" 98 | AC_MSG_RESULT([[unable to detect (assuming 1)]]) 99 | ])dnl 100 | ])dnl 101 | ])dnl 102 | 103 | -------------------------------------------------------------------------------- /m4/ax_cpu_vendor.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_cpu_vendor.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CPU_VENDOR 8 | # 9 | # DESCRIPTION 10 | # 11 | # Find your CPU's vendor by requesting cpuid and define "ax_cpu_vendor" 12 | # accordingly. This macro depends on AX_GCC_X86_CPUID. 13 | # 14 | # LICENSE 15 | # 16 | # Copyright (c) 2008 Christophe Tournayre 17 | # 18 | # Edited by Emre Ates, 2018 19 | # 20 | # Copying and distribution of this file, with or without modification, are 21 | # permitted in any medium without royalty provided the copyright notice 22 | # and this notice are preserved. This file is offered as-is, without any 23 | # warranty. 24 | 25 | #serial 8 26 | 27 | AC_DEFUN([AX_CPU_VENDOR], 28 | [ 29 | AC_REQUIRE([AX_GCC_X86_CPUID]) 30 | AX_GCC_X86_CPUID(0x0) 31 | 32 | vendor=`echo $ax_cv_gcc_x86_cpuid_0x0 | cut -d ":" -f 2` 33 | 34 | case $vendor in 35 | 756e6547*) 36 | ax_cpu_vendor="Intel" 37 | ;; 38 | 68747541*) 39 | ax_cpu_vendor="AMD" 40 | ;; 41 | 69727943*) 42 | ax_cpu_vendor="Cyrix" 43 | ;; 44 | 746e6543*) 45 | ax_cpu_vendor="IDT" 46 | ;; 47 | 646f6547*) 48 | ax_cpu_vendor="Natsemi Geode" 49 | ;; 50 | 52697365*) 51 | ax_cpu_vendor="Rise" 52 | ;; 53 | 65736952*) 54 | ax_cpu_vendor="Rise" 55 | ;; 56 | 20536953*) 57 | ax_cpu_vendor="SiS" 58 | ;; 59 | *) 60 | ax_cpu_vendor="Unknown" 61 | ;; 62 | esac 63 | ]) 64 | 65 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the specified 12 | # version of the C++ standard. If necessary, add switches to CXX and 13 | # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) 14 | # or '14' (for the C++14 standard). 15 | # 16 | # The second argument, if specified, indicates whether you insist on an 17 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 18 | # -std=c++11). If neither is specified, you get whatever works, with 19 | # preference for an extended mode. 20 | # 21 | # The third argument, if specified 'mandatory' or if left unspecified, 22 | # indicates that baseline support for the specified C++ standard is 23 | # required and that the macro should error out if no mode with that 24 | # support is found. If specified 'optional', then configuration proceeds 25 | # regardless, after defining HAVE_CXX${VERSION} if and only if a 26 | # supporting mode is found. 27 | # 28 | # LICENSE 29 | # 30 | # Copyright (c) 2008 Benjamin Kosnik 31 | # Copyright (c) 2012 Zack Weinberg 32 | # Copyright (c) 2013 Roy Stogner 33 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 34 | # Copyright (c) 2015 Paul Norman 35 | # Copyright (c) 2015 Moritz Klammler 36 | # Copyright (c) 2016, 2018 Krzesimir Nowak 37 | # 38 | # Copying and distribution of this file, with or without modification, are 39 | # permitted in any medium without royalty provided the copyright notice 40 | # and this notice are preserved. This file is offered as-is, without any 41 | # warranty. 42 | 43 | #serial 10 44 | 45 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 46 | dnl (serial version number 13). 47 | 48 | AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 49 | m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], 50 | [$1], [14], [ax_cxx_compile_alternatives="14 1y"], 51 | [$1], [17], [ax_cxx_compile_alternatives="17 1z"], 52 | [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 53 | m4_if([$2], [], [], 54 | [$2], [ext], [], 55 | [$2], [noext], [], 56 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 57 | m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 58 | [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 59 | [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 60 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 61 | AC_LANG_PUSH([C++])dnl 62 | ac_success=no 63 | 64 | m4_if([$2], [noext], [], [dnl 65 | if test x$ac_success = xno; then 66 | for alternative in ${ax_cxx_compile_alternatives}; do 67 | switch="-std=gnu++${alternative}" 68 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 69 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 70 | $cachevar, 71 | [ac_save_CXX="$CXX" 72 | CXX="$CXX $switch" 73 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 74 | [eval $cachevar=yes], 75 | [eval $cachevar=no]) 76 | CXX="$ac_save_CXX"]) 77 | if eval test x\$$cachevar = xyes; then 78 | CXX="$CXX $switch" 79 | if test -n "$CXXCPP" ; then 80 | CXXCPP="$CXXCPP $switch" 81 | fi 82 | ac_success=yes 83 | break 84 | fi 85 | done 86 | fi]) 87 | 88 | m4_if([$2], [ext], [], [dnl 89 | if test x$ac_success = xno; then 90 | dnl HP's aCC needs +std=c++11 according to: 91 | dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 92 | dnl Cray's crayCC needs "-h std=c++11" 93 | for alternative in ${ax_cxx_compile_alternatives}; do 94 | for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do 95 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 96 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 97 | $cachevar, 98 | [ac_save_CXX="$CXX" 99 | CXX="$CXX $switch" 100 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 101 | [eval $cachevar=yes], 102 | [eval $cachevar=no]) 103 | CXX="$ac_save_CXX"]) 104 | if eval test x\$$cachevar = xyes; then 105 | CXX="$CXX $switch" 106 | if test -n "$CXXCPP" ; then 107 | CXXCPP="$CXXCPP $switch" 108 | fi 109 | ac_success=yes 110 | break 111 | fi 112 | done 113 | if test x$ac_success = xyes; then 114 | break 115 | fi 116 | done 117 | fi]) 118 | AC_LANG_POP([C++]) 119 | if test x$ax_cxx_compile_cxx$1_required = xtrue; then 120 | if test x$ac_success = xno; then 121 | AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 122 | fi 123 | fi 124 | if test x$ac_success = xno; then 125 | HAVE_CXX$1=0 126 | AC_MSG_NOTICE([No compiler with C++$1 support was found]) 127 | else 128 | HAVE_CXX$1=1 129 | AC_DEFINE(HAVE_CXX$1,1, 130 | [define if the compiler supports basic C++$1 syntax]) 131 | fi 132 | AC_SUBST(HAVE_CXX$1) 133 | ]) 134 | 135 | 136 | dnl Test body for checking C++11 support 137 | 138 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 139 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 140 | ) 141 | 142 | 143 | dnl Test body for checking C++14 support 144 | 145 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 146 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 147 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 148 | ) 149 | 150 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], 151 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 152 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 153 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 154 | ) 155 | 156 | dnl Tests for new features in C++11 157 | 158 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 159 | 160 | // If the compiler admits that it is not ready for C++11, why torture it? 161 | // Hopefully, this will speed up the test. 162 | 163 | #ifndef __cplusplus 164 | 165 | #error "This is not a C++ compiler" 166 | 167 | #elif __cplusplus < 201103L 168 | 169 | #error "This is not a C++11 compiler" 170 | 171 | #else 172 | 173 | namespace cxx11 174 | { 175 | 176 | namespace test_static_assert 177 | { 178 | 179 | template 180 | struct check 181 | { 182 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 183 | }; 184 | 185 | } 186 | 187 | namespace test_final_override 188 | { 189 | 190 | struct Base 191 | { 192 | virtual void f() {} 193 | }; 194 | 195 | struct Derived : public Base 196 | { 197 | virtual void f() override {} 198 | }; 199 | 200 | } 201 | 202 | namespace test_double_right_angle_brackets 203 | { 204 | 205 | template < typename T > 206 | struct check {}; 207 | 208 | typedef check single_type; 209 | typedef check> double_type; 210 | typedef check>> triple_type; 211 | typedef check>>> quadruple_type; 212 | 213 | } 214 | 215 | namespace test_decltype 216 | { 217 | 218 | int 219 | f() 220 | { 221 | int a = 1; 222 | decltype(a) b = 2; 223 | return a + b; 224 | } 225 | 226 | } 227 | 228 | namespace test_type_deduction 229 | { 230 | 231 | template < typename T1, typename T2 > 232 | struct is_same 233 | { 234 | static const bool value = false; 235 | }; 236 | 237 | template < typename T > 238 | struct is_same 239 | { 240 | static const bool value = true; 241 | }; 242 | 243 | template < typename T1, typename T2 > 244 | auto 245 | add(T1 a1, T2 a2) -> decltype(a1 + a2) 246 | { 247 | return a1 + a2; 248 | } 249 | 250 | int 251 | test(const int c, volatile int v) 252 | { 253 | static_assert(is_same::value == true, ""); 254 | static_assert(is_same::value == false, ""); 255 | static_assert(is_same::value == false, ""); 256 | auto ac = c; 257 | auto av = v; 258 | auto sumi = ac + av + 'x'; 259 | auto sumf = ac + av + 1.0; 260 | static_assert(is_same::value == true, ""); 261 | static_assert(is_same::value == true, ""); 262 | static_assert(is_same::value == true, ""); 263 | static_assert(is_same::value == false, ""); 264 | static_assert(is_same::value == true, ""); 265 | return (sumf > 0.0) ? sumi : add(c, v); 266 | } 267 | 268 | } 269 | 270 | namespace test_noexcept 271 | { 272 | 273 | int f() { return 0; } 274 | int g() noexcept { return 0; } 275 | 276 | static_assert(noexcept(f()) == false, ""); 277 | static_assert(noexcept(g()) == true, ""); 278 | 279 | } 280 | 281 | namespace test_constexpr 282 | { 283 | 284 | template < typename CharT > 285 | unsigned long constexpr 286 | strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 287 | { 288 | return *s ? strlen_c_r(s + 1, acc + 1) : acc; 289 | } 290 | 291 | template < typename CharT > 292 | unsigned long constexpr 293 | strlen_c(const CharT *const s) noexcept 294 | { 295 | return strlen_c_r(s, 0UL); 296 | } 297 | 298 | static_assert(strlen_c("") == 0UL, ""); 299 | static_assert(strlen_c("1") == 1UL, ""); 300 | static_assert(strlen_c("example") == 7UL, ""); 301 | static_assert(strlen_c("another\0example") == 7UL, ""); 302 | 303 | } 304 | 305 | namespace test_rvalue_references 306 | { 307 | 308 | template < int N > 309 | struct answer 310 | { 311 | static constexpr int value = N; 312 | }; 313 | 314 | answer<1> f(int&) { return answer<1>(); } 315 | answer<2> f(const int&) { return answer<2>(); } 316 | answer<3> f(int&&) { return answer<3>(); } 317 | 318 | void 319 | test() 320 | { 321 | int i = 0; 322 | const int c = 0; 323 | static_assert(decltype(f(i))::value == 1, ""); 324 | static_assert(decltype(f(c))::value == 2, ""); 325 | static_assert(decltype(f(0))::value == 3, ""); 326 | } 327 | 328 | } 329 | 330 | namespace test_uniform_initialization 331 | { 332 | 333 | struct test 334 | { 335 | static const int zero {}; 336 | static const int one {1}; 337 | }; 338 | 339 | static_assert(test::zero == 0, ""); 340 | static_assert(test::one == 1, ""); 341 | 342 | } 343 | 344 | namespace test_lambdas 345 | { 346 | 347 | void 348 | test1() 349 | { 350 | auto lambda1 = [](){}; 351 | auto lambda2 = lambda1; 352 | lambda1(); 353 | lambda2(); 354 | } 355 | 356 | int 357 | test2() 358 | { 359 | auto a = [](int i, int j){ return i + j; }(1, 2); 360 | auto b = []() -> int { return '0'; }(); 361 | auto c = [=](){ return a + b; }(); 362 | auto d = [&](){ return c; }(); 363 | auto e = [a, &b](int x) mutable { 364 | const auto identity = [](int y){ return y; }; 365 | for (auto i = 0; i < a; ++i) 366 | a += b--; 367 | return x + identity(a + b); 368 | }(0); 369 | return a + b + c + d + e; 370 | } 371 | 372 | int 373 | test3() 374 | { 375 | const auto nullary = [](){ return 0; }; 376 | const auto unary = [](int x){ return x; }; 377 | using nullary_t = decltype(nullary); 378 | using unary_t = decltype(unary); 379 | const auto higher1st = [](nullary_t f){ return f(); }; 380 | const auto higher2nd = [unary](nullary_t f1){ 381 | return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 382 | }; 383 | return higher1st(nullary) + higher2nd(nullary)(unary); 384 | } 385 | 386 | } 387 | 388 | namespace test_variadic_templates 389 | { 390 | 391 | template 392 | struct sum; 393 | 394 | template 395 | struct sum 396 | { 397 | static constexpr auto value = N0 + sum::value; 398 | }; 399 | 400 | template <> 401 | struct sum<> 402 | { 403 | static constexpr auto value = 0; 404 | }; 405 | 406 | static_assert(sum<>::value == 0, ""); 407 | static_assert(sum<1>::value == 1, ""); 408 | static_assert(sum<23>::value == 23, ""); 409 | static_assert(sum<1, 2>::value == 3, ""); 410 | static_assert(sum<5, 5, 11>::value == 21, ""); 411 | static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 412 | 413 | } 414 | 415 | // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 416 | // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 417 | // because of this. 418 | namespace test_template_alias_sfinae 419 | { 420 | 421 | struct foo {}; 422 | 423 | template 424 | using member = typename T::member_type; 425 | 426 | template 427 | void func(...) {} 428 | 429 | template 430 | void func(member*) {} 431 | 432 | void test(); 433 | 434 | void test() { func(0); } 435 | 436 | } 437 | 438 | } // namespace cxx11 439 | 440 | #endif // __cplusplus >= 201103L 441 | 442 | ]]) 443 | 444 | 445 | dnl Tests for new features in C++14 446 | 447 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 448 | 449 | // If the compiler admits that it is not ready for C++14, why torture it? 450 | // Hopefully, this will speed up the test. 451 | 452 | #ifndef __cplusplus 453 | 454 | #error "This is not a C++ compiler" 455 | 456 | #elif __cplusplus < 201402L 457 | 458 | #error "This is not a C++14 compiler" 459 | 460 | #else 461 | 462 | namespace cxx14 463 | { 464 | 465 | namespace test_polymorphic_lambdas 466 | { 467 | 468 | int 469 | test() 470 | { 471 | const auto lambda = [](auto&&... args){ 472 | const auto istiny = [](auto x){ 473 | return (sizeof(x) == 1UL) ? 1 : 0; 474 | }; 475 | const int aretiny[] = { istiny(args)... }; 476 | return aretiny[0]; 477 | }; 478 | return lambda(1, 1L, 1.0f, '1'); 479 | } 480 | 481 | } 482 | 483 | namespace test_binary_literals 484 | { 485 | 486 | constexpr auto ivii = 0b0000000000101010; 487 | static_assert(ivii == 42, "wrong value"); 488 | 489 | } 490 | 491 | namespace test_generalized_constexpr 492 | { 493 | 494 | template < typename CharT > 495 | constexpr unsigned long 496 | strlen_c(const CharT *const s) noexcept 497 | { 498 | auto length = 0UL; 499 | for (auto p = s; *p; ++p) 500 | ++length; 501 | return length; 502 | } 503 | 504 | static_assert(strlen_c("") == 0UL, ""); 505 | static_assert(strlen_c("x") == 1UL, ""); 506 | static_assert(strlen_c("test") == 4UL, ""); 507 | static_assert(strlen_c("another\0test") == 7UL, ""); 508 | 509 | } 510 | 511 | namespace test_lambda_init_capture 512 | { 513 | 514 | int 515 | test() 516 | { 517 | auto x = 0; 518 | const auto lambda1 = [a = x](int b){ return a + b; }; 519 | const auto lambda2 = [a = lambda1(x)](){ return a; }; 520 | return lambda2(); 521 | } 522 | 523 | } 524 | 525 | namespace test_digit_separators 526 | { 527 | 528 | constexpr auto ten_million = 100'000'000; 529 | static_assert(ten_million == 100000000, ""); 530 | 531 | } 532 | 533 | namespace test_return_type_deduction 534 | { 535 | 536 | auto f(int& x) { return x; } 537 | decltype(auto) g(int& x) { return x; } 538 | 539 | template < typename T1, typename T2 > 540 | struct is_same 541 | { 542 | static constexpr auto value = false; 543 | }; 544 | 545 | template < typename T > 546 | struct is_same 547 | { 548 | static constexpr auto value = true; 549 | }; 550 | 551 | int 552 | test() 553 | { 554 | auto x = 0; 555 | static_assert(is_same::value, ""); 556 | static_assert(is_same::value, ""); 557 | return x; 558 | } 559 | 560 | } 561 | 562 | } // namespace cxx14 563 | 564 | #endif // __cplusplus >= 201402L 565 | 566 | ]]) 567 | 568 | 569 | dnl Tests for new features in C++17 570 | 571 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ 572 | 573 | // If the compiler admits that it is not ready for C++17, why torture it? 574 | // Hopefully, this will speed up the test. 575 | 576 | #ifndef __cplusplus 577 | 578 | #error "This is not a C++ compiler" 579 | 580 | #elif __cplusplus < 201703L 581 | 582 | #error "This is not a C++17 compiler" 583 | 584 | #else 585 | 586 | #include 587 | #include 588 | #include 589 | 590 | namespace cxx17 591 | { 592 | 593 | namespace test_constexpr_lambdas 594 | { 595 | 596 | constexpr int foo = [](){return 42;}(); 597 | 598 | } 599 | 600 | namespace test::nested_namespace::definitions 601 | { 602 | 603 | } 604 | 605 | namespace test_fold_expression 606 | { 607 | 608 | template 609 | int multiply(Args... args) 610 | { 611 | return (args * ... * 1); 612 | } 613 | 614 | template 615 | bool all(Args... args) 616 | { 617 | return (args && ...); 618 | } 619 | 620 | } 621 | 622 | namespace test_extended_static_assert 623 | { 624 | 625 | static_assert (true); 626 | 627 | } 628 | 629 | namespace test_auto_brace_init_list 630 | { 631 | 632 | auto foo = {5}; 633 | auto bar {5}; 634 | 635 | static_assert(std::is_same, decltype(foo)>::value); 636 | static_assert(std::is_same::value); 637 | } 638 | 639 | namespace test_typename_in_template_template_parameter 640 | { 641 | 642 | template typename X> struct D; 643 | 644 | } 645 | 646 | namespace test_fallthrough_nodiscard_maybe_unused_attributes 647 | { 648 | 649 | int f1() 650 | { 651 | return 42; 652 | } 653 | 654 | [[nodiscard]] int f2() 655 | { 656 | [[maybe_unused]] auto unused = f1(); 657 | 658 | switch (f1()) 659 | { 660 | case 17: 661 | f1(); 662 | [[fallthrough]]; 663 | case 42: 664 | f1(); 665 | } 666 | return f1(); 667 | } 668 | 669 | } 670 | 671 | namespace test_extended_aggregate_initialization 672 | { 673 | 674 | struct base1 675 | { 676 | int b1, b2 = 42; 677 | }; 678 | 679 | struct base2 680 | { 681 | base2() { 682 | b3 = 42; 683 | } 684 | int b3; 685 | }; 686 | 687 | struct derived : base1, base2 688 | { 689 | int d; 690 | }; 691 | 692 | derived d1 {{1, 2}, {}, 4}; // full initialization 693 | derived d2 {{}, {}, 4}; // value-initialized bases 694 | 695 | } 696 | 697 | namespace test_general_range_based_for_loop 698 | { 699 | 700 | struct iter 701 | { 702 | int i; 703 | 704 | int& operator* () 705 | { 706 | return i; 707 | } 708 | 709 | const int& operator* () const 710 | { 711 | return i; 712 | } 713 | 714 | iter& operator++() 715 | { 716 | ++i; 717 | return *this; 718 | } 719 | }; 720 | 721 | struct sentinel 722 | { 723 | int i; 724 | }; 725 | 726 | bool operator== (const iter& i, const sentinel& s) 727 | { 728 | return i.i == s.i; 729 | } 730 | 731 | bool operator!= (const iter& i, const sentinel& s) 732 | { 733 | return !(i == s); 734 | } 735 | 736 | struct range 737 | { 738 | iter begin() const 739 | { 740 | return {0}; 741 | } 742 | 743 | sentinel end() const 744 | { 745 | return {5}; 746 | } 747 | }; 748 | 749 | void f() 750 | { 751 | range r {}; 752 | 753 | for (auto i : r) 754 | { 755 | [[maybe_unused]] auto v = i; 756 | } 757 | } 758 | 759 | } 760 | 761 | namespace test_lambda_capture_asterisk_this_by_value 762 | { 763 | 764 | struct t 765 | { 766 | int i; 767 | int foo() 768 | { 769 | return [*this]() 770 | { 771 | return i; 772 | }(); 773 | } 774 | }; 775 | 776 | } 777 | 778 | namespace test_enum_class_construction 779 | { 780 | 781 | enum class byte : unsigned char 782 | {}; 783 | 784 | byte foo {42}; 785 | 786 | } 787 | 788 | namespace test_constexpr_if 789 | { 790 | 791 | template 792 | int f () 793 | { 794 | if constexpr(cond) 795 | { 796 | return 13; 797 | } 798 | else 799 | { 800 | return 42; 801 | } 802 | } 803 | 804 | } 805 | 806 | namespace test_selection_statement_with_initializer 807 | { 808 | 809 | int f() 810 | { 811 | return 13; 812 | } 813 | 814 | int f2() 815 | { 816 | if (auto i = f(); i > 0) 817 | { 818 | return 3; 819 | } 820 | 821 | switch (auto i = f(); i + 4) 822 | { 823 | case 17: 824 | return 2; 825 | 826 | default: 827 | return 1; 828 | } 829 | } 830 | 831 | } 832 | 833 | namespace test_template_argument_deduction_for_class_templates 834 | { 835 | 836 | template 837 | struct pair 838 | { 839 | pair (T1 p1, T2 p2) 840 | : m1 {p1}, 841 | m2 {p2} 842 | {} 843 | 844 | T1 m1; 845 | T2 m2; 846 | }; 847 | 848 | void f() 849 | { 850 | [[maybe_unused]] auto p = pair{13, 42u}; 851 | } 852 | 853 | } 854 | 855 | namespace test_non_type_auto_template_parameters 856 | { 857 | 858 | template 859 | struct B 860 | {}; 861 | 862 | B<5> b1; 863 | B<'a'> b2; 864 | 865 | } 866 | 867 | namespace test_structured_bindings 868 | { 869 | 870 | int arr[2] = { 1, 2 }; 871 | std::pair pr = { 1, 2 }; 872 | 873 | auto f1() -> int(&)[2] 874 | { 875 | return arr; 876 | } 877 | 878 | auto f2() -> std::pair& 879 | { 880 | return pr; 881 | } 882 | 883 | struct S 884 | { 885 | int x1 : 2; 886 | volatile double y1; 887 | }; 888 | 889 | S f3() 890 | { 891 | return {}; 892 | } 893 | 894 | auto [ x1, y1 ] = f1(); 895 | auto& [ xr1, yr1 ] = f1(); 896 | auto [ x2, y2 ] = f2(); 897 | auto& [ xr2, yr2 ] = f2(); 898 | const auto [ x3, y3 ] = f3(); 899 | 900 | } 901 | 902 | namespace test_exception_spec_type_system 903 | { 904 | 905 | struct Good {}; 906 | struct Bad {}; 907 | 908 | void g1() noexcept; 909 | void g2(); 910 | 911 | template 912 | Bad 913 | f(T*, T*); 914 | 915 | template 916 | Good 917 | f(T1*, T2*); 918 | 919 | static_assert (std::is_same_v); 920 | 921 | } 922 | 923 | namespace test_inline_variables 924 | { 925 | 926 | template void f(T) 927 | {} 928 | 929 | template inline T g(T) 930 | { 931 | return T{}; 932 | } 933 | 934 | template<> inline void f<>(int) 935 | {} 936 | 937 | template<> int g<>(int) 938 | { 939 | return 5; 940 | } 941 | 942 | } 943 | 944 | } // namespace cxx17 945 | 946 | #endif // __cplusplus < 201703L 947 | 948 | ]]) 949 | 950 | -------------------------------------------------------------------------------- /m4/ax_gcc_x86_cpuid.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_GCC_X86_CPUID(OP) 8 | # AX_GCC_X86_CPUID_COUNT(OP, COUNT) 9 | # 10 | # DESCRIPTION 11 | # 12 | # On Pentium and later x86 processors, with gcc or a compiler that has a 13 | # compatible syntax for inline assembly instructions, run a small program 14 | # that executes the cpuid instruction with input OP. This can be used to 15 | # detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT 16 | # parameter that gets passed into register ECX before calling cpuid. 17 | # 18 | # On output, the values of the eax, ebx, ecx, and edx registers are stored 19 | # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable 20 | # ax_cv_gcc_x86_cpuid_OP. 21 | # 22 | # If the cpuid instruction fails (because you are running a 23 | # cross-compiler, or because you are not using gcc, or because you are on 24 | # a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP 25 | # is set to the string "unknown". 26 | # 27 | # This macro mainly exists to be used in AX_GCC_ARCHFLAG. 28 | # 29 | # LICENSE 30 | # 31 | # Copyright (c) 2008 Steven G. Johnson 32 | # Copyright (c) 2008 Matteo Frigo 33 | # Copyright (c) 2015 Michael Petch 34 | # 35 | # This program is free software: you can redistribute it and/or modify it 36 | # under the terms of the GNU General Public License as published by the 37 | # Free Software Foundation, either version 3 of the License, or (at your 38 | # option) any later version. 39 | # 40 | # This program is distributed in the hope that it will be useful, but 41 | # WITHOUT ANY WARRANTY; without even the implied warranty of 42 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 43 | # Public License for more details. 44 | # 45 | # You should have received a copy of the GNU General Public License along 46 | # with this program. If not, see . 47 | # 48 | # As a special exception, the respective Autoconf Macro's copyright owner 49 | # gives unlimited permission to copy, distribute and modify the configure 50 | # scripts that are the output of Autoconf when processing the Macro. You 51 | # need not follow the terms of the GNU General Public License when using 52 | # or distributing such scripts, even though portions of the text of the 53 | # Macro appear in them. The GNU General Public License (GPL) does govern 54 | # all other use of the material that constitutes the Autoconf Macro. 55 | # 56 | # This special exception to the GPL applies to versions of the Autoconf 57 | # Macro released by the Autoconf Archive. When you make and distribute a 58 | # modified version of the Autoconf Macro, you may extend this special 59 | # exception to the GPL to apply to your modified version as well. 60 | 61 | #serial 10 62 | 63 | AC_DEFUN([AX_GCC_X86_CPUID], 64 | [AX_GCC_X86_CPUID_COUNT($1, 0) 65 | ]) 66 | 67 | AC_DEFUN([AX_GCC_X86_CPUID_COUNT], 68 | [AC_REQUIRE([AC_PROG_CC]) 69 | AC_LANG_PUSH([C]) 70 | AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, 71 | [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ 72 | int op = $1, level = $2, eax, ebx, ecx, edx; 73 | FILE *f; 74 | __asm__ __volatile__ ("xchg %%ebx, %1\n" 75 | "cpuid\n" 76 | "xchg %%ebx, %1\n" 77 | : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) 78 | : "a" (op), "2" (level)); 79 | 80 | f = fopen("conftest_cpuid", "w"); if (!f) return 1; 81 | fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); 82 | fclose(f); 83 | return 0; 84 | ])], 85 | [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], 86 | [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], 87 | [ax_cv_gcc_x86_cpuid_$1=unknown])]) 88 | AC_LANG_POP([C]) 89 | ]) 90 | 91 | -------------------------------------------------------------------------------- /src/anomalies.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANOMALIES_H 2 | #define _ANOMALIES_H 3 | 4 | int memleak(int argc, char *argv[]); 5 | int membw(int argc, char *argv[]); 6 | int memeater(int argc, char *argv[]); 7 | int cachecopy(int argc, char *argv[]); 8 | int cpuoccupy(int argc, char *argv[]); 9 | int netoccupy(int argc, char *argv[]); 10 | int iometadata(int argc, char *argv[]); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/cachecopy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "src/utils.h" 13 | 14 | static struct option const long_opt[] = 15 | { 16 | {"help", no_argument, NULL, 'h'}, 17 | {"verbose", no_argument, NULL, 'v'}, 18 | {"cache", required_argument, NULL, 'c'}, 19 | {"multiplier", required_argument, NULL, 'm'}, 20 | {"start", required_argument, NULL, 't'}, 21 | {"period", required_argument, NULL, 'p'}, 22 | {"duration", required_argument, NULL, 'd'}, 23 | {NULL, 0, NULL, 0} 24 | }; 25 | 26 | const char *cachecopy_usage = "cache.\n\n" 27 | "-c, --cache (=L1) Which cache to use (L1, L2, L3).\n" 28 | "-m, --multiplier (=1.0) The multiplier for cache size.\n" 29 | "-p, --period (=0.0) The time to wait (in seconds) between tests.\n" 30 | "-d, --duration (=-1.0) The total duration (in seconds), -1 for infinite.\n" 31 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 32 | "-v, --verbose Prints execution information.\n" 33 | "-h, --help Prints this message.\n"; 34 | static const char short_opt[] = "hvd:c:p:m:t:"; 35 | 36 | double run_one(const double *lptr, double *rptr, size_t ndouble) 37 | { 38 | uint32_t i; 39 | double sum = 0; 40 | for (i=0; i < ndouble; ++rptr, ++lptr, ++i) 41 | { 42 | (*rptr) = (*lptr); 43 | } 44 | return sum; 45 | } 46 | 47 | int cachecopy(int argc, char *argv[]) 48 | { 49 | int c; 50 | 51 | bool verbose = false; 52 | size_t size = CPU_L3_CACHE; 53 | double multiplier = 1.0; 54 | double period = 0; 55 | double duration = -1; 56 | double start_time = 0; 57 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 58 | { 59 | switch(c) 60 | { 61 | case -1: 62 | case 0: 63 | break; 64 | 65 | case 't': 66 | start_time = strtod(optarg, NULL); 67 | if (start_time < 0) { 68 | printf("Start time cannot be negative.\n"); 69 | _exit(0); 70 | } 71 | break; 72 | 73 | case 'c': 74 | if (optarg[0] != 'L' && optarg[0] != 'l') { 75 | printf("Cache size can only be L1, L2 or L3\n"); 76 | return -1; 77 | } 78 | if (optarg[2] != '\0') { 79 | printf("Cache size can only be L1, L2 or L3\n"); 80 | return -1; 81 | } 82 | switch(optarg[1]) { 83 | case '1': 84 | size = CPU_L1_CACHE; 85 | break; 86 | case '2': 87 | size = CPU_L2_CACHE; 88 | break; 89 | case '3': 90 | size = CPU_L3_CACHE; 91 | break; 92 | default: 93 | printf("Cache size can only be L1, L2 or L3\n"); 94 | return -1; 95 | } 96 | break; 97 | 98 | case 'p': 99 | period = strtod(optarg, NULL); 100 | if (period < 0) { 101 | printf("Period cannot be smaller than zero.\n"); 102 | _exit(0); 103 | } 104 | break; 105 | 106 | case 'd': 107 | duration = strtod(optarg, NULL); 108 | break; 109 | 110 | case 'm': 111 | multiplier = strtof(optarg, NULL); 112 | break; 113 | 114 | case 'v': 115 | verbose = true; 116 | break; 117 | 118 | case 'h': 119 | default: 120 | printf("Usage: %s [OPTIONS]\n%s", argv[0], cachecopy_usage); 121 | return 0; 122 | } 123 | } 124 | hpas_sleep(start_time); 125 | time_t rawtime; 126 | struct tm *timeinfo; 127 | time(&rawtime); 128 | timeinfo = localtime(&rawtime); 129 | /* Each array is half the size of the chosen cache size * multiplier */ 130 | long ndouble = (long) ((((double) size) * multiplier) / (sizeof(double))); 131 | if (ndouble % 2 == 1) { 132 | ndouble++; 133 | } 134 | printf("%sStarting cache with ndouble:%ld period:%f duration:%f\n\n", 135 | asctime(timeinfo), ndouble, period, duration); 136 | fflush(stdout); 137 | 138 | double sum = 0; 139 | double *ldata; 140 | int k, counter = 0; 141 | k = posix_memalign((void **) &ldata, CPU_L1_CACHE, ndouble * sizeof(double)); 142 | if (k!=0) { 143 | printf("Failed to allocate memory\n"); 144 | exit(1); 145 | } 146 | double *rdata = ldata + (ndouble / 2); 147 | uint32_t j; 148 | for (j=0; j < ndouble / 2; ++j) { 149 | ldata[j] = 0.02; 150 | rdata[j] = 0.01; 151 | } 152 | 153 | set_duration(duration); 154 | while (timer_flag) { 155 | sum += run_one(ldata, rdata, ndouble / 2); 156 | hpas_sleep(period); 157 | if (verbose && ++counter % 100 == 0) { 158 | printf("."); 159 | fflush(stdout); 160 | } 161 | } 162 | 163 | free(ldata); 164 | printf("\nFinished cache anomaly\n"); 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /src/cpuoccupy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "src/utils.h" 12 | 13 | unsigned int flag; 14 | 15 | void fct (int x) { 16 | if (x == SIGALRM) { 17 | flag = 0; 18 | } 19 | } 20 | 21 | static struct option const long_opt[] = 22 | { 23 | {"help", no_argument, NULL, 'h'}, 24 | {"verbose", no_argument, NULL, 'v'}, 25 | {"utilization", required_argument, NULL, 'u'}, 26 | {"duration", required_argument, NULL, 'd'}, 27 | {"start", required_argument, NULL, 't'}, 28 | {NULL, 0, NULL, 0} 29 | }; 30 | 31 | static const char *cpuoccupy_usage = "CPU intensive orphan process.\n\n" 32 | "-u, --utilization (=100%) The utilization (%) of one core.\n" 33 | "-d, --duration (=-1.0) The total duration (in seconds), -1 for infinite.\n" 34 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 35 | "-v, --verbose Prints execution information.\n" 36 | "-h, --help Prints this message.\n"; 37 | static const char short_opt[] = "hvd:u:t:"; 38 | 39 | int cpuoccupy(int argc, char* argv[]){ 40 | time_t rawtime; 41 | struct tm *timeinfo; 42 | bool verbose = false; 43 | 44 | unsigned int codebegin, codeend; 45 | long utilsec, utilusec, intervalsec, intervalusec; 46 | double dursec = -1; 47 | int counter = 0; 48 | 49 | struct itimerval itv; 50 | int percutil = 100; 51 | double intervalsize, utiltime, sleeptime; 52 | double res = 1.0; 53 | int c; 54 | double start_time = 0; 55 | 56 | 57 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) { 58 | switch(c) { 59 | case -1: 60 | case 0: 61 | break; 62 | 63 | case 'u': 64 | percutil = (int) strtol(optarg, NULL, 10); 65 | if (percutil < 0 || percutil > 100){ 66 | printf("bad percent util\n"); 67 | exit(-1); 68 | } 69 | break; 70 | 71 | case 't': 72 | start_time = strtod(optarg, NULL); 73 | if (start_time < 0) { 74 | printf("Start time cannot be negative.\n"); 75 | _exit(0); 76 | } 77 | break; 78 | 79 | case 'd': 80 | dursec = strtod(optarg, NULL); 81 | break; 82 | 83 | case 'v': 84 | verbose = true; 85 | break; 86 | 87 | case 'h': 88 | default: 89 | printf("Usage: %s [OPTIONS]\n%s", argv[0], cpuoccupy_usage); 90 | return 0; 91 | } 92 | } 93 | 94 | hpas_sleep(start_time); 95 | 96 | //check args 97 | //get times 98 | intervalsize = 0.25; 99 | intervalsec = (long) intervalsize; 100 | intervalusec = (long) ((intervalsize - (double) intervalsec) * 1000000); 101 | utiltime = ((double)percutil/100.0) *(intervalsize); 102 | utilsec = (long) utiltime; 103 | utilusec = (long) ((utiltime - (double) utilsec) * 1000000); 104 | 105 | sleeptime = intervalsize - utiltime; 106 | if (sleeptime < 0){ //this shouldnt happen 107 | printf("bad sleeptime\n"); 108 | exit(-1); 109 | } 110 | 111 | //start the timing of the code 112 | codebegin = time(NULL); 113 | 114 | time(&rawtime); 115 | timeinfo = localtime(&rawtime); 116 | printf("%sStarting cpuoccupy with utilization:%d%%\n\n", 117 | asctime(timeinfo), percutil); 118 | fflush(stdout); 119 | 120 | //set times for ending calc 121 | itv.it_interval.tv_sec = intervalsec; 122 | itv.it_interval.tv_usec = intervalusec; 123 | itv.it_value.tv_sec = utilsec; 124 | itv.it_value.tv_usec = utilusec; 125 | 126 | //set up the signal for the calc 127 | struct sigaction sa; 128 | memset (&sa, 0, sizeof (sa)); 129 | sa.sa_handler = &fct; 130 | sigaction(SIGALRM, &sa, NULL); 131 | setitimer(ITIMER_REAL, &itv, NULL); 132 | 133 | while(1){ 134 | // do the sleep 135 | hpas_sleep(sleeptime); 136 | 137 | flag = 1; 138 | while(flag){ //do the calc 139 | double vala, valb; 140 | 141 | //calculation 142 | srand(time(NULL)); 143 | vala=1+(int) (0.9*rand()/(RAND_MAX+2.0)); 144 | valb=1+(int) (0.9*rand()/(RAND_MAX+1.0)); 145 | res += vala/valb; 146 | } 147 | 148 | //test if we want to exit the code entirely 149 | codeend = time(NULL); 150 | if (dursec > 0 && codeend - codebegin > dursec){ 151 | break; 152 | } 153 | if (verbose && ++counter % 100 == 0) { 154 | printf("."); 155 | fflush(stdout); 156 | } 157 | } 158 | printf("Exiting cpuoccupy, duration=%us\n", codeend - codebegin); 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /src/iobandwidth: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | size="1G" 4 | multiplier=10 5 | runtime=-1 6 | outdir="./hpas_tmp" 7 | nthreads=1 8 | start_time=0 9 | verbose='' 10 | while getopts "s:m:d:t:l:n:hv" opt 11 | do 12 | case $opt in 13 | s) 14 | size="$OPTARG" 15 | ;; 16 | m) 17 | multiplier="$OPTARG" 18 | ;; 19 | d) 20 | runtime="$OPTARG" 21 | ;; 22 | l) 23 | outdir="$OPTARG" 24 | ;; 25 | t) 26 | start_time="$OPTARG" 27 | ;; 28 | n) 29 | nthreads="$OPTARG" 30 | ;; 31 | v) 32 | verbose='1' 33 | ;; 34 | *) 35 | echo "Usage: iobandwidth [OPTIONS]" 36 | echo "IO Bandwidth anomaly." 37 | echo "" 38 | echo "-s (=1G) Block size (in bytes)" 39 | echo "-m (=10) Multiplier for block size" 40 | echo "-d (=-1) Duration of anomaly (in seconds)" 41 | echo "-l (='./hpas_tmp') Location of output folder" 42 | echo "-t (=0) Start time (in seconds)" 43 | echo "-n (=1) Number of simultaneous threads of I/O" 44 | echo "-h Print this message" 45 | echo "-v Verbose mode" 46 | exit 1 47 | ;; 48 | esac 49 | done 50 | 51 | trap 'exit 1' SIGINT 52 | outdir=$outdir/$(uuidgen) 53 | sleep $start_time 54 | SECONDS=0 55 | mkdir -p $outdir 56 | 57 | function move_files () { 58 | local outdir=$1 59 | dd if=/dev/urandom of=$outdir/tmp bs=$size count=$multiplier 60 | dd if=$outdir/tmp of=$outdir/tmp1 bs=$size count=$multiplier 61 | dd if=$outdir/tmp1 of=$outdir/tmp2 bs=$size count=$multiplier 62 | rm $outdir/tmp $outdir/tmp1 $outdir/tmp2 63 | } 64 | 65 | echo $(date) 66 | echo $(printf "Starting io anomaly for %s x %s bytes, at %s for %d seconds" \ 67 | $multiplier $size $outdir $runtime) 68 | 69 | 70 | while [[ "$runtime" -le "0" || "$SECONDS" -le "$runtime" ]] 71 | do 72 | for i in $(seq $nthreads) 73 | do 74 | mkdir -p $outdir/$i 75 | move_files $outdir/$i & 76 | pids[$i]=$! 77 | done 78 | for i in $(seq $nthreads) 79 | do 80 | wait ${pids[$i]} 81 | done 82 | [[ $verbose ]] && echo "Looping" 83 | done 84 | rm -r $outdir 85 | -------------------------------------------------------------------------------- /src/iometadata.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "src/utils.h" 13 | 14 | 15 | static struct option const long_opt[] = 16 | { 17 | {"help", no_argument, NULL, 'h'}, 18 | {"verbose", no_argument, NULL, 'v'}, 19 | {"start", required_argument, NULL, 't'}, 20 | {"duration", required_argument, NULL, 'd'}, 21 | {"location", required_argument, NULL, 'l'}, 22 | {NULL, 0, NULL, 0} 23 | }; 24 | 25 | const char *iometadata_usage = "Metadata Server Interference Anomaly\n\n" 26 | "-d, --duration (=-1.0) Duration of the anomaly (in seconds).\n" 27 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 28 | "-l, --location (='./hpas_tmp') Target directory \n" 29 | "-v, --verbose Prints execution information.\n" 30 | "-h, --help Prints this message.\n"; 31 | static const char short_opt[] = "hvd:l:t:"; 32 | 33 | int iometadata(int argc, char *argv[]) 34 | { 35 | int c=-1; 36 | bool verbose = false; 37 | double start_time = 0; 38 | double duration = -1; 39 | char *location = NULL; 40 | size_t location_size; 41 | 42 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 43 | { 44 | 45 | 46 | switch(c) 47 | { 48 | case -1: 49 | case 0: 50 | break; 51 | 52 | case 't': 53 | start_time = strtol(optarg, NULL, 10); 54 | if (start_time < 0) { 55 | printf("Start time cannot be negative.\n"); 56 | _exit(0); 57 | } 58 | break; 59 | 60 | case 'l': 61 | location_size = strlen(optarg) + 1; 62 | if (location_size > PATH_MAX) { 63 | printf("Location name too long"); 64 | _exit(0); 65 | } 66 | location = (char *) malloc(location_size); 67 | if (location == NULL) { 68 | printf("Malloc failed.\n"); 69 | _exit(0); 70 | } 71 | memcpy(location, optarg, location_size); 72 | break; 73 | 74 | case 'd': 75 | duration = strtod(optarg, NULL); 76 | break; 77 | 78 | case 'v': 79 | verbose = true; 80 | break; 81 | 82 | case 'h': 83 | default: 84 | printf("Usage: %s [OPTIONS]\n%s", argv[0], iometadata_usage); 85 | return 0; 86 | } 87 | } 88 | hpas_sleep(start_time); 89 | if (location == NULL) { 90 | location_size = 11; 91 | location = (char *) malloc(location_size); 92 | strncpy(location, "./hpas_tmp", location_size); 93 | mkdir(location, 0700); 94 | } 95 | location[location_size - 1] = '\0'; 96 | char *foldername; 97 | foldername = (char *) malloc(location_size + 8); 98 | sprintf(foldername, "%s/XXXXXX", location); 99 | 100 | char *filename = malloc(location_size + 10); 101 | char *filenames[10]; 102 | int ite; 103 | for (ite = 0; ite < 10; ite++) { 104 | filenames[ite] = malloc(location_size + 10); 105 | } 106 | 107 | char *tempdir = mkdtemp(foldername); 108 | if (tempdir == NULL) { 109 | fprintf(stderr, "mkdtemp failed for template %s with the error: %s\n", 110 | foldername, strerror(errno)); 111 | return -1; 112 | } 113 | time_t rawtime; 114 | struct tm *timeinfo; 115 | time(&rawtime); 116 | timeinfo = localtime(&rawtime); 117 | printf("%sStarting metadata anomaly with d=%f, l=%s\n", 118 | asctime(timeinfo), duration, tempdir); 119 | int write_result; 120 | int k = 0; 121 | int i = 0; 122 | int counter = 0; 123 | int fds[10]; 124 | set_duration(duration); 125 | while(timer_flag) 126 | { 127 | sprintf(filename, "%s/%d", tempdir, k % 10); 128 | remove(filename); 129 | // O_RDONLY: Read only 130 | // O_CREAT: Create file if doesn't exist 131 | // S_IRUSR: Set read rights for the owner true. 132 | fds[k % 10] = open(filename, O_RDWR | O_CREAT, S_IRUSR); 133 | /* printf("Opened the file with fd = %d \n",fds[k % 10]); */ 134 | strncpy(filenames[k % 10], filename, location_size + 10); 135 | 136 | write_result = write(fds[k % 10], "a\n", 2); 137 | if (write_result != 2) { 138 | printf("Write failed.\n"); 139 | _exit(0); 140 | } 141 | if ((k % 10) == 9) { 142 | for (i=0; i < 10; i++) { 143 | close(fds[i]); 144 | /* printf("Closed the file with fd = %d \n",fds[i]); */ 145 | remove(filenames[i]); 146 | } 147 | } 148 | if (verbose && ++counter % 1000 == 0) { 149 | printf("."); 150 | fflush(stdout); 151 | } 152 | k = k + 1; 153 | } 154 | for (i=0; i < k % 10; i++) { 155 | close(fds[i]); 156 | remove(filenames[i]); 157 | } 158 | rmdir(tempdir); 159 | for (i=0; i<10; i++) { 160 | free(filenames[i]); 161 | } 162 | free(filename); 163 | free(foldername); 164 | free(location); 165 | return 0; 166 | } 167 | 168 | 169 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "src/anomalies.h" 7 | 8 | #ifndef BINDIR 9 | # define BINDIR "." 10 | #endif 11 | 12 | static const char *main_usage = "Please input a valid anomaly name:\n" 13 | "memleak, memeater, membw, cpuoccupy, netoccupy, cachecopy,\n" 14 | "iometadata, iobandwidth.\n"; 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | if (argc < 2) { 19 | printf("%s", main_usage); 20 | _exit(0); 21 | } 22 | if (strcmp(argv[1], "memleak") == 0) { 23 | return memleak(argc - 1, &argv[1]); 24 | } 25 | if (strcmp(argv[1], "memeater") == 0) { 26 | return memeater(argc - 1, &argv[1]); 27 | } 28 | if (strcmp(argv[1], "membw") == 0) { 29 | #ifndef HAVE_XMMINTRIN_H 30 | printf("Please compile with xmmintrin.h to get memory bandwidth anomaly.\n"); 31 | #else 32 | return membw(argc - 1, &argv[1]); 33 | #endif 34 | } 35 | if (strcmp(argv[1], "cpuoccupy") == 0) { 36 | return cpuoccupy(argc - 1, &argv[1]); 37 | } 38 | if (strcmp(argv[1], "netoccupy") == 0) { 39 | #if HAVE_SHMEM != 1 40 | printf("Please compile with SHMEM to get network contention anomaly.\n"); 41 | return 0; 42 | #else 43 | return netoccupy(argc - 1, &argv[1]); 44 | #endif 45 | } 46 | if (strcmp(argv[1], "cachecopy") == 0) { 47 | return cachecopy(argc - 1, &argv[1]); 48 | } 49 | if (strcmp(argv[1], "iometadata") == 0) { 50 | return iometadata(argc - 1, &argv[1]); 51 | } 52 | if (strcmp(argv[1], "iobandwidth") == 0) { 53 | execvp(BINDIR"/iobandwidth", &argv[1]); 54 | if (errno != 0) { 55 | printf("exec failed: %s\n" 56 | "This may be because `make install` is not executed.\n" 57 | "Check if %s exists.\n", 58 | strerror(errno), BINDIR"/iobandwidth"); 59 | _exit(0); 60 | } 61 | return 0; 62 | } 63 | printf("%s", main_usage); 64 | _exit(0); 65 | } 66 | -------------------------------------------------------------------------------- /src/membw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "src/utils.h" 8 | 9 | static struct option const long_opt[] = 10 | { 11 | {"help", no_argument, NULL, 'h'}, 12 | {"verbose", no_argument, NULL, 'v'}, 13 | {"size", required_argument, NULL, 's'}, 14 | {"start", required_argument, NULL, 't'}, 15 | {"duration", required_argument, NULL, 'd'}, 16 | {NULL, 0, NULL, 0} 17 | }; 18 | 19 | const char *membw_usage = "Memory Bandwidth Contention.\n\n" 20 | "-s, --size (=4K) One dimension (in bytes) of 2D array.\n" 21 | "-d, --duration (=-1.0) The total duration (in seconds), -1 for infinite.\n" 22 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 23 | "-v, --verbose Prints execution information.\n" 24 | "-h, --help Prints this message.\n"; 25 | static const char short_opt[] = "hvd:s:t:"; 26 | 27 | void temporalCopy(const double *orig, double *swap, size_t size) 28 | { 29 | size_t m, i; 30 | for(m = 0; m < size; m++) { 31 | for (i = 0; i < size; i++) { 32 | _mm_stream_pi( 33 | (__m64 *) (&swap[size * i + m]), 34 | *(__m64 *) (&orig[size * m + i])); // MOVNTQ 35 | _mm_empty(); // EMMS 36 | } 37 | } 38 | } 39 | 40 | int membw(int argc, char *argv[]) 41 | { 42 | 43 | clock_t start_loop, end_loop; 44 | double loop_time; 45 | double *array; 46 | double *swap_array; 47 | bool verbose = false; 48 | ssize_t size = 4096; 49 | double start_time = 0; 50 | double duration = -1; 51 | 52 | int m, i, c; 53 | srand(time(NULL)); 54 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 55 | { 56 | switch(c) 57 | { 58 | case -1: 59 | case 0: 60 | break; 61 | 62 | case 't': 63 | start_time = strtod(optarg, NULL); 64 | if (start_time < 0) { 65 | printf("Start time cannot be negative.\n"); 66 | _exit(0); 67 | } 68 | break; 69 | 70 | case 'd': 71 | duration = strtod(optarg, NULL); 72 | break; 73 | 74 | case 's': 75 | size = parse_size(optarg); 76 | if (size == -1) { 77 | printf("Wrong size input\n"); 78 | return -1; 79 | } 80 | break; 81 | 82 | case 'v': 83 | verbose = true; 84 | break; 85 | 86 | case 'h': 87 | default: 88 | printf("Usage: %s [OPTIONS]\n%s", argv[0], membw_usage); 89 | return 0; 90 | } 91 | } 92 | hpas_sleep(start_time); 93 | size = size / sizeof(double); 94 | array = (double *) malloc(size * size * sizeof(double)); 95 | swap_array = (double *) malloc(size * size * sizeof(double)); 96 | if (array == NULL || swap_array == NULL) { 97 | printf("Failed to allocate memory\n"); 98 | return -1; 99 | } 100 | 101 | time_t rawtime; 102 | struct tm * timeinfo; 103 | time(&rawtime); 104 | timeinfo = localtime(&rawtime); 105 | printf("%sStarting membw with doublecount:%ld duration:%f\n\n", 106 | asctime(timeinfo), size * size, duration); 107 | fflush(stdout); 108 | 109 | start_loop = clock(); 110 | for(m = 0; m < size; m++) { 111 | for (i = 0; i < size; i++) { 112 | swap_array[m * size + i] = (double) rand(); 113 | } 114 | } 115 | end_loop = clock(); 116 | 117 | if (verbose) { 118 | loop_time = ((double)(end_loop - start_loop))/CLOCKS_PER_SEC; 119 | printf("Started memory bandwidth anomaly, array is filled: %fs\n", loop_time); 120 | } 121 | 122 | int counter = 0; 123 | start_loop = clock(); 124 | set_duration(duration); 125 | while (timer_flag) { 126 | temporalCopy(array, swap_array, size); 127 | if (verbose && ++counter % 100 == 0) { 128 | printf("."); 129 | fflush(stdout); 130 | } 131 | } 132 | end_loop = clock(); 133 | 134 | if (verbose) { 135 | loop_time = ((double)(end_loop - start_loop))/CLOCKS_PER_SEC; 136 | printf("\n Array generation, first row is filled: %fs\n", loop_time); 137 | } 138 | free(array); 139 | free(swap_array); 140 | return 0; 141 | } 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/memeater.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "src/utils.h" 9 | 10 | static struct option const long_opt[] = 11 | { 12 | {"help", no_argument, NULL, 'h'}, 13 | {"verbose", no_argument, NULL, 'v'}, 14 | {"size", required_argument, NULL, 's'}, 15 | {"start", required_argument, NULL, 't'}, 16 | {"period", required_argument, NULL, 'p'}, 17 | {"duration", required_argument, NULL, 'd'}, 18 | {NULL, 0, NULL, 0} 19 | }; 20 | 21 | const char *memeater_usage = "Memory intensive orphan process.\n\n" 22 | "-s, --size (=35M) The size (in bytes) of the array to be allocated.\n" 23 | "-p, --period (=0.2) The time to wait (in seconds) between array allocations.\n" 24 | "-d, --duration (=-1.0) The total duration (in seconds), -1 for infinite.\n" 25 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 26 | "-v, --verbose Prints execution information.\n" 27 | "-h, --help Prints this message.\n"; 28 | static const char *short_opt = "hvd:s:p:t:"; 29 | 30 | int memeater(int argc, char *argv[]) 31 | { 32 | int c; 33 | 34 | bool verbose = false; 35 | long int size = 35 * 1024 * 1024; 36 | long int intcount; 37 | double period = 0.2; 38 | double duration = -1; 39 | double start_time = 0; 40 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 41 | { 42 | switch(c) 43 | { 44 | case -1: 45 | case 0: 46 | break; 47 | 48 | case 't': 49 | start_time = strtod(optarg, NULL); 50 | if (start_time < 0) { 51 | printf("Start time cannot be negative.\n"); 52 | _exit(0); 53 | } 54 | break; 55 | 56 | case 's': 57 | size = parse_size(optarg); 58 | if (size == -1) { 59 | printf("Wrong size input\n"); 60 | return -1; 61 | } 62 | break; 63 | 64 | case 'p': 65 | period = strtod(optarg, NULL); 66 | if (period < 0) { 67 | printf("Period cannot be smaller than zero.\n"); 68 | _exit(0); 69 | } 70 | break; 71 | 72 | case 'd': 73 | duration = strtod(optarg, NULL); 74 | break; 75 | 76 | case 'v': 77 | verbose = true; 78 | break; 79 | 80 | case 'h': 81 | default: 82 | printf("Usage: %s [OPTIONS]\n%s", argv[0], memeater_usage); 83 | return 0; 84 | } 85 | } 86 | hpas_sleep(start_time); 87 | time_t rawtime; 88 | struct tm * timeinfo; 89 | FILE *fpipe; 90 | char *command="cat /proc/meminfo | grep -i active"; 91 | char line[256]; 92 | int *keep = NULL; 93 | int *temp; 94 | int i,j,r,count = 0; 95 | 96 | time(&rawtime); 97 | timeinfo = localtime(&rawtime); 98 | intcount = size / sizeof(int); 99 | printf("%sStarting memeater with intcount:%ld period:%f duration:%f\n\n", 100 | asctime(timeinfo), intcount, period, duration); 101 | fflush(stdout); 102 | 103 | srand(time(NULL)); 104 | set_duration(duration); 105 | while (1) { 106 | count = 0; 107 | for (i =0; i < 10; i++){ 108 | if (!timer_flag) break; 109 | hpas_sleep(period); 110 | 111 | temp = (int*) realloc (keep, (intcount + count) * sizeof(int)); 112 | if (!temp){ 113 | break; 114 | /* malloc will return NULL sooner or later, due to lack of memory */ 115 | } 116 | 117 | keep = temp; 118 | for (j = 0; j < intcount; j++){ 119 | r = rand(); 120 | keep[count+j] = r; 121 | } 122 | count += intcount; 123 | 124 | if (verbose) { 125 | if (!(fpipe = (FILE*) popen(command, "r"))){ 126 | perror("Problems with pipe"); 127 | exit(1); 128 | } 129 | while (fgets( line, sizeof line, fpipe)){ 130 | printf("%s", line); 131 | } 132 | printf("alloc: %d\n",count); 133 | printf("\n"); 134 | pclose(fpipe); 135 | } 136 | } 137 | if (!timer_flag) break; 138 | hpas_sleep(120.0); 139 | free(keep); 140 | keep = NULL; 141 | hpas_sleep(10.0); 142 | } 143 | free(keep); 144 | time(&rawtime); 145 | timeinfo = localtime(&rawtime); 146 | printf("%sFinished memeater.\n", asctime(timeinfo)); 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /src/memleak.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static struct option const long_opt[] = 10 | { 11 | {"help", no_argument, NULL, 'h'}, 12 | {"verbose", no_argument, NULL, 'v'}, 13 | {"size", required_argument, NULL, 's'}, 14 | {"period", required_argument, NULL, 'p'}, 15 | {"duration", required_argument, NULL, 'd'}, 16 | {"start", required_argument, NULL, 't'}, 17 | {NULL, 0, NULL, 0} 18 | }; 19 | 20 | const char *memleak_usage = "Memory leak.\n\n" 21 | "-s, --size (=20M) The size (in bytes) of the array to be allocated.\n" 22 | "-p, --period (=0.2) The time to wait (in seconds) between array allocations.\n" 23 | "-d, --duration (=-1.0) The total duration (in seconds), -1 for infinite.\n" 24 | "-t, --start (=0.0) The time to wait (in seconds) before starting the anomaly.\n" 25 | "-v, --verbose Prints execution information.\n" 26 | "-h, --help Prints this message.\n"; 27 | static const char *short_opt = "hvd:s:p:t:"; 28 | 29 | int memleak(int argc, char *argv[]) 30 | { 31 | int c; 32 | 33 | bool verbose = false; 34 | long int size = 20 * 1024 * 1024; 35 | double period = 0.2; 36 | double duration = -1; 37 | double start_time = 0; 38 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 39 | { 40 | switch(c) 41 | { 42 | case -1: 43 | case 0: 44 | break; 45 | 46 | case 't': 47 | start_time = strtod(optarg, NULL); 48 | if (start_time < 0) { 49 | printf("Start time cannot be negative.\n"); 50 | _exit(0); 51 | } 52 | break; 53 | 54 | case 's': 55 | size = parse_size(optarg); 56 | if (size == -1) { 57 | printf("Wrong size input\n"); 58 | return -1; 59 | } 60 | break; 61 | 62 | case 'p': 63 | period = strtod(optarg, NULL); 64 | if (period < 0) { 65 | printf("Period cannot be smaller than zero.\n"); 66 | _exit(0); 67 | } 68 | break; 69 | 70 | case 'd': 71 | duration = strtod(optarg, NULL); 72 | break; 73 | 74 | case 'v': 75 | verbose = true; 76 | break; 77 | 78 | case 'h': 79 | default: 80 | printf("Usage: %s [OPTIONS]\n%s", argv[0], memleak_usage); 81 | return 0; 82 | } 83 | } 84 | hpas_sleep(start_time); 85 | time_t rawtime; 86 | struct tm *timeinfo; 87 | FILE *fpipe; 88 | char *command = "cat /proc/meminfo | grep -i active"; 89 | char line[256]; 90 | char *keep; 91 | long int j; 92 | 93 | time(&rawtime); 94 | timeinfo = localtime(&rawtime); 95 | printf("%sStarting leak with size:%ld period:%f duration:%f\n\n", 96 | asctime(timeinfo), size, period, duration); 97 | fflush(stdout); 98 | 99 | /* this is a loop calling the malloc function which 100 | * allocates the memory but without saving the address of the 101 | * allocated place 102 | */ 103 | set_duration(duration); 104 | while (timer_flag) { 105 | hpas_sleep(period); 106 | 107 | char *temp = malloc(size * sizeof(char)); 108 | if (!temp){ 109 | break; 110 | /* malloc will return NULL sooner or later, due to lack of memory */ 111 | } 112 | 113 | for (j = 0; j < size; j++){ 114 | temp[j] = 'a'; 115 | } 116 | 117 | if (verbose) { 118 | if (!(fpipe = (FILE*) popen(command, "r"))){ 119 | perror("Problems with pipe"); 120 | exit(1); 121 | } 122 | while (fgets( line, sizeof line, fpipe)){ 123 | printf("%s", line); 124 | } 125 | printf("\n"); 126 | pclose(fpipe); 127 | } 128 | 129 | keep = temp; 130 | } 131 | time(&rawtime); 132 | timeinfo = localtime(&rawtime); 133 | printf("%sFinished leak.\n", asctime(timeinfo)); 134 | return keep + 0 - keep; /* suppress unused variable warning */ 135 | /* free the allocated memory by operating system itself after program exits */ 136 | } 137 | -------------------------------------------------------------------------------- /src/netoccupy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #include "src/utils.h" 10 | #include 11 | 12 | char *s_buf_original; 13 | char *r_buf_original; 14 | 15 | static struct option const long_opt[] = 16 | { 17 | {"help", no_argument, NULL, 'h'}, 18 | {"verbose", no_argument, NULL, 'v'}, 19 | {"size", required_argument, NULL, 's'}, 20 | {"duration", required_argument, NULL, 'd'}, 21 | {"start", required_argument, NULL, 't'}, 22 | {NULL, 0, NULL, 0} 23 | }; 24 | 25 | const char *netoccupy_usage = "Network contention.\n\n" 26 | "-s, --size (=100M) The size (in bytes) of messages.\n" 27 | "-d, --duration (=-1.0) The total duration (in miliseconds), -1 for infinite.\n" 28 | "-t, --start (=0.0) The time to wait (in miliseconds) before starting the anomaly.\n" 29 | "-v, --verbose Prints execution information.\n" 30 | "-h, --help Prints this message.\n"; 31 | static const char *short_opt = "hvs:d:t:"; 32 | 33 | int netoccupy(int argc, char *argv[]) 34 | { 35 | long int myid, numprocs, i; 36 | ssize_t size = 100000000; 37 | double duration = -1; 38 | double start_time = 0; 39 | int c; 40 | bool verbose = false; 41 | char *s_buf, *r_buf; 42 | char hostname[64]; 43 | int *hostnum; 44 | int *all_hosts; 45 | int first_host = -1; 46 | int second_host = -1; 47 | int loop = 100; 48 | while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) 49 | { 50 | switch(c) 51 | { 52 | case -1: 53 | case 0: 54 | break; 55 | 56 | case 't': 57 | start_time = strtod(optarg, NULL); 58 | if (start_time < 0) { 59 | printf("Start time cannot be negative.\n"); 60 | return -1; 61 | } 62 | break; 63 | 64 | case 's': 65 | size = parse_size(optarg); 66 | if (size == -1) { 67 | printf("Wrong size input\n"); 68 | return -1; 69 | } 70 | break; 71 | 72 | case 'd': 73 | duration = strtod(optarg, NULL); 74 | break; 75 | 76 | case 'v': 77 | verbose = true; 78 | break; 79 | 80 | case 'h': 81 | default: 82 | printf("Usage: %s [OPTIONS]\n%s", argv[0], netoccupy_usage); 83 | return 0; 84 | } 85 | } 86 | hpas_sleep(start_time); 87 | static long pSync[_SHMEM_COLLECT_SYNC_SIZE]; 88 | for (i=0; i<_SHMEM_COLLECT_SYNC_SIZE; i++) { 89 | pSync[i] = _SHMEM_SYNC_VALUE; 90 | } 91 | s_buf_original = (char *)malloc(size); 92 | r_buf_original = (char *)malloc(size); 93 | 94 | shmem_init(); 95 | myid = shmem_my_pe(); 96 | numprocs = shmem_n_pes(); 97 | 98 | s_buf = (char *)shmalloc(size); 99 | r_buf = (char *)shmalloc(size); 100 | all_hosts = (int *)shmalloc(sizeof(int) * numprocs); 101 | hostnum = (int *)shmalloc(sizeof(int)); 102 | 103 | if(!myid && verbose) { 104 | fprintf(stdout, "Starting network anomaly.\n"); 105 | fflush(stdout); 106 | } 107 | 108 | // This section needs to be changed for correct node no. parsing 109 | gethostname(hostname, sizeof(hostname)); 110 | sscanf(hostname, "nid%d", hostnum); 111 | // end section 112 | 113 | shmem_barrier_all(); 114 | shmem_fcollect32(all_hosts, hostnum, 1, 0, 0, numprocs, pSync); 115 | shmem_barrier_all(); 116 | if (myid == 0 && verbose) { 117 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "src/utils.h" 10 | 11 | unsigned int timer_flag = 1; 12 | 13 | void timer_callback(int x) { 14 | if (x == SIGALRM) { 15 | timer_flag = 0; 16 | } 17 | } 18 | 19 | void set_duration(double duration) { 20 | timer_flag = 1; 21 | if (duration < 0) { 22 | return; 23 | } 24 | struct itimerval itv; 25 | struct sigaction sa; 26 | memset (&sa, 0, sizeof (sa)); 27 | sa.sa_handler = &timer_callback; 28 | long utilsec, utilusec; 29 | utilsec = (long) duration; 30 | utilusec = (long) ((duration - (double) utilsec) * 1000000); 31 | //set times for ending calc 32 | itv.it_interval.tv_sec = 1; 33 | itv.it_interval.tv_usec = 0; 34 | itv.it_value.tv_sec = utilsec; 35 | itv.it_value.tv_usec = utilusec; 36 | 37 | //set up the signal for the calc 38 | sigaction(SIGALRM, &sa, NULL); 39 | setitimer(ITIMER_REAL, &itv, NULL); 40 | } 41 | 42 | void hpas_sleep(double sleeptime) { 43 | long sleepsec, sleepusec; 44 | struct timeval sleeptv; 45 | sleepsec = (long) sleeptime; 46 | sleepusec = (long) ((sleeptime - (double) sleepsec) * 1000000); 47 | sleeptv.tv_sec = sleepsec; 48 | sleeptv.tv_usec = sleepusec; 49 | 50 | select(0,NULL,NULL,NULL,&sleeptv); //do the sleep 51 | } 52 | 53 | ssize_t parse_size(char *input) 54 | { 55 | char *c; 56 | unsigned multiple; 57 | long result = strtol(input, &c, 10); 58 | switch(*c) { 59 | case '\0': 60 | multiple = 0; 61 | break; 62 | case 'K': 63 | case 'k': 64 | multiple = 1; 65 | break; 66 | case 'M': 67 | case 'm': 68 | multiple = 2; 69 | break; 70 | case 'G': 71 | case 'g': 72 | multiple = 3; 73 | break; 74 | case 'T': 75 | case 't': 76 | multiple = 4; 77 | break; 78 | case 'P': 79 | case 'p': 80 | multiple = 5; 81 | break; 82 | case 'E': 83 | case 'e': 84 | multiple = 6; 85 | break; 86 | default: 87 | return -1; 88 | } 89 | result *= ((unsigned long) 1) << (multiple * 10); 90 | return result; 91 | } 92 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H_ 2 | #define UTILS_H_ 3 | 4 | extern unsigned int timer_flag; 5 | 6 | void set_duration(double duration); // Time in seconds 7 | void hpas_sleep(double sleeptime); // Time in seconds 8 | 9 | long int parse_size(char *input); 10 | 11 | #endif /* UTILS_H_ */ 12 | --------------------------------------------------------------------------------