diff --git a/.github/workflows/h5bench-hdf5-1.12.0.yml b/.github/workflows/h5bench-hdf5-1.12.0.yml index aa324560..cd17043a 100644 --- a/.github/workflows/h5bench-hdf5-1.12.0.yml +++ b/.github/workflows/h5bench-hdf5-1.12.0.yml @@ -28,7 +28,12 @@ jobs: cd build cmake .. \ - -DH5BENCH_ALL=ON + -DH5BENCH_METADATA=ON \ + -DH5BENCH_EXERCISER=ON \ + -DH5BENCH_AMREX=ON \ + -DH5BENCH_OPENPMD=ON \ + -DH5BENCH_E3SM=ON \ + -DH5BENCH_QMCPACK=OFF make -j 2 make install diff --git a/.github/workflows/h5bench-hdf5-1.13.0.yml b/.github/workflows/h5bench-hdf5-1.13.0.yml index 73eca4d6..13d302b4 100644 --- a/.github/workflows/h5bench-hdf5-1.13.0.yml +++ b/.github/workflows/h5bench-hdf5-1.13.0.yml @@ -22,9 +22,16 @@ jobs: - name: Dependencies run: | + sudo apt-get update + sudo apt-get install libblas-dev liblapack-dev -y + # VOL-ASYNC git clone --recursive https://github.com/hpc-io/vol-async.git /opt/vol-async + # FFTW + wget https://www.fftw.org/fftw-3.3.10.tar.gz + tar zxf fftw-3.3.10.tar.gz + - name: Build Argobots run: | export ABT_DIR=/opt/argobots @@ -37,6 +44,14 @@ jobs: make -j 2 make install + - name: Build FFTW + run: | + cd fftw-3.3.10 + + ./configure + + sudo make install + - name: Build VOL-ASYNC run: | export HDF5_DIR=/opt/hdf5 @@ -266,6 +281,13 @@ jobs: cd build-sync ./h5bench --debug --abort-on-failure ../samples/sync-e3sm.json + - name: Test h5bench SYNC qmcpack + run: | + export LD_LIBRARY_PATH=/opt/hdf5/lib:$LD_LIBRARY_PATH + + cd build + ./h5bench --debug --abort-on-failure ../samples/sync-qmcpack.json + - name: Test h5bench ASYNC write/read run: | export HDF5_DIR=/opt/hdf5 diff --git a/.github/workflows/h5bench-hdf5-develop.yml b/.github/workflows/h5bench-hdf5-develop.yml index 58ed2f20..b71f3727 100644 --- a/.github/workflows/h5bench-hdf5-develop.yml +++ b/.github/workflows/h5bench-hdf5-develop.yml @@ -22,7 +22,7 @@ jobs: - name: Dependencies run: | sudo apt-get update - sudo apt-get install cmake gcc gdb libtool zlib1g-dev python3 libopenmpi-dev -y + sudo apt-get install cmake gcc gdb libtool zlib1g-dev python3 libopenmpi-dev libblas-dev liblapack-dev -y # HDF5 git clone https://github.com/HDFGroup/hdf5.git @@ -30,6 +30,10 @@ jobs: # VOL-ASYNC git clone --recursive https://github.com/hpc-io/vol-async.git /opt/vol-async + # FFTW + wget https://www.fftw.org/fftw-3.3.10.tar.gz + tar zxf fftw-3.3.10.tar.gz + - name: Build HDF5 develop run: | export HDF5_DIR=/opt/hdf5 @@ -59,6 +63,14 @@ jobs: make -j 2 make install + - name: Build FFTW + run: | + cd fftw-3.3.10 + + ./configure + + sudo make install + - name: Build VOL-ASYNC run: | export HDF5_DIR=/opt/hdf5 @@ -405,6 +417,17 @@ jobs: cd build-sync ./h5bench --debug --abort-on-failure ../samples/sync-e3sm.json + - name: Test h5bench SYNC qmcpack + run: | + export HDF5_HOME=/opt/hdf5 + export ABT_HOME=/opt/argobots + export ASYNC_HOME=/opt/vol-async + + export LD_LIBRARY_PATH=$ASYNC_HOME/lib:$HDF5_HOME/lib:$ABT_HOME/lib:$LD_LIBRARY_PATH + + cd build-sync + ./h5bench --debug --abort-on-failure ../samples/sync-qmcpack.json + - name: Test h5bench ASYNC write/read run: | export HDF5_DIR=/opt/hdf5 diff --git a/.gitmodules b/.gitmodules index 3ac7ac39..73945f35 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,3 +9,6 @@ [submodule "e3sm"] path = e3sm url = https://github.com/Parallel-NetCDF/E3SM-IO +[submodule "qmcpack"] + path = qmcpack + url = https://github.com/QMCPACK/qmcpack diff --git a/CMakeLists.txt b/CMakeLists.txt index ce126988..127c6151 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ option(H5BENCH_EXERCISER "Enable Exerciser benchmark" OFF) option(H5BENCH_AMREX "Enable AMReX benchmark" OFF) option(H5BENCH_OPENPMD "Enable OpenPMD benchmark" OFF) option(H5BENCH_E3SM "Enable E3SM benchmark" OFF) +option(H5BENCH_QMCPACK "Enable QMCPACK benchmark" OFF) message(STATUS "h5bench baseline: ON") @@ -39,6 +40,7 @@ if(H5BENCH_ALL) set(H5BENCH_AMREX ON) set(H5BENCH_OPENPMD ON) set(H5BENCH_E3SM ON) + set(H5BENCH_QMCPACK ON) endif() message(STATUS "h5bench METADATA: ${H5BENCH_METADATA}") @@ -46,6 +48,7 @@ message(STATUS "h5bench EXERCISER: ${H5BENCH_EXERCISER}") message(STATUS "h5bench AMREX: ${H5BENCH_AMREX}") message(STATUS "h5bench OPENPMD: ${H5BENCH_OPENPMD}") message(STATUS "h5bench E3SM: ${H5BENCH_E3SM}") +message(STATUS "h5bench QMCPACK: ${H5BENCH_QMCPACK}") # HDF5 Dependency ############################################################# # @@ -258,6 +261,29 @@ configure_file(${CMAKE_SOURCE_DIR}/src/h5bench.py ${CMAKE_BINARY_DIR}/h5bench CO configure_file(${CMAKE_SOURCE_DIR}/src/h5bench_version.py ${CMAKE_BINARY_DIR}/h5bench_version.py COPYONLY) configure_file(${CMAKE_SOURCE_DIR}/src/h5bench_configuration.py.in ${CMAKE_BINARY_DIR}/h5bench_configuration.py) +# QMCPACK ##################################################################### +# +# https://github.com/QMCPACK/qmcpack + +if(H5BENCH_QMCPACK) + if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.2.0) + if(${HDF5_VERSION} VERSION_GREATER_EQUAL "1.12.1") + set(ENV{HDF5_ROOT} ${HDF5_HOME}) + set(QMC_BUILD_SANDBOX_ONLY ON) + + add_subdirectory(qmcpack) + + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/qmcpack/bin/restart ${CMAKE_BINARY_DIR}/h5bench_qmcpack + ) + else() + message(FATAL_ERROR "QMCPACK requires at least HDF5 1.12.1") + endif() + else() + message(FATAL_ERROR "QMCPACK requires at least gcc-9.2") + endif() +endif() + # Install binaries ############################################################ install( @@ -332,6 +358,15 @@ if(H5BENCH_AMREX) endif() endif() +if(H5BENCH_QMCPACK) + install( + FILES + h5bench_qmcpack + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION bin + ) +endif() + # Testing ##################################################################### add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests) diff --git a/docs/source/index.rst b/docs/source/index.rst index e1b2fee8..1069a297 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -35,6 +35,7 @@ Exerciser ``h5bench_exerciser`` |:white_check_mark:| |:white_la OpenPMD (write) ``h5bench_openpmd_write`` |:white_check_mark:| |:white_large_square:| |:white_large_square:| |:white_large_square:| OpenPMD (read) ``h5bench_openpmd_read`` |:white_check_mark:| |:white_large_square:| |:white_large_square:| |:white_large_square:| E3SM-IO ``h5bench_e3sm`` |:white_check_mark:| |:white_large_square:| |:white_large_square:| |:white_check_mark:| +QMCPACK ``h5bench_qmcpack`` |:white_check_mark:| |:white_large_square:| |:white_large_square:| |:white_check_mark:| ==================== =========================== ==================== ======================== ======================== ======================== .. toctree:: @@ -54,6 +55,7 @@ E3SM-IO ``h5bench_e3sm`` |:white_check_mark:| |:white_la openpmd exerciser e3sm + qmcpack .. toctree:: :maxdepth: 2 diff --git a/docs/source/qmcpack.rst b/docs/source/qmcpack.rst new file mode 100644 index 00000000..4153f4a5 --- /dev/null +++ b/docs/source/qmcpack.rst @@ -0,0 +1,38 @@ +QMCPACK +======== + +QMCPACK is an open-source production-level many-body ab initio Quantum Monte Carlo code for computing the electronic structure of atoms, molecules, 2D nanomaterials and solids. The solid-state capabilities include metallic systems as well as insulators. + +QMCPACK has a checkpoint/restart miniapp which has been integrated into `h5bench`. It dumps walker configurations and random number seeds to the HDF5 files and then reads them in and check the correctness. To have good performance at large scale, HDF5 version >= 1.10 is needed. + +You can find more information in QMCPACK `GitHub repository `_. + +Configuration +------------- + +You can configure QMCPACK benchmark with the following options. Notice that if you use the ``configuration.json`` approach to define the runs for ``h5bench``, we will automatically generate the final configuration file based on the options you provide in the JSON file. For standalone usage of this benchmark, you can refer to E3SM-IO repository. + +====================== ============================================================================== +**Parameter** **Description** +====================== ============================================================================== +``i`` Number of Monte Carlo steps +``g`` Tiling (``tiling_1 tiling_2 tiling_3``) +``s`` Random seed +``w`` Number of walkers +``r`` Maximum pair distance (i.e., ``rmax``) +====================== ============================================================================== + +JSON Configuration (recomended) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To run an instance of AMReX HDF5 benchmark you need to include the following in the ``benchmarks`` property of your ``configuration.json`` file: + +.. code-block:: + + { + "benchmark": "qmcpack", + "configuration": { + "i": "100", + "g": "4 4 1" + } + } \ No newline at end of file diff --git a/qmcpack b/qmcpack new file mode 160000 index 00000000..5a317ffe --- /dev/null +++ b/qmcpack @@ -0,0 +1 @@ +Subproject commit 5a317ffed3f5ff47149691a277882a903d1f44cc diff --git a/samples/sync-qmcpack.json b/samples/sync-qmcpack.json new file mode 100644 index 00000000..b910c8a9 --- /dev/null +++ b/samples/sync-qmcpack.json @@ -0,0 +1,22 @@ +{ + "mpi": { + "command": "mpirun", + "configuration": "--allow-run-as-root --oversubscribe -np 2 " + }, + "vol": { + + }, + "file-system": { + + }, + "directory": "storage", + "benchmarks": [ + { + "benchmark": "qmcpack", + "configuration": { + "i": "100", + "g": "4 4 1" + } + } + ] +} \ No newline at end of file diff --git a/src/h5bench.py b/src/h5bench.py index 7341d60d..404fd89f 100755 --- a/src/h5bench.py +++ b/src/h5bench.py @@ -32,6 +32,7 @@ class H5bench: H5BENCH_OPENPMD_WRITE = 'h5bench_openpmd_write' H5BENCH_OPENPMD_READ = 'h5bench_openpmd_read' H5BENCH_E3SM = 'h5bench_e3sm' + H5BENCH_QMCPACK = 'h5bench_qmcpack' def __init__(self, setup, prefix=None, debug=None, abort=None, validate=None, filter=None): """Initialize the suite.""" @@ -236,6 +237,8 @@ def run(self): self.run_openpmd(id, benchmark) elif name == 'e3sm': self.run_e3sm(id, benchmark) + elif name == 'qmcpack': + self.run_qmcpack(id, benchmark) else: self.logger.critical('{} - Unsupported benchmark/kernel') @@ -855,6 +858,70 @@ def run_e3sm(self, id, setup): except Exception as e: self.logger.error('Unable to run the benchmark: %s', e) + def run_qmcpack(self, id, setup): + """Run the QMCPACK benchmark.""" + if not self.is_available(self.H5BENCH_QMCPACK): + self.logger.critical('{} is not available'.format(self.H5BENCH_QMCPACK)) + + sys.exit(os.EX_UNAVAILABLE) + + try: + start = time.time() + + configuration = setup['configuration'] + + parameters = [] + + # Create the configuration parameter list + for key in configuration: + if key not in ['d'] and configuration[key]: + parameters.append('-{} {} '.format(key, configuration[key])) + + # Waiting for https://github.com/QMCPACK/qmcpack/pull/4343 to be merged + # parameters.append('-d {}/{} '.format(self.directory, id)) + + if self.prefix: + benchmark_path = self.prefix + '/' + self.H5BENCH_QMCPACK + else: + if os.path.isfile(h5bench_configuration.__install__ + '/' + self.H5BENCH_QMCPACK): + benchmark_path = h5bench_configuration.__install__ + '/' + self.H5BENCH_QMCPACK + else: + benchmark_path = self.H5BENCH_QMCPACK + + command = '{} {} {}'.format( + self.mpi, + benchmark_path, + ' '.join(parameters) + ) + + self.logger.info(command) + + # Make sure the command line is in the correct format + arguments = shlex.split(command) + + stdout_file_name = '{}/{}/stdout'.format(self.directory, id) + stderr_file_name = '{}/{}/stderr'.format(self.directory, id) + + with open(stdout_file_name, mode='w') as stdout_file, open(stderr_file_name, mode='w') as stderr_file: + s = subprocess.Popen(arguments, stdout=stdout_file, stderr=stderr_file, env=self.vol_environment) + sOutput, sError = s.communicate() + + if s.returncode == 0 and not self.check_for_hdf5_error(stderr_file_name): + self.logger.info('SUCCESS (all output files are located at %s/%s)', self.directory, id) + else: + self.logger.error('Return: %s (check %s for detailed log)', s.returncode, stderr_file_name) + + if self.abort: + self.logger.critical('h5bench execution aborted upon first error') + + sys.exit(os.EX_SOFTWARE) + + end = time.time() + + self.logger.info('Runtime: {:.7f} seconds (elapsed time, includes allocation wait time)'.format(end - start)) + except Exception as e: + self.logger.error('Unable to run the benchmark: %s', e) + def main(): PARSER = argparse.ArgumentParser(