# Installation Instructions for Parallel HDF5 ## 1. Overview This file contains instructions for installing parallel HDF5 (PHDF5) using CMake. The document covers: - **Section 1:** Requirements and prerequisites - **Section 2:** Obtaining HDF5 source - **Section 3:** Quick start instructions - **Section 4:** Automated builds with ctest (HPC systems) - **Section 5:** Manual CMake configuration - **Section 6:** Cross-compiling for HPC hardware - **Section 7:** Running parallel tests - **Appendix A:** Sample MPI-IO programs ### 1.1. Requirements PHDF5 requires: - CMake version 3.26 or greater - An MPI compiler with MPI-IO support - A POSIX compliant parallel file system (see References) You should first consult with your system support staff for information on: - How to compile an MPI program - How to run an MPI application - How to access the parallel file system Sample MPI-IO C and Fortran programs are provided in Appendix A. Use them to test your MPI compiler and parallel file system before building HDF5. ### 1.2. Prerequisites for HPC Systems When building on HPC systems: 1. **Create a working directory** accessible from compute nodes for running tests. Use a scratch space or parallel file system - **NOT** your home directory, as this typically causes test failures. 2. **Load required modules:** - Desired compiler modules (and set CC, FC, CXX if needed) - CMake version 3.26 or greater - MPI implementation module 3. **For Cray and other systems with recommend compiler wrappers,** set compiler environment variables AFTER loading modules: ```bash export CC=cc export FC=ftn export CXX=CC ``` ### 1.3. Further Help For installation help, post questions to the HDF Forum or HDF Support: - **HDF Forum:** - **HDF Support:** Include the output of `uname -a` and the contents of `CMakeCache.txt` and `CMakeError.log` from your build directory, and the loaded modules if applicable. --- ## 2. Obtaining HDF5 Source Obtain HDF5 source code from the HDF5 repository or from a release tar file: ```bash git clone https://github.com/HDFGroup/hdf5.git [-b branch] [directory] ``` If no branch is specified, the `develop` branch will be checked out. If no directory is specified, source will be in the `hdf5` directory. For release or snapshot tar files, extract them to your working directory. > **Note:** When using the ctest automated build method (Section 4), the source > directory should be named `hdf5-`, where version uses format `1.xx.xx` > or `2.xx.xx`. Check `H5_VERS_STR` in `src/H5public.h` to determine the version string if needed. --- ## 3. Quick Start Instructions ### 3.1. Using CMake Presets (Recommended for General Builds) For building with CMake 3.26 or greater using presets: ```bash cd hdf5 cmake --workflow --preset ci-StdShar-GNUC --fresh ``` > **Note:** Standard presets do not enable parallel by default. To enable parallel > support, you need to create a custom preset in `CMakeUserPresets.json` that sets > `-DHDF5_ENABLE_PARALLEL=ON`, or use the standard CMake build approach below. ### 3.2. Standard CMake Build (Recommended for Parallel) For a basic parallel build: ```bash mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release \ -DHDF5_ENABLE_PARALLEL=ON \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_TESTING=ON \ .. cmake --build . --config Release ctest . -C Release cmake --install . --prefix /path/to/install ``` ### 3.3. Specifying MPI Compiler CMake can usually find MPI automatically. To specify explicitly: ```bash cmake -DCMAKE_C_COMPILER=mpicc \ -DCMAKE_Fortran_COMPILER=mpif90 \ -DHDF5_ENABLE_PARALLEL=ON \ .. ``` Or use MPI compiler wrappers: ```bash export CC=mpicc export FC=mpif90 cmake -DHDF5_ENABLE_PARALLEL=ON .. ``` ### 3.4. Important Configuration Options | Option | Description | |--------|-------------| | `-DHDF5_ENABLE_PARALLEL=ON` | Enable parallel HDF5 (required) | | `-DBUILD_SHARED_LIBS=ON` | Build shared libraries | | `-DBUILD_STATIC_LIBS=ON` | Build static libraries | | `-DHDF5_BUILD_FORTRAN=ON` | Build Fortran interface | | `-DHDF5_BUILD_CPP_LIB=OFF` | C++ disabled in parallel builds | | `-DHDF5_ENABLE_THREADSAFE=OFF` | Thread safety disabled in parallel builds | | `-DHDF5_ENABLE_SUBFILING_VFD=ON` | Enable subfiling VFD (parallel I/O optimization) | | `-DMPIEXEC_EXECUTABLE=mpiexec` | MPI launcher executable | | `-DMPIEXEC_NUMPROC_FLAG=-n` | MPI flag for number of processes | | `-DMPIEXEC_MAX_NUMPROCS=6` | Number of processes for tests | > **Note:** Some MPI implementations (e.g., OpenMPI 4.0+) disallow oversubscribing > by default. Set `MPIEXEC_MAX_NUMPROCS` to available processors or fewer, or add > appropriate flags (e.g., `--oversubscribe` for OpenMPI). --- ## 4. Automated Builds with ctest (HPC Systems) The ctest command provides automated configure, build, test, and package workflow for HPC systems with batch schedulers. ### 4.1. Setup Steps 1. Rename source directory to `hdf5-` (e.g., `hdf5-2.0.0`) 2. Copy or link these CMake scripts to your working directory: - `hdf5-/config/cmake/scripts/HDF5config.cmake` - `hdf5-/config/cmake/scripts/CTestScript.cmake` - `hdf5-/config/cmake/scripts/HDF5options.cmake` 3. Your working directory should contain: ``` CTestScript.cmake HDF5config.cmake HDF5options.cmake hdf5-/ ``` ### 4.2. Running ctest Basic ctest command: ```bash ctest -S HDF5config.cmake,BUILD_GENERATOR=Unix -C Release -V -O hdf5.log ``` For parallel builds on HPC systems with batch schedulers: ```bash ctest -S HDF5config.cmake,HPC=sbatch,MPI=true -C Release -V -O hdf5.log ``` #### Available HPC Options Add after `HDF5config.cmake,` separated by commas: | Option | Description | |--------|-------------| | `HPC=sbatch` | Use SLURM batch system | | `HPC=bsub` | Use LSF batch system | | `MPI=true` | Enable parallel (disables C++, Java, threadsafe) | | `LOCAL_BATCH_SCRIPT_ARGS="--account="` | Supply batch job account information | #### Examples **SLURM system with parallel:** ```bash ctest -S HDF5config.cmake,HPC=sbatch,MPI=true \ -C Release -V -O hdf5.log ``` Use `-VV` instead of `-V` for more detailed logging. --- ## 5. Manual CMake Configuration If the automated ctest approach is not suitable, you can manually configure and build HDF5. ### 5.1. Create Build Directory ```bash mkdir build && cd build ``` ### 5.2. Run CMake Configure Example for parallel build with Fortran on HPC system: ```bash cmake \ -C ../hdf5-/config/cmake/cacheinit.cmake \ -DCMAKE_BUILD_TYPE:STRING=Release \ -DCMAKE_INSTALL_PREFIX:PATH=/install/path \ -DHDF5_ENABLE_PARALLEL:BOOL=ON \ -DHDF5_BUILD_FORTRAN:BOOL=ON \ -DHDF5_BUILD_CPP_LIB:BOOL=OFF \ -DHDF5_BUILD_JAVA:BOOL=OFF \ -DHDF5_ENABLE_THREADSAFE:BOOL=OFF \ -DHDF5_ENABLE_ZLIB_SUPPORT:BOOL=OFF \ -DHDF5_ENABLE_SZIP_SUPPORT:BOOL=OFF \ -DMPIEXEC_EXECUTABLE:STRING=srun \ -DMPIEXEC_NUMPROC_FLAG:STRING=-n \ -DMPIEXEC_MAX_NUMPROCS:STRING=6 \ -G"Unix Makefiles" \ ../hdf5- ``` ### 5.3. Build ```bash cmake --build . --config Release -j 8 ``` ### 5.4. Test For systems where you can run MPI directly: ```bash ctest . -C Release ``` For batch systems, create and submit batch scripts (see section 7.3). ### 5.5. Install ```bash cmake --install . --prefix /install/path ``` --- ## 6. Cross-Compiling for HPC Hardware ### 6.1. Overview Cross-compiling is the process of building software on one system architecture (like a login node) to be run on a different architecture (like a compute node). This section provides a historical overview of how this was done on systems that are no longer in service. ### 6.2. Historical Example: Knights Landing (KNL) on Cray XC40 A common historical use case was compiling for Intel Knights Landing (KNL) nodes on Cray XC40 systems, such as the retired Mutrino and Cori machines. These supercomputers had login nodes with a standard CPU architecture (e.g., Haswell) but used the different KNL architecture for their compute nodes. To build software for KNL, a "module swapping" technique was required. The build process involved: 1. Loading the compiler module for the login node architecture (e.g., `craype-haswell`) to configure the project. 2. Switching to the compiler module for the compute node architecture (e.g., `craype-mic-knl`) before starting the actual compilation. This process was managed by special CMake toolchain files and custom batch scripts, which were often automated within the `ctest` framework. ### 6.3. Cross-Compilation on Current Systems The specific hardware (Cray XC40, KNL) and the build procedures described above are historical and no longer in use. While cross-compilation is less common on many modern, homogeneous HPC clusters, it is still a necessary technique for advanced architectures, such as systems with different processor types or accelerators (e.g., GPUs). **If you need assistance with cross-compiling for a current HPC system, please contact the facility administrators or The HDF Group (Section 1.3).** --- ## 7. Running Parallel Tests ### 7.1. Test Directory Location The parallel test suite (`testpar/`) contains tests for Parallel HDF5 and MPI-IO. By default, tests use the current directory for test files. To specify a different location (e.g., parallel file system): ```bash export HDF5_PARAPREFIX=/scratch/username/hdf5test ctest . -C Release ``` > **Important:** This is critical for performance - avoid using NFS or home > directories for parallel testing. ### 7.2. Important Test Notes #### t_mpi Tests basic MPI-IO features used by Parallel HDF5. Returns non-zero exit code if required features fail. **Exception:** Testing files >2GB will print informational messages but not fail, as HDF5 can use alternative file drivers (e.g., family driver) to handle size limits. #### t_cache Performs many small I/O requests. May run slowly on NFS or other non-parallel file systems. Set `HDF5_PARAPREFIX` to a parallel file system if this test is slow. #### Test Express Level Controls test thoroughness: ```bash export HDF5_TEST_EXPRESS=3 # Quick tests (default) export HDF5_TEST_EXPRESS=0 # Exhaustive tests ``` #### Test Timeout Default is 1200 seconds (20 minutes). Modify in CMake with: ```bash -DDART_TESTING_TIMEOUT=3600 ``` ### 7.3. Running Tests on Batch Systems **For SLURM systems:** ```bash sbatch -C quad,cache build/bin/batch/ctestS.sl # Serial tests sbatch -C quad,cache build/bin/batch/ctestP.sl # Parallel tests ``` **For LSF systems:** ```bash bsub build/bin/batch/ctestS.lsf # Serial tests bsub build/bin/batch/ctestP.lsf # Parallel tests ``` Batch scripts are generated during CMake configuration in the build directory. ### 7.4. Running Specific Test Categories To run specific test suites: ```bash ctest -R "H5TEST" # Core library tests ctest -R "MPI_TEST" # Parallel/MPI tests ctest -R "CPP|FORTRAN" # C++ and Fortran tests ctest -E "MPI_TEST" # Exclude parallel tests ctest --parallel 4 # Run 4 tests in parallel ``` --- ## 8. Known Platform Notes ### 8.1. Linux Systems For MPICH on Linux, ensure >2GB file support by configuring MPICH with: ```bash -cflags="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64" ``` This is available on Linux kernels 2.4 and greater. ### 8.2. Cray Systems - Use `CC=cc`, `FC=ftn`, `CXX=CC` after loading compiler modules - Unload `craype-hugepages2M` if loaded (**Note**: This is situational advice and is not a universal rule, but it may be a valid troubleshooting step if you encounter memory-related performance issues or allocation errors.) - Disable shared libraries if encountering linking issues: ```bash -DBUILD_SHARED_LIBS=OFF ``` ### 8.3. OpenMPI OpenMPI 4.0+ disallows oversubscribing by default. Either: - Set `MPIEXEC_MAX_NUMPROCS` to actual processor count, or - Add `--oversubscribe` flag: `-DMPIEXEC_PREFLAGS=--oversubscribe` --- ## References **POSIX Compliant:** After a write() to a regular file has successfully returned, any successful read() from each byte position modified by that write() will return the data that was written. A subsequent write() to the same byte will overwrite the file data. If a read() can be proven by any means [e.g., MPI_Barrier()] to occur after a write() of that data, it must reflect that write(), even if calls are made by different processes. > Lewin, D. (1994). "POSIX Programmer's Guide (pg. 513-4)". O'Reilly & > Associates. --- ## Appendix A. Sample MPI-IO Programs Here are sample MPI-IO C and Fortran programs to test your MPI compiler and parallel file system before building HDF5. The programs assume they run in a parallel file system (create test files in current directory). For more examples, please refer to the following directories: HDF5Examples/C/H5PAR and HDF5Examples/FORTRAN/H5PAR ### Example Compiling and Running ```bash mpicc Sample_mpio.c -o c.out mpiexec -np 4 c.out mpif90 Sample_mpio.f90 -o f.out mpiexec -np 4 f.out ``` ### Sample_mpio.c ```c /* Simple MPI-IO program testing if a parallel file can be created. * Default filename can be specified via first program argument. * Each process writes something, then reads all data back. */ #include #include #include #ifndef MPI_FILE_NULL /*MPIO may be defined in mpi.h already */ # include #endif #define DIMSIZE 10 /* dimension size, avoid powers of 2. */ #define PRINTID printf("Proc %d: ", mpi_rank) int main(int ac, char **av) { char hostname[128]; int mpi_size, mpi_rank; MPI_File fh; char *filename = "./mpitest.data"; char mpi_err_str[MPI_MAX_ERROR_STRING]; int mpi_err_strlen; int mpi_err; char writedata[DIMSIZE], readdata[DIMSIZE]; char expect_val; int i, irank; int nerrors = 0; /* number of errors */ MPI_Offset mpi_off; MPI_Status mpi_stat; MPI_Init(&ac, &av); MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); /* get file name if provided */ if (ac > 1){ filename = *++av; } if (mpi_rank==0){ printf("Testing simple MPIO program with %d processes accessing file %s\n", mpi_size, filename); printf(" (Filename can be specified via program argument)\n"); } /* show the hostname so that we can tell where the processes are running */ if (gethostname(hostname, 128) < 0){ PRINTID; printf("gethostname failed\n"); return 1; } PRINTID; printf("hostname=%s\n", hostname); if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDWR | MPI_MODE_CREATE | MPI_MODE_DELETE_ON_CLOSE, MPI_INFO_NULL, &fh)) != MPI_SUCCESS){ MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen); PRINTID; printf("MPI_File_open failed (%s)\n", mpi_err_str); return 1; } /* each process writes some data */ for (i=0; i < DIMSIZE; i++) writedata[i] = mpi_rank*DIMSIZE + i; mpi_off = mpi_rank*DIMSIZE; if ((mpi_err = MPI_File_write_at(fh, mpi_off, writedata, DIMSIZE, MPI_BYTE, &mpi_stat)) != MPI_SUCCESS){ MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen); PRINTID; printf("MPI_File_write_at offset(%ld), bytes (%d), failed (%s)\n", (long) mpi_off, (int) DIMSIZE, mpi_err_str); return 1; }; /* make sure all processes has done writing. */ MPI_Barrier(MPI_COMM_WORLD); /* each process reads all data and verify. */ for (irank=0; irank < mpi_size; irank++){ mpi_off = irank*DIMSIZE; if ((mpi_err = MPI_File_read_at(fh, mpi_off, readdata, DIMSIZE, MPI_BYTE, &mpi_stat)) != MPI_SUCCESS){ MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen); PRINTID; printf("MPI_File_read_at offset(%ld), bytes (%d), failed (%s)\n", (long) mpi_off, (int) DIMSIZE, mpi_err_str); return 1; }; for (i=0; i < DIMSIZE; i++){ expect_val = irank*DIMSIZE + i; if (readdata[i] != expect_val){ PRINTID; printf("read data[%d:%d] got %d, expect %d\n", irank, i, readdata[i], expect_val); nerrors++; } } } if (nerrors) return 1; MPI_File_close(&fh); PRINTID; printf("all tests passed\n"); MPI_Finalize(); return 0; } ``` ### Sample_mpio.f90 ```fortran ! ! The following example demonstrates how to create and close a parallel ! file using MPI-IO calls. ! ! USE MPI is the proper way to bring in MPI definitions but many ! MPI Fortran compiler supports the pseudo standard of INCLUDE. ! So, HDF5 uses the INCLUDE statement instead. ! PROGRAM MPIOEXAMPLE USE mpi IMPLICIT NONE CHARACTER(LEN=80), PARAMETER :: filename = "filef.h5" ! File name INTEGER :: ierror ! Error flag INTEGER :: fh ! File handle INTEGER :: amode ! File access mode call MPI_INIT(ierror) amode = MPI_MODE_RDWR + MPI_MODE_CREATE + MPI_MODE_DELETE_ON_CLOSE call MPI_FILE_OPEN(MPI_COMM_WORLD, filename, amode, MPI_INFO_NULL, fh, ierror) print *, "Trying to create ", filename if ( ierror .eq. MPI_SUCCESS ) then print *, "MPI_FILE_OPEN succeeded" call MPI_FILE_CLOSE(fh, ierror) else print *, "MPI_FILE_OPEN failed" endif call MPI_FINALIZE(ierror); END PROGRAM ```