From d5450f601fb30e988e86e1a4554b9669ef7ca614 Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Fri, 5 Oct 2018 20:13:00 +0200 Subject: [PATCH 01/29] Create benchmarks Benchmarking suite to measure the integrator execution time under various conditions: build features, struct Particle implementation, number of cores, number of particles, interaction types. --- CMakeLists.txt | 6 + maintainer/benchmarks/CMakeLists.txt | 78 ++++++++++ maintainer/benchmarks/lj.py | 193 ++++++++++++++++++++++++ maintainer/benchmarks/p3m.py | 215 +++++++++++++++++++++++++++ maintainer/benchmarks/suite.sh | 39 +++++ 5 files changed, 531 insertions(+) create mode 100644 maintainer/benchmarks/CMakeLists.txt create mode 100644 maintainer/benchmarks/lj.py create mode 100644 maintainer/benchmarks/p3m.py create mode 100644 maintainer/benchmarks/suite.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 924abc2333e..c3ecf5dcc10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ option(WITH_GSL "Build with GSL support" ON) option(WITH_CUDA "Build with GPU support" ON) option(WITH_HDF5 "Build with HDF5 support" ON) option(WITH_TESTS "Enable tests" ON) +option(WITH_BENCHMARKS "Enable benchmarks" OFF) option(WITH_SCAFACOS "Build with Scafacos support" ON) option(WITH_VALGRIND_INSTRUMENTATION "Build with valgrind instrumentation markers" OFF) if( CMAKE_VERSION VERSION_GREATER 3.5.2 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) @@ -453,6 +454,11 @@ if(WITH_TESTS) add_subdirectory(testsuite) endif(WITH_TESTS) +if(WITH_BENCHMARKS) + add_custom_target(benchmark) + add_subdirectory(maintainer/benchmarks) +endif(WITH_BENCHMARKS) + ####################################################################### # Subdirectories ####################################################################### diff --git a/maintainer/benchmarks/CMakeLists.txt b/maintainer/benchmarks/CMakeLists.txt new file mode 100644 index 00000000000..69b49633afa --- /dev/null +++ b/maintainer/benchmarks/CMakeLists.txt @@ -0,0 +1,78 @@ +ProcessorCount(NP) + +if(EXISTS ${MPIEXEC}) + # OpenMPI 3.0 and higher checks the number of processes against the number of CPUs + execute_process(COMMAND ${MPIEXEC} --version RESULT_VARIABLE mpi_version_result OUTPUT_VARIABLE mpi_version_output ERROR_VARIABLE mpi_version_output) + if (mpi_version_result EQUAL 0 AND mpi_version_output MATCHES "\\(Open(RTE| MPI)\\) ([3-9]\\.|1[0-9])") + set(MPIEXEC_OVERSUBSCRIBE "-oversubscribe") + else() + set(MPIEXEC_OVERSUBSCRIBE "") + endif() +endif() + +add_custom_target(benchmark_python) + +function(PYTHON_BENCHMARK) + cmake_parse_arguments(BENCHMARK "" "FILE;RUN_WITH_MPI;MIN_NUM_PROC;MAX_NUM_PROC" "ARGUMENTS;DEPENDENCIES" ${ARGN}) + get_filename_component(BENCHMARK_NAME ${BENCHMARK_FILE} NAME_WE) + foreach(argument IN LISTS BENCHMARK_ARGUMENTS) + set(BENCHMARK_NAME "${BENCHMARK_NAME}_${argument}") + endforeach(argument) + configure_file(${BENCHMARK_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${BENCHMARK_FILE}) + foreach(dependency IN LISTS BENCHMARK_DEPENDENCIES) + configure_file(${dependency} ${CMAKE_CURRENT_BINARY_DIR}/${dependency}) + endforeach(dependency) + set(BENCHMARK_FILE "${CMAKE_CURRENT_BINARY_DIR}/${BENCHMARK_FILE}") + + # default values + if (NOT DEFINED BENCHMARK_RUN_WITH_MPI) + set(BENCHMARK_RUN_WITH_MPI TRUE) + endif() + if (NOT DEFINED BENCHMARK_MIN_NUM_PROC) + set(BENCHMARK_MIN_NUM_PROC 1) + endif() + if (NOT DEFINED BENCHMARK_MAX_NUM_PROC) + set(BENCHMARK_MAX_NUM_PROC ${NP}) + endif() + # parallel schemes + if(EXISTS ${MPIEXEC} AND ${BENCHMARK_RUN_WITH_MPI}) + set(BENCHMARK_CONFIGURATIONS "0") + if(${NP} GREATER 0 AND ${BENCHMARK_MAX_NUM_PROC} GREATER 0 AND ${BENCHMARK_MIN_NUM_PROC} LESS 2) + list(APPEND BENCHMARK_CONFIGURATIONS 1) + endif() + if(${NP} GREATER 1 AND ${BENCHMARK_MAX_NUM_PROC} GREATER 1 AND ${BENCHMARK_MIN_NUM_PROC} LESS 3) + list(APPEND BENCHMARK_CONFIGURATIONS 2) + endif() + if(${NP} GREATER 3 AND ${BENCHMARK_MAX_NUM_PROC} GREATER 3 AND ${BENCHMARK_MIN_NUM_PROC} LESS 5) + list(APPEND BENCHMARK_CONFIGURATIONS 4) + endif() + if(${NP} GREATER 7 AND ${BENCHMARK_MAX_NUM_PROC} GREATER 7 AND ${BENCHMARK_MIN_NUM_PROC} LESS 9) + list(APPEND BENCHMARK_CONFIGURATIONS 8) + endif() + if(${NP} GREATER 15 AND ${BENCHMARK_MAX_NUM_PROC} GREATER 15 AND ${BENCHMARK_MIN_NUM_PROC} LESS 17) + list(APPEND BENCHMARK_CONFIGURATIONS 16) + endif() + list(REMOVE_AT BENCHMARK_CONFIGURATIONS 0) + foreach(nproc IN LISTS BENCHMARK_CONFIGURATIONS) + add_custom_target(${BENCHMARK_NAME}_parallel_${nproc} + ${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE} ${MPIEXEC_NUMPROC_FLAG} ${nproc} + ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) + add_dependencies(benchmark_python ${BENCHMARK_NAME}_parallel_${nproc}) + endforeach(nproc) + else() + add_custom_target(${BENCHMARK_NAME}_serial + ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) + add_dependencies(benchmark_python ${BENCHMARK_NAME}_serial) + endif() +endfunction(PYTHON_BENCHMARK) + +python_benchmark(FILE lj.py ARGUMENTS 1000 liquid) +python_benchmark(FILE lj.py ARGUMENTS 1000 gas) +python_benchmark(FILE lj.py ARGUMENTS 10000 liquid) +python_benchmark(FILE lj.py ARGUMENTS 10000 gas) +python_benchmark(FILE p3m.py ARGUMENTS 1000 solution) +python_benchmark(FILE p3m.py ARGUMENTS 1000 gas) +python_benchmark(FILE p3m.py ARGUMENTS 10000 solution) +python_benchmark(FILE p3m.py ARGUMENTS 10000 gas) + +add_dependencies(benchmark benchmark_python) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py new file mode 100644 index 00000000000..275690ca2f3 --- /dev/null +++ b/maintainer/benchmarks/lj.py @@ -0,0 +1,193 @@ +# +# Copyright (C) 2013-2018 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +from __future__ import print_function +import os +import sys +import numpy as np +import espressomd +from time import time, sleep +from espressomd import thermostat + +required_features = ["LENNARD_JONES"] +espressomd.assert_features(required_features) + +print(espressomd.features()) + +# Interaction parameters (repulsive Lennard-Jones) +############################################################# + +lj_eps = 1.0 # LJ epsilon +lj_sig = 1.0 # particle diameter +lj_cap = 20. # force cap +lj_cut = lj_sig * 2**(1. / 6.) # cutoff distance + +# System parameters +############################################################# + +try: + nproc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) + n_part_per_core = int(sys.argv[1]) + n_part = nproc * n_part_per_core + if sys.argv[2] == 'gas': + density = 0.02 + elif sys.argv[2] == 'liquid': + density = 0.30 + else: + density = float(sys.argv[2]) + assert density > 0, "density must be a positive number" + assert density < np.pi / (3 * np.sqrt(2)), \ + "density exceeds the physical limit of sphere packing (~0.74)" + mode = "benchmark" + if len(sys.argv) == 4: + assert sys.argv[3] == "--visualize" + mode = "visualization" + from espressomd import visualization + from threading import Thread +except (ValueError, IndexError) as err: + print(err.message) + print("\nUsage: [mpiexec -np ] pypresso lj.py " + " [--visualize]\n") + exit(1) + +measurement_steps = int(np.round(5e6 / n_part_per_core, -2)) +assert(measurement_steps >= 100), \ + "{} steps per tick are too short".format(measurement_steps) +# volume of N spheres with radius r: N * (4/3*pi*r^3) +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1./3.) + +# System +############################################################# +system = espressomd.System(box_l=3*(box_l,)) +# PRNG seeds +############################################################# +system.random_number_generator_state = list(range( + nproc * (system._get_PRNG_state_size() + 1))) +#system.random_number_generator_state = list(range(len(system.random_number_generator_state))) +np.random.seed(1) +# Integration parameters +############################################################# +system.time_step = 0.01 +system.cell_system.skin = 0.5 +system.thermostat.turn_off() + + +############################################################# +# Setup System # +############################################################# + +# Interaction setup +############################################################# +system.non_bonded_inter[0, 0].lennard_jones.set_params( + epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") +system.force_cap = lj_cap + +print("LJ-parameters:") +print(system.non_bonded_inter[0, 0].lennard_jones.get_params()) + +# Particle setup +############################################################# + +for i in range(n_part): + system.part.add(id=i, pos=np.random.random(3) * system.box_l) + +############################################################# +# Warmup Integration # +############################################################# + +system.integrator.set_steepest_descent(f_max=0, gamma=0.001, max_displacement=0.01) + +# warmup +while system.analysis.energy()["total"] > 10 * n_part: + print('minimization: {:.1f}'.format(system.analysis.energy()["total"])) + system.integrator.run(10) +print() +system.integrator.set_vv() + +system.thermostat.set_langevin(kT=1.0, gamma=1.0) + +# tune skin +print('tune: {}'.format(system.cell_system.tune_skin(min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) +system.integrator.run(min(30 * measurement_steps, 60000)) +print('tune: {}'.format(system.cell_system.tune_skin(min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) + +print(system.non_bonded_inter[0, 0].lennard_jones) + +if mode == 'benchmark': + report_path = 'benchmarks.csv' + if '${CMAKE_BINARY_DIR}'[0] != '$': # CMake variable + report_path = '${CMAKE_BINARY_DIR}/benchmarks.csv.part' + + # print initial energies + energies = system.analysis.energy() + print(energies) + + # time integration loop + print("Timing every {} steps".format(measurement_steps)) + main_tick = time() + all_t = [] + for i in range(30): + tick = time() + system.integrator.run(measurement_steps) + tock = time() + t = (tock-tick) / measurement_steps + print('step {}, time = {:.2e}, verlet: {:.2f}'.format(i, t, + system.cell_system.get_state()["verlet_reuse"])) + all_t.append(t) + main_tock = time() + # average time + all_t = np.array(all_t) + avg = np.average(all_t) + ci = 1.96 * np.std(all_t) / np.sqrt(len(all_t) - 1) + print("average: {:.3e} +/- {:.3e} (95% C.I.)".format(avg, ci)) + + # print final energies + energies = system.analysis.energy() + print(energies) + + # write report + report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' + '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( + script=os.path.basename(sys.argv[0]), + arguments=" ".join(map(str, sys.argv[1:])), + cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, + E1=system.analysis.energy()["total"], + E2=system.analysis.energy()["kinetic"], + E3=system.analysis.energy()["non_bonded"])) + if not os.path.isfile(report_path): + report = ('"script","arguments","cores","MPI","mean","ci",' + '"steps_per_tick","duration","E1","E2","E3"\n' + report) + with open(report_path, 'a') as f: + f.write(report) +else: + # use visualizer + visualizer = visualization.openGLLive(system) + + def main_thread(): + while True: + system.integrator.run(1) + visualizer.update() + sleep(1/60.) # limit framerate to at most 60 FPS + + t = Thread(target=main_thread) + t.daemon = True + t.start() + visualizer.start() + + diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py new file mode 100644 index 00000000000..b9cc111c995 --- /dev/null +++ b/maintainer/benchmarks/p3m.py @@ -0,0 +1,215 @@ +# +# Copyright (C) 2013-2018 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +from __future__ import print_function +import os +import sys +import numpy as np +import espressomd +from time import time, sleep +from espressomd import thermostat +from espressomd import electrostatics + +required_features = ["ELECTROSTATICS", "LENNARD_JONES", "MASS"] +espressomd.assert_features(required_features) + +print(espressomd.features()) + +# Interaction parameters (repulsive Lennard-Jones) +############################################################# + +lj_cap = 20. # force cap +species = ["Cl", "Na", "Solvent"] +types = {"Cl": 0, "Na": 1, "Solvent": 2} +charges = {"Cl": -1.0, "Na": 1.0, "Solvent": 0.0} +lj_sigmas = {"Cl": 3.85, "Na": 2.52, "Solvent": 1.8} +lj_epsilons = {"Cl": 192.45, "Na": 17.44, "Solvent": 50.0} +lj_cuts = {"Cl": 2.0 * lj_sigmas["Cl"], "Na": 2.0 * lj_sigmas["Na"], + "Solvent": 2.0 * lj_sigmas["Solvent"]} +masses = {"Cl": 35.453, "Na": 22.99, "Solvent": 18.0} + +# System parameters +############################################################# + +try: + nproc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) + n_part_per_core = int(sys.argv[1]) + n_part = nproc * n_part_per_core + sim_type = sys.argv[2] + assert sim_type in ('solution', 'gas') + mode = "benchmark" + if len(sys.argv) == 4: + assert sys.argv[3] == "--visualize" + mode = "visualization" + from espressomd import visualization + from threading import Thread +except (ValueError, IndexError) as err: + print(err.message) + print("\nUsage: [mpiexec -np ] pypresso lj.py " + " [--visualize]\n") + exit(1) + +measurement_steps = int(np.round(2e6 / n_part_per_core, -2)) +assert(measurement_steps >= 100), \ + "{} steps per tick are too short".format(measurement_steps) +# volume of N spheres with radius r: N * (4/3*pi*r^3) +density = 0.25 +if sim_type == "gas": + lj_sig = lj_sigmas["Na"] + lj_sigmas["Cl"] +else: + lj_sig = lj_sigmas["Solvent"] +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1./3.) +if sim_type == "gas": + species = ["Cl", "Na"] + +# electrostatics +# E = 1 /(4*pi*e_0*e_r)*q1*q2/r +# e_0 in F/m or C^2/N/m^2 +# E in N.M or J +Na = 6.0221408e23 # Avogadro's constant +epsilon_0 = 8.85419e-12 # vacuum permittivity +epsilon_r = 4.0 # relative permittivity +q = 1.6021766e-19 # elementary charge +# Coulomb prefactor in kJ/mol, using Angstroms +prefactor = 1 / (4 * np.pi * epsilon_0 * epsilon_r) * q**2 * Na * 1e-3 * 1e10 + +# temperature +kB = 1.38064852e-23 # Boltzmann's constant in J/K +kB_kjmol = kB * Na / 1000 # Boltzmann's constant in kJ/mol/K +SI_temperature = 400.0 +temperature = SI_temperature * kB_kjmol + +# System +############################################################# +system = espressomd.System(box_l=3*(box_l,)) +system.cell_system.set_domain_decomposition(use_verlet_lists=True) +# PRNG seeds +############################################################# +system.random_number_generator_state = list(range( + nproc * (system._get_PRNG_state_size() + 1))) +#system.random_number_generator_state = list(range(len(system.random_number_generator_state))) +np.random.seed(1) +# Integration parameters +############################################################# +system.time_step = 0.01 +system.cell_system.skin = 1.2 +system.thermostat.turn_off() + + +############################################################# +# Setup System # +############################################################# + +# Interaction setup +############################################################# + +for i in range(len(species)): + for j in range(i, len(species)): + s = [species[i], species[j]] + lj_sig = (lj_sigmas[s[0]] + lj_sigmas[s[1]]) * 0.5 + lj_cut = (lj_cuts[s[0]] + lj_cuts[s[1]]) * 0.5 + lj_eps = (lj_epsilons[s[0]] * lj_epsilons[s[1]])**0.5 + system.non_bonded_inter[types[s[0]], types[s[1]]].lennard_jones.set_params( + epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") + +# Particle setup +############################################################# + +if sim_type == "gas": + for i in range(int(n_part / 2.)): + for t in ["Na", "Cl"]: + system.part.add(pos=np.random.random(3) * system.box_l, + q=charges[t], type=types[t], mass=masses[t]) +else: + for i in range(int(n_part / 30.)): + for t in ["Na", "Cl"] + 28* ["Solvent"]: + system.part.add(pos=np.random.random(3) * system.box_l, + q=charges[t], type=types[t], mass=masses[t]) + +############################################################# +# Warmup Integration # +############################################################# + +energy = system.analysis.energy() +print("Before Minimization: E_total = {}".format(energy['total'])) +system.minimize_energy.init(f_max=1000, gamma=30.0, + max_steps=1000, max_displacement=0.01) +system.minimize_energy.minimize() +energy = system.analysis.energy() +print("After Minimization: E_total = {}".format(energy['total'])) + +print("Tune p3m") +p3m = electrostatics.P3M(prefactor=prefactor, accuracy=1e-1) +system.actors.add(p3m) + +system.thermostat.set_langevin(kT=temperature, gamma=2.0) + + +if mode == 'benchmark': + report_path = 'benchmarks.csv' + if '${CMAKE_BINARY_DIR}'[0] != '$': # CMake variable + report_path = '${CMAKE_BINARY_DIR}/benchmarks.csv.part' + + # print initial energies + energies = system.analysis.energy() + print(energies) + + # time integration loop + print("Timing every {} steps".format(measurement_steps)) + main_tick = time() + all_t = [] + for i in range(30): + tick = time() + system.integrator.run(measurement_steps) + tock = time() + t = (tock-tick) / measurement_steps + print('step {}, time = {:.2e}, verlet: {:.2f}'.format(i, t, + system.cell_system.get_state()["verlet_reuse"])) + all_t.append(t) + main_tock = time() + # average time + all_t = np.array(all_t) + avg = np.average(all_t) + ci = 1.96 * np.std(all_t) / np.sqrt(len(all_t) - 1) + print("average: {:.3e} +/- {:.3e} (95% C.I.)".format(avg, ci)) + + # print final energies + energies = system.analysis.energy() + print(energies) + + # write report + report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' + '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( + script=os.path.basename(sys.argv[0]), + arguments=" ".join(map(str, sys.argv[1:])), + cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, + E1=system.analysis.energy()["total"], + E2=system.analysis.energy()["coulomb"], + E3=system.analysis.energy()["non_bonded"])) + if not os.path.isfile(report_path): + report = ('"script","arguments","cores","MPI","mean","ci",' + '"steps_per_tick","duration","E1","E2","E3"\n' + report) + with open(report_path, 'a') as f: + f.write(report) +else: + # use visualizer + visualizer = visualization.openGLLive(system) + visualizer.run(1) + + diff --git a/maintainer/benchmarks/suite.sh b/maintainer/benchmarks/suite.sh new file mode 100644 index 00000000000..db9740c77a8 --- /dev/null +++ b/maintainer/benchmarks/suite.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +commits="c1d850ef3c4 c72cb35c3c5 eaa84cd1c92" +configs="myconfig-minimal.hpp ../src/core/myconfig-default.hpp ../maintainer/configs/maxset.hpp" + +cd "$(git rev-parse --show-toplevel)" +mkdir -p build +cd build + +cat > myconfig-minimal.hpp << EOF +#define ELECTROSTATICS +#define LENNARD_JONES +#define MASS +EOF + +rm -f benchmarks.log +cat > benchmarks.csv << EOF +"commit","config","script","arguments","cores","MPI","mean","ci","steps_per_tick","duration","E1","E2","E3" +EOF + +for commit in ${commits} +do + rm -rf src/ maintainer/ + git checkout ${commit} ../src + cmake .. -DWITH_BENCHMARKS=ON + for config in ${configs} + do + cp ${config} myconfig.hpp + make -j$(nproc) + rm -f benchmarks.csv.part + touch benchmarks.csv.part + make benchmark 2>&1 | tee benchmarks.log + sed -ri "s/^/\"${commit}\",\"$(basename ${config})\",/" benchmarks.csv.part + cat benchmarks.csv.part >> benchmarks.csv + done +done + +git checkout HEAD ../src + From 141c79652c6a4c0154f757d17b1359c737ba98ba Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Thu, 22 Nov 2018 17:49:06 +0100 Subject: [PATCH 02/29] Document and tweak LJ benchmarks --- maintainer/benchmarks/lj.py | 2 +- maintainer/benchmarks/suite.sh | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index 275690ca2f3..4c771c93512 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -47,7 +47,7 @@ if sys.argv[2] == 'gas': density = 0.02 elif sys.argv[2] == 'liquid': - density = 0.30 + density = 0.50 else: density = float(sys.argv[2]) assert density > 0, "density must be a positive number" diff --git a/maintainer/benchmarks/suite.sh b/maintainer/benchmarks/suite.sh index db9740c77a8..366101f5637 100644 --- a/maintainer/benchmarks/suite.sh +++ b/maintainer/benchmarks/suite.sh @@ -1,39 +1,49 @@ #!/bin/bash +# list of commits to benchmark commits="c1d850ef3c4 c72cb35c3c5 eaa84cd1c92" -configs="myconfig-minimal.hpp ../src/core/myconfig-default.hpp ../maintainer/configs/maxset.hpp" cd "$(git rev-parse --show-toplevel)" mkdir -p build cd build +# manage headers files with different features +configs="myconfig-minimal.hpp myconfig-default.hpp myconfig-maxset.hpp" cat > myconfig-minimal.hpp << EOF #define ELECTROSTATICS #define LENNARD_JONES #define MASS EOF +cp ../src/core/myconfig-default.hpp myconfig-default.hpp +sed 's/#define ADDITIONAL_CHECKS//' ../maintainer/configs/maxset.hpp > myconfig-maxset.hpp +# disable features interfering with LJ benchmarks +sed -ri 's/#define +(THOLE|COLLISION_DETECTION|GHOSTS_HAVE_BONDS)/\/\/#define \1/' myconfig-*.hpp +# output files rm -f benchmarks.log cat > benchmarks.csv << EOF "commit","config","script","arguments","cores","MPI","mean","ci","steps_per_tick","duration","E1","E2","E3" EOF +# run benchmarks for commit in ${commits} do rm -rf src/ maintainer/ - git checkout ${commit} ../src + git checkout ${commit} ../src ../libs cmake .. -DWITH_BENCHMARKS=ON for config in ${configs} do + echo "### ${commit} ${config}" >> benchmarks.log cp ${config} myconfig.hpp make -j$(nproc) rm -f benchmarks.csv.part touch benchmarks.csv.part - make benchmark 2>&1 | tee benchmarks.log + make benchmark 2>&1 | tee -a benchmarks.log sed -ri "s/^/\"${commit}\",\"$(basename ${config})\",/" benchmarks.csv.part cat benchmarks.csv.part >> benchmarks.csv done done -git checkout HEAD ../src +# restore files +git checkout HEAD ../src ../libs From ea315a13a41707dadeaf210dcc718905411308ac Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Thu, 22 Nov 2018 19:19:30 +0100 Subject: [PATCH 03/29] Patch style --- maintainer/benchmarks/lj.py | 64 ++++++++++++++++++++---------------- maintainer/benchmarks/p3m.py | 35 +++++++++----------- 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index 4c771c93512..187303e7e3d 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -32,10 +32,10 @@ # Interaction parameters (repulsive Lennard-Jones) ############################################################# -lj_eps = 1.0 # LJ epsilon -lj_sig = 1.0 # particle diameter -lj_cap = 20. # force cap -lj_cut = lj_sig * 2**(1. / 6.) # cutoff distance +lj_eps = 1.0 # LJ epsilon +lj_sig = 1.0 # particle diameter +lj_cap = 20. # force cap +lj_cut = lj_sig * 2**(1. / 6.) # cutoff distance # System parameters ############################################################# @@ -52,7 +52,7 @@ density = float(sys.argv[2]) assert density > 0, "density must be a positive number" assert density < np.pi / (3 * np.sqrt(2)), \ - "density exceeds the physical limit of sphere packing (~0.74)" + "density exceeds the physical limit of sphere packing (~0.74)" mode = "benchmark" if len(sys.argv) == 4: assert sys.argv[3] == "--visualize" @@ -67,18 +67,17 @@ measurement_steps = int(np.round(5e6 / n_part_per_core, -2)) assert(measurement_steps >= 100), \ - "{} steps per tick are too short".format(measurement_steps) + "{} steps per tick are too short".format(measurement_steps) # volume of N spheres with radius r: N * (4/3*pi*r^3) -box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1./3.) +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1. / 3.) # System ############################################################# -system = espressomd.System(box_l=3*(box_l,)) +system = espressomd.System(box_l=3 * (box_l,)) # PRNG seeds ############################################################# system.random_number_generator_state = list(range( - nproc * (system._get_PRNG_state_size() + 1))) -#system.random_number_generator_state = list(range(len(system.random_number_generator_state))) + nproc * (system._get_PRNG_state_size() + 1))) np.random.seed(1) # Integration parameters ############################################################# @@ -110,21 +109,32 @@ # Warmup Integration # ############################################################# -system.integrator.set_steepest_descent(f_max=0, gamma=0.001, max_displacement=0.01) +system.integrator.set_steepest_descent( + f_max=0, + gamma=0.001, + max_displacement=0.01) # warmup while system.analysis.energy()["total"] > 10 * n_part: - print('minimization: {:.1f}'.format(system.analysis.energy()["total"])) - system.integrator.run(10) + print('minimization: {:.1f}'.format(system.analysis.energy()["total"])) + system.integrator.run(10) print() system.integrator.set_vv() system.thermostat.set_langevin(kT=1.0, gamma=1.0) # tune skin -print('tune: {}'.format(system.cell_system.tune_skin(min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) +print('tune: {}'.format(system.cell_system.tune_skin( + min_skin=0.2, + max_skin=1, + tol=0.05, + int_steps=100))) system.integrator.run(min(30 * measurement_steps, 60000)) -print('tune: {}'.format(system.cell_system.tune_skin(min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) +print('tune: {}'.format(system.cell_system.tune_skin( + min_skin=0.2, + max_skin=1, + tol=0.05, + int_steps=100))) print(system.non_bonded_inter[0, 0].lennard_jones) @@ -145,9 +155,9 @@ tick = time() system.integrator.run(measurement_steps) tock = time() - t = (tock-tick) / measurement_steps - print('step {}, time = {:.2e}, verlet: {:.2f}'.format(i, t, - system.cell_system.get_state()["verlet_reuse"])) + t = (tock - tick) / measurement_steps + print('step {}, time = {:.2e}, verlet: {:.2f}' + .format(i, t, system.cell_system.get_state()["verlet_reuse"])) all_t.append(t) main_tock = time() # average time @@ -163,13 +173,13 @@ # write report report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( - script=os.path.basename(sys.argv[0]), - arguments=" ".join(map(str, sys.argv[1:])), - cores=nproc, dur=main_tock - main_tick, n=measurement_steps, - mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, - E1=system.analysis.energy()["total"], - E2=system.analysis.energy()["kinetic"], - E3=system.analysis.energy()["non_bonded"])) + script=os.path.basename(sys.argv[0]), + arguments=" ".join(map(str, sys.argv[1:])), + cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, + E1=system.analysis.energy()["total"], + E2=system.analysis.energy()["kinetic"], + E3=system.analysis.energy()["non_bonded"])) if not os.path.isfile(report_path): report = ('"script","arguments","cores","MPI","mean","ci",' '"steps_per_tick","duration","E1","E2","E3"\n' + report) @@ -183,11 +193,9 @@ def main_thread(): while True: system.integrator.run(1) visualizer.update() - sleep(1/60.) # limit framerate to at most 60 FPS + sleep(1 / 60.) # limit framerate to at most 60 FPS t = Thread(target=main_thread) t.daemon = True t.start() visualizer.start() - - diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index b9cc111c995..5dde11a3207 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -33,7 +33,7 @@ # Interaction parameters (repulsive Lennard-Jones) ############################################################# -lj_cap = 20. # force cap +lj_cap = 20. # force cap species = ["Cl", "Na", "Solvent"] types = {"Cl": 0, "Na": 1, "Solvent": 2} charges = {"Cl": -1.0, "Na": 1.0, "Solvent": 0.0} @@ -66,14 +66,14 @@ measurement_steps = int(np.round(2e6 / n_part_per_core, -2)) assert(measurement_steps >= 100), \ - "{} steps per tick are too short".format(measurement_steps) + "{} steps per tick are too short".format(measurement_steps) # volume of N spheres with radius r: N * (4/3*pi*r^3) density = 0.25 if sim_type == "gas": lj_sig = lj_sigmas["Na"] + lj_sigmas["Cl"] else: lj_sig = lj_sigmas["Solvent"] -box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1./3.) +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1. / 3.) if sim_type == "gas": species = ["Cl", "Na"] @@ -96,13 +96,12 @@ # System ############################################################# -system = espressomd.System(box_l=3*(box_l,)) +system = espressomd.System(box_l=3 * (box_l,)) system.cell_system.set_domain_decomposition(use_verlet_lists=True) # PRNG seeds ############################################################# system.random_number_generator_state = list(range( - nproc * (system._get_PRNG_state_size() + 1))) -#system.random_number_generator_state = list(range(len(system.random_number_generator_state))) + nproc * (system._get_PRNG_state_size() + 1))) np.random.seed(1) # Integration parameters ############################################################# @@ -137,7 +136,7 @@ q=charges[t], type=types[t], mass=masses[t]) else: for i in range(int(n_part / 30.)): - for t in ["Na", "Cl"] + 28* ["Solvent"]: + for t in ["Na", "Cl"] + 28 * ["Solvent"]: system.part.add(pos=np.random.random(3) * system.box_l, q=charges[t], type=types[t], mass=masses[t]) @@ -177,9 +176,9 @@ tick = time() system.integrator.run(measurement_steps) tock = time() - t = (tock-tick) / measurement_steps - print('step {}, time = {:.2e}, verlet: {:.2f}'.format(i, t, - system.cell_system.get_state()["verlet_reuse"])) + t = (tock - tick) / measurement_steps + print('step {}, time = {:.2e}, verlet: {:.2f}' + .format(i, t, system.cell_system.get_state()["verlet_reuse"])) all_t.append(t) main_tock = time() # average time @@ -195,13 +194,13 @@ # write report report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( - script=os.path.basename(sys.argv[0]), - arguments=" ".join(map(str, sys.argv[1:])), - cores=nproc, dur=main_tock - main_tick, n=measurement_steps, - mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, - E1=system.analysis.energy()["total"], - E2=system.analysis.energy()["coulomb"], - E3=system.analysis.energy()["non_bonded"])) + script=os.path.basename(sys.argv[0]), + arguments=" ".join(map(str, sys.argv[1:])), + cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, + E1=system.analysis.energy()["total"], + E2=system.analysis.energy()["coulomb"], + E3=system.analysis.energy()["non_bonded"])) if not os.path.isfile(report_path): report = ('"script","arguments","cores","MPI","mean","ci",' '"steps_per_tick","duration","E1","E2","E3"\n' + report) @@ -211,5 +210,3 @@ # use visualizer visualizer = visualization.openGLLive(system) visualizer.run(1) - - From bb1f0189989ff68e576cd0fde2bcc2099d881264 Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Wed, 28 Nov 2018 18:06:30 +0100 Subject: [PATCH 04/29] Use reduced units and remove solvent, force cap --- maintainer/benchmarks/lj.py | 2 - maintainer/benchmarks/p3m.py | 87 +++++++++++++----------------------- 2 files changed, 30 insertions(+), 59 deletions(-) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index 187303e7e3d..a44d0dbc66d 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -34,7 +34,6 @@ lj_eps = 1.0 # LJ epsilon lj_sig = 1.0 # particle diameter -lj_cap = 20. # force cap lj_cut = lj_sig * 2**(1. / 6.) # cutoff distance # System parameters @@ -94,7 +93,6 @@ ############################################################# system.non_bonded_inter[0, 0].lennard_jones.set_params( epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") -system.force_cap = lj_cap print("LJ-parameters:") print(system.non_bonded_inter[0, 0].lennard_jones.get_params()) diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index 5dde11a3207..7de15783b4c 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -33,15 +33,15 @@ # Interaction parameters (repulsive Lennard-Jones) ############################################################# -lj_cap = 20. # force cap -species = ["Cl", "Na", "Solvent"] -types = {"Cl": 0, "Na": 1, "Solvent": 2} -charges = {"Cl": -1.0, "Na": 1.0, "Solvent": 0.0} -lj_sigmas = {"Cl": 3.85, "Na": 2.52, "Solvent": 1.8} -lj_epsilons = {"Cl": 192.45, "Na": 17.44, "Solvent": 50.0} -lj_cuts = {"Cl": 2.0 * lj_sigmas["Cl"], "Na": 2.0 * lj_sigmas["Na"], - "Solvent": 2.0 * lj_sigmas["Solvent"]} -masses = {"Cl": 35.453, "Na": 22.99, "Solvent": 18.0} +species = ["anion", "cation"] +types = {"anion": 0, "cation": 1} +charges = {"anion": -1.0, "cation": 1.0} +lj_sigmas = {"anion": 1.0, "cation": 1.0} +lj_epsilons = {"anion": 1.0, "cation": 1.0} +WCA_cut = 2.**(1. / 6.) +lj_cuts = {"anion": WCA_cut * lj_sigmas["anion"], + "cation": WCA_cut * lj_sigmas["cation"]} +masses = {"anion": 1.0, "cation": 1.0} # System parameters ############################################################# @@ -50,8 +50,7 @@ nproc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) n_part_per_core = int(sys.argv[1]) n_part = nproc * n_part_per_core - sim_type = sys.argv[2] - assert sim_type in ('solution', 'gas') + bjerrum_length = float(sys.argv[2]) mode = "benchmark" if len(sys.argv) == 4: assert sys.argv[3] == "--visualize" @@ -61,38 +60,16 @@ except (ValueError, IndexError) as err: print(err.message) print("\nUsage: [mpiexec -np ] pypresso lj.py " - " [--visualize]\n") + " [--visualize]\n") exit(1) -measurement_steps = int(np.round(2e6 / n_part_per_core, -2)) -assert(measurement_steps >= 100), \ +measurement_steps = int(np.round(5e5 / n_part_per_core, -1)) +assert(measurement_steps >= 50), \ "{} steps per tick are too short".format(measurement_steps) # volume of N spheres with radius r: N * (4/3*pi*r^3) density = 0.25 -if sim_type == "gas": - lj_sig = lj_sigmas["Na"] + lj_sigmas["Cl"] -else: - lj_sig = lj_sigmas["Solvent"] +lj_sig = (lj_sigmas["cation"] + lj_sigmas["anion"]) / 2 box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1. / 3.) -if sim_type == "gas": - species = ["Cl", "Na"] - -# electrostatics -# E = 1 /(4*pi*e_0*e_r)*q1*q2/r -# e_0 in F/m or C^2/N/m^2 -# E in N.M or J -Na = 6.0221408e23 # Avogadro's constant -epsilon_0 = 8.85419e-12 # vacuum permittivity -epsilon_r = 4.0 # relative permittivity -q = 1.6021766e-19 # elementary charge -# Coulomb prefactor in kJ/mol, using Angstroms -prefactor = 1 / (4 * np.pi * epsilon_0 * epsilon_r) * q**2 * Na * 1e-3 * 1e10 - -# temperature -kB = 1.38064852e-23 # Boltzmann's constant in J/K -kB_kjmol = kB * Na / 1000 # Boltzmann's constant in kJ/mol/K -SI_temperature = 400.0 -temperature = SI_temperature * kB_kjmol # System ############################################################# @@ -118,27 +95,23 @@ ############################################################# for i in range(len(species)): + ion1 = species[i] for j in range(i, len(species)): - s = [species[i], species[j]] - lj_sig = (lj_sigmas[s[0]] + lj_sigmas[s[1]]) * 0.5 - lj_cut = (lj_cuts[s[0]] + lj_cuts[s[1]]) * 0.5 - lj_eps = (lj_epsilons[s[0]] * lj_epsilons[s[1]])**0.5 - system.non_bonded_inter[types[s[0]], types[s[1]]].lennard_jones.set_params( - epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") + ion2 = species[j] + lj_sig = (lj_sigmas[ion1] + lj_sigmas[ion2]) / 2 + lj_cut = (lj_cuts[ion1] + lj_cuts[ion2]) / 2 + lj_eps = (lj_epsilons[ion1] * lj_epsilons[ion2])**(1. / 2.) + system.non_bonded_inter[types[ion1], + types[ion2]].lennard_jones.set_params( + epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") # Particle setup ############################################################# -if sim_type == "gas": - for i in range(int(n_part / 2.)): - for t in ["Na", "Cl"]: - system.part.add(pos=np.random.random(3) * system.box_l, - q=charges[t], type=types[t], mass=masses[t]) -else: - for i in range(int(n_part / 30.)): - for t in ["Na", "Cl"] + 28 * ["Solvent"]: - system.part.add(pos=np.random.random(3) * system.box_l, - q=charges[t], type=types[t], mass=masses[t]) +for i in range(0, n_part, len(species)): + for t in species: + system.part.add(pos=np.random.random(3) * system.box_l, + q=charges[t], type=types[t], mass=masses[t]) ############################################################# # Warmup Integration # @@ -147,17 +120,17 @@ energy = system.analysis.energy() print("Before Minimization: E_total = {}".format(energy['total'])) system.minimize_energy.init(f_max=1000, gamma=30.0, - max_steps=1000, max_displacement=0.01) + max_steps=1000, max_displacement=0.05) +system.minimize_energy.minimize() system.minimize_energy.minimize() energy = system.analysis.energy() print("After Minimization: E_total = {}".format(energy['total'])) print("Tune p3m") -p3m = electrostatics.P3M(prefactor=prefactor, accuracy=1e-1) +p3m = electrostatics.P3M(prefactor=bjerrum_length, accuracy=1e-4) system.actors.add(p3m) -system.thermostat.set_langevin(kT=temperature, gamma=2.0) - +system.thermostat.set_langevin(kT=1.0, gamma=1.0) if mode == 'benchmark': report_path = 'benchmarks.csv' From 495fed40fa45b499e47f325a3a1bee9782bb4294 Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Wed, 28 Nov 2018 21:17:57 +0100 Subject: [PATCH 05/29] Use argparse for cmd interface --- maintainer/benchmarks/CMakeLists.txt | 27 ++++---- maintainer/benchmarks/lj.py | 94 ++++++++++++++------------- maintainer/benchmarks/p3m.py | 96 ++++++++++++++++------------ 3 files changed, 119 insertions(+), 98 deletions(-) diff --git a/maintainer/benchmarks/CMakeLists.txt b/maintainer/benchmarks/CMakeLists.txt index 69b49633afa..0089c64dc72 100644 --- a/maintainer/benchmarks/CMakeLists.txt +++ b/maintainer/benchmarks/CMakeLists.txt @@ -16,13 +16,16 @@ function(PYTHON_BENCHMARK) cmake_parse_arguments(BENCHMARK "" "FILE;RUN_WITH_MPI;MIN_NUM_PROC;MAX_NUM_PROC" "ARGUMENTS;DEPENDENCIES" ${ARGN}) get_filename_component(BENCHMARK_NAME ${BENCHMARK_FILE} NAME_WE) foreach(argument IN LISTS BENCHMARK_ARGUMENTS) - set(BENCHMARK_NAME "${BENCHMARK_NAME}_${argument}") + string(REGEX REPLACE "[^-a-zA-Z0-9_\\.]+" "_" argument ${argument}) + string(REGEX REPLACE "^[-_]+" "" argument ${argument}) + set(BENCHMARK_NAME "${BENCHMARK_NAME}__${argument}") endforeach(argument) configure_file(${BENCHMARK_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${BENCHMARK_FILE}) foreach(dependency IN LISTS BENCHMARK_DEPENDENCIES) configure_file(${dependency} ${CMAKE_CURRENT_BINARY_DIR}/${dependency}) endforeach(dependency) set(BENCHMARK_FILE "${CMAKE_CURRENT_BINARY_DIR}/${BENCHMARK_FILE}") + list(APPEND BENCHMARK_ARGUMENTS "--output=${CMAKE_BINARY_DIR}/benchmarks.csv.part") # default values if (NOT DEFINED BENCHMARK_RUN_WITH_MPI) @@ -54,25 +57,23 @@ function(PYTHON_BENCHMARK) endif() list(REMOVE_AT BENCHMARK_CONFIGURATIONS 0) foreach(nproc IN LISTS BENCHMARK_CONFIGURATIONS) - add_custom_target(${BENCHMARK_NAME}_parallel_${nproc} + add_custom_target(${BENCHMARK_NAME}__parallel_${nproc} ${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE} ${MPIEXEC_NUMPROC_FLAG} ${nproc} ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) - add_dependencies(benchmark_python ${BENCHMARK_NAME}_parallel_${nproc}) + add_dependencies(benchmark_python ${BENCHMARK_NAME}__parallel_${nproc}) endforeach(nproc) else() - add_custom_target(${BENCHMARK_NAME}_serial + add_custom_target(${BENCHMARK_NAME}__serial ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) - add_dependencies(benchmark_python ${BENCHMARK_NAME}_serial) + add_dependencies(benchmark_python ${BENCHMARK_NAME}__serial) endif() endfunction(PYTHON_BENCHMARK) -python_benchmark(FILE lj.py ARGUMENTS 1000 liquid) -python_benchmark(FILE lj.py ARGUMENTS 1000 gas) -python_benchmark(FILE lj.py ARGUMENTS 10000 liquid) -python_benchmark(FILE lj.py ARGUMENTS 10000 gas) -python_benchmark(FILE p3m.py ARGUMENTS 1000 solution) -python_benchmark(FILE p3m.py ARGUMENTS 1000 gas) -python_benchmark(FILE p3m.py ARGUMENTS 10000 solution) -python_benchmark(FILE p3m.py ARGUMENTS 10000 gas) +python_benchmark(FILE lj.py ARGUMENTS "--particles_per_core=1000;--volume_fraction=0.50") +python_benchmark(FILE lj.py ARGUMENTS "--particles_per_core=1000;--volume_fraction=0.02") +python_benchmark(FILE lj.py ARGUMENTS "--particles_per_core=10000;--volume_fraction=0.50") +python_benchmark(FILE lj.py ARGUMENTS "--particles_per_core=10000;--volume_fraction=0.02") +python_benchmark(FILE p3m.py ARGUMENTS "--particles_per_core=1000;--volume_fraction=0.25;--bjerrum_length=4") +python_benchmark(FILE p3m.py ARGUMENTS "--particles_per_core=10000;--volume_fraction=0.25;--bjerrum_length=4") add_dependencies(benchmark benchmark_python) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index a44d0dbc66d..e23f27a237f 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -20,9 +20,44 @@ import os import sys import numpy as np -import espressomd from time import time, sleep +import argparse + +parser = argparse.ArgumentParser(description="Benchmark LJ simulations. " + "Save the results to a CSV file.") +parser.add_argument("--particles_per_core", metavar="N", action="store", + type=int, default=1000, required=False, + help="Number of particles in the simulation box") +parser.add_argument("--volume_fraction", metavar="FRAC", action="store", + type=float, default=0.50, required=False, + help="Fraction of the simulation box volume occupied by " + "particles (range: [0.01-0.74], default: 0.50)") +group = parser.add_mutually_exclusive_group() +group.add_argument("--output", metavar="FILEPATH", action="store", + type=str, required=False, + help="Output file (default: benchmarks.csv)") +group.add_argument("--visualizer", action="store_true", + help="Starts the visualizer (for debugging purposes)") + +args = parser.parse_args() + +# process and check arguments +n_proc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) +n_part = n_proc * args.particles_per_core +measurement_steps = int(np.round(5e6 / args.particles_per_core, -2)) +assert args.volume_fraction > 0, "volume_fraction must be a positive number" +assert args.volume_fraction < np.pi / (3 * np.sqrt(2)), \ + "volume_fraction exceeds the physical limit of sphere packing (~0.74)" +if not args.visualizer: + assert(measurement_steps >= 100), \ + "{} steps per tick are too short".format(measurement_steps) + + +import espressomd from espressomd import thermostat +if args.visualizer: + from espressomd import visualization + from threading import Thread required_features = ["LENNARD_JONES"] espressomd.assert_features(required_features) @@ -39,36 +74,9 @@ # System parameters ############################################################# -try: - nproc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) - n_part_per_core = int(sys.argv[1]) - n_part = nproc * n_part_per_core - if sys.argv[2] == 'gas': - density = 0.02 - elif sys.argv[2] == 'liquid': - density = 0.50 - else: - density = float(sys.argv[2]) - assert density > 0, "density must be a positive number" - assert density < np.pi / (3 * np.sqrt(2)), \ - "density exceeds the physical limit of sphere packing (~0.74)" - mode = "benchmark" - if len(sys.argv) == 4: - assert sys.argv[3] == "--visualize" - mode = "visualization" - from espressomd import visualization - from threading import Thread -except (ValueError, IndexError) as err: - print(err.message) - print("\nUsage: [mpiexec -np ] pypresso lj.py " - " [--visualize]\n") - exit(1) - -measurement_steps = int(np.round(5e6 / n_part_per_core, -2)) -assert(measurement_steps >= 100), \ - "{} steps per tick are too short".format(measurement_steps) # volume of N spheres with radius r: N * (4/3*pi*r^3) -box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1. / 3.) +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 + / args.volume_fraction)**(1. / 3.) # System ############################################################# @@ -76,7 +84,7 @@ # PRNG seeds ############################################################# system.random_number_generator_state = list(range( - nproc * (system._get_PRNG_state_size() + 1))) + n_proc * (system._get_PRNG_state_size() + 1))) np.random.seed(1) # Integration parameters ############################################################# @@ -114,7 +122,7 @@ # warmup while system.analysis.energy()["total"] > 10 * n_part: - print('minimization: {:.1f}'.format(system.analysis.energy()["total"])) + print("minimization: {:.1f}".format(system.analysis.energy()["total"])) system.integrator.run(10) print() system.integrator.set_vv() @@ -122,13 +130,13 @@ system.thermostat.set_langevin(kT=1.0, gamma=1.0) # tune skin -print('tune: {}'.format(system.cell_system.tune_skin( +print("tune: {}".format(system.cell_system.tune_skin( min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) system.integrator.run(min(30 * measurement_steps, 60000)) -print('tune: {}'.format(system.cell_system.tune_skin( +print("tune: {}".format(system.cell_system.tune_skin( min_skin=0.2, max_skin=1, tol=0.05, @@ -136,11 +144,7 @@ print(system.non_bonded_inter[0, 0].lennard_jones) -if mode == 'benchmark': - report_path = 'benchmarks.csv' - if '${CMAKE_BINARY_DIR}'[0] != '$': # CMake variable - report_path = '${CMAKE_BINARY_DIR}/benchmarks.csv.part' - +if not args.visualizer: # print initial energies energies = system.analysis.energy() print(energies) @@ -154,7 +158,7 @@ system.integrator.run(measurement_steps) tock = time() t = (tock - tick) / measurement_steps - print('step {}, time = {:.2e}, verlet: {:.2f}' + print("step {}, time = {:.2e}, verlet: {:.2f}" .format(i, t, system.cell_system.get_state()["verlet_reuse"])) all_t.append(t) main_tock = time() @@ -169,19 +173,19 @@ print(energies) # write report + cmd = " ".join(x for x in sys.argv[1:] if not x.startswith("--output")) report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( - script=os.path.basename(sys.argv[0]), - arguments=" ".join(map(str, sys.argv[1:])), - cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + script=os.path.basename(sys.argv[0]), arguments=cmd, + cores=n_proc, dur=main_tock - main_tick, n=measurement_steps, mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, E1=system.analysis.energy()["total"], E2=system.analysis.energy()["kinetic"], E3=system.analysis.energy()["non_bonded"])) - if not os.path.isfile(report_path): + if not os.path.isfile(args.output): report = ('"script","arguments","cores","MPI","mean","ci",' '"steps_per_tick","duration","E1","E2","E3"\n' + report) - with open(report_path, 'a') as f: + with open(args.output, "a") as f: f.write(report) else: # use visualizer diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index 7de15783b4c..b73c9c020d3 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -20,10 +20,49 @@ import os import sys import numpy as np +from time import time +import argparse + +parser = argparse.ArgumentParser(description="Benchmark P3M simulations. " + "Save the results to a CSV file.") +parser.add_argument("--particles_per_core", metavar="N", action="store", + type=int, default=1000, required=False, + help="Number of particles in the simulation box") +parser.add_argument("--volume_fraction", metavar="FRAC", action="store", + type=float, default=0.25, required=False, + help="Fraction of the simulation box volume occupied by " + "particles (range: [0.01-0.74], default: 0.25)") +parser.add_argument("--bjerrum_length", metavar="LENGTH", action="store", + type=float, default=4., required=False, + help="Bjerrum length (default: 4)") +group = parser.add_mutually_exclusive_group() +group.add_argument("--output", metavar="FILEPATH", action="store", + type=str, required=False, + help="Output file (default: benchmarks.csv)") +group.add_argument("--visualizer", action="store_true", + help="Starts the visualizer (for debugging purposes)") + +args = parser.parse_args() + +# process and check arguments +n_proc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) +n_part = n_proc * args.particles_per_core +measurement_steps = int(np.round(5e5 / args.particles_per_core, -1)) +assert args.bjerrum_length > 0, "bjerrum_length must be a positive number" +assert args.volume_fraction > 0, "volume_fraction must be a positive number" +assert args.volume_fraction < np.pi / (3 * np.sqrt(2)), \ + "volume_fraction exceeds the physical limit of sphere packing (~0.74)" +if not args.visualizer: + assert(measurement_steps >= 50), \ + "{} steps per tick are too short".format(measurement_steps) + + import espressomd -from time import time, sleep from espressomd import thermostat from espressomd import electrostatics +if args.visualizer: + from espressomd import visualization + from threading import Thread required_features = ["ELECTROSTATICS", "LENNARD_JONES", "MASS"] espressomd.assert_features(required_features) @@ -40,36 +79,16 @@ lj_epsilons = {"anion": 1.0, "cation": 1.0} WCA_cut = 2.**(1. / 6.) lj_cuts = {"anion": WCA_cut * lj_sigmas["anion"], - "cation": WCA_cut * lj_sigmas["cation"]} + "cation": WCA_cut * lj_sigmas["cation"]} masses = {"anion": 1.0, "cation": 1.0} # System parameters ############################################################# -try: - nproc = int(os.environ.get("OMPI_COMM_WORLD_SIZE", 1)) - n_part_per_core = int(sys.argv[1]) - n_part = nproc * n_part_per_core - bjerrum_length = float(sys.argv[2]) - mode = "benchmark" - if len(sys.argv) == 4: - assert sys.argv[3] == "--visualize" - mode = "visualization" - from espressomd import visualization - from threading import Thread -except (ValueError, IndexError) as err: - print(err.message) - print("\nUsage: [mpiexec -np ] pypresso lj.py " - " [--visualize]\n") - exit(1) - -measurement_steps = int(np.round(5e5 / n_part_per_core, -1)) -assert(measurement_steps >= 50), \ - "{} steps per tick are too short".format(measurement_steps) # volume of N spheres with radius r: N * (4/3*pi*r^3) -density = 0.25 lj_sig = (lj_sigmas["cation"] + lj_sigmas["anion"]) / 2 -box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 / density)**(1. / 3.) +box_l = (n_part * 4. / 3. * np.pi * (lj_sig / 2.)**3 + / args.volume_fraction)**(1. / 3.) # System ############################################################# @@ -78,7 +97,7 @@ # PRNG seeds ############################################################# system.random_number_generator_state = list(range( - nproc * (system._get_PRNG_state_size() + 1))) + n_proc * (system._get_PRNG_state_size() + 1))) np.random.seed(1) # Integration parameters ############################################################# @@ -102,8 +121,8 @@ lj_cut = (lj_cuts[ion1] + lj_cuts[ion2]) / 2 lj_eps = (lj_epsilons[ion1] * lj_epsilons[ion2])**(1. / 2.) system.non_bonded_inter[types[ion1], - types[ion2]].lennard_jones.set_params( - epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") + types[ion2]].lennard_jones.set_params( + epsilon=lj_eps, sigma=lj_sig, cutoff=lj_cut, shift="auto") # Particle setup ############################################################# @@ -118,25 +137,22 @@ ############################################################# energy = system.analysis.energy() -print("Before Minimization: E_total = {}".format(energy['total'])) +print("Before Minimization: E_total = {}".format(energy["total"])) system.minimize_energy.init(f_max=1000, gamma=30.0, max_steps=1000, max_displacement=0.05) system.minimize_energy.minimize() system.minimize_energy.minimize() energy = system.analysis.energy() -print("After Minimization: E_total = {}".format(energy['total'])) +print("After Minimization: E_total = {}".format(energy["total"])) print("Tune p3m") -p3m = electrostatics.P3M(prefactor=bjerrum_length, accuracy=1e-4) +p3m = electrostatics.P3M(prefactor=args.bjerrum_length, accuracy=1e-4) system.actors.add(p3m) system.thermostat.set_langevin(kT=1.0, gamma=1.0) -if mode == 'benchmark': - report_path = 'benchmarks.csv' - if '${CMAKE_BINARY_DIR}'[0] != '$': # CMake variable - report_path = '${CMAKE_BINARY_DIR}/benchmarks.csv.part' +if not args.visualizer: # print initial energies energies = system.analysis.energy() print(energies) @@ -150,7 +166,7 @@ system.integrator.run(measurement_steps) tock = time() t = (tock - tick) / measurement_steps - print('step {}, time = {:.2e}, verlet: {:.2f}' + print("step {}, time = {:.2e}, verlet: {:.2f}" .format(i, t, system.cell_system.get_state()["verlet_reuse"])) all_t.append(t) main_tock = time() @@ -165,19 +181,19 @@ print(energies) # write report + cmd = " ".join(x for x in sys.argv[1:] if not x.startswith("--output")) report = ('"{script}","{arguments}",{cores},"{mpi}",{mean:.3e},' '{ci:.3e},{n},{dur:.1f},{E1:.5e},{E2:.5e},{E3:.5e}\n'.format( - script=os.path.basename(sys.argv[0]), - arguments=" ".join(map(str, sys.argv[1:])), - cores=nproc, dur=main_tock - main_tick, n=measurement_steps, + script=os.path.basename(sys.argv[0]), arguments=cmd, + cores=n_proc, dur=main_tock - main_tick, n=measurement_steps, mpi="OMPI_COMM_WORLD_SIZE" in os.environ, mean=avg, ci=ci, E1=system.analysis.energy()["total"], E2=system.analysis.energy()["coulomb"], E3=system.analysis.energy()["non_bonded"])) - if not os.path.isfile(report_path): + if not os.path.isfile(args.output): report = ('"script","arguments","cores","MPI","mean","ci",' '"steps_per_tick","duration","E1","E2","E3"\n' + report) - with open(report_path, 'a') as f: + with open(args.output, "a") as f: f.write(report) else: # use visualizer From fa834e033e37df2fcb3bdedd49a58223f35b839c Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Wed, 28 Nov 2018 21:53:58 +0100 Subject: [PATCH 06/29] Split benchmarking script in two files runner.sh runs benchmarks on the currently checked out version suite.sh runs runner.sh on different commits --- maintainer/benchmarks/runner.sh | 40 +++++++++++++++++++++++++++++++++ maintainer/benchmarks/suite.sh | 35 +++++++---------------------- 2 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 maintainer/benchmarks/runner.sh diff --git a/maintainer/benchmarks/runner.sh b/maintainer/benchmarks/runner.sh new file mode 100644 index 00000000000..ba9576945d7 --- /dev/null +++ b/maintainer/benchmarks/runner.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +cd "$(git rev-parse --show-toplevel)" +mkdir -p build +cd build + +# manage headers files with different features +configs="myconfig-minimal.hpp myconfig-default.hpp myconfig-maxset.hpp" +cat > myconfig-minimal.hpp << EOF +#define ELECTROSTATICS +#define LENNARD_JONES +#define MASS +EOF +cp ../src/core/myconfig-default.hpp myconfig-default.hpp +sed 's/#define ADDITIONAL_CHECKS//' ../maintainer/configs/maxset.hpp > myconfig-maxset.hpp +# disable features interfering with LJ benchmarks +sed -ri 's/#define +(THOLE|COLLISION_DETECTION|GHOSTS_HAVE_BONDS)/\/\/#define \1/' myconfig-*.hpp + +# prepare build area +rm -rf src/ maintainer/ +cmake -DWITH_BENCHMARKS=ON .. +cat > benchmarks.csv << EOF +"config","script","arguments","cores","MPI","mean","ci","steps_per_tick","duration","E1","E2","E3" +EOF + +# run benchmarks +for config in ${configs} +do + echo "### ${config}" >> benchmarks.log + cp ${config} myconfig.hpp + make -j$(nproc) + rm -f benchmarks.csv.part + touch benchmarks.csv.part + make benchmark 2>&1 | tee -a benchmarks.log + sed -ri "s/^/\"$(basename ${config})\",/" benchmarks.csv.part + cat benchmarks.csv.part >> benchmarks.csv +done + +rm benchmarks.csv.part + diff --git a/maintainer/benchmarks/suite.sh b/maintainer/benchmarks/suite.sh index 366101f5637..0c4604b46ce 100644 --- a/maintainer/benchmarks/suite.sh +++ b/maintainer/benchmarks/suite.sh @@ -7,43 +7,24 @@ cd "$(git rev-parse --show-toplevel)" mkdir -p build cd build -# manage headers files with different features -configs="myconfig-minimal.hpp myconfig-default.hpp myconfig-maxset.hpp" -cat > myconfig-minimal.hpp << EOF -#define ELECTROSTATICS -#define LENNARD_JONES -#define MASS -EOF -cp ../src/core/myconfig-default.hpp myconfig-default.hpp -sed 's/#define ADDITIONAL_CHECKS//' ../maintainer/configs/maxset.hpp > myconfig-maxset.hpp -# disable features interfering with LJ benchmarks -sed -ri 's/#define +(THOLE|COLLISION_DETECTION|GHOSTS_HAVE_BONDS)/\/\/#define \1/' myconfig-*.hpp - -# output files +# prepare output files rm -f benchmarks.log -cat > benchmarks.csv << EOF +cat > benchmarks_suite.csv << EOF "commit","config","script","arguments","cores","MPI","mean","ci","steps_per_tick","duration","E1","E2","E3" EOF # run benchmarks for commit in ${commits} do - rm -rf src/ maintainer/ + echo "### commit ${commit}" >> benchmarks.log git checkout ${commit} ../src ../libs - cmake .. -DWITH_BENCHMARKS=ON - for config in ${configs} - do - echo "### ${commit} ${config}" >> benchmarks.log - cp ${config} myconfig.hpp - make -j$(nproc) - rm -f benchmarks.csv.part - touch benchmarks.csv.part - make benchmark 2>&1 | tee -a benchmarks.log - sed -ri "s/^/\"${commit}\",\"$(basename ${config})\",/" benchmarks.csv.part - cat benchmarks.csv.part >> benchmarks.csv - done + bash ../maintainer/benchmarks/runner.sh + sed -ri "s/^/\"${commit}\",/" benchmarks.csv + tail -n +2 benchmarks.csv >> benchmarks_suite.csv done +rm benchmarks.csv + # restore files git checkout HEAD ../src ../libs From 7c9e934ef45b0aff47a19232622d72c79f8033af Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Fri, 30 Nov 2018 11:21:44 +0100 Subject: [PATCH 07/29] Run benchmarks through CTest Benchmarks are now created in CMake using add_test(). Failing benchmarks no longer break the runner.sh and suite.sh scripts. Error messages are still visible. --- maintainer/benchmarks/CMakeLists.txt | 35 ++++++++++++++++++++-------- maintainer/benchmarks/lj.py | 2 +- maintainer/benchmarks/p3m.py | 2 +- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/maintainer/benchmarks/CMakeLists.txt b/maintainer/benchmarks/CMakeLists.txt index 0089c64dc72..c438d02aaae 100644 --- a/maintainer/benchmarks/CMakeLists.txt +++ b/maintainer/benchmarks/CMakeLists.txt @@ -1,4 +1,8 @@ -ProcessorCount(NP) +if(NOT DEFINED TEST_NP) + include(ProcessorCount) + ProcessorCount(NP) + math(EXPR TEST_NP "${NP}/2 + 1") +endif() if(EXISTS ${MPIEXEC}) # OpenMPI 3.0 and higher checks the number of processes against the number of CPUs @@ -10,8 +14,6 @@ if(EXISTS ${MPIEXEC}) endif() endif() -add_custom_target(benchmark_python) - function(PYTHON_BENCHMARK) cmake_parse_arguments(BENCHMARK "" "FILE;RUN_WITH_MPI;MIN_NUM_PROC;MAX_NUM_PROC" "ARGUMENTS;DEPENDENCIES" ${ARGN}) get_filename_component(BENCHMARK_NAME ${BENCHMARK_FILE} NAME_WE) @@ -57,15 +59,15 @@ function(PYTHON_BENCHMARK) endif() list(REMOVE_AT BENCHMARK_CONFIGURATIONS 0) foreach(nproc IN LISTS BENCHMARK_CONFIGURATIONS) - add_custom_target(${BENCHMARK_NAME}__parallel_${nproc} - ${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE} ${MPIEXEC_NUMPROC_FLAG} ${nproc} - ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) - add_dependencies(benchmark_python ${BENCHMARK_NAME}__parallel_${nproc}) + add_test(NAME benchmark__${BENCHMARK_NAME}__parallel_${nproc} + COMMAND ${MPIEXEC} ${MPIEXEC_OVERSUBSCRIBE} ${MPIEXEC_NUMPROC_FLAG} ${nproc} + ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS} + CONFIGURATIONS "parallel") endforeach(nproc) else() - add_custom_target(${BENCHMARK_NAME}__serial - ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS}) - add_dependencies(benchmark_python ${BENCHMARK_NAME}__serial) + add_test(NAME benchmark__${BENCHMARK_NAME}__serial + COMMAND ${CMAKE_BINARY_DIR}/pypresso ${BENCHMARK_FILE} ${BENCHMARK_ARGUMENTS} + CONFIGURATIONS "serial") endif() endfunction(PYTHON_BENCHMARK) @@ -76,4 +78,17 @@ python_benchmark(FILE lj.py ARGUMENTS "--particles_per_core=10000;--volume_fract python_benchmark(FILE p3m.py ARGUMENTS "--particles_per_core=1000;--volume_fraction=0.25;--bjerrum_length=4") python_benchmark(FILE p3m.py ARGUMENTS "--particles_per_core=10000;--volume_fraction=0.25;--bjerrum_length=4") +add_custom_target(benchmark_python_serial COMMAND ${CMAKE_CTEST_COMMAND} $(ARGS) -C serial --output-on-failure) +add_dependencies(benchmark_python_serial pypresso) + +add_custom_target(benchmark_python_parallel COMMAND ${CMAKE_CTEST_COMMAND} $(ARGS) -C parallel --output-on-failure) +add_dependencies(benchmark_python_parallel pypresso) + +add_custom_target(benchmark_python) +if(EXISTS ${MPIEXEC}) + add_dependencies(benchmark_python pypresso benchmark_python_parallel) +else() + add_dependencies(benchmark_python pypresso benchmark_python_serial) +endif() + add_dependencies(benchmark benchmark_python) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index e23f27a237f..a53bad6472d 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -34,7 +34,7 @@ "particles (range: [0.01-0.74], default: 0.50)") group = parser.add_mutually_exclusive_group() group.add_argument("--output", metavar="FILEPATH", action="store", - type=str, required=False, + type=str, required=False, default="benchmarks.csv", help="Output file (default: benchmarks.csv)") group.add_argument("--visualizer", action="store_true", help="Starts the visualizer (for debugging purposes)") diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index b73c9c020d3..3d6476c59c9 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -37,7 +37,7 @@ help="Bjerrum length (default: 4)") group = parser.add_mutually_exclusive_group() group.add_argument("--output", metavar="FILEPATH", action="store", - type=str, required=False, + type=str, required=False, default="benchmarks.csv", help="Output file (default: benchmarks.csv)") group.add_argument("--visualizer", action="store_true", help="Starts the visualizer (for debugging purposes)") From bbfa2067eeff58719885edf4fd24912ef3e93b8c Mon Sep 17 00:00:00 2001 From: Jean-Noel Grad Date: Fri, 30 Nov 2018 19:00:13 +0100 Subject: [PATCH 08/29] P3M: tune skin, particle type 0 --- maintainer/benchmarks/lj.py | 16 +++++----------- maintainer/benchmarks/p3m.py | 9 +++++++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index a53bad6472d..5bb4a1f11b3 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -64,7 +64,7 @@ print(espressomd.features()) -# Interaction parameters (repulsive Lennard-Jones) +# Interaction parameters (Lennard-Jones) ############################################################# lj_eps = 1.0 # LJ epsilon @@ -130,17 +130,11 @@ system.thermostat.set_langevin(kT=1.0, gamma=1.0) # tune skin -print("tune: {}".format(system.cell_system.tune_skin( - min_skin=0.2, - max_skin=1, - tol=0.05, - int_steps=100))) +print("Tune skin: {}".format(system.cell_system.tune_skin( + min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) system.integrator.run(min(30 * measurement_steps, 60000)) -print("tune: {}".format(system.cell_system.tune_skin( - min_skin=0.2, - max_skin=1, - tol=0.05, - int_steps=100))) +print("Tune skin: {}".format(system.cell_system.tune_skin( + min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) print(system.non_bonded_inter[0, 0].lennard_jones) diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index 3d6476c59c9..80e8b5d70a2 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -69,11 +69,11 @@ print(espressomd.features()) -# Interaction parameters (repulsive Lennard-Jones) +# Interaction parameters (Lennard-Jones, Coulomb) ############################################################# species = ["anion", "cation"] -types = {"anion": 0, "cation": 1} +types = {"anion": 0, "cation": 0} charges = {"anion": -1.0, "cation": 1.0} lj_sigmas = {"anion": 1.0, "cation": 1.0} lj_epsilons = {"anion": 1.0, "cation": 1.0} @@ -145,9 +145,14 @@ energy = system.analysis.energy() print("After Minimization: E_total = {}".format(energy["total"])) +print("Tune skin: {}".format(system.cell_system.tune_skin( + min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) print("Tune p3m") p3m = electrostatics.P3M(prefactor=args.bjerrum_length, accuracy=1e-4) system.actors.add(p3m) +system.integrator.run(min(3 * measurement_steps, 6000)) +print("Tune skin: {}".format(system.cell_system.tune_skin( + min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) system.thermostat.set_langevin(kT=1.0, gamma=1.0) From 02c252791718e214335f2b69d67d0e95f1de0506 Mon Sep 17 00:00:00 2001 From: Jonas Landsgesell Date: Fri, 7 Dec 2018 11:49:12 +0100 Subject: [PATCH 09/29] introduce testing for checkpoints of WangLandauReactionEnsemble and the energy recording part of the preliminary wanglandau runs if energy reweighting is intended to be used --- .../python/wang_landau_reaction_ensemble.py | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/testsuite/python/wang_landau_reaction_ensemble.py b/testsuite/python/wang_landau_reaction_ensemble.py index deb7a5cd917..7cfe6e4b137 100644 --- a/testsuite/python/wang_landau_reaction_ensemble.py +++ b/testsuite/python/wang_landau_reaction_ensemble.py @@ -29,6 +29,7 @@ from espressomd.interactions import * from espressomd import reaction_ensemble from espressomd import system +import numpy.testing as npt class ReactionEnsembleTest(ut.TestCase): @@ -70,9 +71,9 @@ class ReactionEnsembleTest(ut.TestCase): h = HarmonicBond(r_0=0, k=1) system.bonded_inter[0] = h system.part[0].add_bond((h, 1)) - RE = reaction_ensemble.WangLandauReactionEnsemble( + WLRE = reaction_ensemble.WangLandauReactionEnsemble( temperature=temperature, exclusion_radius=0) - RE.add_reaction(gamma=K_diss, reactant_types=[0], reactant_coefficients=[ + WLRE.add_reaction(gamma=K_diss, reactant_types=[0], reactant_coefficients=[ 1], product_types=[1, 2], product_coefficients=[1, 1], default_charges={0: 0, 1: -1, 2: +1}) system.setup_type_map([0, 1, 2, 3]) # initialize wang_landau @@ -82,19 +83,27 @@ class ReactionEnsembleTest(ut.TestCase): np.savetxt("energy_boundaries.dat", np.c_[ [0, 1], [0, 0], [9, 9]], delimiter='\t', header="nbar E_potmin E_potmax") - RE.add_collective_variable_degree_of_association( + WLRE.add_collective_variable_degree_of_association( associated_type=0, min=0, max=1, corresponding_acid_types=[0, 1]) - RE.add_collective_variable_potential_energy( - filename="energy_boundaries.dat", delta=0.05) - RE.set_wang_landau_parameters( + WLRE.set_wang_landau_parameters( final_wang_landau_parameter=1e-2, do_not_sample_reaction_partition_function=True, full_path_to_output_filename="WL_potential_out.dat") + def test_wang_landau_energy_recording(self): + self.WLRE.update_maximum_and_minimum_energies_at_current_state() + self.WLRE.write_out_preliminary_energy_run_results() + nbars, E_mins, E_maxs=np.loadtxt("preliminary_energy_run_results", unpack=True) + npt.assert_almost_equal(nbars,[0,1]) + npt.assert_almost_equal(E_mins,[27.0,-10]) + npt.assert_almost_equal(E_maxs,[27.0,-10]) + def test_wang_landau_output(self): + self.WLRE.add_collective_variable_potential_energy( + filename="energy_boundaries.dat", delta=0.05) while True: try: - self.RE.reaction() + self.WLRE.reaction() for i in range(2): - self.RE.displacement_mc_move_for_particles_of_type(3) + self.WLRE.displacement_mc_move_for_particles_of_type(3) except reaction_ensemble.WangLandauHasConverged: # only catch my exception break # test as soon as wang_landau has converged (throws exception then) @@ -127,6 +136,28 @@ def test_wang_landau_output(self): expected_canonical_configurational_heat_capacity - 1.5, 0.00, places=1, msg="difference to analytical expected canonical configurational heat capacity too big") + def _wang_landau_output_checkpoint(self, filename): + #write first checkpoint + self.WLRE.write_wang_landau_checkpoint() + old_checkpoint=np.loadtxt(filename) + + #modify old_checkpoint in memory and in file (this destroys the information contained in the checkpoint, but allows for testing of the functions) + modified_checkpoint=old_checkpoint + modified_checkpoint[0]=1 + np.savetxt(filename, modified_checkpoint) + + #check whether changes are carried out correctly + self.WLRE.load_wang_landau_checkpoint() + self.WLRE.write_wang_landau_checkpoint() + new_checkpoint=np.loadtxt(filename) + npt.assert_almost_equal(new_checkpoint,modified_checkpoint) + + def test_wang_landau_output_checkpoint(self): + filenames=["checkpoint_wang_landau_potential_checkpoint","checkpoint_wang_landau_histogram_checkpoint"] + for filename in filenames: + self._wang_landau_output_checkpoint(filename) + + if __name__ == "__main__": print("Features: ", espressomd.features()) ut.main() From 122cbcbc49a959e53347b7c5d360107c96c9ad4e Mon Sep 17 00:00:00 2001 From: Jonas Landsgesell Date: Fri, 7 Dec 2018 11:50:57 +0100 Subject: [PATCH 10/29] autopep8 --- .../python/wang_landau_reaction_ensemble.py | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/testsuite/python/wang_landau_reaction_ensemble.py b/testsuite/python/wang_landau_reaction_ensemble.py index 7cfe6e4b137..816cf4cf2cb 100644 --- a/testsuite/python/wang_landau_reaction_ensemble.py +++ b/testsuite/python/wang_landau_reaction_ensemble.py @@ -91,14 +91,15 @@ class ReactionEnsembleTest(ut.TestCase): def test_wang_landau_energy_recording(self): self.WLRE.update_maximum_and_minimum_energies_at_current_state() self.WLRE.write_out_preliminary_energy_run_results() - nbars, E_mins, E_maxs=np.loadtxt("preliminary_energy_run_results", unpack=True) - npt.assert_almost_equal(nbars,[0,1]) - npt.assert_almost_equal(E_mins,[27.0,-10]) - npt.assert_almost_equal(E_maxs,[27.0,-10]) + nbars, E_mins, E_maxs = np.loadtxt( + "preliminary_energy_run_results", unpack=True) + npt.assert_almost_equal(nbars, [0, 1]) + npt.assert_almost_equal(E_mins, [27.0, -10]) + npt.assert_almost_equal(E_maxs, [27.0, -10]) def test_wang_landau_output(self): self.WLRE.add_collective_variable_potential_energy( - filename="energy_boundaries.dat", delta=0.05) + filename="energy_boundaries.dat", delta=0.05) while True: try: self.WLRE.reaction() @@ -131,32 +132,33 @@ def test_wang_landau_output(self): # compared here, see Master Thesis Jonas Landsgesell p. 72 self.assertAlmostEqual( expected_canonical_potential_energy - 1.5, 0.00, places=1, - msg="difference to analytical expected canonical potential energy too big") + msg="difference to analytical expected canonical potential energy too big") self.assertAlmostEqual( expected_canonical_configurational_heat_capacity - 1.5, 0.00, places=1, - msg="difference to analytical expected canonical configurational heat capacity too big") + msg="difference to analytical expected canonical configurational heat capacity too big") def _wang_landau_output_checkpoint(self, filename): - #write first checkpoint + # write first checkpoint self.WLRE.write_wang_landau_checkpoint() - old_checkpoint=np.loadtxt(filename) - - #modify old_checkpoint in memory and in file (this destroys the information contained in the checkpoint, but allows for testing of the functions) - modified_checkpoint=old_checkpoint - modified_checkpoint[0]=1 + old_checkpoint = np.loadtxt(filename) + + # modify old_checkpoint in memory and in file (this destroys the information contained in the checkpoint, but allows for testing of the functions) + modified_checkpoint = old_checkpoint + modified_checkpoint[0] = 1 np.savetxt(filename, modified_checkpoint) - - #check whether changes are carried out correctly + + # check whether changes are carried out correctly self.WLRE.load_wang_landau_checkpoint() self.WLRE.write_wang_landau_checkpoint() - new_checkpoint=np.loadtxt(filename) - npt.assert_almost_equal(new_checkpoint,modified_checkpoint) - + new_checkpoint = np.loadtxt(filename) + npt.assert_almost_equal(new_checkpoint, modified_checkpoint) + def test_wang_landau_output_checkpoint(self): - filenames=["checkpoint_wang_landau_potential_checkpoint","checkpoint_wang_landau_histogram_checkpoint"] + filenames = ["checkpoint_wang_landau_potential_checkpoint", + "checkpoint_wang_landau_histogram_checkpoint"] for filename in filenames: self._wang_landau_output_checkpoint(filename) - + if __name__ == "__main__": print("Features: ", espressomd.features()) From 249b88a1e554344694eacfacbfd99674d17d05a1 Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Fri, 7 Dec 2018 14:46:39 +0100 Subject: [PATCH 11/29] Add job for new check with no-dependencies-installed container. --- .gitlab-ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51b0ceac9ef..60411792784 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -205,6 +205,16 @@ empty: - linux - cuda +ubuntu:wo-dependencies: + stage: build + image: gitlab.icp.uni-stuttgart.de:4567/espressomd/docker/$CI_JOB_NAME + script: + - export myconfig=maxset make_check=false + - bash maintainer/CI/build_cmake.sh + tags: + - docker + - linux + ### Builds with ROCm rocm-maxset: From 8415f29e54edab0b029e4f574d94e21edab37064 Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Fri, 7 Dec 2018 14:47:25 +0100 Subject: [PATCH 12/29] Update of maxset.hpp. --- maintainer/configs/maxset.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/maintainer/configs/maxset.hpp b/maintainer/configs/maxset.hpp index fa3ece39c48..92f2f56138f 100755 --- a/maintainer/configs/maxset.hpp +++ b/maintainer/configs/maxset.hpp @@ -71,7 +71,10 @@ along with this program. If not, see . #define SOFT_SPHERE #define INTER_RF #define OVERLAPPED + +#ifdef P3M #define THOLE +#endif #define BOND_ANGLE From 35615ac3a5b5ab6730af58c5c709ab8907188e70 Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Fri, 7 Dec 2018 16:43:02 +0100 Subject: [PATCH 13/29] Guard MDLC. --- src/core/electrostatics_magnetostatics/mdlc_correction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/electrostatics_magnetostatics/mdlc_correction.cpp b/src/core/electrostatics_magnetostatics/mdlc_correction.cpp index 176ac87e50c..8040a4b2691 100644 --- a/src/core/electrostatics_magnetostatics/mdlc_correction.cpp +++ b/src/core/electrostatics_magnetostatics/mdlc_correction.cpp @@ -44,7 +44,7 @@ #include "particle_data.hpp" #include "utils.hpp" -#ifdef DIPOLES +#if defined(DIPOLES) && defined(DP3M) DLC_struct dlc_params = {1e100, 0, 0, 0, 0}; From db10276ba3aff3d18c2634814a7164e4aa5a4d0e Mon Sep 17 00:00:00 2001 From: Jonas Landsgesell Date: Mon, 10 Dec 2018 17:46:48 +0100 Subject: [PATCH 14/29] restart code style check From 93dc1f3c8569945b9c8dee80e920721b2119da04 Mon Sep 17 00:00:00 2001 From: Jonas Landsgesell Date: Mon, 10 Dec 2018 17:48:53 +0100 Subject: [PATCH 15/29] up --- testsuite/python/wang_landau_reaction_ensemble.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/python/wang_landau_reaction_ensemble.py b/testsuite/python/wang_landau_reaction_ensemble.py index 816cf4cf2cb..4661c3e0fac 100644 --- a/testsuite/python/wang_landau_reaction_ensemble.py +++ b/testsuite/python/wang_landau_reaction_ensemble.py @@ -142,7 +142,9 @@ def _wang_landau_output_checkpoint(self, filename): self.WLRE.write_wang_landau_checkpoint() old_checkpoint = np.loadtxt(filename) - # modify old_checkpoint in memory and in file (this destroys the information contained in the checkpoint, but allows for testing of the functions) + # modify old_checkpoint in memory and in file (this destroys the + # information contained in the checkpoint, but allows for testing of + # the functions) modified_checkpoint = old_checkpoint modified_checkpoint[0] = 1 np.savetxt(filename, modified_checkpoint) From 6381403266bb17c943a3ed456ad5c208c1a2e383 Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Tue, 11 Dec 2018 09:24:14 +0100 Subject: [PATCH 16/29] Some more guards. --- src/core/communication.cpp | 4 ++-- src/core/electrostatics_magnetostatics/mdlc_correction.hpp | 2 +- src/core/energy.cpp | 2 ++ src/core/forces.cpp | 2 ++ .../nonbonded_interactions/nonbonded_interaction_data.cpp | 4 +--- src/python/espressomd/magnetostatic_extensions.pxd | 2 +- src/python/espressomd/magnetostatic_extensions.pyx | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/communication.cpp b/src/core/communication.cpp index ab135b1bc74..94c845024bf 100644 --- a/src/core/communication.cpp +++ b/src/core/communication.cpp @@ -2045,7 +2045,7 @@ void mpi_send_fluid_populations_slave(int node, int index) { /****************************************************/ void mpi_bcast_max_mu() { -#ifdef DIPOLES +#if defined(DIPOLES) and defined(DP3M) mpi_call(mpi_bcast_max_mu_slave, -1, 0); calc_mu_max(); @@ -2054,7 +2054,7 @@ void mpi_bcast_max_mu() { } void mpi_bcast_max_mu_slave(int node, int dummy) { -#ifdef DIPOLES +#if defined(DIPOLES) and defined(DP3M) calc_mu_max(); diff --git a/src/core/electrostatics_magnetostatics/mdlc_correction.hpp b/src/core/electrostatics_magnetostatics/mdlc_correction.hpp index 615b8863665..49c9083bb7d 100644 --- a/src/core/electrostatics_magnetostatics/mdlc_correction.hpp +++ b/src/core/electrostatics_magnetostatics/mdlc_correction.hpp @@ -42,7 +42,7 @@ #include "config.hpp" -#ifdef DIPOLES +#if defined(DIPOLES) && defined(DP3M) /** parameters for the MDLC method */ typedef struct { diff --git a/src/core/energy.cpp b/src/core/energy.cpp index 04fba01e3e9..56aafceaf59 100644 --- a/src/core/energy.cpp +++ b/src/core/energy.cpp @@ -245,10 +245,12 @@ void calc_long_range_energies() { case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: energy.dipolar[1] = dawaanr_calculations(0, 1); break; +#ifdef DP3M case DIPOLAR_MDLC_DS: energy.dipolar[1] = magnetic_dipolar_direct_sum_calculations(0, 1); energy.dipolar[2] = add_mdlc_energy_corrections(); break; +#endif case DIPOLAR_DS: energy.dipolar[1] = magnetic_dipolar_direct_sum_calculations(0, 1); break; diff --git a/src/core/forces.cpp b/src/core/forces.cpp index 6160d0bce64..a168d04b5ba 100644 --- a/src/core/forces.cpp +++ b/src/core/forces.cpp @@ -292,9 +292,11 @@ void calc_long_range_forces() { case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: dawaanr_calculations(1, 0); break; +#ifdef DP3M case DIPOLAR_MDLC_DS: add_mdlc_force_corrections(); // fall through +#endif case DIPOLAR_DS: magnetic_dipolar_direct_sum_calculations(1, 0); break; diff --git a/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp b/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp index 6d7a441a32d..7d9bf038924 100644 --- a/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp +++ b/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp @@ -472,9 +472,8 @@ int interactions_sanity_checks() { } #endif /* ifdef ELECTROSTATICS */ -#ifdef DIPOLES +#if defined(DIPOLES) and defined(DP3M) switch (coulomb.Dmethod) { -#ifdef DP3M case DIPOLAR_MDLC_P3M: if (mdlc_sanity_checks()) state = 0; // fall through @@ -482,7 +481,6 @@ int interactions_sanity_checks() { if (dp3m_sanity_checks()) state = 0; break; -#endif case DIPOLAR_MDLC_DS: if (mdlc_sanity_checks()) state = 0; // fall through diff --git a/src/python/espressomd/magnetostatic_extensions.pxd b/src/python/espressomd/magnetostatic_extensions.pxd index c7803c693b0..2897489bb21 100644 --- a/src/python/espressomd/magnetostatic_extensions.pxd +++ b/src/python/espressomd/magnetostatic_extensions.pxd @@ -23,7 +23,7 @@ include "myconfig.pxi" from espressomd.system cimport * from espressomd.utils cimport * -IF DIPOLES == 1: +IF DIPOLES and DP3M: cdef extern from "electrostatics_magnetostatics/mdlc_correction.hpp": ctypedef struct dlc_struct "DLC_struct": diff --git a/src/python/espressomd/magnetostatic_extensions.pyx b/src/python/espressomd/magnetostatic_extensions.pyx index 0cfdc1a4d6b..523726b0fad 100644 --- a/src/python/espressomd/magnetostatic_extensions.pyx +++ b/src/python/espressomd/magnetostatic_extensions.pyx @@ -22,7 +22,7 @@ from . cimport utils include "myconfig.pxi" from .actors import Actor -IF DIPOLES == 1: +IF DIPOLES and DP3M: class MagnetostaticExtension(Actor): pass From ad9bd852d4e3972eaf096cab5a68bcbdbedecd12 Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Tue, 11 Dec 2018 09:32:03 +0100 Subject: [PATCH 17/29] Formatting. --- src/core/forces.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/forces.cpp b/src/core/forces.cpp index a168d04b5ba..e041385d097 100644 --- a/src/core/forces.cpp +++ b/src/core/forces.cpp @@ -295,7 +295,7 @@ void calc_long_range_forces() { #ifdef DP3M case DIPOLAR_MDLC_DS: add_mdlc_force_corrections(); - // fall through + // fall through #endif case DIPOLAR_DS: magnetic_dipolar_direct_sum_calculations(1, 0); From 284772282ad04156b18b418cb0acd2a613cab54a Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Thu, 13 Dec 2018 17:20:27 +0100 Subject: [PATCH 18/29] Core: fold_coordinate rewrite to avoid rounding corner cases --- src/core/grid.hpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/core/grid.hpp b/src/core/grid.hpp index 04c0af19a07..324d37b7271 100644 --- a/src/core/grid.hpp +++ b/src/core/grid.hpp @@ -214,19 +214,13 @@ Vector3d get_mi_vector(T const &a, U const &b) { template void fold_coordinate(T1 &pos, T2 &vel, T3 &image_box, int dir) { if (PERIODIC(dir)) { - int img_count = (int)floor(pos[dir] * box_l_i[dir]); - image_box[dir] += img_count; - pos[dir] = pos[dir] - img_count * box_l[dir]; - - if (pos[dir] * box_l_i[dir] < -ROUND_ERROR_PREC || - pos[dir] * box_l_i[dir] >= 1 + ROUND_ERROR_PREC) { - - runtimeErrorMsg() << "particle coordinate out of range, pos = " - << pos[dir] << ", image box = " << image_box[dir]; - - image_box[dir] = 0; - pos[dir] = 0; - return; + while (pos[dir] < 0) { + pos[dir] += box_l[dir]; + image_box[dir] -= 1; + } + while (pos[dir] >= box_l[dir]) { + pos[dir] -= box_l[dir]; + image_box[dir] += 1; } } } From e2b3f5f94ee2c1881cdb8f6c93945ca47552fa7e Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Mon, 17 Dec 2018 13:44:59 +0100 Subject: [PATCH 19/29] python: set exclusions after all particles are set. --- src/python/espressomd/particle_data.pyx | 31 +++++++++++++------------ src/python/espressomd/utils.pyx | 2 +- testsuite/python/save_checkpoint.py | 1 + testsuite/python/test_checkpoint.py | 8 ++++++- testsuite/python/tests_common.py | 7 ++++-- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/python/espressomd/particle_data.pyx b/src/python/espressomd/particle_data.pyx index eefd40bc515..099323a1c71 100644 --- a/src/python/espressomd/particle_data.pyx +++ b/src/python/espressomd/particle_data.pyx @@ -1140,22 +1140,16 @@ cdef class ParticleHandle(object): for e in self.exclusions: self.delete_exclusion(e) - # Empty list? ony delete - if _partners: - - nlvl = nesting_level(_partners) - - if nlvl == 0: # Single item - self.add_exclusion(_partners) - elif nlvl == 1: # List of items - for partner in _partners: - self.add_exclusion(partner) - else: - raise ValueError( - "Exclusions have to specified as a lists of partners or a single partner.") + nlvl = nesting_level(_partners) - # Set new exclusion list - # self.add_exclusion(_partners) + if nlvl == 0: # Single item + self.add_exclusion(_partners) + elif nlvl == 1: # List of items + for partner in _partners: + self.add_exclusion(partner) + else: + raise ValueError( + "Exclusions have to be specified as a lists of partners or a single item.") def __get__(self): self.update_particle_data() @@ -1813,9 +1807,16 @@ cdef class ParticleList(object): return odict def __setstate__(self, params): + exclusions = collections.OrderedDict() for particle_number in params.keys(): params[particle_number]["id"] = particle_number + IF EXCLUSIONS: + exclusions[particle_number] = params[particle_number]["exclusions"] + del params[particle_number]["exclusions"] self._place_new_particle(params[particle_number]) + IF EXCLUSIONS: + for pid in exclusions: + self[pid].exclusions = exclusions[pid] def __len__(self): return n_part diff --git a/src/python/espressomd/utils.pyx b/src/python/espressomd/utils.pyx index 24ecb31c868..b0c5a199a5b 100644 --- a/src/python/espressomd/utils.pyx +++ b/src/python/espressomd/utils.pyx @@ -310,7 +310,7 @@ def nesting_level(obj): """ - if not isinstance(obj, (list, tuple)): + if not isinstance(obj, (list, tuple, np.ndarray)): return 0 obj = list(obj) diff --git a/testsuite/python/save_checkpoint.py b/testsuite/python/save_checkpoint.py index df35dd79d3b..d80b20f1c7a 100644 --- a/testsuite/python/save_checkpoint.py +++ b/testsuite/python/save_checkpoint.py @@ -40,6 +40,7 @@ system.part.add(pos=[1.0] * 3) system.part.add(pos=[1.0, 1.0, 2.0]) +system.part.add(pos=[2.0]*3, exclusions=[0,1]) if espressomd.has_features('ELECTROSTATICS'): system.part[0].q = 1 system.part[1].q = -1 diff --git a/testsuite/python/test_checkpoint.py b/testsuite/python/test_checkpoint.py index 5d8c6fe07eb..cc385a3c3cd 100644 --- a/testsuite/python/test_checkpoint.py +++ b/testsuite/python/test_checkpoint.py @@ -21,7 +21,7 @@ import espressomd import espressomd.checkpointing import espressomd.virtual_sites - +import tests_common class CheckpointTest(ut.TestCase): @@ -120,6 +120,12 @@ def test_collision_detection(self): self.assertAlmostEqual(coldet.distance, 0.11, delta=1E-9) self.assertTrue(coldet.bond_centers, system.bonded_inter[0]) + @ut.skipIf(not espressomd.has_features("EXCLUSIONS"), "Skipped because feature EXCLUSIONS missing.") + def test_exclusions(self): + self.assertTrue(tests_common.lists_contain_same_elements(system.part[0].exclusions, [2])) + self.assertTrue(tests_common.lists_contain_same_elements(system.part[1].exclusions, [2])) + self.assertTrue(tests_common.lists_contain_same_elements(system.part[2].exclusions, [0,1])) + if __name__ == '__main__': ut.main() diff --git a/testsuite/python/tests_common.py b/testsuite/python/tests_common.py index c87132c3afe..880d4eea2c1 100644 --- a/testsuite/python/tests_common.py +++ b/testsuite/python/tests_common.py @@ -139,8 +139,8 @@ def lj_force_vector(v_d, d, lj_params): def verify_lj_forces(system, tolerance, ids_to_skip=[]): - """Goes over all pairs of paritcles in system and compares the forces on them - to what would be expected based on the systems lj parametes. + """Goes over all pairs of particles in system and compares the forces on them + to what would be expected based on the systems LJ parametes. Particle ids listed in ids_to_skip are not checked Do not run this with a thermostat enabled.""" @@ -594,3 +594,6 @@ def single_component_maxwell(x1, x2, kT): """Integrate the probability density from x1 to x2 using the trapezoidal rule""" x = np.linspace(x1, x2, 1000) return np.trapz(np.exp(-x**2 / (2. * kT)), x) / np.sqrt(2. * np.pi * kT) + +def lists_contain_same_elements(list1, list2): + return len(list1) == len(list2) and sorted(list1) == sorted(list2) From 99ed5e7bc86d3840531842cf81080ce89e16fa9d Mon Sep 17 00:00:00 2001 From: Kai Szuttor Date: Mon, 17 Dec 2018 13:54:43 +0100 Subject: [PATCH 20/29] Formatting. --- src/python/espressomd/particle_data.pyx | 5 ++++- testsuite/python/save_checkpoint.py | 2 +- testsuite/python/test_checkpoint.py | 10 +++++++--- testsuite/python/tests_common.py | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/python/espressomd/particle_data.pyx b/src/python/espressomd/particle_data.pyx index 099323a1c71..064add1f72c 100644 --- a/src/python/espressomd/particle_data.pyx +++ b/src/python/espressomd/particle_data.pyx @@ -1811,7 +1811,10 @@ cdef class ParticleList(object): for particle_number in params.keys(): params[particle_number]["id"] = particle_number IF EXCLUSIONS: - exclusions[particle_number] = params[particle_number]["exclusions"] + exclusions[ + particle_number] = params[ + particle_number][ + "exclusions"] del params[particle_number]["exclusions"] self._place_new_particle(params[particle_number]) IF EXCLUSIONS: diff --git a/testsuite/python/save_checkpoint.py b/testsuite/python/save_checkpoint.py index d80b20f1c7a..60423caafab 100644 --- a/testsuite/python/save_checkpoint.py +++ b/testsuite/python/save_checkpoint.py @@ -40,7 +40,7 @@ system.part.add(pos=[1.0] * 3) system.part.add(pos=[1.0, 1.0, 2.0]) -system.part.add(pos=[2.0]*3, exclusions=[0,1]) +system.part.add(pos=[2.0] * 3, exclusions=[0, 1]) if espressomd.has_features('ELECTROSTATICS'): system.part[0].q = 1 system.part[1].q = -1 diff --git a/testsuite/python/test_checkpoint.py b/testsuite/python/test_checkpoint.py index cc385a3c3cd..dace9ea0a3c 100644 --- a/testsuite/python/test_checkpoint.py +++ b/testsuite/python/test_checkpoint.py @@ -23,6 +23,7 @@ import espressomd.virtual_sites import tests_common + class CheckpointTest(ut.TestCase): @classmethod @@ -122,9 +123,12 @@ def test_collision_detection(self): @ut.skipIf(not espressomd.has_features("EXCLUSIONS"), "Skipped because feature EXCLUSIONS missing.") def test_exclusions(self): - self.assertTrue(tests_common.lists_contain_same_elements(system.part[0].exclusions, [2])) - self.assertTrue(tests_common.lists_contain_same_elements(system.part[1].exclusions, [2])) - self.assertTrue(tests_common.lists_contain_same_elements(system.part[2].exclusions, [0,1])) + self.assertTrue( + tests_common.lists_contain_same_elements(system.part[0].exclusions, [2])) + self.assertTrue( + tests_common.lists_contain_same_elements(system.part[1].exclusions, [2])) + self.assertTrue( + tests_common.lists_contain_same_elements(system.part[2].exclusions, [0, 1])) if __name__ == '__main__': diff --git a/testsuite/python/tests_common.py b/testsuite/python/tests_common.py index 880d4eea2c1..c6a3058756a 100644 --- a/testsuite/python/tests_common.py +++ b/testsuite/python/tests_common.py @@ -595,5 +595,6 @@ def single_component_maxwell(x1, x2, kT): x = np.linspace(x1, x2, 1000) return np.trapz(np.exp(-x**2 / (2. * kT)), x) / np.sqrt(2. * np.pi * kT) + def lists_contain_same_elements(list1, list2): return len(list1) == len(list2) and sorted(list1) == sorted(list2) From e55cbd8dc133951e8300300b9a69a4328d7e71d0 Mon Sep 17 00:00:00 2001 From: Kai Szuttor <2150555+KaiSzuttor@users.noreply.github.com> Date: Mon, 17 Dec 2018 15:18:57 +0100 Subject: [PATCH 21/29] testsuite: Guard usage of exclusions in checkpoint test. --- testsuite/python/save_checkpoint.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/python/save_checkpoint.py b/testsuite/python/save_checkpoint.py index 60423caafab..d74da95c9dc 100644 --- a/testsuite/python/save_checkpoint.py +++ b/testsuite/python/save_checkpoint.py @@ -40,7 +40,8 @@ system.part.add(pos=[1.0] * 3) system.part.add(pos=[1.0, 1.0, 2.0]) -system.part.add(pos=[2.0] * 3, exclusions=[0, 1]) +if espressomd.has_features('EXCLUSIONS'): + system.part.add(pos=[2.0] * 3, exclusions=[0, 1]) if espressomd.has_features('ELECTROSTATICS'): system.part[0].q = 1 system.part[1].q = -1 From 34cf2bed2cf9307bdc3744c67781913f2d3b0283 Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Tue, 18 Dec 2018 14:29:52 +0100 Subject: [PATCH 22/29] Core: Use fold_coordinate in folded_pposition(Particle*) --- src/core/grid.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/core/grid.hpp b/src/core/grid.hpp index 324d37b7271..43b967ed569 100644 --- a/src/core/grid.hpp +++ b/src/core/grid.hpp @@ -271,14 +271,9 @@ template void fold_position(T1 &pos, T2 &image_box) { */ inline Vector3d folded_position(Particle const &p) { Vector3d pos{p.r.p}; - + int tmp[3] = {0, 0, 0}; for (int dir = 0; dir < 3; dir++) { - if (PERIODIC(dir)) { - const int img_count = - static_cast(std::floor(pos[dir] * box_l_i[dir])); - - pos[dir] -= img_count * box_l[dir]; - } + fold_coordinate(pos, tmp, dir); } return pos; From bf850638612b8470d338474cac596cad55abfb4d Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Tue, 18 Dec 2018 14:53:22 +0100 Subject: [PATCH 23/29] Core: Throw in image box count overflow when folding coords --- src/core/grid.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/grid.hpp b/src/core/grid.hpp index 43b967ed569..436cf70d43a 100644 --- a/src/core/grid.hpp +++ b/src/core/grid.hpp @@ -214,14 +214,20 @@ Vector3d get_mi_vector(T const &a, U const &b) { template void fold_coordinate(T1 &pos, T2 &vel, T3 &image_box, int dir) { if (PERIODIC(dir)) { - while (pos[dir] < 0) { + while ((pos[dir] < 0) && (image_box[dir] > INT_MIN)) { pos[dir] += box_l[dir]; image_box[dir] -= 1; } - while (pos[dir] >= box_l[dir]) { + while ((pos[dir] >= box_l[dir]) && (image_box[dir] < INT_MAX)) { pos[dir] -= box_l[dir]; image_box[dir] += 1; } + if ((image_box[dir] == INT_MIN) || (image_box[dir] == INT_MAX)) { + throw std::runtime_error( + "Overflow in the image box count while folding a particle coordinate " + "into the primary simulation box. Maybe a particle experienced a " + "huge force."); + } } } From 8a3c24e6db84cf5487405c61509ea1a4667de1a7 Mon Sep 17 00:00:00 2001 From: Jonas Landsgesell Date: Thu, 20 Dec 2018 02:45:34 +0100 Subject: [PATCH 24/29] Electrostatic pressure consistency (#2409) * add check * add check * patch * imports * up * Update p3m_electrostatic_pressure.py * format * Update p3m_electrostatic_pressure.py * apply patch * exchange assert code * docstring for test * apply patch * reformulate comparison * year * patch * revert to np testing * changed comparison to maximal 2 percent deviation * changed comparison to maximal 2 percent deviation * patch * empty * add tune skin * add warmup * patch * refactor pressure calculation in small python class * patch * new style class * add LJ to required features * patch --- testsuite/python/CMakeLists.txt | 1 + .../python/p3m_electrostatic_pressure.py | 142 ++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 testsuite/python/p3m_electrostatic_pressure.py diff --git a/testsuite/python/CMakeLists.txt b/testsuite/python/CMakeLists.txt index 17778e8dca6..ee682ae70fd 100644 --- a/testsuite/python/CMakeLists.txt +++ b/testsuite/python/CMakeLists.txt @@ -167,6 +167,7 @@ python_test(FILE lb_boundary.py MAX_NUM_PROC 2) python_test(FILE lb_streaming.py MAX_NUM_PROC 4) python_test(FILE lb_shear.py MAX_NUM_PROC 2) python_test(FILE lb_thermostat.py MAX_NUM_PROC 2) +python_test(FILE p3m_electrostatic_pressure.py MAX_NUM_PROC 2) if(PY_H5PY) python_test(FILE h5md.py MAX_NUM_PROC 2) diff --git a/testsuite/python/p3m_electrostatic_pressure.py b/testsuite/python/p3m_electrostatic_pressure.py new file mode 100644 index 00000000000..0f2b982a43a --- /dev/null +++ b/testsuite/python/p3m_electrostatic_pressure.py @@ -0,0 +1,142 @@ +# +# Copyright (C) 2013-2018 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +from __future__ import print_function +import unittest as ut +import numpy as np +import numpy.testing as npt + +import espressomd +from espressomd import electrostatics + + +class pressureViaVolumeScaling(object): + + def __init__(self, system, kbT): + self.system = system + self.kbT = kbT + self.old_box_lengths = np.copy(system.box_l) + self.old_volume = np.prod(self.old_box_lengths) + dV_div_old_volume = 0.001 + self.dV = -dV_div_old_volume * self.old_volume + self.new_volume = self.old_volume + self.dV + self.new_box_l = (self.new_volume)**(1. / 3.) + + self.list_of_previous_values = [] + + def measure_pressure_via_volume_scaling( + self): + # taken from "Efficient pressure estimation in molecular simulations without evaluating the virial" + # only works so far for isotropic volume changes, i.e. the isotropic + # pressure + energy = self.system.analysis.energy() + Epot_old = energy["total"] - energy["kinetic"] + self.system.change_volume_and_rescale_particles(self.new_box_l, "xyz") + self.system.integrator.run(0) + energy = self.system.analysis.energy() + Epot_new = energy["total"] - energy["kinetic"] + self.system.change_volume_and_rescale_particles( + self.old_box_lengths[0], "xyz") + self.system.integrator.run(0) + DeltaEpot = Epot_new - Epot_old + particle_number = len(self.system.part[:].id) + current_value = (self.new_volume / self.old_volume)**particle_number * \ + np.exp(-DeltaEpot / self.kbT) + self.list_of_previous_values.append(current_value) + + def get_result(self): + average_value = np.mean(self.list_of_previous_values) + + pressure = self.kbT / self.dV * np.log(average_value) + return pressure + + +@ut.skipIf(not espressomd.has_features(["ELECTROSTATICS, LENNARD_JONES"]), + "Features not available, skipping test!") +class VirialPressureConsistency(ut.TestCase): + + """Test the consistency of the core implementation of the virial pressure with an analytical relation which allows + for the calculation of the pressure as a volume derivative of a function of the potential energy change on infinitesimal volume changes. + The relation and its derivation can be found in the paper with the name "Efficient pressure estimation in molecular simulations without evaluating the virial" + by Harismiadis, V. I., J. Vorholz, and A. Z. Panagiotopoulos. 1996 + + """ + # Handle to espresso system + system = espressomd.System(box_l=[50, 50, 50]) + + def setUp(self): + np.random.seed(seed=1) + self.system.seed = range( + self.system.cell_system.get_state()["n_nodes"]) + self.system.time_step = 0.01 + self.kT = 0.5 + self.system.non_bonded_inter[0, 0].lennard_jones.set_params( + epsilon=1.0, sigma=1.0, cutoff=2**(1.0 / 6.0), shift="auto") + num_part = 40 + mass = 1 + + for i in range(num_part): + self.system.part.add(pos=np.random.random( + 3) * self.system.box_l, q=1, v=np.sqrt(self.kT / mass) * np.random.normal(loc=[0, 0, 0])) + self.system.part.add(pos=np.random.random( + 3) * self.system.box_l, q=-1, v=np.sqrt(self.kT / mass) * np.random.normal(loc=[0, 0, 0])) + + ############################################################# + # Warmup Integration # + ############################################################# + + self.system.integrator.set_steepest_descent( + f_max=0, + gamma=0.001, + max_displacement=0.01) + + # warmup + while self.system.analysis.energy()["total"] > 10 * num_part: + print("minimization: {:.1f}".format( + self.system.analysis.energy()["total"])) + self.system.integrator.run(10) + self.system.integrator.set_vv() + self.system.thermostat.set_langevin(kT=self.kT, gamma=1.0) + + def test_p3m_pressure(self): + pressures_via_virial = [] + pressures_via_volume_scaling = [] + print("Tune skin: {}".format(self.system.cell_system.tune_skin( + min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) + p3m = electrostatics.P3M(prefactor=2.0, accuracy=1e-3) + self.system.actors.add(p3m) + print("Tune skin: {}".format(self.system.cell_system.tune_skin( + min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) + num_samples = 100 + pressure_via_volume_scaling = pressureViaVolumeScaling( + self.system, self.kT) + for i in range(num_samples): + self.system.integrator.run(100) + pressures_via_virial.append( + self.system.analysis.pressure()['total']) + pressure_via_volume_scaling.measure_pressure_via_volume_scaling() + pressure_virial = np.mean(pressures_via_virial) + abs_deviation_in_percent = abs( + pressure_virial / pressure_via_volume_scaling.get_result() - 1.0) * 100.0 # should be 0% ideally + npt.assert_array_less( + abs_deviation_in_percent, + 5.0) # devation should be below 5% + + +if __name__ == "__main__": + ut.main() From c0cebb7c3c47fde0c1910ff4db8a88a3c1cbf1bb Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Thu, 20 Dec 2018 11:05:20 +0100 Subject: [PATCH 25/29] AMD GPU: require ROCm 2.0 --- CMakeLists.txt | 3 +- cmake/FindHIP.cmake | 579 ----------------------------- cmake/FindHIP/run_hipcc.cmake | 168 --------- cmake/FindHIP/run_make2cmake.cmake | 50 --- doc/sphinx/installation.rst | 2 +- src/core/cuda_wrapper.hpp | 6 +- 6 files changed, 4 insertions(+), 804 deletions(-) delete mode 100644 cmake/FindHIP.cmake delete mode 100644 cmake/FindHIP/run_hipcc.cmake delete mode 100644 cmake/FindHIP/run_make2cmake.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 9626b9fbed9..f7631db2788 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,8 @@ if (WITH_CUDA) target_link_libraries(${target} ${CUFFT_LIBRARY}) endfunction() else() - find_package(HIP QUIET MODULE) + list(APPEND CMAKE_MODULE_PATH "/opt/rocm/hip/cmake") + find_package(HIP 1.5.18494 QUIET MODULE) if(HIP_FOUND) set(HCC_PATH "${HIP_ROOT_DIR}") find_package(HIP MODULE) diff --git a/cmake/FindHIP.cmake b/cmake/FindHIP.cmake deleted file mode 100644 index d2377e9adb8..00000000000 --- a/cmake/FindHIP.cmake +++ /dev/null @@ -1,579 +0,0 @@ -############################################################################### -# FindHIP.cmake -############################################################################### - -############################################################################### -# SET: Variable defaults -############################################################################### -# User defined flags -set(HIP_HIPCC_FLAGS "" CACHE STRING "Semicolon delimited flags for HIPCC") -set(HIP_HCC_FLAGS "" CACHE STRING "Semicolon delimited flags for HCC") -set(HIP_NVCC_FLAGS "" CACHE STRING "Semicolon delimted flags for NVCC") -mark_as_advanced(HIP_HIPCC_FLAGS HIP_HCC_FLAGS HIP_NVCC_FLAGS) -set(_hip_configuration_types ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE} Debug MinSizeRel Release RelWithDebInfo) -list(REMOVE_DUPLICATES _hip_configuration_types) -foreach(config ${_hip_configuration_types}) - string(TOUPPER ${config} config_upper) - set(HIP_HIPCC_FLAGS_${config_upper} "" CACHE STRING "Semicolon delimited flags for HIPCC") - set(HIP_HCC_FLAGS_${config_upper} "" CACHE STRING "Semicolon delimited flags for HCC") - set(HIP_NVCC_FLAGS_${config_upper} "" CACHE STRING "Semicolon delimited flags for NVCC") - mark_as_advanced(HIP_HIPCC_FLAGS_${config_upper} HIP_HCC_FLAGS_${config_upper} HIP_NVCC_FLAGS_${config_upper}) -endforeach() -option(HIP_HOST_COMPILATION_CPP "Host code compilation mode" ON) -option(HIP_VERBOSE_BUILD "Print out the commands run while compiling the HIP source file. With the Makefile generator this defaults to VERBOSE variable specified on the command line, but can be forced on with this option." OFF) -mark_as_advanced(HIP_HOST_COMPILATION_CPP) - -############################################################################### -# Set HIP CMAKE Flags -############################################################################### -# Copy the invocation styles from CXX to HIP -set(CMAKE_HIP_ARCHIVE_CREATE ${CMAKE_CXX_ARCHIVE_CREATE}) -set(CMAKE_HIP_ARCHIVE_APPEND ${CMAKE_CXX_ARCHIVE_APPEND}) -set(CMAKE_HIP_ARCHIVE_FINISH ${CMAKE_CXX_ARCHIVE_FINISH}) -set(CMAKE_SHARED_LIBRARY_SONAME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG}) -set(CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS}) -set(CMAKE_SHARED_LIBRARY_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) -#set(CMAKE_SHARED_LIBRARY_LINK_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS}) -set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}) -set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP}) -set(CMAKE_SHARED_LIBRARY_LINK_STATIC_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_STATIC_CXX_FLAGS}) -set(CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_CXX_FLAGS}) - -# Set the CMake Flags to use the HCC Compilier. -set(CMAKE_HIP_CREATE_SHARED_LIBRARY "${HIP_HIPCC_CMAKE_LINKER_HELPER} ${HCC_PATH} -o ") -set(CMAKE_HIP_CREATE_SHARED_MODULE "${HIP_HIPCC_CMAKE_LINKER_HELPER} ${HCC_PATH} -o -shared" ) -set(CMAKE_HIP_LINK_EXECUTABLE "${HIP_HIPCC_CMAKE_LINKER_HELPER} ${HCC_PATH} -o ") - -############################################################################### -# FIND: HIP and associated helper binaries -############################################################################### -# HIP is supported on Linux only -if(UNIX AND NOT APPLE AND NOT CYGWIN) - # Search for HIP installation - if(NOT HIP_ROOT_DIR) - # Search in user specified path first - find_path( - HIP_ROOT_DIR - NAMES hipconfig - PATHS - ENV ROCM_PATH - ENV HIP_PATH - PATH_SUFFIXES bin - DOC "HIP installed location" - NO_DEFAULT_PATH - ) - # Now search in default path - find_path( - HIP_ROOT_DIR - NAMES hipconfig - PATHS - /opt/rocm - /opt/rocm/hip - PATH_SUFFIXES bin - DOC "HIP installed location" - ) - - # Check if we found HIP installation - if(HIP_ROOT_DIR) - # If so, fix the path - string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" HIP_ROOT_DIR ${HIP_ROOT_DIR}) - # And push it back to the cache - set(HIP_ROOT_DIR ${HIP_ROOT_DIR} CACHE PATH "HIP installed location" FORCE) - endif() - if(NOT EXISTS ${HIP_ROOT_DIR}) - if(HIP_FIND_REQUIRED) - message(FATAL_ERROR "Specify HIP_ROOT_DIR") - elseif(NOT HIP_FIND_QUIETLY) - message("HIP_ROOT_DIR not found or specified") - endif() - endif() - endif() - - # Find HIPCC executable - find_program( - HIP_HIPCC_EXECUTABLE - NAMES hipcc - PATHS - "${HIP_ROOT_DIR}" - ENV ROCM_PATH - ENV HIP_PATH - /opt/rocm - /opt/rocm/hip - PATH_SUFFIXES bin - NO_DEFAULT_PATH - ) - if(NOT HIP_HIPCC_EXECUTABLE) - # Now search in default paths - find_program(HIP_HIPCC_EXECUTABLE hipcc) - endif() - mark_as_advanced(HIP_HIPCC_EXECUTABLE) - - # Find HIPCONFIG executable - find_program( - HIP_HIPCONFIG_EXECUTABLE - NAMES hipconfig - PATHS - "${HIP_ROOT_DIR}" - ENV ROCM_PATH - ENV HIP_PATH - /opt/rocm - /opt/rocm/hip - PATH_SUFFIXES bin - NO_DEFAULT_PATH - ) - if(NOT HIP_HIPCONFIG_EXECUTABLE) - # Now search in default paths - find_program(HIP_HIPCONFIG_EXECUTABLE hipconfig) - endif() - mark_as_advanced(HIP_HIPCONFIG_EXECUTABLE) - - # Find HIPCC_CMAKE_LINKER_HELPER executable - find_program( - HIP_HIPCC_CMAKE_LINKER_HELPER - NAMES hipcc_cmake_linker_helper - PATHS - "${HIP_ROOT_DIR}" - ENV ROCM_PATH - ENV HIP_PATH - /opt/rocm - /opt/rocm/hip - PATH_SUFFIXES bin - NO_DEFAULT_PATH - ) - if(NOT HIP_HIPCC_CMAKE_LINKER_HELPER) - # Now search in default paths - find_program(HIP_HIPCC_CMAKE_LINKER_HELPER hipcc_cmake_linker_helper) - endif() - mark_as_advanced(HIP_HIPCC_CMAKE_LINKER_HELPER) - - if(HIP_HIPCONFIG_EXECUTABLE AND NOT HIP_VERSION) - # Compute the version - execute_process( - COMMAND ${HIP_HIPCONFIG_EXECUTABLE} --version - OUTPUT_VARIABLE _hip_version - ERROR_VARIABLE _hip_error - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE - ) - if(NOT _hip_error) - set(HIP_VERSION ${_hip_version} CACHE STRING "Version of HIP as computed from hipcc") - else() - set(HIP_VERSION "0.0.0" CACHE STRING "Version of HIP as computed by FindHIP()") - endif() - mark_as_advanced(HIP_VERSION) - endif() - if(HIP_VERSION) - string(REPLACE "." ";" _hip_version_list "${HIP_VERSION}") - list(GET _hip_version_list 0 HIP_VERSION_MAJOR) - list(GET _hip_version_list 1 HIP_VERSION_MINOR) - list(GET _hip_version_list 2 HIP_VERSION_PATCH) - set(HIP_VERSION_STRING "${HIP_VERSION}") - endif() - - if(HIP_HIPCONFIG_EXECUTABLE AND NOT HIP_PLATFORM) - # Compute the platform - execute_process( - COMMAND ${HIP_HIPCONFIG_EXECUTABLE} --platform - OUTPUT_VARIABLE _hip_platform - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - set(HIP_PLATFORM ${_hip_platform} CACHE STRING "HIP platform as computed by hipconfig") - mark_as_advanced(HIP_PLATFORM) - endif() -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - HIP - REQUIRED_VARS - HIP_ROOT_DIR - HIP_HIPCC_EXECUTABLE - HIP_HIPCONFIG_EXECUTABLE - HIP_PLATFORM - VERSION_VAR HIP_VERSION - ) - -############################################################################### -# MACRO: Locate helper files -############################################################################### -macro(HIP_FIND_HELPER_FILE _name _extension) - set(_hip_full_name "${_name}.${_extension}") - get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - set(HIP_${_name} "${CMAKE_CURRENT_LIST_DIR}/FindHIP/${_hip_full_name}") - if(NOT EXISTS "${HIP_${_name}}") - set(error_message "${_hip_full_name} not found in ${CMAKE_CURRENT_LIST_DIR}/FindHIP") - if(HIP_FIND_REQUIRED) - message(FATAL_ERROR "${error_message}") - else() - if(NOT HIP_FIND_QUIETLY) - message(STATUS "${error_message}") - endif() - endif() - endif() - # Set this variable as internal, so the user isn't bugged with it. - set(HIP_${_name} ${HIP_${_name}} CACHE INTERNAL "Location of ${_full_name}" FORCE) -endmacro() - -############################################################################### -hip_find_helper_file(run_make2cmake cmake) -hip_find_helper_file(run_hipcc cmake) -############################################################################### - -############################################################################### -# MACRO: Reset compiler flags -############################################################################### -macro(HIP_RESET_FLAGS) - unset(HIP_HIPCC_FLAGS) - unset(HIP_HCC_FLAGS) - unset(HIP_NVCC_FLAGS) - foreach(config ${_hip_configuration_types}) - string(TOUPPER ${config} config_upper) - unset(HIP_HIPCC_FLAGS_${config_upper}) - unset(HIP_HCC_FLAGS_${config_upper}) - unset(HIP_NVCC_FLAGS_${config_upper}) - endforeach() -endmacro() - -############################################################################### -# MACRO: Separate the options from the sources -############################################################################### -macro(HIP_GET_SOURCES_AND_OPTIONS _sources _cmake_options _hipcc_options _hcc_options _nvcc_options) - set(${_sources}) - set(${_cmake_options}) - set(${_hipcc_options}) - set(${_hcc_options}) - set(${_nvcc_options}) - set(_hipcc_found_options FALSE) - set(_hcc_found_options FALSE) - set(_nvcc_found_options FALSE) - foreach(arg ${ARGN}) - if("x${arg}" STREQUAL "xHIPCC_OPTIONS") - set(_hipcc_found_options TRUE) - set(_hcc_found_options FALSE) - set(_nvcc_found_options FALSE) - elseif("x${arg}" STREQUAL "xHCC_OPTIONS") - set(_hipcc_found_options FALSE) - set(_hcc_found_options TRUE) - set(_nvcc_found_options FALSE) - elseif("x${arg}" STREQUAL "xNVCC_OPTIONS") - set(_hipcc_found_options FALSE) - set(_hcc_found_options FALSE) - set(_nvcc_found_options TRUE) - elseif( - "x${arg}" STREQUAL "xEXCLUDE_FROM_ALL" OR - "x${arg}" STREQUAL "xSTATIC" OR - "x${arg}" STREQUAL "xSHARED" OR - "x${arg}" STREQUAL "xMODULE" - ) - list(APPEND ${_cmake_options} ${arg}) - else() - if(_hipcc_found_options) - list(APPEND ${_hipcc_options} ${arg}) - elseif(_hcc_found_options) - list(APPEND ${_hcc_options} ${arg}) - elseif(_nvcc_found_options) - list(APPEND ${_nvcc_options} ${arg}) - else() - # Assume this is a file - list(APPEND ${_sources} ${arg}) - endif() - endif() - endforeach() -endmacro() - -############################################################################### -# MACRO: Add include directories to pass to the hipcc command -############################################################################### -set(HIP_HIPCC_INCLUDE_ARGS_USER "") -macro(HIP_INCLUDE_DIRECTORIES) - foreach(dir ${ARGN}) - list(APPEND HIP_HIPCC_INCLUDE_ARGS_USER $<$:-I${dir}>) - endforeach() -endmacro() - -############################################################################### -# FUNCTION: Helper to avoid clashes of files with the same basename but different paths -############################################################################### -function(HIP_COMPUTE_BUILD_PATH path build_path) - # Convert to cmake style paths - file(TO_CMAKE_PATH "${path}" bpath) - if(IS_ABSOLUTE "${bpath}") - string(FIND "${bpath}" "${CMAKE_CURRENT_BINARY_DIR}" _binary_dir_pos) - if(_binary_dir_pos EQUAL 0) - file(RELATIVE_PATH bpath "${CMAKE_CURRENT_BINARY_DIR}" "${bpath}") - else() - file(RELATIVE_PATH bpath "${CMAKE_CURRENT_SOURCE_DIR}" "${bpath}") - endif() - endif() - - # Remove leading / - string(REGEX REPLACE "^[/]+" "" bpath "${bpath}") - # Avoid absolute paths by removing ':' - string(REPLACE ":" "_" bpath "${bpath}") - # Avoid relative paths that go up the tree - string(REPLACE "../" "__/" bpath "${bpath}") - # Avoid spaces - string(REPLACE " " "_" bpath "${bpath}") - # Strip off the filename - get_filename_component(bpath "${bpath}" PATH) - - set(${build_path} "${bpath}" PARENT_SCOPE) -endfunction() - -############################################################################### -# MACRO: Parse OPTIONS from ARGN & set variables prefixed by _option_prefix -############################################################################### -macro(HIP_PARSE_HIPCC_OPTIONS _option_prefix) - set(_hip_found_config) - foreach(arg ${ARGN}) - # Determine if we are dealing with a per-configuration flag - foreach(config ${_hip_configuration_types}) - string(TOUPPER ${config} config_upper) - if(arg STREQUAL "${config_upper}") - set(_hip_found_config _${arg}) - # Clear arg to prevent it from being processed anymore - set(arg) - endif() - endforeach() - if(arg) - list(APPEND ${_option_prefix}${_hip_found_config} "${arg}") - endif() - endforeach() -endmacro() - -############################################################################### -# MACRO: Try and include dependency file if it exists -############################################################################### -macro(HIP_INCLUDE_HIPCC_DEPENDENCIES dependency_file) - set(HIP_HIPCC_DEPEND) - set(HIP_HIPCC_DEPEND_REGENERATE FALSE) - - # Create the dependency file if it doesn't exist - if(NOT EXISTS ${dependency_file}) - file(WRITE ${dependency_file} "# Generated by: FindHIP.cmake. Do not edit.\n") - endif() - # Include the dependency file - include(${dependency_file}) - - # Verify the existence of all the included files - if(HIP_HIPCC_DEPEND) - foreach(f ${HIP_HIPCC_DEPEND}) - if(NOT EXISTS ${f}) - # If they aren't there, regenerate the file again - set(HIP_HIPCC_DEPEND_REGENERATE TRUE) - endif() - endforeach() - else() - # No dependencies, so regenerate the file - set(HIP_HIPCC_DEPEND_REGENERATE TRUE) - endif() - - # Regenerate the dependency file if needed - if(HIP_HIPCC_DEPEND_REGENERATE) - set(HIP_HIPCC_DEPEND ${dependency_file}) - file(WRITE ${dependency_file} "# Generated by: FindHIP.cmake. Do not edit.\n") - endif() -endmacro() - -############################################################################### -# MACRO: Prepare cmake commands for the target -############################################################################### -macro(HIP_PREPARE_TARGET_COMMANDS _target _format _generated_files _source_files) - set(_hip_flags "") - string(TOUPPER "${CMAKE_BUILD_TYPE}" _hip_build_configuration) - if(HIP_HOST_COMPILATION_CPP) - set(HIP_C_OR_CXX CXX) - else() - set(HIP_C_OR_CXX C) - endif() - set(generated_extension ${CMAKE_${HIP_C_OR_CXX}_OUTPUT_EXTENSION}) - - # Initialize list of includes with those specified by the user. Append with - # ones specified to cmake directly. - set(HIP_HIPCC_INCLUDE_ARGS ${HIP_HIPCC_INCLUDE_ARGS_USER}) - - # Add the include directories - set(include_directories_generator "$") - list(APPEND HIP_HIPCC_INCLUDE_ARGS "$<$:-I$>") - - get_directory_property(_hip_include_directories INCLUDE_DIRECTORIES) - list(REMOVE_DUPLICATES _hip_include_directories) - if(_hip_include_directories) - foreach(dir ${_hip_include_directories}) - list(APPEND HIP_HIPCC_INCLUDE_ARGS $<$:-I${dir}>) - endforeach() - endif() - - HIP_GET_SOURCES_AND_OPTIONS(_hip_sources _hip_cmake_options _hipcc_options _hcc_options _nvcc_options ${ARGN}) - HIP_PARSE_HIPCC_OPTIONS(HIP_HIPCC_FLAGS ${_hipcc_options}) - HIP_PARSE_HIPCC_OPTIONS(HIP_HCC_FLAGS ${_hcc_options}) - HIP_PARSE_HIPCC_OPTIONS(HIP_NVCC_FLAGS ${_nvcc_options}) - - # Add the compile definitions - set(compile_definition_generator "$") - list(APPEND HIP_HIPCC_FLAGS "$<$:-D$>") - - # Check if we are building shared library. - set(_hip_build_shared_libs FALSE) - list(FIND _hip_cmake_options SHARED _hip_found_SHARED) - list(FIND _hip_cmake_options MODULE _hip_found_MODULE) - if(_hip_found_SHARED GREATER -1 OR _hip_found_MODULE GREATER -1) - set(_hip_build_shared_libs TRUE) - endif() - list(FIND _hip_cmake_options STATIC _hip_found_STATIC) - if(_hip_found_STATIC GREATER -1) - set(_hip_build_shared_libs FALSE) - endif() - - # If we are building a shared library, add extra flags to HIP_HIPCC_FLAGS - if(_hip_build_shared_libs) - list(APPEND HIP_HCC_FLAGS "-fPIC") - list(APPEND HIP_NVCC_FLAGS "--shared -Xcompiler '-fPIC'") - endif() - - # Set host compiler - set(HIP_HOST_COMPILER "${CMAKE_${HIP_C_OR_CXX}_COMPILER}") - - # Set compiler flags - set(_HIP_HOST_FLAGS "set(CMAKE_HOST_FLAGS ${CMAKE_${HIP_C_OR_CXX}_FLAGS})") - set(_HIP_HIPCC_FLAGS "set(HIP_HIPCC_FLAGS ${HIP_HIPCC_FLAGS})") - set(_HIP_HCC_FLAGS "set(HIP_HCC_FLAGS ${HIP_HCC_FLAGS})") - set(_HIP_NVCC_FLAGS "set(HIP_NVCC_FLAGS ${HIP_NVCC_FLAGS})") - foreach(config ${_hip_configuration_types}) - string(TOUPPER ${config} config_upper) - set(_HIP_HOST_FLAGS "${_HIP_HOST_FLAGS}\nset(CMAKE_HOST_FLAGS_${config_upper} ${CMAKE_${HIP_C_OR_CXX}_FLAGS_${config_upper}})") - set(_HIP_HIPCC_FLAGS "${_HIP_HIPCC_FLAGS}\nset(HIP_HIPCC_FLAGS_${config_upper} ${HIP_HIPCC_FLAGS_${config_upper}})") - set(_HIP_HCC_FLAGS "${_HIP_HCC_FLAGS}\nset(HIP_HCC_FLAGS_${config_upper} ${HIP_HCC_FLAGS_${config_upper}})") - set(_HIP_NVCC_FLAGS "${_HIP_NVCC_FLAGS}\nset(HIP_NVCC_FLAGS_${config_upper} ${HIP_NVCC_FLAGS_${config_upper}})") - endforeach() - - # Reset the output variable - set(_hip_generated_files "") - set(_hip_source_files "") - - # Iterate over all arguments and create custom commands for all source files - foreach(file ${ARGN}) - # Ignore any file marked as a HEADER_FILE_ONLY - get_source_file_property(_is_header ${file} HEADER_FILE_ONLY) - # Allow per source file overrides of the format. Also allows compiling non .cu files. - get_source_file_property(_hip_source_format ${file} HIP_SOURCE_PROPERTY_FORMAT) - if((${file} MATCHES "\\.cu$" OR _hip_source_format) AND NOT _is_header) - set(host_flag FALSE) - else() - set(host_flag TRUE) - endif() - - if(NOT host_flag) - # Determine output directory - HIP_COMPUTE_BUILD_PATH("${file}" hip_build_path) - set(hip_compile_output_dir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_target}.dir/${hip_build_path}") - - get_filename_component(basename ${file} NAME) - set(generated_file_path "${hip_compile_output_dir}/${CMAKE_CFG_INTDIR}") - set(generated_file_basename "${_target}_generated_${basename}${generated_extension}") - - # Set file names - set(generated_file "${generated_file_path}/${generated_file_basename}") - set(cmake_dependency_file "${hip_compile_output_dir}/${generated_file_basename}.depend") - set(custom_target_script_pregen "${hip_compile_output_dir}/${generated_file_basename}.cmake.pre-gen") - set(custom_target_script "${hip_compile_output_dir}/${generated_file_basename}.cmake") - - # Set properties for object files - set_source_files_properties("${generated_file}" - PROPERTIES - EXTERNAL_OBJECT true # This is an object file not to be compiled, but only be linked - ) - - # Don't add CMAKE_CURRENT_SOURCE_DIR if the path is already an absolute path - get_filename_component(file_path "${file}" PATH) - if(IS_ABSOLUTE "${file_path}") - set(source_file "${file}") - else() - set(source_file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") - endif() - - # Bring in the dependencies - HIP_INCLUDE_HIPCC_DEPENDENCIES(${cmake_dependency_file}) - - # Configure the build script - configure_file("${HIP_run_hipcc}" "${custom_target_script_pregen}" @ONLY) - file(GENERATE - OUTPUT "${custom_target_script}" - INPUT "${custom_target_script_pregen}" - ) - set(main_dep DEPENDS ${source_file}) - if(CMAKE_GENERATOR MATCHES "Makefiles") - set(verbose_output "$(VERBOSE)") - elseif(HIP_VERBOSE_BUILD) - set(verbose_output ON) - else() - set(verbose_output OFF) - endif() - - # Create up the comment string - file(RELATIVE_PATH generated_file_relative_path "${CMAKE_BINARY_DIR}" "${generated_file}") - set(hip_build_comment_string "Building HIPCC object ${generated_file_relative_path}") - - # Build the generated file and dependency file - add_custom_command( - OUTPUT ${generated_file} - # These output files depend on the source_file and the contents of cmake_dependency_file - ${main_dep} - DEPENDS ${HIP_HIPCC_DEPEND} - DEPENDS ${custom_target_script} - # Make sure the output directory exists before trying to write to it. - COMMAND ${CMAKE_COMMAND} -E make_directory "${generated_file_path}" - COMMAND ${CMAKE_COMMAND} ARGS - -D verbose:BOOL=${verbose_output} - -D build_configuration:STRING=${_hip_build_configuration} - -D "generated_file:STRING=${generated_file}" - -P "${custom_target_script}" - WORKING_DIRECTORY "${hip_compile_output_dir}" - COMMENT "${hip_build_comment_string}" - ) - - # Make sure the build system knows the file is generated - set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE) - list(APPEND _hip_generated_files ${generated_file}) - list(APPEND _hip_source_files ${file}) - endif() - endforeach() - - # Set the return parameter - set(${_generated_files} ${_hip_generated_files}) - set(${_source_files} ${_hip_source_files}) -endmacro() - -############################################################################### -# HIP_ADD_EXECUTABLE -############################################################################### -macro(HIP_ADD_EXECUTABLE hip_target) - # Separate the sources from the options - HIP_GET_SOURCES_AND_OPTIONS(_sources _cmake_options _hipcc_options _hcc_options _nvcc_options ${ARGN}) - HIP_PREPARE_TARGET_COMMANDS(${hip_target} OBJ _generated_files _source_files ${_sources} HIPCC_OPTIONS ${_hipcc_options} HCC_OPTIONS ${_hcc_options} NVCC_OPTIONS ${_nvcc_options}) - if(_source_files) - list(REMOVE_ITEM _sources ${_source_files}) - endif() - if("x${HCC_HOME}" STREQUAL "x") - set(HCC_HOME "/opt/rocm/hcc") - endif() - set(CMAKE_HIP_LINK_EXECUTABLE "${HIP_HIPCC_CMAKE_LINKER_HELPER} ${HCC_HOME} -o ") - add_executable(${hip_target} ${_cmake_options} ${_generated_files} ${_sources}) - set_target_properties(${hip_target} PROPERTIES LINKER_LANGUAGE HIP) -endmacro() - -############################################################################### -# HIP_ADD_LIBRARY -############################################################################### -macro(HIP_ADD_LIBRARY hip_target) - # Separate the sources from the options - HIP_GET_SOURCES_AND_OPTIONS(_sources _cmake_options _hipcc_options _hcc_options _nvcc_options ${ARGN}) - HIP_PREPARE_TARGET_COMMANDS(${hip_target} OBJ _generated_files _source_files ${_sources} ${_cmake_options} HIPCC_OPTIONS ${_hipcc_options} HCC_OPTIONS ${_hcc_options} NVCC_OPTIONS ${_nvcc_options}) - if(_source_files) - list(REMOVE_ITEM _sources ${_source_files}) - endif() - add_library(${hip_target} ${_cmake_options} ${_generated_files} ${_sources}) - set_target_properties(${hip_target} PROPERTIES LINKER_LANGUAGE ${HIP_C_OR_CXX}) -endmacro() - -# vim: ts=4:sw=4:expandtab:smartindent diff --git a/cmake/FindHIP/run_hipcc.cmake b/cmake/FindHIP/run_hipcc.cmake deleted file mode 100644 index 4dc2572e981..00000000000 --- a/cmake/FindHIP/run_hipcc.cmake +++ /dev/null @@ -1,168 +0,0 @@ -############################################################################### -# Runs commands using HIPCC -############################################################################### - -############################################################################### -# This file runs the hipcc commands to produce the desired output file -# along with the dependency file needed by CMake to compute dependencies. -# -# Input variables: -# -# verbose:BOOL=<> OFF: Be as quiet as possible (default) -# ON : Describe each step -# build_configuration:STRING=<> Build configuration. Defaults to Debug. -# generated_file:STRING=<> File to generate. Mandatory argument. - -if(NOT build_configuration) - set(build_configuration Debug) -endif() -if(NOT generated_file) - message(FATAL_ERROR "You must specify generated_file on the command line") -endif() - -# Set these up as variables to make reading the generated file easier -set(HIP_HIPCC_EXECUTABLE "@HIP_HIPCC_EXECUTABLE@") # path -set(HIP_HIPCONFIG_EXECUTABLE "@HIP_HIPCONFIG_EXECUTABLE@") #path -set(HIP_HOST_COMPILER "@HIP_HOST_COMPILER@") # path -set(CMAKE_COMMAND "@CMAKE_COMMAND@") # path -set(HIP_run_make2cmake "@HIP_run_make2cmake@") # path -set(HCC_HOME "@HCC_HOME@") #path - -@HIP_HOST_FLAGS@ -@_HIP_HIPCC_FLAGS@ -@_HIP_HCC_FLAGS@ -@_HIP_NVCC_FLAGS@ -set(HIP_HIPCC_INCLUDE_ARGS "@HIP_HIPCC_INCLUDE_ARGS@") # list (needs to be in quotes to handle spaces properly) - -set(cmake_dependency_file "@cmake_dependency_file@") # path -set(source_file "@source_file@") # path -set(host_flag "@host_flag@") # bool - -# Determine compiler and compiler flags -execute_process(COMMAND ${HIP_HIPCONFIG_EXECUTABLE} --platform OUTPUT_VARIABLE HIP_PLATFORM OUTPUT_STRIP_TRAILING_WHITESPACE) -if(NOT host_flag) - set(__CC ${HIP_HIPCC_EXECUTABLE}) - if(HIP_PLATFORM STREQUAL "hcc") - if(NOT "x${HCC_HOME}" STREQUAL "x") - set(ENV{HCC_HOME} ${HCC_HOME}) - endif() - set(__CC_FLAGS ${HIP_HIPCC_FLAGS} ${HIP_HCC_FLAGS} ${HIP_HIPCC_FLAGS_${build_configuration}} ${HIP_HCC_FLAGS_${build_configuration}}) - else() - set(__CC_FLAGS ${HIP_HIPCC_FLAGS} ${HIP_NVCC_FLAGS} ${HIP_HIPCC_FLAGS_${build_configuration}} ${HIP_NVCC_FLAGS_${build_configuration}}) - endif() -else() - set(__CC ${HIP_HOST_COMPILER}) - set(__CC_FLAGS ${CMAKE_HOST_FLAGS} ${CMAKE_HOST_FLAGS_${build_configuration}}) -endif() -set(__CC_INCLUDES ${HIP_HIPCC_INCLUDE_ARGS}) - -# hip_execute_process - Executes a command with optional command echo and status message. -# status - Status message to print if verbose is true -# command - COMMAND argument from the usual execute_process argument structure -# ARGN - Remaining arguments are the command with arguments -# HIP_result - Return value from running the command -macro(hip_execute_process status command) - set(_command ${command}) - if(NOT "x${_command}" STREQUAL "xCOMMAND") - message(FATAL_ERROR "Malformed call to hip_execute_process. Missing COMMAND as second argument. (command = ${command})") - endif() - if(verbose) - execute_process(COMMAND "${CMAKE_COMMAND}" -E echo -- ${status}) - # Build command string to print - set(hip_execute_process_string) - foreach(arg ${ARGN}) - # Escape quotes if any - string(REPLACE "\"" "\\\"" arg ${arg}) - # Surround args with spaces with quotes - if(arg MATCHES " ") - list(APPEND hip_execute_process_string "\"${arg}\"") - else() - list(APPEND hip_execute_process_string ${arg}) - endif() - endforeach() - # Echo the command - execute_process(COMMAND ${CMAKE_COMMAND} -E echo ${hip_execute_process_string}) - endif() - # Run the command - execute_process(COMMAND ${ARGN} RESULT_VARIABLE HIP_result) -endmacro() - -# Delete the target file -hip_execute_process( - "Removing ${generated_file}" - COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" - ) - -# Generate the dependency file -hip_execute_process( - "Generating dependency file: ${cmake_dependency_file}.pre" - COMMAND "${__CC}" - -M - "${source_file}" - -o "${cmake_dependency_file}.pre" - ${__CC_FLAGS} - ${__CC_INCLUDES} - ) - -if(HIP_result) - message(FATAL_ERROR "Error generating ${generated_file}") -endif() - -# Generate the cmake readable dependency file to a temp file -hip_execute_process( - "Generating temporary cmake readable file: ${cmake_dependency_file}.tmp" - COMMAND "${CMAKE_COMMAND}" - -D "input_file:FILEPATH=${cmake_dependency_file}.pre" - -D "output_file:FILEPATH=${cmake_dependency_file}.tmp" - -D "verbose=${verbose}" - -P "${HIP_run_make2cmake}" - ) - -if(HIP_result) - message(FATAL_ERROR "Error generating ${generated_file}") -endif() - -# Copy the file if it is different -hip_execute_process( - "Copy if different ${cmake_dependency_file}.tmp to ${cmake_dependency_file}" - COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${cmake_dependency_file}.tmp" "${cmake_dependency_file}" - ) - -if(HIP_result) - message(FATAL_ERROR "Error generating ${generated_file}") -endif() - -# Delete the temporary file -hip_execute_process( - "Removing ${cmake_dependency_file}.tmp and ${cmake_dependency_file}.pre" - COMMAND "${CMAKE_COMMAND}" -E remove "${cmake_dependency_file}.tmp" "${cmake_dependency_file}.pre" - ) - -if(HIP_result) - message(FATAL_ERROR "Error generating ${generated_file}") -endif() - -# Generate the output file -hip_execute_process( - "Generating ${generated_file}" - COMMAND "${__CC}" - -c - "${source_file}" - -o "${generated_file}" - ${__CC_FLAGS} - ${__CC_INCLUDES} - ) - -if(HIP_result) - # Make sure that we delete the output file - hip_execute_process( - "Removing ${generated_file}" - COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" - ) - message(FATAL_ERROR "Error generating file ${generated_file}") -else() - if(verbose) - message("Generated ${generated_file} successfully.") - endif() -endif() -# vim: ts=4:sw=4:expandtab:smartindent diff --git a/cmake/FindHIP/run_make2cmake.cmake b/cmake/FindHIP/run_make2cmake.cmake deleted file mode 100644 index d2e3eb51690..00000000000 --- a/cmake/FindHIP/run_make2cmake.cmake +++ /dev/null @@ -1,50 +0,0 @@ -############################################################################### -# Computes dependencies using HIPCC -############################################################################### - -############################################################################### -# This file converts dependency files generated using hipcc to a format that -# cmake can understand. - -# Input variables: -# -# input_file:STRING=<> Dependency file to parse. Required argument -# output_file:STRING=<> Output file to generate. Required argument - -if(NOT input_file OR NOT output_file) - message(FATAL_ERROR "You must specify input_file and output_file on the command line") -endif() - -file(READ ${input_file} depend_text) - -if (NOT "${depend_text}" STREQUAL "") - string(REPLACE " /" "\n/" depend_text ${depend_text}) - string(REGEX REPLACE "^.*:" "" depend_text ${depend_text}) - string(REGEX REPLACE "[ \\\\]*\n" ";" depend_text ${depend_text}) - - set(dependency_list "") - - foreach(file ${depend_text}) - string(REGEX REPLACE "^ +" "" file ${file}) - if(NOT EXISTS "${file}") - message(WARNING " Removing non-existent dependency file: ${file}") - set(file "") - endif() - - if(NOT IS_DIRECTORY "${file}") - get_filename_component(file_absolute "${file}" ABSOLUTE) - list(APPEND dependency_list "${file_absolute}") - endif() - endforeach() -endif() - -# Remove the duplicate entries and sort them. -list(REMOVE_DUPLICATES dependency_list) -list(SORT dependency_list) - -foreach(file ${dependency_list}) - set(hip_hipcc_depend "${hip_hipcc_depend} \"${file}\"\n") -endforeach() - -file(WRITE ${output_file} "# Generated by: FindHIP.cmake. Do not edit.\nSET(HIP_HIPCC_DEPEND\n ${hip_hipcc_depend})\n\n") -# vim: ts=4:sw=4:expandtab:smartindent diff --git a/doc/sphinx/installation.rst b/doc/sphinx/installation.rst index 4099308a567..e60be756438 100644 --- a/doc/sphinx/installation.rst +++ b/doc/sphinx/installation.rst @@ -103,7 +103,7 @@ ROCm SDK to make use of GPU computation: wget -qO - http://repo.radeon.com/rocm/apt/debian/rocm.gpg.key | sudo apt-key add - echo 'deb [arch=amd64] http://repo.radeon.com/rocm/apt/debian/ xenial main' | sudo tee /etc/apt/sources.list.d/rocm.list sudo apt update - sudo apt install libnuma-dev rocm-dkms rocblas rocfft rocrand + sudo apt install libnuma-dev rocm-dkms rocblas rocfft rocrand hip-thrust .. _Installing Requirements on Mac OS X: diff --git a/src/core/cuda_wrapper.hpp b/src/core/cuda_wrapper.hpp index 0b4483e3c70..4d8bf355f40 100644 --- a/src/core/cuda_wrapper.hpp +++ b/src/core/cuda_wrapper.hpp @@ -22,6 +22,7 @@ #define cudaGetDeviceProperties hipGetDeviceProperties #define cudaGetErrorString hipGetErrorString #define cudaGetLastError hipGetLastError +#define cudaGetSymbolAddress hipGetSymbolAddress #define cudaFreeHost hipHostFree #define cudaHostAlloc hipHostMalloc #define cudaHostAllocWriteCombined hipHostMallocWriteCombined @@ -57,11 +58,6 @@ #define make_uint3 dim3 -inline cudaError_t cudaGetSymbolAddress(void **devPtr, const char *symbol) { - size_t bytes = 0; - return hipModuleGetGlobal(devPtr, &bytes, 0, symbol); -} - #endif #endif // CUDA_WRAPPER_HPP From c27e9b0c39ef2d6391616e7e102b29485a10463c Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Fri, 4 Jan 2019 16:13:53 +0100 Subject: [PATCH 26/29] Benchmark: Use HEAD as revision --- maintainer/benchmarks/suite.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintainer/benchmarks/suite.sh b/maintainer/benchmarks/suite.sh index 0c4604b46ce..0fd59db15f5 100644 --- a/maintainer/benchmarks/suite.sh +++ b/maintainer/benchmarks/suite.sh @@ -1,7 +1,7 @@ #!/bin/bash # list of commits to benchmark -commits="c1d850ef3c4 c72cb35c3c5 eaa84cd1c92" +commits="HEAD" cd "$(git rev-parse --show-toplevel)" mkdir -p build From 0e054893de1a79e9e630cda713652b46ba5e5ba8 Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Fri, 4 Jan 2019 16:14:14 +0100 Subject: [PATCH 27/29] Benchmark: Corrections to benchmark scripts --- maintainer/benchmarks/lj.py | 7 ++++--- maintainer/benchmarks/p3m.py | 14 +++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/maintainer/benchmarks/lj.py b/maintainer/benchmarks/lj.py index 5bb4a1f11b3..1b77fd0dea9 100644 --- a/maintainer/benchmarks/lj.py +++ b/maintainer/benchmarks/lj.py @@ -85,7 +85,7 @@ ############################################################# system.random_number_generator_state = list(range( n_proc * (system._get_PRNG_state_size() + 1))) -np.random.seed(1) +#np.random.seed(1) # Integration parameters ############################################################# system.time_step = 0.01 @@ -121,7 +121,7 @@ max_displacement=0.01) # warmup -while system.analysis.energy()["total"] > 10 * n_part: +while system.analysis.energy()["total"] > 3 * n_part: print("minimization: {:.1f}".format(system.analysis.energy()["total"])) system.integrator.run(10) print() @@ -132,9 +132,10 @@ # tune skin print("Tune skin: {}".format(system.cell_system.tune_skin( min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) -system.integrator.run(min(30 * measurement_steps, 60000)) +system.integrator.run(min(5 * measurement_steps, 60000)) print("Tune skin: {}".format(system.cell_system.tune_skin( min_skin=0.2, max_skin=1, tol=0.05, int_steps=100))) +system.integrator.run(min(10 * measurement_steps, 60000)) print(system.non_bonded_inter[0, 0].lennard_jones) diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index 80e8b5d70a2..184f4f4514c 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -98,11 +98,10 @@ ############################################################# system.random_number_generator_state = list(range( n_proc * (system._get_PRNG_state_size() + 1))) -np.random.seed(1) # Integration parameters ############################################################# system.time_step = 0.01 -system.cell_system.skin = 1.2 +system.cell_system.skin = .4 system.thermostat.turn_off() @@ -145,16 +144,21 @@ energy = system.analysis.energy() print("After Minimization: E_total = {}".format(energy["total"])) + +system.integrator.set_vv() +system.thermostat.set_langevin(kT=1.0, gamma=1.0) + +system.integrator.run(min(3 * measurement_steps, 1000)) print("Tune skin: {}".format(system.cell_system.tune_skin( - min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) + min_skin=0.4, max_skin=1.6, tol=0.05, int_steps=100))) +system.integrator.run(min(3 * measurement_steps, 3000)) print("Tune p3m") p3m = electrostatics.P3M(prefactor=args.bjerrum_length, accuracy=1e-4) system.actors.add(p3m) -system.integrator.run(min(3 * measurement_steps, 6000)) +system.integrator.run(min(3 * measurement_steps, 3000)) print("Tune skin: {}".format(system.cell_system.tune_skin( min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) -system.thermostat.set_langevin(kT=1.0, gamma=1.0) if not args.visualizer: From 9522b281470e57a7378a99b0e52f82efd0fa594e Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Fri, 4 Jan 2019 16:32:13 +0100 Subject: [PATCH 28/29] Formatting --- maintainer/benchmarks/p3m.py | 1 - 1 file changed, 1 deletion(-) diff --git a/maintainer/benchmarks/p3m.py b/maintainer/benchmarks/p3m.py index 184f4f4514c..819648f901e 100644 --- a/maintainer/benchmarks/p3m.py +++ b/maintainer/benchmarks/p3m.py @@ -160,7 +160,6 @@ min_skin=1.0, max_skin=1.6, tol=0.05, int_steps=100))) - if not args.visualizer: # print initial energies energies = system.analysis.energy() From 6db935b7467d0dc7e542bc9bfab04a84460e9415 Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Fri, 4 Jan 2019 16:32:23 +0100 Subject: [PATCH 29/29] Benchmark: Do not exclude GHOSTS_HAVE_BONDS related features --- maintainer/benchmarks/runner.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/maintainer/benchmarks/runner.sh b/maintainer/benchmarks/runner.sh index ba9576945d7..245b10ca9b5 100644 --- a/maintainer/benchmarks/runner.sh +++ b/maintainer/benchmarks/runner.sh @@ -13,8 +13,6 @@ cat > myconfig-minimal.hpp << EOF EOF cp ../src/core/myconfig-default.hpp myconfig-default.hpp sed 's/#define ADDITIONAL_CHECKS//' ../maintainer/configs/maxset.hpp > myconfig-maxset.hpp -# disable features interfering with LJ benchmarks -sed -ri 's/#define +(THOLE|COLLISION_DETECTION|GHOSTS_HAVE_BONDS)/\/\/#define \1/' myconfig-*.hpp # prepare build area rm -rf src/ maintainer/