├── .gitignore ├── .gitignore-bootstrapped ├── .gitmodules ├── .mailmap ├── .travis.yml ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── LICENSE ├── Makefile.am ├── NEWS ├── README ├── README.md ├── bin ├── test_headers.sh └── timpi-config.in ├── bootstrap ├── configure.ac ├── m4 ├── acsm_cxx_tests.m4 ├── ax_cxx_compile_stdcxx_11.m4 ├── build_method.m4 ├── config_summary.m4 ├── timpi_compiler.m4 ├── timpi_optional_features.m4 └── timpi_set_cxx_flags.m4 ├── makerelease.sh ├── src ├── Makefile.am ├── algorithms │ └── include │ │ └── timpi │ │ └── parallel_sync.h ├── apps │ └── version.C ├── parallel │ ├── include │ │ └── timpi │ │ │ ├── attributes.h │ │ │ ├── communicator.h │ │ │ ├── data_type.h │ │ │ ├── message_tag.h │ │ │ ├── op_function.h │ │ │ ├── packing.h │ │ │ ├── packing_decl.h │ │ │ ├── packing_forward.h │ │ │ ├── parallel_communicator_specializations │ │ │ ├── parallel_implementation.h │ │ │ ├── post_wait_copy_buffer.h │ │ │ ├── post_wait_delete_buffer.h │ │ │ ├── post_wait_dereference_shared_ptr.h │ │ │ ├── post_wait_dereference_tag.h │ │ │ ├── post_wait_free_buffer.h │ │ │ ├── post_wait_unpack_buffer.h │ │ │ ├── post_wait_unpack_nested_buffer.h │ │ │ ├── post_wait_work.h │ │ │ ├── request.h │ │ │ ├── serial_implementation.h │ │ │ ├── standard_type.h │ │ │ ├── standard_type_forward.h │ │ │ └── status.h │ └── src │ │ ├── communicator.C │ │ ├── message_tag.C │ │ └── request.C └── utilities │ ├── include │ └── timpi │ │ ├── ignore_warnings.h │ │ ├── restore_warnings.h │ │ ├── semipermanent.h │ │ ├── timpi.h │ │ ├── timpi_assert.h │ │ ├── timpi_call_mpi.h │ │ ├── timpi_init.h │ │ ├── timpi_macros.h │ │ └── timpi_version.h.in │ └── src │ ├── semipermanent.C │ ├── timpi_assert.C │ ├── timpi_init.C │ └── timpi_version.C ├── test ├── Makefile.am ├── dispatch_to_packed_unit.C ├── message_tag_unit.C ├── packed_range_unit.C ├── parallel_sync_unit.C ├── parallel_unit.C ├── run_unit_tests.sh.in ├── set_unit.C └── utility_unit.C └── timpi.pc.in /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | aclocal.m4 3 | timpi_config.h.tmp.in 4 | timpi_config.h.tmp.in~ 5 | timpi_config.h 6 | autom4te.cache 7 | build-aux 8 | configure 9 | doxygen/Makefile.in 10 | m4/libtool.m4 11 | m4/ltoptions.m4 12 | m4/ltsugar.m4 13 | m4/ltversion.m4 14 | m4/lt~obsolete.m4 15 | src/Makefile.in 16 | test/Makefile.in 17 | *~ 18 | build 19 | installed 20 | .clang-format 21 | TAGS 22 | -------------------------------------------------------------------------------- /.gitignore-bootstrapped: -------------------------------------------------------------------------------- 1 | autom4te.cache 2 | *~ 3 | build 4 | installed 5 | .clang-format 6 | TAGS 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "m4/autoconf-submodule"] 2 | path = m4/autoconf-submodule 3 | url = ../../libMesh/autoconf-submodule 4 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Roy H. Stogner 2 | Roy H. Stogner 3 | John W. Peterson 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | script: 3 | - ./bootstrap 4 | - ./configure || cat config.log 5 | - (make check CXXFLAGS='-std=c++11 -Werror -Wall -Wextra -Wcast-align -Wdisabled-optimization -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Winvalid-pch -Wmissing-field-initializers -Wmissing-include-dirs -Wpacked -Wstack-protector -Wtrigraphs -Wunreachable-code -Wunused-label -Wunused-parameter -Wunused-value -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings' && cat test/run_unit_tests.sh.log) || (cat test/run_unit_tests.sh.log test/test-suite.log && false) 6 | matrix: 7 | include: 8 | - os: linux 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-7 openmpi-bin openmpi-common libopenmpi-dev 15 | env: 16 | - MATRIX_EVAL="CC=mpicc && CXX=mpicxx && export TIMPI_RUN='mpirun -np 4'" 17 | 18 | - os: linux 19 | addons: 20 | apt: 21 | sources: 22 | - ubuntu-toolchain-r-test 23 | - llvm-toolchain-precise-3.6 24 | packages: 25 | - clang-3.6 26 | env: 27 | - MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6" 28 | 29 | - os: linux 30 | addons: 31 | apt: 32 | sources: 33 | - ubuntu-toolchain-r-test 34 | packages: 35 | - g++-7 36 | env: 37 | - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" 38 | 39 | before_install: 40 | - eval "${MATRIX_EVAL}" 41 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | This is the output of "git shortlog -s | sort -nr", updated periodically. 2 | 3 | 313 Roy H. Stogner 4 | 105 John W. Peterson 5 | 34 Benjamin S. Kirk 6 | 19 Derek Gaston 7 | 11 Cody Permann 8 | 3 Daniel Schwen 9 | 2 Alexander Lindsay 10 | 1 Hannah Rittich 11 | 1 David Andrs 12 | 1 Boris Boutkov 13 | 1 Andrew E Slaughter 14 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | To see recent changes, run 2 | 3 | $ git log 4 | 5 | To see older changes, visit http://github.com/libMesh/libmesh/commits/master 6 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | # AUTOMAKE_OPTIONS = foreign # Conflicts with libMesh options 3 | AUTOMAKE_OPTIONS = gnu 4 | ACLOCAL_AMFLAGS = -I m4 -I m4/autoconf-submodule 5 | 6 | SUBDIRS = src test 7 | EXTRA_DIST = COPYING 8 | 9 | # Tools in the auxiliary directory 10 | 11 | AUX_DIST = build-aux/install-sh 12 | AUX_DIST += build-aux/missing 13 | AUX_DIST += build-aux/config.guess 14 | AUX_DIST += build-aux/config.sub 15 | AUX_DIST += build-aux/depcomp 16 | AUX_DIST += build-aux/ltmain.sh 17 | 18 | # Support for pkgconfig 19 | pkgconfigdir = $(libdir)/pkgconfig 20 | pkgconfig_DATA = timpi.pc 21 | 22 | # Support for timpi-config in $(exec_prefix)/bin 23 | timpi_configdir = $(exec_prefix)/bin 24 | timpi_config_SCRIPTS = bin/timpi-config 25 | # 26 | # support top-level 'make test_headers' 27 | test_headers: 28 | @cd $(top_builddir)/src && $(MAKE) test_headers 29 | 30 | 31 | # ------------------------------------------- 32 | # Optional support for code coverage analysis 33 | # ------------------------------------------- 34 | 35 | if CODE_COVERAGE_ENABLED 36 | 37 | lcov_dir=$(top_builddir)/doc/lcov/html 38 | 39 | # General philosophy is to maintain code coverage for the 40 | # base library as generated by "make check" tests. 41 | # 42 | # We don't distribute lcov ourselves; it needs to be installed in your 43 | # $PATH, if not on your system then from another third-party 44 | # distribution like $LIBMESH_DIR/contrib/lcov/lconv-1.15/bin/ 45 | 46 | lcov-report: 47 | @mkdir -p $(lcov_dir) 48 | lcov --compat-libtool --directory . --capture --output-file $(lcov_dir)/lcov.info 49 | lcov --list-full-path -l $(lcov_dir)/lcov.info | grep -v "`cd -P $(top_srcdir)/src && pwd`" | cut -d\| -f1 > $(lcov_dir)/remove 50 | lcov --ignore-errors unused -q -r $(lcov_dir)/lcov.info `cat $(lcov_dir)/remove` > $(lcov_dir)/lcov.cleaned.info 51 | @rm $(lcov_dir)/remove 52 | @mv -f $(lcov_dir)/lcov.cleaned.info $(lcov_dir)/lcov.info 53 | genhtml -t "TIMPI" -o $(lcov_dir) $(lcov_dir)/lcov.info 54 | 55 | lcov-reset: 56 | @rm -rf $(lcov_dir) 57 | @find . -name "*.gcda" -exec rm {} \; 58 | lcov --directory . --zerocounters 59 | 60 | coverage: 61 | $(MAKE) lcov-reset 62 | $(MAKE) check 63 | $(MAKE) lcov-report 64 | 65 | CLEANFILES = src/apps/*.gcda src/apps/*.gcno 66 | 67 | .PHONY: lcov-report lcov-reset coverage 68 | 69 | endif 70 | 71 | 72 | # Support 'make install prefix=/other/path' with pkgconfig 73 | install-data-hook: 74 | @if (test "x$(prefix)" != "x@prefix@"); then \ 75 | oldprefix="@prefix@" ; \ 76 | newprefix="$(prefix)" ; \ 77 | cd $(DESTDIR)$(libdir)/pkgconfig ; \ 78 | for genfile in $(pkgconfig_DATA) $(DESTDIR)$(prefix)/bin/timpi-config; do \ 79 | echo " " ; \ 80 | echo " *** replacing $$oldprefix" ; \ 81 | echo " *** with $$newprefix" ; \ 82 | echo " *** in generated file $$genfile" ; \ 83 | echo " " ; \ 84 | cd $(DESTDIR)$(prefix) && cat $$genfile | $(SED) "s,$$oldprefix,$$newprefix,g" > $$genfile.replaced ; \ 85 | cd $(DESTDIR)$(prefix) && mv -f $$genfile.replaced $$genfile ; \ 86 | done ; \ 87 | fi 88 | cat $(DESTDIR)$(timpi_configdir)/timpi-config | $(SED) "s/has_been_installed=no/has_been_installed=yes/g" > $(DESTDIR)$(timpi_configdir)/timpi-config.installed 89 | mv -f $(DESTDIR)$(timpi_configdir)/timpi-config.installed $(DESTDIR)$(timpi_configdir)/timpi-config && chmod +x $(DESTDIR)$(timpi_configdir)/timpi-config 90 | 91 | # Additional files to be deleted by 'make distclean' 92 | DISTCLEANFILES = _configs.sed 93 | DISTCLEANFILES += src/utilities/include/timpi/timpi_config.h 94 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 0.0.0 2 | * Made TIMPI code independent of libMesh 3 | 4 | 0.1.0 5 | * Split TIMPI into a separate repository 6 | 7 | 1.0.0 8 | * automake fixups 9 | * Nonblocking vec receives + syncs 10 | * MPI detection round 2 11 | * Add Communicator::max(map) 12 | * export TIMPI_RUN in Travis MATRIX_EVAL 13 | * Add identical_sizes argument to broadcast 14 | * Make sure that we can test OPROF and PROF methods 15 | * Add map_sum() specialization for non*fixed types 16 | * Add back old map broadcast method 17 | * Parallel testing 18 | * Add Communicator::broadcast(unordered_map) specialization 19 | * Communicator::broadcast(map): Save one communication 20 | * Add Communicator::sum(std::unordered_map) 21 | * Add support for a timpi*config 22 | * Add Communicator::sum(std::map) 23 | * Unit test, compilation fixes 24 | * Dispatch to allgather_packed_range from allgather for dynamic size types 25 | * Remove configure output, temp file 26 | * Added .travis.yml CI tests 27 | 28 | 1.1.0 29 | * broadcast now autodispatches to packed_range when necessary 30 | * Recursive specializations for Packing 31 | * configure bugfix for when environment sets LIBS, CPPFLAGS 32 | 33 | 1.1.1 34 | * autoconf m4 refactoring 35 | 36 | 1.1.2 37 | * Fix for push_parallel_packed_range 38 | 39 | 1.1.3 40 | * Warnings fixes in push_parallel_packed_range 41 | * More container support in push_parallel_packed_range 42 | * push_parallel_packed_range is no longer timpi_experimental 43 | * More unit tests 44 | * Better buffer size control in more packed_range functions 45 | * Reuse derived type object in push_parallel_vector_data 46 | * Have bootstrap check for autoconf submodule initialization 47 | 48 | 1.2 49 | * Directly include header files in parallel_sync.h 50 | * Use default constructor/destructor/assignment in Status, DataType 51 | * Oversized pull responses bugfix 52 | * Clarified Communicator::duplicate() doc comment 53 | 54 | 1.2.1 55 | * Use "-f" when using mv to overwrite our own files 56 | 57 | 1.3 58 | * More dispatches to packed range; displace is_fixed_type idiom 59 | * Add nonblocking min, max, and sum 60 | 61 | 1.4 62 | * Explicitly instantiate DataType superclass for tuple 63 | * Add -Wcast-align to clang ignore_warnings.h 64 | * Ensure methods with SFINAE abling can be used in serial 65 | * Support build_standard_type w/ user allocators 66 | * Quad-precision support 67 | 68 | 1.5 69 | * Move Packing into sources 70 | * Packing specialization 71 | * StandardType support 72 | * Packing support 73 | * Packing 74 | 75 | 1.6 76 | * Generalize push_parallel_[packed_range/vector_data] to allow data moves 77 | 78 | 1.7 79 | * Packing support 80 | 81 | 1.7.1 82 | * Packing size fixes 83 | * Update autoconf submodule 84 | * Make DataType destructor virtual to avoid leaks 85 | 86 | 1.7.2 87 | * Implement copy assignment operators for StandardType 88 | 89 | 1.8.0 90 | * Expanded OpFunction capabilities 91 | * Use SemiPermanent for derived StandardType classes 92 | * Update compiler requirements from C++11 to C++14 93 | * Code coverage support 94 | 95 | 1.8.1 96 | * Simplify logic in parallel_sync (fixing oversized pulls) 97 | 98 | 1.8.2 99 | * Fix new bug in parallel_sync (possible vector corruption) 100 | 101 | 1.8.3 102 | * Prevent gcc spurious warnings in unit test 103 | * Add Intel(R) icc 21 support 104 | * Avoid overzealous gcc memcpy warnings, do our own checks 105 | 106 | 1.8.4 107 | * Avoid our *own* overzealous checks before memcpy 108 | * Dispatch to packed range for gather of dynamic size types 109 | 110 | 1.8.5 111 | * Fixes for packed range specializations 112 | * Avoid overwriting user-specified $LIBS 113 | * More parallel unit testing 114 | * Disable overzealous compiler warning 115 | 116 | 1.9.0 117 | * Packing now uses unsigned int buffer_type too, for better 118 | compatibility in nested Packing types 119 | * More unit test coverage, including for packed ranges, vector 120 | specializations, allgather> 121 | * Auto-dispatch from parallel push to packed_range 122 | * Multiset (multimap, etc) support in set_union() 123 | * Break out Packing declarations in their own header 124 | * Many assorted compiler warning and bug fixes 125 | * Wider compiler support 126 | * Better error messages 127 | * More assertions 128 | * Clarified comments 129 | * Autoconf submodule updates 130 | * Support for 64-bit counts when MPI-4 is available 131 | * Enabled `MPI_THREAD_SERIALIZED` and `MPI_THREAD_MULTIPLE` 132 | * More efficient parallel_sync with rvalue references 133 | * Non-Blocking eXchange algorithm improvements. 134 | * Options to use older parallel synch algorithms in lieu of 135 | Non-Blocking eXchange. 136 | * Default to FPE-safe flags when building 137 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | # TIMPI 2 | Templated Interface to MPI 3 | 4 | ## Build Instructions 5 | 1. `cd` to location of TIMPI clone or extracted tarball. 6 | 2. `mkdir build` 7 | 3. `cd build` 8 | 4. `../configure --prefix=/path/to/timpi/install` 9 | 5. `make` 10 | 6. `make check` (eventually will run example programs and unit tests) 11 | 7. `make install` 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TIMPI 2 | Templated Interface to MPI 3 | 4 | ## Build Instructions 5 | 1. `cd` to location of TIMPI clone or extracted tarball. 6 | 2. `mkdir build` 7 | 3. `cd build` 8 | 4. `../configure --prefix=/path/to/timpi/install` 9 | 5. `make` 10 | 6. `make check` (eventually will run example programs and unit tests) 11 | 7. `make install` 12 | -------------------------------------------------------------------------------- /bin/test_headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -e 3 | 4 | # You can run this script on a single header file by doing: 5 | # test_CXXFLAGS="`timpi-config --cppflags --cxxflags --include`" HEADERS_TO_TEST=exact_solution.h ./bin/test_headers.sh 6 | 7 | # To run this script on *every* header file in an installed TIMPI: 8 | # test_CXXFLAGS="`timpi-config --cppflags --cxxflags --include`" HEADERS_TO_TEST="`find $TIMPI_DIR -name "*.h" -type f -exec basename {} \;`" ./bin/test_headers.sh 9 | 10 | # prefix to use when including headers 11 | PACKAGE_PREFIX=timpi 12 | 13 | # Respect the JOBS environment variable, if it is set 14 | if [ -n "$JOBS" ]; then 15 | n_concurrent=$JOBS 16 | else 17 | n_concurrent=20 18 | fi 19 | 20 | #echo MAKEFLAGS=$MAKEFLAGS 21 | 22 | # Terminal commands to goto specific columns 23 | rescol=65; 24 | 25 | # Terminal commands for setting the color 26 | gotocolumn=; 27 | white=; 28 | green=; 29 | red=; 30 | grey=; 31 | colorreset=; 32 | if (test "X$TERM" != Xdumb && { test -t 1; } 2>/dev/null); then 33 | gotocolumn="\033["$rescol"G"; 34 | white="\033[01;37m"; 35 | green="\033[01;32m"; 36 | red="\033[01;31m"; 37 | grey="\033[00;37m"; 38 | colorreset="\033[m"; # Terminal command to reset to terminal default 39 | fi 40 | 41 | 42 | #echo "CXX=$CXX" 43 | 44 | testing_installed_tree="no" 45 | 46 | if (test "x$test_CXXFLAGS" = "x"); then 47 | 48 | testing_installed_tree="yes" 49 | 50 | if (test "x$PKG_CONFIG" != "xno"); then 51 | test_CXXFLAGS=`pkg-config timpi --cflags` 52 | 53 | elif (command -v timpi-config); then 54 | test_CXXFLAGS=`timpi-config --cppflags --cxxflags --include` 55 | 56 | else 57 | echo "Cannot query package installation!!" 58 | exit 1 59 | fi 60 | fi 61 | 62 | echo "Using test_CXXFLAGS =" $test_CXXFLAGS 63 | 64 | # this function handles the I/O and compiling of a particular header file 65 | # by encapsulating this in a function we can fork it and run multiple builds 66 | # simultaneously 67 | function test_header() 68 | { 69 | myreturn=0 70 | header_to_test=$1 71 | header_name=`basename $header_to_test` 72 | app_file=`mktemp -t $header_name.XXXXXXXXXX` 73 | source_file=$app_file.cxx 74 | object_file=$app_file.o 75 | errlog=$app_file.log 76 | stdout=$app_file.stdout 77 | 78 | printf '%s' "Testing Header $header_to_test ... " > $stdout 79 | echo "#include \"$PACKAGE_PREFIX/$header_name\"" >> $source_file 80 | echo "int foo () { return 0; }" >> $source_file 81 | 82 | #echo $CXX $test_CXXFLAGS $source_file -o $app_file 83 | if $CXX $test_CXXFLAGS $source_file -c -o $object_file >$errlog 2>&1 ; then 84 | # See color codes above. We: 85 | # .) skip to column 65 86 | # .) print [ in white 87 | # .) print OK in green 88 | # .) print ] in white 89 | # .) reset the terminal color 90 | # .) print a newline 91 | printf '\e[65G\e[1;37m[\e[1;32m%s\e[1;37m]\e[m\e[m\n' " OK " >> $stdout 92 | else 93 | # See comment above for OK status 94 | printf '\e[65G\e[1;37m[\e[1;31m%s\e[1;37m]\e[m\e[m\n' " FAILED " >> $stdout 95 | echo "Source file:" >> $stdout 96 | cat $source_file >> $stdout 97 | echo "" >> $stdout 98 | echo "Command line:" >> $stdout 99 | echo $CXX $test_CXXFLAGS $source_file -c -o $object_file >> $stdout 100 | echo "" >> $stdout 101 | echo "Output:" >> $stdout 102 | cat $errlog >> $stdout 103 | echo "" >> $stdout 104 | myreturn=1 105 | fi 106 | 107 | cat $stdout 108 | rm -f $source_file $app_file $object_file $errlog $stdout 109 | 110 | return $myreturn 111 | } 112 | 113 | 114 | if [ "x$HEADERS_TO_TEST" = "x" ]; then 115 | HEADERS_TO_TEST=$DEFAULT_HEADERS_TO_TEST 116 | fi 117 | 118 | 119 | # loop over each header and fork tests 120 | returnval=0 121 | nrunning=0 122 | ntotal=0 123 | runninglist="" 124 | for header_to_test in $HEADERS_TO_TEST ; do 125 | if [ $nrunning -ge $n_concurrent ]; then 126 | for pid in $runninglist ; do 127 | wait $pid 128 | # accumulate the number of failed tests 129 | returnval=$(($returnval+$?)) 130 | done 131 | nrunning=0 132 | runninglist="" 133 | fi 134 | 135 | test_header $header_to_test & 136 | runninglist="$runninglist $!" 137 | nrunning=$(($nrunning+1)) 138 | ntotal=$(($ntotal+1)) 139 | done 140 | 141 | for pid in $runninglist ; do 142 | wait $pid 143 | returnval=$(($returnval+$?)) 144 | done 145 | 146 | echo "$returnval failed tests of $ntotal header files" 147 | 148 | exit $returnval 149 | -------------------------------------------------------------------------------- /bin/timpi-config.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # values substituted from configure 5 | # 6 | host=@host@ 7 | prefix=@prefix@ 8 | exec_prefix=@exec_prefix@ 9 | libdir=@libdir@ 10 | includedir=@includedir@ 11 | legacyinclude=@enablelegacyincludepaths@ 12 | builddir=@abs_top_builddir@ 13 | has_been_installed=no 14 | 15 | # 16 | # Define the usage() function 17 | # 18 | usage () 19 | { 20 | echo "usage: $0 --cppflags --cxxflags --include --libs" 21 | echo " $0 --cxx" 22 | echo " $0 --cc" 23 | echo " $0 --fc" 24 | echo " $0 --fflags" 25 | echo " $0 --version" 26 | echo " $0 --host" 27 | echo " $0 --ldflags" 28 | exit 29 | } 30 | 31 | # 32 | # Need at least one command-line argument 33 | # 34 | if [ "$#" = "0" ] ; then 35 | usage $0 36 | fi 37 | 38 | # 39 | # Need a valid METHOD 40 | # 41 | if (test "x$METHOD" = x); then 42 | #echo "No METHOD specified - defaulting to opt" 43 | METHOD=opt 44 | fi 45 | 46 | case "$METHOD" in 47 | optimized|opt) 48 | CXXFLAGS="@CXXFLAGS_OPT@" 49 | CPPFLAGS="@CPPFLAGS_OPT@" 50 | CFLAGS="@CFLAGS_OPT@" 51 | libext="_opt" 52 | ;; 53 | debug|dbg) 54 | CXXFLAGS="@CXXFLAGS_DBG@" 55 | CPPFLAGS="@CPPFLAGS_DBG@" 56 | CFLAGS="@CFLAGS_DBG@" 57 | libext="_dbg" 58 | ;; 59 | devel) 60 | CXXFLAGS="@CXXFLAGS_DEVEL@" 61 | CPPFLAGS="@CPPFLAGS_DEVEL@" 62 | CFLAGS="@CFLAGS_DEVEL@" 63 | libext="_devel" 64 | ;; 65 | profiling|pro|prof) 66 | CXXFLAGS="@CXXFLAGS_PROF@" 67 | CPPFLAGS="@CPPFLAGS_PROF@" 68 | CFLAGS="@CFLAGS_PROF@" 69 | libext="_prof" 70 | ;; 71 | oprofile|oprof) 72 | CXXFLAGS="@CXXFLAGS_OPROF@" 73 | CPPFLAGS="@CPPFLAGS_OPROF@" 74 | CFLAGS="@CFLAGS_OPROF@" 75 | libext="_oprof" 76 | ;; 77 | *) 78 | echo "ERROR: Unknown \$METHOD: $METHOD" 79 | echo " should be one of: " 80 | exit 1 81 | ;; 82 | esac 83 | 84 | # 85 | # Process the command-line arguments, build up 86 | # return_val 87 | # 88 | return_val="" 89 | 90 | while [ "x$1" != "x" ]; do 91 | case "$1" in 92 | "--cxx") 93 | return_val="@CXX@ $return_val" 94 | ;; 95 | 96 | "--cc") 97 | return_val="@CC@ $return_val" 98 | ;; 99 | 100 | "--f77") 101 | return_val="@F77@ $return_val" 102 | ;; 103 | 104 | "--fc") 105 | return_val="@FC@ $return_val" 106 | ;; 107 | 108 | "--cppflags") 109 | return_val="${CPPFLAGS} $return_val" 110 | ;; 111 | 112 | "--cxxflags") 113 | return_val="${CXXFLAGS} $return_val" 114 | ;; 115 | 116 | "--cflags") 117 | return_val="${CFLAGS} $return_val" 118 | ;; 119 | 120 | "--fflags") 121 | return_val="@FFLAGS@ $return_val" 122 | ;; 123 | 124 | "--include") 125 | # handle legacy include paths when needed. 126 | if (test "x$legacyinclude" = "xyes"); then 127 | return_val="-I${includedir}/timpi $return_val" 128 | fi 129 | return_val="-I${includedir} 130 | @timpi_optional_INCLUDES@ 131 | $return_val" 132 | ;; 133 | 134 | "--libs") 135 | return_val="-Wl,-rpath,${libdir} -L${libdir} -ltimpi${libext} @timpi_optional_LIBS@ $return_val" 136 | ;; 137 | 138 | "--ldflags") 139 | return_val="@timpi_LDFLAGS@ $return_val" 140 | ;; 141 | 142 | "--version") 143 | return_val="@VERSION@" 144 | ;; 145 | 146 | "--host") 147 | return_val="$host" 148 | ;; 149 | 150 | *) 151 | echo "Unknown argument: $1" 152 | usage $0 153 | esac 154 | shift 155 | done 156 | 157 | echo $return_val 158 | 159 | # Local Variables: 160 | # mode: shell-script 161 | # End: 162 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if [ ! -f m4/autoconf-submodule/acsm_mpi.m4 ]; then 4 | echo "autoconf-submodule is needed to bootstrap!" 5 | echo "Try 'git submodule update --init --recursive'" 6 | exit 1 7 | fi 8 | 9 | cmd="autoreconf -v -f -i" 10 | echo "Bootstrapping using $cmd ..." 11 | 12 | $cmd 13 | 14 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl -*- Autoconf -*- 2 | dnl Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.61) 5 | AC_INIT(timpi, 1.9.0, roystgnr@gmail.com) 6 | AC_CONFIG_MACRO_DIR([m4]) 7 | 8 | AC_CONFIG_HEADERS([src/utilities/include/timpi/timpi_config.h.tmp]) 9 | dnl Prefixes everything in the temporary file with TIMPI_ 10 | AX_PREFIX_CONFIG_H(src/utilities/include/timpi/timpi_config.h,TIMPI,src/utilities/include/timpi/timpi_config.h.tmp) 11 | 12 | AC_CONFIG_AUX_DIR([build-aux]) 13 | AC_CANONICAL_TARGET() 14 | AM_INIT_AUTOMAKE([dist-bzip2 tar-ustar 1.11 no-define color-tests parallel-tests subdir-objects]) 15 | AM_SILENT_RULES(yes) # use silent rules where available - automake 1.11 16 | 17 | dnl Turn off AM_MAINTAINER_MODE for bootstrapped release by 18 | dnl uncommenting this: 19 | AM_MAINTAINER_MODE # git trashes timestamps, forcing autoreconf needlessly 20 | 21 | dnl Release versioning 22 | AX_SPLIT_VERSION 23 | GENERIC_MAJOR_VERSION=$AX_MAJOR_VERSION 24 | GENERIC_MINOR_VERSION=$AX_MINOR_VERSION 25 | GENERIC_MICRO_VERSION=$AX_POINT_VERSION 26 | GENERIC_LIBRARY_NAME=timpi 27 | 28 | dnl shared library versioning 29 | 30 | PACKAGE=$GENERIC_LIBRARY_NAME 31 | GENERIC_VERSION=$GENERIC_MAJOR_VERSION.$GENERIC_MINOR_VERSION.$GENERIC_MICRO_VERSION 32 | GENERIC_RELEASE=$GENERIC_MAJOR_VERSION.$GENERIC_MINOR_VERSION 33 | 34 | dnl AC_SUBST(GENERIC_LIBRARY_VERSION) 35 | dnl AC_SUBST(GENERIC_LIBRARY_NAME) 36 | 37 | AC_SUBST(GENERIC_VERSION) 38 | AC_SUBST(GENERIC_RELEASE) 39 | AC_SUBST(GENERIC_MAJOR_VERSION) 40 | AC_SUBST(GENERIC_MINOR_VERSION) 41 | AC_SUBST(GENERIC_MICRO_VERSION) 42 | 43 | AC_DEFINE_UNQUOTED([MAJOR_VERSION],$GENERIC_MAJOR_VERSION,[Major version]) 44 | AC_DEFINE_UNQUOTED([MINOR_VERSION],$GENERIC_MINOR_VERSION,[Minor version]) 45 | AC_DEFINE_UNQUOTED([MICRO_VERSION],$GENERIC_MICRO_VERSION,[Micro version]) 46 | 47 | 48 | # by default CFLAGS and CXXFLAGS are set to '-g -O2' on systems that support them. 49 | # this causes a problem if we then declare a different optimization level. So 50 | # default them to empty, regardless of what the system supports. 51 | : ${CFLAGS=""} 52 | : ${CXXFLAGS=""} 53 | 54 | #-------------------------------------------------------------------- 55 | # Check for whether to enable MPI and PETSc which will influence our 56 | # choice of compiler 57 | #-------------------------------------------------------------------- 58 | ACSM_COMPILER_CONTROL_ARGS 59 | 60 | #----------------------------------------------------------------------- 61 | # Scrape PETSc configure information for their CXX, MPI_INCLUDE, MPI_LIB 62 | #----------------------------------------------------------------------- 63 | ACSM_SCRAPE_PETSC_CONFIGURE 64 | 65 | 66 | dnl------------------------------ 67 | dnl Checks for compilers 68 | dnl------------------------------ 69 | 70 | TIMPI_SET_COMPILERS 71 | 72 | # -------------------------------------------------------------- 73 | # Autoconf macro for determining the proper -std=c++?? 74 | # flag, for the current compiler, for the user's requested C++ 75 | # standards level. Adds the required flag to CXXFLAGS if 76 | # one is found. Exits if no acceptable flag is found. 77 | # 78 | # We've started relying on C++14 code in TIMPI; we also use C++17 79 | # but with backward compatibility shims. 80 | # -------------------------------------------------------------- 81 | ACSM_CXX_COMPILER_STANDARD([2014], [2017]) 82 | 83 | #----------------------------------------------------- 84 | # Set compiler flags for devel, opt, etc. methods 85 | #----------------------------------------------------- 86 | TIMPI_SET_CXX_FLAGS 87 | 88 | #------------------------------------------------------ 89 | # Checks for code coverage 90 | # this must be done after we look for our own compilers 91 | #------------------------------------------------------ 92 | ACSM_CODE_COVERAGE 93 | timpi_CFLAGS="$GCOV_FLAGS $timpi_CFLAGS" 94 | timpi_CXXFLAGS="$GCOV_FLAGS $timpi_CXXFLAGS" 95 | 96 | SET_BUILD_METHODS 97 | 98 | ACSM_ENABLE_PARANOID 99 | 100 | ACSM_ENABLE_WERROR 101 | 102 | dnl--------------------------------------------------------- 103 | dnl Checks for library prerequisites for other libraries... 104 | dnl--------------------------------------------------------- 105 | 106 | dnl------------------------------------------------------ 107 | dnl If the user didn't --disable-mpi, try hard to find it 108 | dnl------------------------------------------------------ 109 | timpi_optional_INCLUDES="" 110 | timpi_optional_LIBS="" 111 | 112 | AS_IF([test "x$enablempi" = xyes], 113 | [ 114 | ACSM_MPI 115 | AS_IF([test "x$enablempi" = xyes], 116 | [ 117 | AS_IF([test x"$MPI_INCLUDES" = x],,[timpi_optional_INCLUDES="$MPI_INCLUDES $timpi_optional_INCLUDES"]) 118 | AS_IF([test x"$MPI_LIBS" != x], [timpi_optional_LIBS="$MPI_LIBS $timpi_optional_LIBS"]) 119 | AS_IF([test x"$MPI_LDFLAGS" != x], [timpi_optional_LIBS="$MPI_LDFLAGS $timpi_optional_LIBS"]) 120 | ]) 121 | ]) 122 | 123 | AC_SUBST(timpi_optional_INCLUDES) 124 | AC_SUBST(timpi_optional_LIBS) 125 | 126 | dnl--------------------------------------------------------- 127 | dnl Sets library options 128 | dnl--------------------------------------------------------- 129 | 130 | TIMPI_OPTIONAL_FEATURES 131 | 132 | dnl----------------------------------------------------- 133 | dnl Initialize libtool. By default, we will build 134 | dnl only shared libraries on platforms that support them 135 | dnl----------------------------------------------------- 136 | LT_INIT([disable-static]) 137 | 138 | dnl--------------------------------- 139 | dnl Query configuration environment 140 | dnl--------------------------------- 141 | ACSM_SUMMARIZE_ENV 142 | 143 | dnl----------------------------------------------- 144 | dnl Generate header files 145 | dnl----------------------------------------------- 146 | AC_CONFIG_FILES(src/utilities/include/timpi/timpi_version.h) 147 | 148 | dnl----------------------------------------------- 149 | dnl Generate Makefiles 150 | dnl----------------------------------------------- 151 | AC_CONFIG_FILES([ 152 | Makefile 153 | timpi.pc 154 | src/Makefile 155 | test/Makefile 156 | ]) 157 | 158 | AC_CONFIG_FILES(bin/timpi-config, [chmod +x bin/timpi-config]) 159 | AC_CONFIG_FILES(test/run_unit_tests.sh, [chmod +x test/run_unit_tests.sh]) 160 | 161 | # Must still call AC_OUTPUT() after generating all the files 162 | AC_OUTPUT() 163 | 164 | dnl------------------------------ 165 | dnl Final summary 166 | dnl------------------------------ 167 | AX_SUMMARIZE_CONFIG 168 | -------------------------------------------------------------------------------- /m4/acsm_cxx_tests.m4: -------------------------------------------------------------------------------- 1 | dnl ---------------------------------------------------------------- 2 | dnl Test callback for use with ACSM. 3 | dnl ---------------------------------------------------------------- 4 | 5 | dnl Currently we don't bother with extra tests ourselves. 6 | dnl 7 | dnl This is in the ACSM namespace because it is a "callback" from an 8 | dnl ACSM macro. 9 | 10 | AC_DEFUN([ACSM_TEST_CXX_ALL], 11 | [ 12 | # Roll the dice! 13 | have_cxx_all=yes 14 | ]) 15 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx_11.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html 3 | # ============================================================================ 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++11 12 | # standard; if necessary, add switches to CXXFLAGS to enable support. 13 | # 14 | # The first argument, if specified, indicates whether you insist on an 15 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 16 | # -std=c++11). If neither is specified, you get whatever works, with 17 | # preference for an extended mode. 18 | # 19 | # The second argument, if specified 'mandatory' or if left unspecified, 20 | # indicates that baseline C++11 support is required and that the macro 21 | # should error out if no mode with that support is found. If specified 22 | # 'optional', then configuration proceeds regardless, after defining 23 | # HAVE_CXX11 if and only if a supporting mode is found. 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2008 Benjamin Kosnik 28 | # Copyright (c) 2012 Zack Weinberg 29 | # Copyright (c) 2013 Roy Stogner 30 | # Copyright (c) 2014 Alexey Sokolov 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 4 38 | 39 | m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ 40 | template 41 | struct check 42 | { 43 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 44 | }; 45 | 46 | typedef check> right_angle_brackets; 47 | 48 | int a; 49 | decltype(a) b; 50 | 51 | typedef check check_type; 52 | check_type c; 53 | check_type&& cr = static_cast(c); 54 | 55 | auto d = a; 56 | auto l = [](){}; 57 | 58 | // The compiler may evaluate something like: 59 | // const int val = multiply(10, 10); 60 | // at compile time. 61 | constexpr int multiply (int x, int y) { return x * y; } 62 | 63 | // A minimally-conforming C++11 compiler must support alias declarations 64 | template 65 | using MyCheck = check; 66 | ]]) 67 | 68 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl 69 | m4_if([$1], [], [], 70 | [$1], [ext], [], 71 | [$1], [noext], [], 72 | [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl 73 | m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], 74 | [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], 75 | [$2], [optional], [ax_cxx_compile_cxx11_required=false], 76 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) 77 | AC_LANG_PUSH([C++])dnl 78 | ac_success=no 79 | AC_CACHE_CHECK(whether $CXX supports C++11 features by default, 80 | ax_cv_cxx_compile_cxx11, 81 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], 82 | [ax_cv_cxx_compile_cxx11=yes], 83 | [ax_cv_cxx_compile_cxx11=no])]) 84 | AS_IF([test "x$ax_cv_cxx_compile_cxx11" = "xyes"], [ac_success=yes]) 85 | 86 | m4_if([$1], [noext], [], [dnl 87 | AS_IF([test "x$ac_success" = "xno"], [ 88 | for switch in -std=gnu++11 -std=gnu++0x; do 89 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) 90 | AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, 91 | $cachevar, 92 | [ac_save_CXXFLAGS="$CXXFLAGS" 93 | CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 94 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], 95 | [eval $cachevar=yes], 96 | [eval $cachevar=no]) 97 | CXXFLAGS="$ac_save_CXXFLAGS"]) 98 | AS_IF([eval test x\$$cachevar = xyes], [ 99 | dnl libmesh propagates CXXFLAGS_OPT, CXXFLAGS_DEVEL, and CXXFLAGS_DBG 100 | dnl to its config script, so make sure they know about the C++11 flag 101 | dnl we found. Note that we still determine the proper switch even if 102 | dnl the user has not enabled C++11, but we only only propagate it to 103 | dnl the flags if the user has enabled C++11. 104 | AS_IF([test "x$enablecxx11" = "xyes"], 105 | [ 106 | CXXFLAGS="$CXXFLAGS $switch" 107 | CXXFLAGS_OPT="$CXXFLAGS_OPT $switch" 108 | CXXFLAGS_DEVEL="$CXXFLAGS_DEVEL $switch" 109 | CXXFLAGS_DBG="$CXXFLAGS_DBG $switch" 110 | ]) 111 | ac_success=yes 112 | break 113 | ]) 114 | done 115 | ])]) 116 | 117 | dnl The only difference between this block of code and the one above appears 118 | dnl to be the noext vs. ext arguments to m4_if. I think the intention was to 119 | dnl allow people to specify whether they want special GNU extensions of the 120 | dnl C++11 standard vs. "vanilla" C++11, but I'm not sure how important this 121 | dnl distinction is nowadays... 122 | m4_if([$1], [ext], [], [dnl 123 | AS_IF([test "x$ac_success" = "xno"], [ 124 | for switch in -std=c++11 -std=c++0x; do 125 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) 126 | AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, 127 | $cachevar, 128 | [ac_save_CXXFLAGS="$CXXFLAGS" 129 | CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 130 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], 131 | [eval $cachevar=yes], 132 | [eval $cachevar=no]) 133 | CXXFLAGS="$ac_save_CXXFLAGS"]) 134 | AS_IF([eval test x\$$cachevar = xyes], [ 135 | dnl libmesh propagates CXXFLAGS_OPT, CXXFLAGS_DEVEL, and CXXFLAGS_DBG 136 | dnl to its config script, so make sure they know about the C++11 flag 137 | dnl we found. Note that we still determine the proper switch even if 138 | dnl the user has not enabled C++11, but we only only propagate it to 139 | dnl the flags if the user has enabled C++11. 140 | AS_IF([test "x$enablecxx11" = "xyes"], 141 | [ 142 | CXXFLAGS="$CXXFLAGS $switch" 143 | CXXFLAGS_OPT="$CXXFLAGS_OPT $switch" 144 | CXXFLAGS_DEVEL="$CXXFLAGS_DEVEL $switch" 145 | CXXFLAGS_DBG="$CXXFLAGS_DBG $switch" 146 | ]) 147 | ac_success=yes 148 | break 149 | ]) 150 | done 151 | ])]) 152 | AC_LANG_POP([C++]) 153 | 154 | AS_IF([test "x$ax_cxx_compile_cxx11_required" = "xtrue"], 155 | [ 156 | AS_IF([test "x$ac_success" = "xno"], 157 | [ 158 | dnl We return error code 2 here, since 0 means success and 1 is 159 | dnl indistinguishable from other errors. Ideally, all of the 160 | dnl AC_MSG_ERROR calls in our m4 files would return a different 161 | dnl error code, but currently this is not implemented. 162 | AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.], 2) 163 | ], 164 | [ 165 | HAVE_CXX11=1 166 | AC_DEFINE(HAVE_CXX11, 1, [define if the compiler supports basic C++11 syntax]) 167 | ]) 168 | ], 169 | [ 170 | AS_IF([test "x$ac_success" = "xno"], 171 | [ 172 | HAVE_CXX11=0 173 | AC_MSG_NOTICE([No compiler with C++11 support was found]) 174 | dnl We couldn't find a working C++11 compiler, so we need to set 175 | dnl enablecxx11=no. This way, other C++11 features can potentially 176 | dnl still be detected, and listed as "have but disabled" by 177 | dnl configure. 178 | enablecxx11=no 179 | ], 180 | [ 181 | dnl Only set LIBMESH_HAVE_CXX11 if the user has actually configured with --enable-cxx11. 182 | AS_IF([test "x$enablecxx11" = "xyes"], 183 | [ 184 | HAVE_CXX11=1 185 | AC_DEFINE(HAVE_CXX11,1, [define if the compiler supports basic C++11 syntax]) 186 | ]) 187 | ]) 188 | 189 | AC_SUBST(HAVE_CXX11) 190 | ]) 191 | ]) 192 | -------------------------------------------------------------------------------- /m4/build_method.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([SET_BUILD_METHODS], 2 | [ 3 | AC_ARG_VAR([METHODS], [methods used to build with, e.g. "opt dbg devel". Possibilities include: (opt,dbg,devel,prof,oprof)]) 4 | 5 | dnl accept --with-methods=METHODS. but default to $METHODS, which is either set 6 | dnl by the user already or defaulted above 7 | AC_ARG_WITH(methods, 8 | AS_HELP_STRING([--with-methods=METHODS], 9 | [methods used to build with (opt,dbg,devel,prof,oprof)]), 10 | [for method in ${withval} ; do 11 | dnl make sure each method specified makes sense 12 | AS_CASE("${method}", 13 | [optimized|opt], [], 14 | [debug|dbg], [], 15 | [devel], [], 16 | [profiling|pro|prof], [], 17 | [oprofile|oprof], [], 18 | [AC_MSG_ERROR(bad value ${method} for --with-methods)]) 19 | done 20 | METHODS=${withval}], 21 | [ 22 | dnl default METHOD is opt if not specified. 23 | AS_IF([test "x${METHODS}" = x], 24 | [ 25 | METHODS="dbg devel opt" 26 | AC_MSG_RESULT([No build methods specified, defaulting to "$METHODS"]) 27 | ]) 28 | ]) 29 | 30 | AC_MSG_RESULT([<<< Configuring with methods "$METHODS" >>>]) 31 | 32 | AC_ARG_VAR([timpi_CPPFLAGS], [User-specified C/C++ preprocessor flags]) 33 | AC_ARG_VAR([timpi_CXXFLAGS], [User-specified C++ compilation flags]) 34 | AC_ARG_VAR([timpi_CFLAGS], [User-specified C compilation flags]) 35 | 36 | build_opt=no 37 | build_dbg=no 38 | build_devel=no 39 | build_prof=no 40 | build_oprof=no 41 | 42 | dnl define compiler flags for all methods 43 | CPPFLAGS_OPT="$CPPFLAGS_OPT $timpi_CPPFLAGS" 44 | CXXFLAGS_OPT="$CXXFLAGS_OPT $timpi_CXXFLAGS" 45 | CFLAGS_OPT="$CFLAGS_OPT $timpi_CFLAGS" 46 | 47 | CPPFLAGS_DBG="$CPPFLAGS_DBG $timpi_CPPFLAGS" 48 | CXXFLAGS_DBG="$CXXFLAGS_DBG $timpi_CXXFLAGS" 49 | CFLAGS_DBG="$CFLAGS_DBG $timpi_CFLAGS" 50 | 51 | CPPFLAGS_DEVEL="$CPPFLAGS_DEVEL $timpi_CPPFLAGS" 52 | CXXFLAGS_DEVEL="$CXXFLAGS_DEVEL $timpi_CXXFLAGS" 53 | CFLAGS_DEVEL="$CFLAGS_DEVEL $timpi_CFLAGS" 54 | 55 | dnl profiling-specific flags are derivatives of optimized flags 56 | CPPFLAGS_PROF="$CPPFLAGS_OPT" 57 | CXXFLAGS_PROF="$CXXFLAGS_OPT $PROFILING_FLAGS" 58 | CFLAGS_PROF="$CFLAGS_OPT $PROFILING_FLAGS" 59 | 60 | CPPFLAGS_OPROF="$CPPFLAGS_OPT" 61 | CXXFLAGS_OPROF="$CXXFLAGS_OPT $OPROFILE_FLAGS" 62 | CFLAGS_OPROF="$CFLAGS_OPT $OPROFILE_FLAGS" 63 | 64 | dnl The PROF and OPROF methods are derived from opt, but we don't want 65 | dnl to turn on address sanitizer stuff in prof/oprof mode just because 66 | dnl it got turned on in opt mode. Hence this second round of setting 67 | dnl all the flags vars... 68 | CXXFLAGS_OPT="$CXXFLAGS_OPT $SANITIZE_OPT_FLAGS" 69 | CFLAGS_OPT="$CFLAGS_OPT $SANITIZE_OPT_FLAGS" 70 | 71 | CXXFLAGS_DBG="$CXXFLAGS_DBG $SANITIZE_DBG_FLAGS" 72 | CFLAGS_DBG="$CFLAGS_DBG $SANITIZE_DBG_FLAGS" 73 | 74 | CXXFLAGS_DEVEL="$CXXFLAGS_DEVEL $SANITIZE_DEVEL_FLAGS" 75 | CFLAGS_DEVEL="$CFLAGS_DEVEL $SANITIZE_DEVEL_FLAGS" 76 | 77 | CXXFLAGS_PROF="$CXXFLAGS_PROF $SANITIZE_PROF_FLAGS" 78 | CFLAGS_PROF="$CFLAGS_PROF $SANITIZE_PROF_FLAGS" 79 | 80 | CXXFLAGS_OPROF="$CXXFLAGS_OPROF $SANITIZE_OPROF_FLAGS" 81 | CFLAGS_OPROF="$CFLAGS_OPROF $SANITIZE_OPROF_FLAGS" 82 | 83 | dnl conditionally compile selected methods 84 | for method in ${METHODS}; do 85 | AS_CASE("${method}", 86 | [optimized|opt], [build_opt=yes], 87 | [debug|dbg], [build_dbg=yes], 88 | [devel], [build_devel=yes], 89 | [profiling|pro|prof], [build_prof=yes], 90 | [oprofile|oprof], [build_oprof=yes], 91 | [AC_MSG_ERROR(bad value ${method} for --with-methods)]) 92 | done 93 | 94 | AM_CONDITIONAL(BUILD_OPT_MODE, test x$build_opt = xyes) 95 | AM_CONDITIONAL(BUILD_DBG_MODE, test x$build_dbg = xyes) 96 | AM_CONDITIONAL(BUILD_DEVEL_MODE, test x$build_devel = xyes) 97 | AM_CONDITIONAL(BUILD_PROF_MODE, test x$build_prof = xyes) 98 | AM_CONDITIONAL(BUILD_OPROF_MODE, test x$build_oprof = xyes) 99 | 100 | dnl substitute all methods 101 | AC_SUBST(CPPFLAGS_DBG) 102 | AC_SUBST(CXXFLAGS_DBG) 103 | AC_SUBST(CFLAGS_DBG) 104 | 105 | AC_SUBST(CPPFLAGS_DEVEL) 106 | AC_SUBST(CXXFLAGS_DEVEL) 107 | AC_SUBST(CFLAGS_DEVEL) 108 | 109 | AC_SUBST(CPPFLAGS_OPT) 110 | AC_SUBST(CXXFLAGS_OPT) 111 | AC_SUBST(CFLAGS_OPT) 112 | 113 | AC_SUBST(CPPFLAGS_PROF) 114 | AC_SUBST(CXXFLAGS_PROF) 115 | AC_SUBST(CFLAGS_PROF) 116 | 117 | AC_SUBST(CPPFLAGS_OPROF) 118 | AC_SUBST(CXXFLAGS_OPROF) 119 | AC_SUBST(CFLAGS_OPROF) 120 | 121 | ]) 122 | -------------------------------------------------------------------------------- /m4/config_summary.m4: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | # 3 | # Summarizes configuration settings. 4 | # 5 | # AX_SUMMARIZE_CONFIG([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) 6 | # 7 | # DESCRIPTION 8 | # 9 | # Outputs a summary of relevant configuration settings. 10 | # 11 | # LAST MODIFICATION 12 | # 13 | # 2019-10-31 14 | # 15 | 16 | AC_DEFUN([AX_SUMMARIZE_CONFIG], 17 | [ 18 | 19 | AS_ECHO([]) 20 | AS_ECHO(["----------------------------------- SUMMARY -----------------------------------"]) 21 | AS_ECHO([]) 22 | AS_ECHO(["Package version............... : $PACKAGE-$VERSION"]) 23 | AS_ECHO([]) 24 | AS_ECHO(["C++ compiler.................. : $CXX"]) 25 | AS_ECHO(["Build Methods...................... : $METHODS"]) 26 | for method in ${METHODS}; do 27 | AS_CASE("${method}", 28 | [opt], [AS_ECHO(["CPPFLAGS...(opt)................... : $CPPFLAGS_OPT $CPPFLAGS"]) 29 | AS_ECHO(["CXXFLAGS...(opt)................... : $CXXFLAGS_OPT $CXXFLAGS"])], 30 | [devel], [AS_ECHO(["CPPFLAGS...(devel)................. : $CPPFLAGS_DEVEL $CPPFLAGS"]) 31 | AS_ECHO(["CXXFLAGS...(devel)................. : $CXXFLAGS_DEVEL $CXXFLAGS"])], 32 | [dbg], [AS_ECHO(["CPPFLAGS...(dbg)................... : $CPPFLAGS_DBG $CPPFLAGS"]) 33 | AS_ECHO(["CXXFLAGS...(dbg)................... : $CXXFLAGS_DBG $CXXFLAGS"])], 34 | [prof], [AS_ECHO(["CPPFLAGS...(prof).................. : $CPPFLAGS_PROF $CPPFLAGS"]) 35 | AS_ECHO(["CXXFLAGS...(prof).................. : $CXXFLAGS_PROF $CXXFLAGS"])], 36 | [oprof], [AS_ECHO(["CPPFLAGS...(oprof)................. : $CPPFLAGS_OPROF $CPPFLAGS"]) 37 | AS_ECHO(["CXXFLAGS...(oprof)................. : $CXXFLAGS_OPROF $CXXFLAGS"])]) 38 | AS_ECHO([]) 39 | done 40 | 41 | AS_ECHO(["Any warnings-to-errors flags.. : $ACSM_ANY_WERROR_FLAG"]) 42 | AS_ECHO(["Any paranoid warning flags.... : $ACSM_ANY_PARANOID_FLAGS"]) 43 | AS_ECHO(["Install dir................... : $prefix"]) 44 | AS_ECHO(["Build user.................... : $USER"]) 45 | AS_ECHO(["Build host.................... : $BUILD_HOST"]) 46 | AS_ECHO(["Configure date................ : $BUILD_DATE"]) 47 | AS_ECHO(["Build architecture............ : $BUILD_ARCH"]) 48 | AS_ECHO(["Git revision number........... : $BUILD_VERSION"]) 49 | AS_ECHO([]) 50 | AS_ECHO(["-------------------------------------------------------------------------------"]) 51 | 52 | AS_ECHO(["Optional Packages for Testing:"]) 53 | AS_IF([test "x$enablempi" = "xyes"], 54 | [ 55 | AS_ECHO([" MPI......................... : yes"]) 56 | AS_ECHO([" MPI_IMPL.................... : $MPI_IMPL"]) 57 | ], 58 | [ 59 | AS_ECHO([" MPI......................... : no"]) 60 | ]) 61 | AS_IF([test "x$timpi_optional_INCLUDES" != "x"], 62 | [ 63 | AS_ECHO([" timpi_optional_INCLUDES..... : $timpi_optional_INCLUDES"]) 64 | ]) 65 | AS_IF([test "x$timpi_optional_LIBS" != "x"], 66 | [ 67 | AS_ECHO([" timpi_optional_LIBS......... : $timpi_optional_LIBS"]) 68 | ]) 69 | 70 | 71 | AS_ECHO([]) 72 | AS_ECHO(["Configure complete, now type \'make\' and then \'make install\'."]) 73 | AS_ECHO([]) 74 | 75 | ]) 76 | -------------------------------------------------------------------------------- /m4/timpi_compiler.m4: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------- 2 | # ------------------------------------------------------------- 3 | AC_DEFUN([TIMPI_SET_COMPILERS], 4 | [ 5 | AC_REQUIRE([ACSM_COMPILER_CONTROL_ARGS]) 6 | AC_REQUIRE([ACSM_SCRAPE_PETSC_CONFIGURE]) 7 | 8 | # -------------------------------------------------------------- 9 | # look for a decent C++ compiler or honor --with-cxx=... 10 | CXX_TRY_LIST="g++ icpc icc pgCC c++" 11 | 12 | AC_ARG_WITH([cxx], 13 | AS_HELP_STRING([--with-cxx=CXX], [C++ compiler to use]), 14 | [CXX="$withval"], 15 | []) 16 | 17 | dnl If we already have CXX either from --with-cxx or from the environment, then there's no sense going 18 | dnl any further. Moreover if we are not enabling mpi then we don't have to query for mpi compilers 19 | dnl or for a compiler from PETSc 20 | AS_IF([test -z "$CXX" && test "$enablempi" != no], 21 | [ 22 | dnl Did we get --with-mpi=DIR or was there a MPI_HOME or MPIHOME set? 23 | AS_IF([test x"$MPI" != x], 24 | [ 25 | dnl Inspect $MPI/bin 26 | AS_IF([test -d "$MPI/bin"], 27 | [ 28 | AC_CHECK_PROGS(LOCAL_CXX, [mpicxx mpiCC mpicc], [], ["$MPI/bin"]) 29 | AS_IF([test -z "$LOCAL_CXX"], 30 | [AS_ECHO(["None of the wrappers we look for exist in $MPI/bin. We will not try to use mpi compiler wrappers"])], 31 | [MPI_USING_WRAPPERS=1;CXX="$MPI/bin/$LOCAL_CXX"]) 32 | ], 33 | [AS_ECHO(["An MPI directory was specified, but $MPI/bin does not exist. We will not try to use mpi compiler wrappers"])]) 34 | ], 35 | [ 36 | dnl No MPI directory specified. If we have PETSc, let's try to snoop some 37 | dnl information from there. We'll use this information further below and in 38 | dnl mpi.m4 39 | AS_IF([test x"$PETSC_HAVE_MPI" = x1 && test x"$PETSC_CXX" != x], 40 | [], 41 | dnl PETSc doesn't define a CXX so we'll just try to pull one from the environment 42 | [CXX_TRY_LIST="mpicxx mpiCC mpicc $CXX_TRY_LIST"]) 43 | ]) dnl AS_IF([test x"$MPI" != x]) 44 | ]) 45 | 46 | dnl See whether we are using PETSC_CXX. Unfortunately PETSC_CXX may 47 | dnl be prefixed with a PATH, and its not straightforward to strip it off. 48 | dnl If CXX is not set AC_PROG_CXX will call AC_CHECK_TOOLS which will prefix 49 | dnl every argument in CXX_TRY_LIST with values in $PATH, so we will 50 | dnl not find something like PATH/PETSC_PREFIX/mpicxx. The solution 51 | dnl then is just to set CXX to PETSC_CXX so that AC_CHECK_TOOLS 52 | dnl never gets called 53 | AS_IF([test -z "$CXX" && test x"$PETSC_HAVE_MPI" = x1 && test x"$PETSC_CXX" != x], 54 | [CXX="$PETSC_CXX"]) 55 | 56 | dnl If we still don't have a CXX set then we will try to pick one up from CXX_TRY_LIST 57 | AC_PROG_CXX([$CXX_TRY_LIST]) 58 | ]) 59 | -------------------------------------------------------------------------------- /m4/timpi_optional_features.m4: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------- 2 | # ------------------------------------------------------------- 3 | AC_DEFUN([TIMPI_OPTIONAL_FEATURES], 4 | [ 5 | AC_MSG_RESULT(---------------------------------------------) 6 | AC_MSG_RESULT(------- Configuring optional features -------) 7 | AC_MSG_RESULT(---------------------------------------------) 8 | 9 | 10 | # -------------------------------------------------------------- 11 | # library deprecated code - enable by default 12 | # -------------------------------------------------------------- 13 | AC_ARG_ENABLE(deprecated, 14 | [AS_HELP_STRING([--disable-deprecated],[Deprecated code use gives errors rather than warnings])], 15 | enabledeprecated=$enableval, 16 | enabledeprecated=yes) 17 | 18 | AC_SUBST(enabledeprecated) 19 | AS_IF([test "$enabledeprecated" != yes], 20 | [ 21 | AC_MSG_RESULT([>>> INFO: Disabling library deprecated code <<<]) 22 | AC_MSG_RESULT([>>> Configuring library without deprecated code support <<<]) 23 | ], 24 | [ 25 | AC_MSG_RESULT([<<< Configuring library with deprecated code support >>>]) 26 | AC_DEFINE(ENABLE_DEPRECATED, 1, [Flag indicating if the library should support deprecated code]) 27 | ]) 28 | # -------------------------------------------------------------- 29 | 30 | 31 | # -------------------------------------------------------------- 32 | # C++ exceptions - enabled by default 33 | # -------------------------------------------------------------- 34 | AC_ARG_ENABLE(exceptions, 35 | AS_HELP_STRING([--disable-exceptions], 36 | [exit rather than throw exceptions on unexpected errors]), 37 | enableexceptions=$enableval, 38 | enableexceptions=yes) 39 | 40 | AS_IF([test "$enableexceptions" != no], 41 | [ 42 | AC_DEFINE(ENABLE_EXCEPTIONS, 1, [Flag indicating if the library should be built to throw C++ exceptions on unexpected errors]) 43 | AC_MSG_RESULT(<<< Configuring library with exception throwing support >>>) 44 | ]) 45 | # -------------------------------------------------------------- 46 | 47 | 48 | # -------------------------------------------------------------- 49 | # Quadruple precision support - off by default 50 | # -------------------------------------------------------------- 51 | ACSM_CHOOSE_PRECISION 52 | 53 | 54 | # -------------------------------------------------------------- 55 | # __TIME__ __DATE__ stamps - enabled by default 56 | # disabling preprocessor timestamps helps compiler caches such 57 | # as ccache to work more effectively. 58 | # -------------------------------------------------------------- 59 | AC_ARG_ENABLE(timestamps, 60 | AS_HELP_STRING([--disable-timestamps], 61 | [do not add preprocessor timestamps to the library (helps ccache)]), 62 | enabletimestamps=$enableval, 63 | enabletimestamps=yes) 64 | 65 | AS_IF([test "$enabletimestamps" != no], 66 | [ 67 | AC_DEFINE(ENABLE_TIMESTAMPS, 1, [Flag indicating if the library should be built with compile time and date timestamps]) 68 | AC_MSG_RESULT(<<< Configuring library with compile timestamps >>>) 69 | ]) 70 | 71 | # -------------------------------------------------------------- 72 | 73 | 74 | # -------------------------------------------------------------- 75 | # library warnings - enable by default 76 | # -------------------------------------------------------------- 77 | AC_ARG_ENABLE(warnings, 78 | [AS_HELP_STRING([--disable-warnings],[Do not warn about deprecated, experimental, or questionable code])], 79 | enablewarnings=$enableval, 80 | enablewarnings=yes) 81 | 82 | AC_SUBST(enablewarnings) 83 | AS_IF([test "$enablewarnings" != yes], 84 | [ 85 | AC_MSG_RESULT([>>> INFO: Disabling library warnings <<<]) 86 | AC_MSG_RESULT([>>> Configuring library without warnings <<<]) 87 | ], 88 | [ 89 | AC_MSG_RESULT([<<< Configuring library with warnings >>>]) 90 | AC_DEFINE(ENABLE_WARNINGS, 1, [Flag indicating if the library should have warnings enabled]) 91 | ]) 92 | # -------------------------------------------------------------- 93 | 94 | 95 | # ------------------------------------------------------------- 96 | # size of processor_id_type -- default 4 bytes 97 | # ------------------------------------------------------------- 98 | AC_ARG_WITH([processor_id_bytes], 99 | AS_HELP_STRING([--with-processor-id-bytes=<1|2|4|8>], 100 | [bytes used for processor id [4]]), 101 | [processor_bytes="$withval"], 102 | [processor_bytes=4]) 103 | 104 | AS_CASE("$processor_bytes", 105 | [1], [AC_DEFINE(PROCESSOR_ID_BYTES, 1, [size of processor_id])], 106 | [2], [AC_DEFINE(PROCESSOR_ID_BYTES, 2, [size of processor_id])], 107 | [4], [AC_DEFINE(PROCESSOR_ID_BYTES, 4, [size of processor_id])], 108 | [8], [AC_DEFINE(PROCESSOR_ID_BYTES, 8, [size of processor_id])], 109 | [ 110 | AC_MSG_RESULT([>>> unrecognized processor_id size: $processor_bytes - configuring size...4]) 111 | AC_DEFINE(PROCESSOR_ID_BYTES, 4, [size of processor_id]) 112 | processor_bytes=4 113 | ]) 114 | 115 | AC_MSG_RESULT([configuring size of processor_id... $processor_bytes]) 116 | # ------------------------------------------------------------- 117 | 118 | 119 | AC_MSG_RESULT(---------------------------------------------) 120 | AC_MSG_RESULT(----- Done configuring optional features ----) 121 | AC_MSG_RESULT(---------------------------------------------) 122 | ]) 123 | -------------------------------------------------------------------------------- /m4/timpi_set_cxx_flags.m4: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------- 2 | # Set C++ compiler flags to their default values. They will be 3 | # modified according to other options in later steps of 4 | # configuration 5 | # 6 | # CXXFLAGS_OPT : flags for optimized mode 7 | # CXXFLAGS_DEVEL : flags for development mode 8 | # CXXFLAGS_DBG : flags for debug mode 9 | # CPPFLAGS_OPT : preprocessor flags for optimized mode 10 | # CPPFLAGS_DEVEL : preprocessor flags for development mode 11 | # CPPFLAGS_DBG : preprocessor flags for debug mode 12 | # PROFILING_FLAGS : flags to enable code profiling 13 | # ASSEMBLY_FLAGS : flags to enable assembly language output 14 | # WERROR_FLAGS : flags to turn compiler warnings into errors 15 | # PARANOID_FLAGS : flags to turn on many more compiler warnings 16 | # 17 | # Usage: SET_CXX_FLAGS 18 | # 19 | # (Note the CXXFLAGS and the CPPFLAGS used for further tests may 20 | # be augmented) 21 | # ------------------------------------------------------------- 22 | AC_DEFUN([TIMPI_SET_CXX_FLAGS], 23 | [ 24 | ACSM_SET_CXX_FLAGS 25 | 26 | #----------------------------------------------------- 27 | # Add compiler flags to respect IEEE FPE behavior. 28 | # This probably doesn't affect TIMPI directly but I'd 29 | # hate to be surprised by it later. 30 | #----------------------------------------------------- 31 | ACSM_SET_FPE_SAFETY_FLAGS 32 | 33 | ACSM_SET_GLIBCXX_DEBUG_FLAGS 34 | 35 | CXXFLAGS_OPT="$ACSM_CXXFLAGS_OPT" 36 | CXXFLAGS_DEVEL="$ACSM_CXXFLAGS_DEVEL" 37 | CXXFLAGS_DBG="$ACSM_CXXFLAGS_DBG" 38 | 39 | CPPFLAGS_OPT="$ACSM_CPPFLAGS_OPT" 40 | CPPFLAGS_DEVEL="$ACSM_CPPFLAGS_DEVEL" 41 | CPPFLAGS_DBG="$ACSM_CPPFLAGS_DBG" 42 | 43 | ASSEMBLY_FLAGS="$ACSM_ASSEMBLY_FLAGS" 44 | NODEPRECATEDFLAG="$ACSM_NODEPRECATEDFLAG" 45 | OPROFILE_FLAGS="$ACSM_OPROFILE_FLAGS" 46 | PARANOID_FLAGS="$ACSM_PARANOID_FLAGS" 47 | PROFILING_FLAGS="$ACSM_PROFILING_FLAGS" 48 | RPATHFLAG="$ACSM_RPATHFLAG" 49 | WERROR_FLAGS="$ACSM_WERROR_FLAGS" 50 | ] 51 | ) 52 | -------------------------------------------------------------------------------- /makerelease.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ "$#" -ne 0 ]; then 5 | echo "Usage: $0" 6 | fi 7 | 8 | VERSION=$(grep AC_INIT configure.ac | sed 's/.*[ ,]\([0-9]\+\(\.[0-9]\+\)\+\).*/\1/') 9 | 10 | git tag v${VERSION} -m "TIMPI $VERSION release" 11 | 12 | git checkout -b branch_$VERSION 13 | 14 | perl -pi -e 's/dnl AM_MAINTAINER_MODE/AM_MAINTAINER_MODE/' configure.ac 15 | 16 | ./bootstrap 17 | 18 | cp .gitignore-bootstrapped .gitignore 19 | 20 | git add .gitignore 21 | 22 | git commit -m "Don't ignore bootstrap output" 23 | 24 | git add Makefile.in aclocal.m4 \ 25 | src/utilities/include/timpi/timpi_config.h.tmp.in build-aux \ 26 | configure m4/libtool.m4 m4/ltoptions.m4 \ 27 | m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 \ 28 | src/Makefile.in test/Makefile.in configure.ac 29 | 30 | git commit -m "Add bootstrap output" 31 | 32 | git tag v${VERSION}_bootstrapped -m "TIMPI $VERSION release, bootstrapped" 33 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | AM_LDFLAGS = -version-info 11:0:0 3 | 4 | CXXFLAGS_DBG += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 5 | CXXFLAGS_DEVEL += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 6 | CXXFLAGS_OPROF += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 7 | CXXFLAGS_OPT += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 8 | CXXFLAGS_PROF += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 9 | 10 | 11 | #---------------------------------------------- 12 | # List of source files to build dynamic library 13 | #---------------------------------------------- 14 | timpi_SOURCES = 15 | 16 | # parallel 17 | timpi_SOURCES += parallel/src/communicator.C 18 | timpi_SOURCES += parallel/src/message_tag.C 19 | timpi_SOURCES += parallel/src/request.C 20 | 21 | # utilities 22 | timpi_SOURCES += utilities/src/semipermanent.C 23 | timpi_SOURCES += utilities/src/timpi_assert.C 24 | timpi_SOURCES += utilities/src/timpi_init.C 25 | timpi_SOURCES += utilities/src/timpi_version.C 26 | 27 | #------------------------------------------ 28 | # List of library configurations to compile 29 | #------------------------------------------ 30 | 31 | lib_LTLIBRARIES = 32 | bin_PROGRAMS = 33 | 34 | if BUILD_DBG_MODE 35 | lib_LTLIBRARIES += libtimpi_dbg.la 36 | libtimpi_dbg_la_SOURCES = $(timpi_SOURCES) 37 | libtimpi_dbg_la_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 38 | libtimpi_dbg_la_CXXFLAGS = $(CXXFLAGS_DBG) 39 | bin_PROGRAMS += timpi_version-dbg 40 | endif 41 | 42 | if BUILD_DEVEL_MODE 43 | lib_LTLIBRARIES += libtimpi_devel.la 44 | libtimpi_devel_la_SOURCES = $(timpi_SOURCES) 45 | libtimpi_devel_la_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 46 | libtimpi_devel_la_CXXFLAGS = $(CXXFLAGS_DEVEL) 47 | bin_PROGRAMS += timpi_version-devel 48 | endif 49 | 50 | if BUILD_OPT_MODE 51 | lib_LTLIBRARIES += libtimpi_opt.la 52 | libtimpi_opt_la_SOURCES = $(timpi_SOURCES) 53 | libtimpi_opt_la_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 54 | libtimpi_opt_la_CXXFLAGS = $(CXXFLAGS_OPT) 55 | bin_PROGRAMS += timpi_version-opt 56 | endif 57 | 58 | if BUILD_PROF_MODE 59 | lib_LTLIBRARIES += libtimpi_prof.la 60 | libtimpi_prof_la_SOURCES = $(timpi_SOURCES) 61 | libtimpi_prof_la_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 62 | libtimpi_prof_la_CXXFLAGS = $(CXXFLAGS_PROF) 63 | bin_PROGRAMS += timpi_version-prof 64 | endif 65 | 66 | if BUILD_OPROF_MODE 67 | lib_LTLIBRARIES += libtimpi_oprof.la 68 | libtimpi_oprof_la_SOURCES = $(timpi_SOURCES) 69 | libtimpi_oprof_la_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 70 | libtimpi_oprof_la_CXXFLAGS = $(CXXFLAGS_OPROF) 71 | bin_PROGRAMS += timpi_version-oprof 72 | endif 73 | 74 | 75 | #---------------------------- 76 | # INCLUDES we want distributed 77 | #---------------------------- 78 | includedir = $(prefix)/include/timpi 79 | include_HEADERS = 80 | 81 | # algorithms 82 | include_HEADERS += algorithms/include/timpi/parallel_sync.h 83 | 84 | # parallel 85 | include_HEADERS += parallel/include/timpi/attributes.h 86 | include_HEADERS += parallel/include/timpi/communicator.h 87 | include_HEADERS += parallel/include/timpi/data_type.h 88 | include_HEADERS += parallel/include/timpi/message_tag.h 89 | include_HEADERS += parallel/include/timpi/op_function.h 90 | include_HEADERS += parallel/include/timpi/packing_decl.h 91 | include_HEADERS += parallel/include/timpi/packing_forward.h 92 | include_HEADERS += parallel/include/timpi/packing.h 93 | include_HEADERS += parallel/include/timpi/parallel_communicator_specializations 94 | include_HEADERS += parallel/include/timpi/parallel_implementation.h 95 | include_HEADERS += parallel/include/timpi/post_wait_copy_buffer.h 96 | include_HEADERS += parallel/include/timpi/post_wait_delete_buffer.h 97 | include_HEADERS += parallel/include/timpi/post_wait_dereference_shared_ptr.h 98 | include_HEADERS += parallel/include/timpi/post_wait_dereference_tag.h 99 | include_HEADERS += parallel/include/timpi/post_wait_free_buffer.h 100 | include_HEADERS += parallel/include/timpi/post_wait_unpack_buffer.h 101 | include_HEADERS += parallel/include/timpi/post_wait_unpack_nested_buffer.h 102 | include_HEADERS += parallel/include/timpi/post_wait_work.h 103 | include_HEADERS += parallel/include/timpi/request.h 104 | include_HEADERS += parallel/include/timpi/serial_implementation.h 105 | include_HEADERS += parallel/include/timpi/standard_type_forward.h 106 | include_HEADERS += parallel/include/timpi/standard_type.h 107 | include_HEADERS += parallel/include/timpi/status.h 108 | 109 | # utilities 110 | include_HEADERS += utilities/include/timpi/ignore_warnings.h 111 | include_HEADERS += utilities/include/timpi/semipermanent.h 112 | include_HEADERS += utilities/include/timpi/timpi.h 113 | include_HEADERS += utilities/include/timpi/timpi_assert.h 114 | include_HEADERS += utilities/include/timpi/timpi_call_mpi.h 115 | include_HEADERS += utilities/include/timpi/timpi_init.h 116 | include_HEADERS += utilities/include/timpi/timpi_macros.h 117 | include_HEADERS += utilities/include/timpi/restore_warnings.h 118 | 119 | # Needs to be builddir since this is generated by configure 120 | include_HEADERS += $(top_builddir)/src/utilities/include/timpi/timpi_version.h 121 | include_HEADERS += $(top_builddir)/src/utilities/include/timpi/timpi_config.h 122 | 123 | # Version app 124 | timpi_version_opt_SOURCES = apps/version.C 125 | timpi_version_opt_LDADD = libtimpi_opt.la 126 | 127 | timpi_version_oprof_SOURCES = apps/version.C 128 | timpi_version_oprof_LDADD = libtimpi_oprof.la 129 | 130 | timpi_version_prof_SOURCES = apps/version.C 131 | timpi_version_prof_LDADD = libtimpi_prof.la 132 | 133 | timpi_version_devel_SOURCES = apps/version.C 134 | timpi_version_devel_LDADD = libtimpi_devel.la 135 | 136 | timpi_version_dbg_SOURCES = apps/version.C 137 | timpi_version_dbg_LDADD = libtimpi_dbg.la 138 | 139 | #-------------------------------------- 140 | #Local Directories to include for build 141 | #-------------------------------------- 142 | AM_CPPFLAGS = $(timpi_optional_INCLUDES) 143 | AM_CPPFLAGS += -I$(top_srcdir)/src/algorithms/include 144 | AM_CPPFLAGS += -I$(top_srcdir)/src/parallel/include 145 | AM_CPPFLAGS += -I$(top_srcdir)/src/utilities/include 146 | AM_CPPFLAGS += -I$(top_builddir)/src/utilities/include #timpi_version.h, timpi_config.h 147 | 148 | LIBS += $(timpi_optional_LIBS) 149 | 150 | 151 | # Note that for "make test_headers" this DEFAULT_HEADERS_TO_TEST business allows us 152 | # to selectively choose individual HEADERS_TO_TEST in the test_headers.sh script, 153 | # e.g. 154 | # $ make HEADERS_TO_TEST="numerics/parsed_function.h base/auto_ptr.h" test_headers 155 | test_headers: 156 | @echo " " 157 | @echo "Checking for standalone headers in source tree $(top_builddir)/include in OPT mode ..." 158 | @echo " " 159 | @CXX="$(CXX)" DEFAULT_HEADERS_TO_TEST="$(include_HEADERS)" \ 160 | test_CXXFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS_OPT) $(CXXFLAGS_OPT) -I$(top_builddir)/include" \ 161 | $(top_srcdir)/bin/test_headers.sh 162 | @echo " " 163 | @echo "Checking for standalone headers in source tree $(top_builddir)/include in DEVEL mode ..." 164 | @echo " " 165 | @CXX="$(CXX)" DEFAULT_HEADERS_TO_TEST="$(include_HEADERS)" \ 166 | test_CXXFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS_DEVEL) $(CXXFLAGS_DEVEL) -I$(top_builddir)/include" \ 167 | $(top_srcdir)/bin/test_headers.sh 168 | @echo " " 169 | @echo "Checking for standalone headers in source tree $(top_builddir)/include in DBG mode ..." 170 | @echo " " 171 | @CXX="$(CXX)" DEFAULT_HEADERS_TO_TEST="$(include_HEADERS)" \ 172 | test_CXXFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS_DBG) $(CXXFLAGS_DBG) -I$(top_builddir)/include" \ 173 | $(top_srcdir)/bin/test_headers.sh 174 | -------------------------------------------------------------------------------- /src/apps/version.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | #include "timpi/timpi_version.h" 19 | 20 | int main() 21 | { 22 | TIMPI::timpi_version_stdout(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/attributes.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_ATTRIBUTES_H 20 | #define TIMPI_ATTRIBUTES_H 21 | 22 | // TIMPI includes 23 | #include "timpi/timpi_config.h" 24 | 25 | // Boost include if necessary for float128 26 | #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 27 | # include 28 | #endif 29 | 30 | // C++ includes 31 | #include 32 | #include 33 | #include 34 | 35 | namespace TIMPI 36 | { 37 | //------------------------------------------------------------------- 38 | 39 | /* 40 | * The unspecialized class gives default, lowest-common-denominator 41 | * attributes, for values which can't be used with Parallel min/max. 42 | * Specialized classes can set this to true, and should define 43 | * the lowest and highest values possible for the type. 44 | */ 45 | template 46 | struct Attributes 47 | { 48 | static const bool has_min_max = false; 49 | /* 50 | static void set_lowest(T & x) { x = as_low_as_it_can_be; } 51 | static void set_highest(T & x) { x = as_high_as_it_can_be; } 52 | */ 53 | }; 54 | 55 | // ------------------------------------------------------------ 56 | // Declare Attributes specializations for C++ built-in types 57 | 58 | #define TIMPI_INT_TYPE(cxxtype) \ 59 | template<> \ 60 | struct Attributes \ 61 | { \ 62 | static const bool has_min_max = true; \ 63 | static void set_lowest(cxxtype & x) { x = std::numeric_limits::min(); } \ 64 | static void set_highest(cxxtype & x) { x = std::numeric_limits::max(); } \ 65 | } 66 | 67 | #define TIMPI_FLOAT_TYPE(cxxtype) \ 68 | template<> \ 69 | struct Attributes \ 70 | { \ 71 | static const bool has_min_max = true; \ 72 | static void set_lowest(cxxtype & x) { x = -std::numeric_limits::infinity(); } \ 73 | static void set_highest(cxxtype & x) { x = std::numeric_limits::infinity(); } \ 74 | } 75 | 76 | #define TIMPI_CONTAINER_TYPE(cxxtype) \ 77 | struct Attributes \ 78 | { \ 79 | static const bool has_min_max = Attributes::has_min_max; \ 80 | static void set_lowest(cxxtype & x) { \ 81 | for (auto & val : x) \ 82 | Attributes::set_lowest(val); } \ 83 | static void set_highest(cxxtype & x) { \ 84 | for (auto & val : x) \ 85 | Attributes::set_highest(val); } \ 86 | } 87 | 88 | 89 | TIMPI_INT_TYPE(char); 90 | TIMPI_INT_TYPE(signed char); 91 | TIMPI_INT_TYPE(unsigned char); 92 | TIMPI_INT_TYPE(short int); 93 | TIMPI_INT_TYPE(unsigned short int); 94 | TIMPI_INT_TYPE(int); 95 | TIMPI_INT_TYPE(unsigned int); 96 | TIMPI_INT_TYPE(long); 97 | TIMPI_INT_TYPE(long long); 98 | TIMPI_INT_TYPE(unsigned long); 99 | TIMPI_INT_TYPE(unsigned long long); 100 | 101 | TIMPI_FLOAT_TYPE(float); 102 | TIMPI_FLOAT_TYPE(double); 103 | TIMPI_FLOAT_TYPE(long double); 104 | #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 105 | TIMPI_FLOAT_TYPE(TIMPI_DEFAULT_SCALAR_TYPE); 106 | #endif 107 | 108 | #define TIMPI_ATTRIBUTES_COMMA , 109 | 110 | template 111 | TIMPI_CONTAINER_TYPE(std::set); 112 | 113 | template 114 | TIMPI_CONTAINER_TYPE(std::vector); 115 | 116 | } // namespace TIMPI 117 | 118 | #endif // TIMPI_ATTRIBUTES_H 119 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/data_type.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_DATA_TYPE_H 20 | #define TIMPI_DATA_TYPE_H 21 | 22 | // TIMPI includes 23 | #include "timpi/timpi_call_mpi.h" 24 | 25 | namespace TIMPI 26 | { 27 | 28 | #ifdef TIMPI_HAVE_MPI 29 | //------------------------------------------------------------------- 30 | /** 31 | * Data types for communication 32 | */ 33 | typedef MPI_Datatype data_type; 34 | 35 | #else 36 | 37 | // These shouldn't actually be needed, but must be 38 | // unique types for function overloading to work 39 | // properly. 40 | struct data_type { /* unsigned int t; */ }; 41 | 42 | #endif // TIMPI_HAVE_MPI 43 | 44 | 45 | 46 | //------------------------------------------------------------------- 47 | /** 48 | * Encapsulates the MPI_Datatype. 49 | */ 50 | class DataType 51 | { 52 | public: 53 | DataType () = default; 54 | DataType (const DataType & other) = default; 55 | DataType (DataType && other) = default; 56 | static const bool is_fixed_type = true; 57 | 58 | DataType (const data_type & type) : 59 | _datatype(type) 60 | {} 61 | 62 | DataType (const DataType & other, unsigned int count) 63 | { 64 | // FIXME - if we nest an inner type here will we run into bug 65 | // https://github.com/libMesh/libmesh/issues/631 again? 66 | timpi_call_mpi(MPI_Type_contiguous(count, other._datatype, &_datatype)); 67 | ignore(other, count); // ifndef TIMPI_HAVE_MPI 68 | this->commit(); 69 | } 70 | 71 | virtual ~DataType () = default; 72 | 73 | DataType & operator = (const DataType & other) = default; 74 | DataType & operator = (DataType && other) = default; 75 | 76 | DataType & operator = (const data_type & type) 77 | { _datatype = type; return *this; } 78 | 79 | operator const data_type & () const 80 | { return _datatype; } 81 | 82 | operator data_type & () 83 | { return _datatype; } 84 | 85 | // operator data_type const * () const 86 | // { return &_datatype; } 87 | 88 | // operator data_type * () 89 | // { return &_datatype; } 90 | 91 | void commit () 92 | { 93 | timpi_call_mpi 94 | (MPI_Type_commit (&_datatype)); 95 | } 96 | 97 | void free () 98 | { 99 | timpi_call_mpi 100 | (MPI_Type_free (&_datatype)); 101 | } 102 | 103 | protected: 104 | 105 | data_type _datatype; 106 | }; 107 | 108 | /** 109 | * StandardType's which do not define a way to \p MPI_Type \p T should 110 | * inherit from this class. This class is primarily defined for backwards 111 | * compatability because it defines \p is_fixed_type = false for 112 | * non-fixed/non-mpi-typed StandardTypes. This class also provides a fairly 113 | * convenient way to define communication overloads that are antithetical to \p 114 | * DataType counterparts. E.g. when doing our parallel algorithms we may build a 115 | * \p StandardType and then call communication routines with that type. We want 116 | * to ensure that we dispatch to different methods when \p StandardType defines 117 | * MPI typing vs. when it does not. The \p DataType vs. \p NotADataType typing 118 | * accomplishes that goal 119 | */ 120 | class NotADataType 121 | { 122 | public: 123 | NotADataType () = default; 124 | NotADataType (const NotADataType & other) = default; 125 | NotADataType (NotADataType && other) = default; 126 | ~NotADataType () = default; 127 | NotADataType & operator = (const NotADataType & other) = default; 128 | NotADataType & operator = (NotADataType && other) = default; 129 | 130 | static const bool is_fixed_type = false; 131 | }; 132 | 133 | template 134 | struct MaybeADataType { 135 | typedef DataType type; 136 | }; 137 | 138 | template <> 139 | struct MaybeADataType 140 | { 141 | typedef NotADataType type; 142 | }; 143 | 144 | } // namespace TIMPI 145 | 146 | #endif // TIMPI_DATA_TYPE_H 147 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/message_tag.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_MESSAGE_TAG_H 20 | #define TIMPI_MESSAGE_TAG_H 21 | 22 | // TIMPI Includes 23 | #include "timpi/timpi_config.h" 24 | 25 | // C/C++ includes 26 | #ifdef TIMPI_HAVE_MPI 27 | # include "timpi/ignore_warnings.h" 28 | # include "mpi.h" 29 | # include "timpi/restore_warnings.h" 30 | #endif // TIMPI_HAVE_MPI 31 | 32 | #include // INT_MIN 33 | 34 | namespace TIMPI 35 | { 36 | //------------------------------------------------------------------- 37 | /** 38 | * Forward declarations of classes we will define later. 39 | */ 40 | class Communicator; 41 | 42 | //------------------------------------------------------------------- 43 | /** 44 | * Encapsulates the MPI tag integers. 45 | */ 46 | class MessageTag 47 | { 48 | public: 49 | 50 | /** 51 | * Invalid tag, to allow for default construction. 52 | */ 53 | static const int invalid_tag = INT_MIN; 54 | 55 | /** 56 | * Explicit constructor, to discourage using "magic numbers" 57 | * as tags. Communicator::get_unique_tag is recommended instead. 58 | */ 59 | explicit MessageTag(int tagvalue = invalid_tag) 60 | : _tagvalue(tagvalue), _comm(nullptr) {} 61 | 62 | /** 63 | * Copy constructor. Helps Communicator do reference counting on 64 | * unique tags 65 | */ 66 | MessageTag(const MessageTag & other); 67 | 68 | /** 69 | * Move constructor. Helps Communicator do reference counting on 70 | * unique tags 71 | */ 72 | MessageTag(MessageTag && other); 73 | 74 | /** 75 | * Copy assignment operator. Helps Communicator do reference 76 | * counting on unique tags 77 | */ 78 | MessageTag & operator = (const MessageTag & other); 79 | 80 | /** 81 | * Move assignment operator. Helps Communicator do reference 82 | * counting on unique tags 83 | */ 84 | MessageTag & operator = (MessageTag && other); 85 | 86 | /** 87 | * Destructor. Helps Communicator do reference counting on unique 88 | * tags 89 | */ 90 | ~MessageTag(); 91 | 92 | int value() const { 93 | return _tagvalue; 94 | } 95 | 96 | private: 97 | int _tagvalue; 98 | const Communicator * _comm; 99 | 100 | // Constructor for reference-counted unique tags 101 | MessageTag(int tagvalue, const Communicator * comm) 102 | : _tagvalue(tagvalue), _comm(comm) {} 103 | 104 | // Let Communicator handle the reference counting 105 | friend class Communicator; 106 | }; 107 | 108 | 109 | //------------------------------------------------------------------- 110 | /** 111 | * Default message tag ids 112 | */ 113 | #ifdef TIMPI_HAVE_MPI 114 | const MessageTag any_tag = MessageTag(MPI_ANY_TAG); 115 | #else 116 | const MessageTag any_tag = MessageTag(-1); 117 | #endif 118 | 119 | const MessageTag no_tag = MessageTag(0); 120 | 121 | } // namespace TIMPI 122 | 123 | #endif // TIMPI_MESSAGE_TAG_H 124 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/op_function.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_OP_FUNCTION_H 20 | #define TIMPI_OP_FUNCTION_H 21 | 22 | #include "timpi/timpi_config.h" 23 | 24 | #include "timpi/semipermanent.h" 25 | #include "timpi/timpi_init.h" 26 | #include "timpi/timpi_call_mpi.h" 27 | 28 | #ifdef TIMPI_HAVE_MPI 29 | # include "timpi/ignore_warnings.h" 30 | # include "mpi.h" 31 | # include "timpi/restore_warnings.h" 32 | #endif // TIMPI_HAVE_MPI 33 | 34 | // Boost include if necessary for float128 35 | #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 36 | # include 37 | #endif 38 | 39 | // C++ includes 40 | #include 41 | #include 42 | 43 | 44 | 45 | namespace TIMPI 46 | { 47 | #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 48 | # ifdef TIMPI_HAVE_MPI 49 | # define TIMPI_MPI_QUAD_BINARY(funcname) \ 50 | inline void \ 51 | timpi_mpi_quad_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 52 | { \ 53 | const int size = *len; \ 54 | \ 55 | TIMPI_DEFAULT_SCALAR_TYPE *in = static_cast(a); \ 56 | TIMPI_DEFAULT_SCALAR_TYPE *inout = static_cast(b); \ 57 | for (int i=0; i != size; ++i) \ 58 | inout[i] = std::funcname(in[i],inout[i]); \ 59 | } 60 | 61 | # define TIMPI_MPI_QUAD_LOCATOR(funcname) \ 62 | inline void \ 63 | timpi_mpi_quad_##funcname##_location(void * a, void * b, int * len, MPI_Datatype *) \ 64 | { \ 65 | const int size = *len; \ 66 | \ 67 | typedef std::pair dtype; \ 68 | \ 69 | dtype *in = static_cast(a); \ 70 | dtype *inout = static_cast(b); \ 71 | for (int i=0; i != size; ++i) \ 72 | { \ 73 | TIMPI_DEFAULT_SCALAR_TYPE old_inout = inout[i].first; \ 74 | inout[i].first = std::funcname(in[i].first,inout[i].first); \ 75 | if (old_inout != inout[i].first) \ 76 | inout[i].second = in[i].second; \ 77 | } \ 78 | } 79 | 80 | 81 | # define TIMPI_MPI_QUAD_BINARY_FUNCTOR(funcname) \ 82 | inline void \ 83 | timpi_mpi_quad_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 84 | { \ 85 | const int size = *len; \ 86 | \ 87 | TIMPI_DEFAULT_SCALAR_TYPE *in = static_cast(a); \ 88 | TIMPI_DEFAULT_SCALAR_TYPE *inout = static_cast(b); \ 89 | for (int i=0; i != size; ++i) \ 90 | inout[i] = std::funcname()(in[i],inout[i]); \ 91 | } 92 | 93 | 94 | TIMPI_MPI_QUAD_BINARY(max) 95 | TIMPI_MPI_QUAD_BINARY(min) 96 | TIMPI_MPI_QUAD_LOCATOR(max) 97 | TIMPI_MPI_QUAD_LOCATOR(min) 98 | TIMPI_MPI_QUAD_BINARY_FUNCTOR(plus) 99 | TIMPI_MPI_QUAD_BINARY_FUNCTOR(multiplies) 100 | 101 | # endif // TIMPI_HAVE_MPI 102 | #endif // TIMPI_DEFAULT_QUADRUPLE_PRECISION 103 | 104 | 105 | //------------------------------------------------------------------- 106 | 107 | // Templated helper class to be used with static_assert. 108 | template 109 | struct opfunction_dependent_false : std::false_type 110 | {}; 111 | 112 | /** 113 | * Templated class to provide the appropriate MPI reduction operations 114 | * for use with built-in C types or simple C++ constructions. 115 | * 116 | * More complicated data types may need to provide a pointer-to-T so 117 | * that we can use MPI_Address without constructing a new T. 118 | */ 119 | template 120 | class OpFunction 121 | { 122 | // Get a slightly better compiler diagnostic if we have C++11 123 | static_assert(opfunction_dependent_false::value, 124 | "Only specializations of OpFunction may be used, did you forget to include a header file (e.g. parallel_algebra.h)?"); 125 | 126 | /* 127 | * The unspecialized class defines none of these functions; 128 | * specializations will need to define any functions that need to be 129 | * usable. 130 | * 131 | * Most specializations will just return MPI_MIN, etc, but we'll use 132 | * a whitelist rather than a default implementation, so that any 133 | * attempt to perform a reduction on an unspecialized type will be a 134 | * compile-time rather than a run-time failure. 135 | */ 136 | // static MPI_Op max(); 137 | // static MPI_Op min(); 138 | // static MPI_Op sum(); 139 | // static MPI_Op product(); 140 | // static MPI_Op logical_and(); 141 | // static MPI_Op bitwise_and(); 142 | // static MPI_Op logical_or(); 143 | // static MPI_Op bitwise_or(); 144 | // static MPI_Op logical_xor(); 145 | // static MPI_Op bitwise_xor(); 146 | // static MPI_Op max_loc(); 147 | // static MPI_Op min_loc(); 148 | }; 149 | 150 | 151 | 152 | // ------------------------------------------------------------ 153 | // Declare OpFunction specializations for C++ built-in types 154 | 155 | #ifdef TIMPI_HAVE_MPI 156 | 157 | #define TIMPI_PARALLEL_INTEGER_OPS(cxxtype) \ 158 | template<> \ 159 | class OpFunction \ 160 | { \ 161 | public: \ 162 | static MPI_Op max() { return MPI_MAX; } \ 163 | static MPI_Op min() { return MPI_MIN; } \ 164 | static MPI_Op sum() { return MPI_SUM; } \ 165 | static MPI_Op product() { return MPI_PROD; } \ 166 | static MPI_Op logical_and() { return MPI_LAND; } \ 167 | static MPI_Op bitwise_and() { return MPI_BAND; } \ 168 | static MPI_Op logical_or() { return MPI_LOR; } \ 169 | static MPI_Op bitwise_or() { return MPI_BOR; } \ 170 | static MPI_Op logical_xor() { return MPI_LXOR; } \ 171 | static MPI_Op bitwise_xor() { return MPI_BXOR; } \ 172 | static MPI_Op max_location() { return MPI_MAXLOC; } \ 173 | static MPI_Op min_location() { return MPI_MINLOC; } \ 174 | } 175 | 176 | #define TIMPI_PARALLEL_FLOAT_OPS(cxxtype) \ 177 | template<> \ 178 | class OpFunction \ 179 | { \ 180 | public: \ 181 | static MPI_Op max() { return MPI_MAX; } \ 182 | static MPI_Op min() { return MPI_MIN; } \ 183 | static MPI_Op sum() { return MPI_SUM; } \ 184 | static MPI_Op product() { return MPI_PROD; } \ 185 | static MPI_Op max_location() { return MPI_MAXLOC; } \ 186 | static MPI_Op min_location() { return MPI_MINLOC; } \ 187 | } 188 | 189 | #else 190 | 191 | #define TIMPI_PARALLEL_INTEGER_OPS(cxxtype) \ 192 | template<> \ 193 | class OpFunction \ 194 | { \ 195 | } 196 | 197 | #define TIMPI_PARALLEL_FLOAT_OPS(cxxtype) \ 198 | template<> \ 199 | class OpFunction \ 200 | { \ 201 | } 202 | 203 | #endif 204 | 205 | TIMPI_PARALLEL_INTEGER_OPS(char); 206 | TIMPI_PARALLEL_INTEGER_OPS(signed char); 207 | TIMPI_PARALLEL_INTEGER_OPS(unsigned char); 208 | TIMPI_PARALLEL_INTEGER_OPS(short int); 209 | TIMPI_PARALLEL_INTEGER_OPS(unsigned short int); 210 | TIMPI_PARALLEL_INTEGER_OPS(int); 211 | TIMPI_PARALLEL_INTEGER_OPS(unsigned int); 212 | TIMPI_PARALLEL_INTEGER_OPS(long); 213 | TIMPI_PARALLEL_INTEGER_OPS(long long); 214 | TIMPI_PARALLEL_INTEGER_OPS(unsigned long); 215 | TIMPI_PARALLEL_INTEGER_OPS(unsigned long long); 216 | 217 | TIMPI_PARALLEL_FLOAT_OPS(float); 218 | TIMPI_PARALLEL_FLOAT_OPS(double); 219 | TIMPI_PARALLEL_FLOAT_OPS(long double); 220 | 221 | #ifdef TIMPI_HAVE_MPI 222 | // Helper class to avoid leaking MPI_Op when TIMPI exits 223 | class ManageOp : public SemiPermanent 224 | { 225 | public: 226 | ManageOp(MPI_User_function * func, int commute, MPI_Op * op) 227 | : _op(op) 228 | { 229 | timpi_call_mpi(MPI_Op_create(func, commute, _op)); 230 | } 231 | 232 | virtual ~ManageOp() override { 233 | MPI_Op_free(_op); 234 | } 235 | private: 236 | MPI_Op * _op; 237 | }; 238 | #endif 239 | 240 | #define TIMPI_MPI_OPFUNCTION(mpiname, funcname) \ 241 | static MPI_Op mpiname() { \ 242 | static MPI_Op TIMPI_MPI_##mpiname = MPI_OP_NULL; \ 243 | if (TIMPI_MPI_##mpiname == MPI_OP_NULL) \ 244 | SemiPermanent::add \ 245 | (std::make_unique(timpi_mpi_##funcname, true, &TIMPI_MPI_##mpiname)); \ 246 | return TIMPI_MPI_##mpiname; \ 247 | } 248 | 249 | #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 250 | # ifdef TIMPI_HAVE_MPI 251 | template<> 252 | class OpFunction 253 | { 254 | public: 255 | TIMPI_MPI_OPFUNCTION(max, quad_max) 256 | TIMPI_MPI_OPFUNCTION(min, quad_min) 257 | TIMPI_MPI_OPFUNCTION(sum, quad_plus) 258 | TIMPI_MPI_OPFUNCTION(product, quad_multiplies) 259 | 260 | TIMPI_MPI_OPFUNCTION(max_location, quad_max_location) 261 | TIMPI_MPI_OPFUNCTION(min_location, quad_min_location) 262 | }; 263 | 264 | # else 265 | TIMPI_PARALLEL_FLOAT_OPS(TIMPI_DEFAULT_SCALAR_TYPE); 266 | # endif 267 | #endif // TIMPI_DEFAULT_QUADRUPLE_PRECISION 268 | 269 | #ifdef TIMPI_HAVE_MPI 270 | 271 | # define TIMPI_MPI_PAIR_BINARY(funcname) \ 272 | static inline void \ 273 | timpi_mpi_pair_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 274 | { \ 275 | const int size = *len; \ 276 | \ 277 | const std::pair * in = static_cast *>(a); \ 278 | std::pair * inout = static_cast *>(b); \ 279 | for (int i=0; i != size; ++i) \ 280 | { \ 281 | inout[i].first = std::funcname(in[i].first,inout[i].first); \ 282 | inout[i].second = std::funcname(in[i].second,inout[i].second); \ 283 | } \ 284 | } 285 | 286 | # define TIMPI_MPI_PAIR_LOCATOR(funcname) \ 287 | static inline void \ 288 | timpi_mpi_pair_##funcname##_location(void * a, void * b, int * len, MPI_Datatype *) \ 289 | { \ 290 | const int size = *len; \ 291 | \ 292 | typedef std::pair, int> dtype; \ 293 | \ 294 | dtype *in = static_cast(a); \ 295 | dtype *inout = static_cast(b); \ 296 | for (int i=0; i != size; ++i) \ 297 | { \ 298 | std::pair old_inout = inout[i].first; \ 299 | inout[i].first.first = std::funcname(in[i].first.first, inout[i].first.first); \ 300 | inout[i].first.second = std::funcname(in[i].first.second,inout[i].first.second); \ 301 | if (old_inout != inout[i].first) \ 302 | inout[i].second = in[i].second; \ 303 | } \ 304 | } 305 | 306 | 307 | # define TIMPI_MPI_PAIR_BINARY_FUNCTOR(funcname) \ 308 | static inline void \ 309 | timpi_mpi_pair_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 310 | { \ 311 | const int size = *len; \ 312 | \ 313 | const std::pair * in = static_cast *>(a); \ 314 | std::pair * inout = static_cast *>(b); \ 315 | for (int i=0; i != size; ++i) \ 316 | { \ 317 | inout[i].first = std::funcname()(in[i].first, inout[i].first); \ 318 | inout[i].second = std::funcname()(in[i].second,inout[i].second); \ 319 | } \ 320 | } 321 | 322 | 323 | template 324 | class OpFunction> 325 | { 326 | TIMPI_MPI_PAIR_BINARY(max) 327 | TIMPI_MPI_PAIR_BINARY(min) 328 | TIMPI_MPI_PAIR_LOCATOR(max) 329 | TIMPI_MPI_PAIR_LOCATOR(min) 330 | TIMPI_MPI_PAIR_BINARY_FUNCTOR(plus) 331 | TIMPI_MPI_PAIR_BINARY_FUNCTOR(multiplies) 332 | 333 | public: 334 | TIMPI_MPI_OPFUNCTION(max, pair_max) 335 | TIMPI_MPI_OPFUNCTION(min, pair_min) 336 | TIMPI_MPI_OPFUNCTION(sum, pair_plus) 337 | TIMPI_MPI_OPFUNCTION(product, pair_multiplies) 338 | 339 | TIMPI_MPI_OPFUNCTION(max_location, pair_max_location) 340 | TIMPI_MPI_OPFUNCTION(min_location, pair_min_location) 341 | }; 342 | # else // TIMPI_HAVE_MPI 343 | template 344 | class OpFunction> {}; 345 | #endif 346 | 347 | } // namespace TIMPI 348 | 349 | #endif // TIMPI_OP_FUNCTION_H 350 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/packing_decl.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_PACKING_DECL_H 20 | #define TIMPI_PACKING_DECL_H 21 | 22 | // TIMPI Includes 23 | #include "timpi/packing_forward.h" 24 | #include "timpi/standard_type.h" 25 | 26 | // C++ includes 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include // enable_if 33 | #include 34 | #include 35 | #include // pair 36 | #include 37 | 38 | 39 | // FIXME: This *should* be in TIMPI namespace but we have libMesh 40 | // users which already partially specialized it 41 | namespace libMesh 42 | { 43 | 44 | namespace Parallel 45 | { 46 | 47 | template 48 | class Packing; 49 | 50 | // Idiom taken from https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector 51 | // 52 | // We need this in _decl because we're using it for SFINAE in 53 | // template declarations 54 | template 55 | class Has_buffer_type 56 | { 57 | using Yes = char[2]; 58 | using No = char[1]; 59 | 60 | struct Fallback { 61 | struct buffer_type {}; 62 | }; 63 | struct Derived : T, Fallback {}; 64 | 65 | template static Yes &test(U *); 66 | 67 | // this template must be more specialized in general than the Yes version because it involves a 68 | // type-dependent expression...? 69 | template static No &test(typename U::buffer_type *); 70 | 71 | public: 72 | static constexpr bool value = sizeof(test(nullptr)) == sizeof(Yes); 73 | }; 74 | 75 | 76 | // specialization for std::pair 77 | template 78 | struct PairHasPacking 79 | { 80 | typedef typename std::remove_const::type cT1; 81 | 82 | static const bool value = 83 | !TIMPI::StandardType>::is_fixed_type && 84 | (Has_buffer_type>::value || 85 | TIMPI::StandardType::is_fixed_type) && 86 | (Has_buffer_type>::value || 87 | TIMPI::StandardType::is_fixed_type); 88 | }; 89 | 90 | 91 | template 92 | class Packing, 93 | typename std::enable_if::value>::type>; 94 | 95 | 96 | // specializations for std::tuple 97 | 98 | template 99 | struct TupleHasPacking; 100 | 101 | template <> 102 | struct TupleHasPacking<> 103 | { 104 | static const bool value = true; 105 | }; 106 | 107 | template 108 | struct TupleHasPacking 109 | { 110 | static const bool value = 111 | !TIMPI::StandardType>::is_fixed_type && 112 | (Has_buffer_type>::value || 113 | TIMPI::StandardType::is_fixed_type) && 114 | (TupleHasPacking::value || 115 | TIMPI::StandardType>::is_fixed_type); 116 | }; 117 | 118 | 119 | template 120 | class Packing, Enable>; 121 | 122 | template 123 | class Packing, 124 | typename std::enable_if::value>::type>; 125 | 126 | 127 | // specialization for std::array 128 | template 129 | class Packing, 130 | typename std::enable_if>::value>::type>; 131 | 132 | 133 | // helper class for any homogeneous-type variable-size containers 134 | // which define the usual iterator ranges, value_type, etc. 135 | template 136 | class PackingRange; 137 | 138 | 139 | #define TIMPI_DECL_PACKING_RANGE_SUBCLASS(Container) \ 140 | class Packing>::value || \ 142 | TIMPI::StandardType::is_fixed_type>::type> 143 | 144 | #define TIMPI_P_COMMA , 145 | 146 | template 147 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::vector); 148 | 149 | template 150 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::list); 151 | 152 | template 153 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::map); 154 | 155 | template 156 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multimap); 157 | 158 | template 159 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multiset); 160 | 161 | template 162 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::set); 163 | 164 | template 165 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_map); 166 | 167 | template 168 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_multimap); 169 | 170 | template 171 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_multiset); 172 | 173 | template 174 | TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_set); 175 | 176 | 177 | 178 | #define TIMPI_HAVE_STRING_PACKING 179 | 180 | template 181 | class Packing, 182 | typename std::enable_if::is_fixed_type>::type>; 183 | 184 | } // namespace Parallel 185 | 186 | } // namespace libMesh 187 | 188 | 189 | namespace TIMPI { 190 | 191 | using libMesh::Parallel::Packing; 192 | 193 | /** 194 | * Decode a range of potentially-variable-size objects from a data 195 | * array. 196 | * 197 | * We take \p out_iter by value for maximum compatibility, but we 198 | * return it afterward for the use of code that needs to unpack 199 | * multiple buffers to the same output iterator. 200 | */ 201 | template 203 | inline OutputIter unpack_range (const typename std::vector & buffer, 204 | Context * context, 205 | OutputIter out_iter, 206 | const T * output_type /* used only to infer T */); 207 | 208 | /** 209 | * Encode a range of potentially-variable-size objects to a data 210 | * array. 211 | * 212 | * The data will be buffered in vectors with lengths that do not 213 | * exceed the sum of \p approx_buffer_size and the size of an 214 | * individual packed object. 215 | */ 216 | template 217 | inline Iter pack_range (const Context * context, 218 | Iter range_begin, 219 | const Iter range_end, 220 | typename std::vector & buffer, 221 | std::size_t approx_buffer_size = 1000000); 222 | 223 | /** 224 | * Return the total buffer size needed to encode a range of 225 | * potentially-variable-size objects to a data array. 226 | */ 227 | template 228 | inline std::size_t packed_range_size (const Context * context, 229 | Iter range_begin, 230 | const Iter range_end); 231 | 232 | } // namespace TIMPI 233 | 234 | #endif // TIMPI_PACKING_H 235 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/packing_forward.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_PACKING_FORWARD_H 20 | #define TIMPI_PACKING_FORWARD_H 21 | 22 | // FIXME: This *should* be in TIMPI namespace but we have libMesh 23 | // users which already partially specialized it 24 | namespace libMesh 25 | { 26 | namespace Parallel 27 | { 28 | /** 29 | * Define data types and (un)serialization functions for use when 30 | * encoding a potentially-variable-size object of type T. 31 | * 32 | * Users will need to specialize this class for their particular data 33 | * types. 34 | */ 35 | template 36 | class Packing; 37 | } 38 | } 39 | 40 | #endif // TIMPI_PACKING_FORWARD_H 41 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_copy_buffer.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_COPY_BUFFER_H 20 | #define TIMPI_POST_WAIT_COPY_BUFFER_H 21 | 22 | // TIMPI includes 23 | #include "timpi/post_wait_work.h" 24 | 25 | // C++ includes 26 | #include 27 | 28 | namespace TIMPI 29 | { 30 | 31 | // PostWaitWork specialization for copying from temporary to 32 | // output containers 33 | template 34 | struct PostWaitCopyBuffer : public PostWaitWork { 35 | PostWaitCopyBuffer(const Container & buffer, const OutputIter out) 36 | : _buf(buffer), _out(out) {} 37 | 38 | virtual void run() override { std::copy(_buf.begin(), _buf.end(), _out); } 39 | 40 | private: 41 | const Container & _buf; 42 | OutputIter _out; 43 | }; 44 | 45 | } // namespace TIMPI 46 | 47 | #endif // TIMPI_POST_WAIT_COPY_BUFFER_H 48 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_delete_buffer.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_DELETE_BUFFER_H 20 | #define TIMPI_POST_WAIT_DELETE_BUFFER_H 21 | 22 | // TIMPI includes 23 | #include "timpi/post_wait_work.h" 24 | 25 | namespace TIMPI 26 | { 27 | 28 | // PostWaitWork specialization for deleting no-longer-needed buffers. 29 | template 30 | struct PostWaitDeleteBuffer : public PostWaitWork { 31 | PostWaitDeleteBuffer(Container * buffer) : _buf(buffer) {} 32 | 33 | virtual void run() override { delete _buf; } 34 | 35 | private: 36 | Container * _buf; 37 | }; 38 | 39 | } // namespace TIMPI 40 | 41 | #endif // TIMPI_POST_WAIT_DELETE_BUFFER_H 42 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_dereference_shared_ptr.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_DEREFERENCE_SHARED_PTR_H 20 | #define TIMPI_POST_WAIT_DEREFERENCE_SHARED_PTR_H 21 | 22 | // TIMPI includes 23 | #include "timpi/post_wait_work.h" 24 | 25 | // System Includes 26 | #include 27 | 28 | namespace TIMPI 29 | { 30 | 31 | // PostWaitWork specialization for holding a shared_ptr reference 32 | template 33 | struct PostWaitDereferenceSharedPtr : public PostWaitWork { 34 | PostWaitDereferenceSharedPtr(const std::shared_ptr & ptr) : _ptr(ptr) {} 35 | 36 | // Our real work is done by the destructor; 37 | virtual void run() {} 38 | 39 | private: 40 | const std::shared_ptr _ptr; 41 | }; 42 | 43 | } // namespace TIMPI 44 | 45 | #endif // TIMPI_POST_WAIT_DEREFERENCE_SHARED_PTR_H 46 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_dereference_tag.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_DEREFERENCE_TAG_H 20 | #define TIMPI_POST_WAIT_DEREFERENCE_TAG_H 21 | 22 | // TIMPI includes 23 | #include "timpi/message_tag.h" 24 | #include "timpi/post_wait_work.h" 25 | 26 | namespace TIMPI 27 | { 28 | 29 | // PostWaitWork specialization for holding a MessageTag. This 30 | // prevents the MessageTag from being completely dereferenced and thus 31 | // prevents a unique tag number from being reused until after the 32 | // Request has been cleaned up. 33 | struct PostWaitDereferenceTag : public PostWaitWork { 34 | PostWaitDereferenceTag(const MessageTag & tag) : _tag(tag) {} 35 | 36 | // Our real work is done by the MessageTag member's destructor; 37 | // there's no advantage to dereferencing our tag slightly earlier. 38 | virtual void run() override {} 39 | 40 | private: 41 | MessageTag _tag; 42 | }; 43 | 44 | } // namespace TIMPI 45 | 46 | #endif // TIMPI_POST_WAIT_DEREFERENCE_TAG_H 47 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_free_buffer.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_FREE_BUFFER_H 20 | #define TIMPI_POST_WAIT_FREE_BUFFER_H 21 | 22 | // TIMPI includes 23 | #include "timpi/post_wait_work.h" 24 | 25 | namespace TIMPI 26 | { 27 | 28 | // PostWaitWork specialization for freeing no-longer-needed buffers. 29 | template 30 | struct PostWaitFreeBuffer : public PostWaitWork { 31 | PostWaitFreeBuffer(T * buffer) : _buf(buffer) {} 32 | 33 | virtual void run() override { free(_buf); } 34 | 35 | private: 36 | T * _buf; 37 | }; 38 | 39 | } // namespace TIMPI 40 | 41 | #endif // TIMPI_POST_WAIT_FREE_BUFFER_H 42 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_unpack_buffer.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_UNPACK_BUFFER_H 20 | #define TIMPI_POST_WAIT_UNPACK_BUFFER_H 21 | 22 | // TIMPI includes 23 | #include "timpi/post_wait_work.h" 24 | #include "timpi/packing.h" 25 | 26 | namespace TIMPI 27 | { 28 | 29 | // PostWaitWork specialization for unpacking received buffers. 30 | template 32 | struct PostWaitUnpackBuffer : public PostWaitWork { 33 | PostWaitUnpackBuffer(const Container & buffer, Context * context, OutputIter out) : 34 | _buf(buffer), _context(context), _out(out) {} 35 | 36 | virtual void run() override { 37 | 38 | unpack_range(_buf, _context, _out, (T*)nullptr); 39 | } 40 | 41 | private: 42 | const Container & _buf; 43 | Context * _context; 44 | OutputIter _out; 45 | }; 46 | 47 | } // namespace TIMPI 48 | 49 | #endif // TIMPI_POST_WAIT_UNPACK_BUFFER_H 50 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_unpack_nested_buffer.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_UNPACK_NESTED_BUFFER_H 20 | #define TIMPI_POST_WAIT_UNPACK_NESTED_BUFFER_H 21 | 22 | // TIMPI includes 23 | #include "timpi/communicator.h" 24 | #include "timpi/post_wait_work.h" 25 | #include "timpi/standard_type.h" 26 | 27 | namespace TIMPI 28 | { 29 | 30 | // PostWaitWork specialization for MPI_Unpack of nested buffers. 31 | // Container will most likely be vector> 32 | template 33 | struct PostWaitUnpackNestedBuffer : public PostWaitWork { 34 | PostWaitUnpackNestedBuffer(const std::vector & buffer, 35 | Container & out, 36 | const DataType & timpi_mpi_var(T_type), 37 | const Communicator & comm_in) : 38 | recvbuf(buffer), recv(out), comm(comm_in) { 39 | timpi_call_mpi(MPI_Type_dup(T_type, &(type.operator data_type &()))); 40 | #ifndef TIMPI_HAVE_MPI 41 | timpi_not_implemented(); // This makes no sense without MPI_Unpack 42 | #endif 43 | } 44 | 45 | ~PostWaitUnpackNestedBuffer() { 46 | #ifdef TIMPI_HAVE_MPI 47 | // Not bothering with return type; we can't throw in a destructor 48 | MPI_Type_free(&(type.operator data_type &())); 49 | #endif 50 | } 51 | 52 | virtual void run() override { 53 | #ifdef TIMPI_HAVE_MPI 54 | 55 | #if MPI_VERSION > 3 56 | # define TIMPI_COUNT_TYPE MPI_COUNT 57 | # define TIMPI_UNPACK MPI_Unpack_c 58 | #else 59 | # define TIMPI_COUNT_TYPE MPI_INT 60 | # define TIMPI_UNPACK MPI_Unpack 61 | #endif 62 | 63 | // We should at least have one header datum, for outer vector size 64 | timpi_assert (!recvbuf.empty()); 65 | 66 | // Unpack the received buffer 67 | CountType bufsize = cast_int(recvbuf.size()); 68 | CountType recvsize, pos=0; 69 | timpi_call_mpi 70 | (TIMPI_UNPACK(recvbuf.data(), bufsize, &pos, &recvsize, 1, 71 | TIMPI_COUNT_TYPE, comm.get())); 72 | 73 | // ... size the outer buffer 74 | recv.resize (recvsize); 75 | 76 | const std::size_t n_vecs = recvsize; 77 | for (std::size_t i = 0; i != n_vecs; ++i) 78 | { 79 | CountType subvec_size; 80 | 81 | timpi_call_mpi 82 | (TIMPI_UNPACK(recvbuf.data(), bufsize, &pos, &subvec_size, 1, 83 | TIMPI_COUNT_TYPE, comm.get())); 84 | 85 | // ... size the inner buffer 86 | recv[i].resize (subvec_size); 87 | 88 | // ... unpack the inner buffer if it is not empty 89 | if (!recv[i].empty()) 90 | timpi_call_mpi 91 | (TIMPI_UNPACK(recvbuf.data(), bufsize, &pos, recv[i].data(), 92 | subvec_size, type, comm.get())); 93 | } 94 | #endif //TIMPI_HAVE_MPI 95 | } 96 | 97 | private: 98 | const std::vector & recvbuf; 99 | Container & recv; 100 | DataType type; 101 | const Communicator & comm; 102 | }; 103 | 104 | } // namespace TIMPI 105 | 106 | #endif // TIMPI_POST_WAIT_UNPACK_NESTED_BUFFER_H 107 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/post_wait_work.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_POST_WAIT_WORK_H 20 | #define TIMPI_POST_WAIT_WORK_H 21 | 22 | namespace TIMPI 23 | { 24 | //------------------------------------------------------------------- 25 | /** 26 | * An abstract base class that can be subclassed to allow other code 27 | * to perform work after a MPI_Wait succeeds. This makes it possible 28 | * to automatically schedule deserialization, cleanup, or other 29 | * operations such that they automatically take place after an 30 | * asynchronous I/O operation has completed. 31 | * 32 | * See PostWaitCopyBuffer, PostWaitDeleteBuffer, and 33 | * PostWaitUnpackBuffer for examples of useful subclasses that are 34 | * automatically employed by the library. See the 35 | * Request::add_post_wait_work method for documentation of how to use 36 | * these subclasses. See Communicator method implementations for 37 | * examples of all this in use, including chaining of multiple 38 | * PostWaitWork operations. 39 | */ 40 | struct PostWaitWork { 41 | virtual ~PostWaitWork() {} 42 | 43 | // Do *something* after a communication wait has succeeded. 44 | virtual void run() = 0; 45 | }; 46 | 47 | } // namespace TIMPI 48 | 49 | #endif // TIMPI_POST_WAIT_WORK_H 50 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/request.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_REQUEST_H 20 | #define TIMPI_REQUEST_H 21 | 22 | // TIMPI includes 23 | #include "timpi/timpi_config.h" 24 | #include "timpi/status.h" 25 | 26 | // C/C++ includes 27 | #ifdef TIMPI_HAVE_MPI 28 | # include "timpi/ignore_warnings.h" 29 | # include "mpi.h" 30 | # include "timpi/restore_warnings.h" 31 | #endif // TIMPI_HAVE_MPI 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TIMPI 38 | { 39 | 40 | // Forward declarations 41 | struct PostWaitWork; 42 | 43 | #ifdef TIMPI_HAVE_MPI 44 | 45 | //------------------------------------------------------------------- 46 | /** 47 | * Request object for non-blocking I/O 48 | */ 49 | typedef MPI_Request request; 50 | 51 | #else 52 | 53 | // This shouldn't actually be needed, but must be 54 | // a unique type for function overloading to work 55 | // properly. 56 | // 57 | // We'll want some actual data in here, to make it possible for 58 | // waitany() to be used in loops that degrade cleanly. 59 | typedef unsigned int request; 60 | #endif // TIMPI_HAVE_MPI 61 | 62 | 63 | //------------------------------------------------------------------- 64 | /** 65 | * Encapsulates the MPI_Request 66 | */ 67 | class Request 68 | { 69 | public: 70 | Request (); 71 | 72 | Request (const request & r); 73 | 74 | Request (const Request & other); 75 | 76 | void cleanup(); 77 | 78 | Request & operator = (const Request & other); 79 | 80 | Request & operator = (const request & r); 81 | 82 | ~Request (); 83 | 84 | request * get() { return &_request; } 85 | 86 | const request * get() const { return &_request; } 87 | 88 | Status wait (); 89 | 90 | bool test (); 91 | 92 | bool test (status & status); 93 | 94 | // Breaking non-blocking sends into multiple requests can require 95 | // chaining multiple requests into a single Request. After using 96 | // add_prior_request, any wait() on this request automatically 97 | // begins with a wait() on a copy of the added Request \p req. 98 | // 99 | // The added request should not already have a prior request of its 100 | // own. However, if \p this request already has a prior, it will be 101 | // moved to and thus invoked prior to the new prior request \p req. 102 | void add_prior_request(const Request & req); 103 | 104 | // Objects of a PostWaitWork subclass can be added to this request, 105 | // and they will automatically be run() after a wait() on this 106 | // request completes. The \p work object must be heap allocated, 107 | // and will be deleted once \p this Request and any Request copies 108 | // made from \p this have been cleaned up. 109 | void add_post_wait_work(PostWaitWork * work); 110 | 111 | static const request null_request; 112 | 113 | private: 114 | request _request; 115 | 116 | std::unique_ptr _prior_request; 117 | 118 | // post_wait_work->first is a vector of work to do after a wait 119 | // finishes; post_wait_work->second is a reference count so that 120 | // Request objects will behave roughly like a shared_ptr and be 121 | // usable in STL containers 122 | // 123 | // FIXME - we require C++11 now, so we can be smarter about this. 124 | std::pair, unsigned int> * post_wait_work; 125 | 126 | // waitany() takes a container of Requests, so it can't be a member 127 | // function, but it needs access to each Request's _prior_request 128 | // and _post_wait_work 129 | friend std::size_t waitany (std::vector &); 130 | }; 131 | 132 | /** 133 | * Wait for a non-blocking send or receive to finish 134 | */ 135 | inline Status wait (Request & r) { return r.wait(); } 136 | 137 | /** 138 | * Wait for all non-blocking operations to finish 139 | */ 140 | void wait (std::vector & r); 141 | 142 | /** 143 | * Wait for at least one non-blocking operation to finish. Return the 144 | * index of the request which completed. 145 | */ 146 | std::size_t waitany (std::vector & r); 147 | 148 | 149 | } // namespace TIMPI 150 | 151 | #endif // TIMPI_REQUEST_H 152 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/standard_type_forward.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | #ifndef TIMPI_STANDARD_TYPE_FORWARD_H 19 | #define TIMPI_STANDARD_TYPE_FORWARD_H 20 | 21 | namespace TIMPI 22 | { 23 | template 24 | class StandardType; 25 | } 26 | 27 | #endif // TIMPI_STANDARD_TYPE_FORWARD_H 28 | -------------------------------------------------------------------------------- /src/parallel/include/timpi/status.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_STATUS_H 20 | #define TIMPI_STATUS_H 21 | 22 | // TIMPI includes 23 | #include "timpi/data_type.h" 24 | #include "timpi/timpi_assert.h" 25 | #include "timpi/timpi_config.h" 26 | 27 | // C/C++ includes 28 | #ifdef TIMPI_HAVE_MPI 29 | # include "timpi/ignore_warnings.h" 30 | # include "mpi.h" 31 | # include "timpi/restore_warnings.h" 32 | #endif // TIMPI_HAVE_MPI 33 | 34 | namespace TIMPI 35 | { 36 | 37 | #ifdef TIMPI_HAVE_MPI 38 | 39 | //------------------------------------------------------------------- 40 | 41 | /** 42 | * Status object for querying messages 43 | */ 44 | typedef MPI_Status status; 45 | 46 | # if MPI_VERSION > 3 47 | typedef MPI_Count CountType; 48 | #define TIMPI_GET_COUNT MPI_Get_count_c 49 | # else 50 | typedef int CountType; 51 | #define TIMPI_GET_COUNT MPI_Get_count 52 | # endif 53 | 54 | #else 55 | 56 | // This shouldn't actually be needed, but must be 57 | // unique types for function overloading to work 58 | // properly. 59 | struct status { /* unsigned int s; */ }; 60 | 61 | // This makes backwards compatibility easiest, and it should be fine 62 | // to use 32 bits here since serial operations are generally no-ops 63 | // that don't actually use a CountType 64 | typedef int CountType; 65 | 66 | #endif // TIMPI_HAVE_MPI 67 | 68 | 69 | 70 | //------------------------------------------------------------------- 71 | /** 72 | * Encapsulates the MPI_Status struct. Allows the source and size 73 | * of the message to be determined. 74 | */ 75 | class Status 76 | { 77 | public: 78 | Status () = default; 79 | ~Status () = default; 80 | Status (const Status &) = default; 81 | Status (Status &&) = default; 82 | Status & operator=(const Status &) = default; 83 | Status & operator=(Status &&) = default; 84 | 85 | explicit Status (const data_type & type); 86 | 87 | explicit Status (const status & status); 88 | 89 | Status (const status & status, 90 | const data_type & type); 91 | 92 | Status (const Status & status, 93 | const data_type & type); 94 | 95 | status * get() { return &_status; } 96 | 97 | status const * get() const { return &_status; } 98 | 99 | int source () const; 100 | 101 | int tag () const; 102 | 103 | data_type & datatype () { return _datatype; } 104 | 105 | const data_type & datatype () const { return _datatype; } 106 | 107 | CountType size (const data_type & type) const; 108 | 109 | CountType size () const; 110 | 111 | private: 112 | 113 | status _status; 114 | data_type _datatype; 115 | }; 116 | 117 | // ------------------------------------------------------------ 118 | // Status member functions 119 | 120 | inline Status::Status (const data_type & type) : 121 | _status(), 122 | _datatype(type) 123 | {} 124 | 125 | inline Status::Status (const status & stat) : 126 | _status(stat), 127 | _datatype() 128 | {} 129 | 130 | inline Status::Status (const status & stat, 131 | const data_type & type) : 132 | _status(stat), 133 | _datatype(type) 134 | {} 135 | 136 | inline Status::Status (const Status & stat, 137 | const data_type & type) : 138 | _status(stat._status), 139 | _datatype(type) 140 | {} 141 | 142 | inline int Status::source () const 143 | { 144 | #ifdef TIMPI_HAVE_MPI 145 | return _status.MPI_SOURCE; 146 | #else 147 | return 0; 148 | #endif 149 | } 150 | 151 | inline int Status::tag () const 152 | { 153 | #ifdef TIMPI_HAVE_MPI 154 | return _status.MPI_TAG; 155 | #else 156 | timpi_not_implemented(); 157 | return 0; 158 | #endif 159 | } 160 | 161 | inline CountType Status::size (const data_type & type) const 162 | { 163 | ignore(type); // We don't use this ifndef TIMPI_HAVE_MPI 164 | CountType msg_size = 1; 165 | timpi_call_mpi 166 | (TIMPI_GET_COUNT(const_cast(&_status), type, 167 | &msg_size)); 168 | 169 | timpi_assert_greater_equal (msg_size, 0); 170 | return msg_size; 171 | } 172 | 173 | inline CountType Status::size () const 174 | { return this->size (this->datatype()); } 175 | 176 | 177 | } // namespace TIMPI 178 | 179 | #endif // TIMPI_STATUS_H 180 | -------------------------------------------------------------------------------- /src/parallel/src/communicator.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Local includes 20 | #include "timpi/communicator.h" 21 | 22 | // TIMPI includes 23 | #include "timpi/parallel_implementation.h" // for inline max(int) 24 | #include "timpi/timpi_assert.h" 25 | 26 | // Disable libMesh logging until we decide how to port it best 27 | // #include "libmesh/libmesh_logging.h" 28 | #define TIMPI_LOG_SCOPE(f,c) 29 | 30 | namespace TIMPI 31 | { 32 | 33 | 34 | // ------------------------------------------------------------ 35 | // Simple Communicator member functions 36 | 37 | void Communicator::reference_unique_tag(int tagvalue) const 38 | { 39 | // This had better be an already-acquired tag. 40 | timpi_assert(used_tag_values.count(tagvalue)); 41 | 42 | used_tag_values[tagvalue]++; 43 | } 44 | 45 | 46 | void Communicator::dereference_unique_tag(int tagvalue) const 47 | { 48 | // This had better be an already-acquired tag. 49 | timpi_assert(used_tag_values.count(tagvalue)); 50 | 51 | used_tag_values[tagvalue]--; 52 | // If we don't have any more outstanding references, we 53 | // don't even need to keep this tag in our "used" set. 54 | if (!used_tag_values[tagvalue]) 55 | used_tag_values.erase(tagvalue); 56 | } 57 | 58 | 59 | Communicator::Communicator () : 60 | #ifdef TIMPI_HAVE_MPI 61 | _communicator(MPI_COMM_SELF), 62 | #endif 63 | _rank(0), 64 | _size(1), 65 | _send_mode(DEFAULT), 66 | _sync_type(NBX), 67 | used_tag_values(), 68 | _next_tag(0), 69 | _max_tag(std::numeric_limits::max()), 70 | _I_duped_it(false) {} 71 | 72 | 73 | Communicator::Communicator (const communicator & comm) : 74 | #ifdef TIMPI_HAVE_MPI 75 | _communicator(MPI_COMM_SELF), 76 | #endif 77 | _rank(0), 78 | _size(1), 79 | _send_mode(DEFAULT), 80 | _sync_type(NBX), 81 | used_tag_values(), 82 | _next_tag(0), 83 | _max_tag(std::numeric_limits::max()), 84 | _I_duped_it(false) 85 | { 86 | this->assign(comm); 87 | } 88 | 89 | 90 | Communicator::~Communicator () 91 | { 92 | this->clear(); 93 | } 94 | 95 | 96 | #ifdef TIMPI_HAVE_MPI 97 | void Communicator::split(int color, int key, Communicator & target) const 98 | { 99 | target.clear(); 100 | MPI_Comm newcomm; 101 | timpi_call_mpi 102 | (MPI_Comm_split(this->get(), color, key, &newcomm)); 103 | 104 | target.assign(newcomm); 105 | target._I_duped_it = (color != MPI_UNDEFINED); 106 | target.send_mode(this->send_mode()); 107 | target.sync_type(this->sync_type()); 108 | } 109 | 110 | 111 | void Communicator::split_by_type(int split_type, int key, info i, Communicator & target) const 112 | { 113 | target.clear(); 114 | MPI_Comm newcomm; 115 | timpi_call_mpi 116 | (MPI_Comm_split_type(this->get(), split_type, key, i, &newcomm)); 117 | 118 | target.assign(newcomm); 119 | target._I_duped_it = (split_type != MPI_UNDEFINED); 120 | target.send_mode(this->send_mode()); 121 | target.sync_type(this->sync_type()); 122 | } 123 | 124 | #else 125 | void Communicator::split(int, int, Communicator & target) const 126 | { 127 | target.assign(this->get()); 128 | } 129 | 130 | void Communicator::split_by_type(int, int, info, Communicator & target) const 131 | { 132 | target.assign(this->get()); 133 | } 134 | #endif 135 | 136 | 137 | void Communicator::duplicate(const Communicator & comm) 138 | { 139 | this->duplicate(comm._communicator); 140 | this->send_mode(comm.send_mode()); 141 | this->sync_type(comm.sync_type()); 142 | } 143 | 144 | 145 | #ifdef TIMPI_HAVE_MPI 146 | void Communicator::duplicate(const communicator & comm) 147 | { 148 | if (_communicator != MPI_COMM_NULL) 149 | { 150 | timpi_call_mpi 151 | (MPI_Comm_dup(comm, &_communicator)); 152 | 153 | _I_duped_it = true; 154 | } 155 | this->assign(_communicator); 156 | } 157 | #else 158 | void Communicator::duplicate(const communicator &) { } 159 | #endif 160 | 161 | 162 | void Communicator::clear() { 163 | #ifdef TIMPI_HAVE_MPI 164 | if (_I_duped_it) 165 | { 166 | timpi_assert (_communicator != MPI_COMM_NULL); 167 | timpi_call_mpi 168 | (MPI_Comm_free(&_communicator)); 169 | 170 | _communicator = MPI_COMM_NULL; 171 | } 172 | _I_duped_it = false; 173 | #endif 174 | } 175 | 176 | 177 | Communicator & Communicator::operator= (const communicator & comm) 178 | { 179 | this->clear(); 180 | this->assign(comm); 181 | return *this; 182 | } 183 | 184 | 185 | void Communicator::assign(const communicator & comm) 186 | { 187 | _communicator = comm; 188 | #ifdef TIMPI_HAVE_MPI 189 | if (_communicator != MPI_COMM_NULL) 190 | { 191 | int i; 192 | timpi_call_mpi 193 | (MPI_Comm_size(_communicator, &i)); 194 | 195 | timpi_assert_greater (i, 0); 196 | _size = cast_int(i); 197 | 198 | timpi_call_mpi 199 | (MPI_Comm_rank(_communicator, &i)); 200 | 201 | timpi_assert_greater_equal (i, 0); 202 | _rank = cast_int(i); 203 | 204 | int * maxTag; 205 | int flag = false; 206 | timpi_call_mpi(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxTag, &flag)); 207 | timpi_assert(flag); 208 | _max_tag = *maxTag; 209 | } 210 | else 211 | { 212 | _rank = 0; 213 | _size = 1; 214 | _max_tag = std::numeric_limits::max(); 215 | } 216 | _next_tag = _max_tag / 2; 217 | #endif 218 | } 219 | 220 | 221 | /** 222 | * Pause execution until all processors reach a certain point. 223 | */ 224 | #ifdef TIMPI_HAVE_MPI 225 | void Communicator::barrier () const 226 | { 227 | if (this->size() > 1) 228 | { 229 | TIMPI_LOG_SCOPE("barrier()", "Communicator"); 230 | timpi_call_mpi(MPI_Barrier (this->get())); 231 | } 232 | } 233 | #else 234 | void Communicator::barrier () const {} 235 | #endif 236 | 237 | #ifdef TIMPI_HAVE_MPI 238 | void Communicator::nonblocking_barrier (Request & req) const 239 | { 240 | if (this->size() > 1) 241 | { 242 | TIMPI_LOG_SCOPE("nonblocking_barrier()", "Communicator"); 243 | timpi_call_mpi(MPI_Ibarrier (this->get(), req.get())); 244 | } 245 | } 246 | #else 247 | void Communicator::nonblocking_barrier (Request & /*req*/) const {} 248 | #endif 249 | 250 | 251 | MessageTag Communicator::get_unique_tag(int tagvalue) const 252 | { 253 | if (tagvalue == MessageTag::invalid_tag) 254 | { 255 | #ifndef NDEBUG 256 | // Automatic tag values have to be requested in sync 257 | int maxval = _next_tag; 258 | this->max(maxval); 259 | timpi_assert_equal_to(_next_tag, maxval); 260 | #endif 261 | tagvalue = _next_tag++; 262 | } 263 | 264 | if (used_tag_values.count(tagvalue)) 265 | { 266 | // Get the largest value in the used values, and pick one 267 | // larger 268 | tagvalue = used_tag_values.rbegin()->first+1; 269 | timpi_assert(!used_tag_values.count(tagvalue)); 270 | } 271 | if (tagvalue >= _next_tag) 272 | _next_tag = tagvalue+1; 273 | 274 | if (_next_tag >= _max_tag) 275 | _next_tag = _max_tag/2; 276 | 277 | used_tag_values[tagvalue] = 1; 278 | 279 | return MessageTag(tagvalue, this); 280 | } 281 | 282 | 283 | status Communicator::probe (const unsigned int src_processor_id, 284 | const MessageTag & tag) const 285 | { 286 | TIMPI_LOG_SCOPE("probe()", "Communicator"); 287 | 288 | #ifndef TIMPI_HAVE_MPI 289 | timpi_not_implemented(); 290 | ignore(src_processor_id, tag); 291 | #endif 292 | 293 | status stat; 294 | 295 | timpi_assert(src_processor_id < this->size() || 296 | src_processor_id == any_source); 297 | 298 | timpi_call_mpi 299 | (MPI_Probe (int(src_processor_id), tag.value(), this->get(), &stat)); 300 | 301 | return stat; 302 | } 303 | 304 | 305 | bool Communicator::verify(const bool & r) const 306 | { 307 | const unsigned char rnew = r; 308 | return this->verify(rnew); 309 | } 310 | 311 | 312 | bool Communicator::semiverify(const bool * r) const 313 | { 314 | if (r) 315 | { 316 | const unsigned char rnew = *r; 317 | return this->semiverify(&rnew); 318 | } 319 | 320 | const unsigned char * rptr = nullptr; 321 | return this->semiverify(rptr); 322 | } 323 | 324 | 325 | bool Communicator::verify(const std::string & r) const 326 | { 327 | if (this->size() > 1) 328 | { 329 | // Cannot use since MPI_MIN is not 330 | // strictly defined for chars! 331 | std::vector temp; temp.reserve(r.size()); 332 | for (std::size_t i=0; i != r.size(); ++i) 333 | temp.push_back(r[i]); 334 | return this->verify(temp); 335 | } 336 | return true; 337 | } 338 | 339 | 340 | bool Communicator::semiverify(const std::string * r) const 341 | { 342 | if (this->size() > 1) 343 | { 344 | std::size_t rsize = r ? r->size() : 0; 345 | std::size_t * psize = r ? &rsize : nullptr; 346 | 347 | if (!this->semiverify(psize)) 348 | return false; 349 | 350 | this->max(rsize); 351 | 352 | // Cannot use since MPI_MIN is not 353 | // strictly defined for chars! 354 | std::vector temp (rsize); 355 | if (r) 356 | { 357 | temp.reserve(rsize); 358 | for (std::size_t i=0; i != rsize; ++i) 359 | temp.push_back((*r)[i]); 360 | } 361 | 362 | std::vector * ptemp = r ? &temp: nullptr; 363 | 364 | return this->semiverify(ptemp); 365 | } 366 | return true; 367 | } 368 | 369 | 370 | void Communicator::min(bool & r) const 371 | { 372 | if (this->size() > 1) 373 | { 374 | TIMPI_LOG_SCOPE("min(bool)", "Communicator"); 375 | 376 | unsigned int temp = r; 377 | timpi_call_mpi 378 | (MPI_Allreduce (MPI_IN_PLACE, &temp, 1, 379 | StandardType(), 380 | OpFunction::min(), 381 | this->get())); 382 | r = temp; 383 | } 384 | } 385 | 386 | 387 | void Communicator::minloc(bool & r, 388 | unsigned int & min_id) const 389 | { 390 | if (this->size() > 1) 391 | { 392 | TIMPI_LOG_SCOPE("minloc(bool)", "Communicator"); 393 | 394 | DataPlusInt data_in; 395 | ignore(data_in); // unused ifndef TIMPI_HAVE_MPI 396 | data_in.val = r; 397 | data_in.rank = this->rank(); 398 | DataPlusInt data_out = data_in; 399 | 400 | timpi_call_mpi 401 | (MPI_Allreduce (&data_in, &data_out, 1, 402 | dataplusint_type_acquire().first, 403 | OpFunction::min_location(), this->get())); 404 | r = data_out.val; 405 | min_id = data_out.rank; 406 | } 407 | else 408 | min_id = this->rank(); 409 | } 410 | 411 | 412 | void Communicator::max(bool & r) const 413 | { 414 | if (this->size() > 1) 415 | { 416 | TIMPI_LOG_SCOPE("max(bool)", "Communicator"); 417 | 418 | unsigned int temp = r; 419 | timpi_call_mpi 420 | (MPI_Allreduce (MPI_IN_PLACE, &temp, 1, 421 | StandardType(), 422 | OpFunction::max(), 423 | this->get())); 424 | r = temp; 425 | } 426 | } 427 | 428 | 429 | void Communicator::maxloc(bool & r, 430 | unsigned int & max_id) const 431 | { 432 | if (this->size() > 1) 433 | { 434 | TIMPI_LOG_SCOPE("maxloc(bool)", "Communicator"); 435 | 436 | DataPlusInt data_in; 437 | ignore(data_in); // unused ifndef TIMPI_HAVE_MPI 438 | data_in.val = r; 439 | data_in.rank = this->rank(); 440 | DataPlusInt data_out = data_in; 441 | 442 | timpi_call_mpi 443 | (MPI_Allreduce (&data_in, &data_out, 1, 444 | dataplusint_type_acquire().first, 445 | OpFunction::max_location(), 446 | this->get())); 447 | r = data_out.val; 448 | max_id = data_out.rank; 449 | } 450 | else 451 | max_id = this->rank(); 452 | } 453 | 454 | 455 | void Communicator::sync_type(const std::string & st) 456 | { 457 | SyncType type = NBX; 458 | if (st == "sendreceive") 459 | type = SENDRECEIVE; 460 | else if (st == "alltoall") 461 | type = ALLTOALL_COUNTS; 462 | else if (st != "nbx") 463 | timpi_error_msg("Unrecognized TIMPI sync type " << st); 464 | this->sync_type(type); 465 | } 466 | 467 | 468 | } // namespace TIMPI 469 | -------------------------------------------------------------------------------- /src/parallel/src/message_tag.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | // Local includes 19 | #include "timpi/message_tag.h" 20 | 21 | // TIMPI includes 22 | #include "timpi/communicator.h" 23 | 24 | 25 | 26 | namespace TIMPI 27 | { 28 | 29 | // ------------------------------------------------------------ 30 | // MessageTag member functions 31 | 32 | MessageTag::~MessageTag() 33 | { 34 | if (_comm) 35 | _comm->dereference_unique_tag(_tagvalue); 36 | } 37 | 38 | 39 | MessageTag::MessageTag(const MessageTag & other) 40 | : _tagvalue(other._tagvalue), _comm(other._comm) 41 | { 42 | if (_comm) 43 | _comm->reference_unique_tag(_tagvalue); 44 | } 45 | 46 | 47 | MessageTag::MessageTag(MessageTag && other) 48 | : _tagvalue(other._tagvalue), _comm(other._comm) 49 | { 50 | // I stole your tag reference! 51 | other._comm = nullptr; 52 | } 53 | 54 | 55 | MessageTag & MessageTag::operator= (const MessageTag & other) 56 | { 57 | if (_comm) 58 | _comm->dereference_unique_tag(_tagvalue); 59 | 60 | _tagvalue = other._tagvalue; 61 | _comm = other._comm; 62 | 63 | if (_comm) 64 | _comm->reference_unique_tag(_tagvalue); 65 | 66 | return *this; 67 | } 68 | 69 | 70 | MessageTag & MessageTag::operator= (MessageTag && other) 71 | { 72 | if (_comm) 73 | _comm->dereference_unique_tag(_tagvalue); 74 | 75 | _tagvalue = other._tagvalue; 76 | _comm = other._comm; 77 | 78 | // I stole your tag reference! 79 | other._comm = nullptr; 80 | 81 | return *this; 82 | } 83 | 84 | 85 | } // namespace TIMPI 86 | -------------------------------------------------------------------------------- /src/parallel/src/request.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | // Local includes 19 | #include "timpi/request.h" 20 | 21 | // TIMPI includes 22 | #include "timpi/timpi_call_mpi.h" 23 | #include "timpi/timpi_assert.h" 24 | #include "timpi/post_wait_work.h" 25 | #include "timpi/status.h" 26 | 27 | // Disable libMesh logging until we decide how to port it best 28 | // #include "libmesh/libmesh_logging.h" 29 | #define TIMPI_LOG_SCOPE(f,c) 30 | 31 | // C++ includes 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | namespace TIMPI 38 | { 39 | 40 | #ifdef TIMPI_HAVE_MPI 41 | const request Request::null_request = MPI_REQUEST_NULL; 42 | #else 43 | const request Request::null_request = 0; 44 | #endif 45 | 46 | // ------------------------------------------------------------ 47 | // Request member functions 48 | Request::Request () : 49 | _request(null_request), 50 | post_wait_work(nullptr) 51 | {} 52 | 53 | Request::Request (const request & r) : 54 | _request(r), 55 | post_wait_work(nullptr) 56 | {} 57 | 58 | Request::Request (const Request & other) : 59 | _request(other._request), 60 | post_wait_work(other.post_wait_work) 61 | { 62 | if (other._prior_request.get()) 63 | _prior_request = std::unique_ptr 64 | (new Request(*other._prior_request.get())); 65 | 66 | // operator= should behave like a shared pointer 67 | if (post_wait_work) 68 | post_wait_work->second++; 69 | } 70 | 71 | void Request::cleanup() 72 | { 73 | if (post_wait_work) 74 | { 75 | // Decrement the use count 76 | post_wait_work->second--; 77 | 78 | if (!post_wait_work->second) 79 | { 80 | #ifdef DEBUG 81 | // If we're done using this request, then we'd better have 82 | // done the work we waited for 83 | for (const auto & item : post_wait_work->first) 84 | timpi_assert(!item); 85 | #endif 86 | delete post_wait_work; 87 | post_wait_work = nullptr; 88 | } 89 | } 90 | } 91 | 92 | Request & Request::operator = (const Request & other) 93 | { 94 | this->cleanup(); 95 | _request = other._request; 96 | post_wait_work = other.post_wait_work; 97 | 98 | if (other._prior_request.get()) 99 | _prior_request = std::unique_ptr 100 | (new Request(*other._prior_request.get())); 101 | 102 | // operator= should behave like a shared pointer 103 | if (post_wait_work) 104 | post_wait_work->second++; 105 | 106 | return *this; 107 | } 108 | 109 | Request & Request::operator = (const request & r) 110 | { 111 | this->cleanup(); 112 | _request = r; 113 | post_wait_work = nullptr; 114 | return *this; 115 | } 116 | 117 | Request::~Request () { 118 | this->cleanup(); 119 | } 120 | 121 | Status Request::wait () 122 | { 123 | TIMPI_LOG_SCOPE("wait()", "Request"); 124 | 125 | if (_prior_request.get()) 126 | { 127 | _prior_request->wait(); 128 | _prior_request.reset(nullptr); 129 | } 130 | 131 | Status stat {}; 132 | #ifdef TIMPI_HAVE_MPI 133 | timpi_call_mpi 134 | (MPI_Wait (&_request, stat.get())); 135 | #endif 136 | if (post_wait_work) 137 | { 138 | for (auto & item : post_wait_work->first) 139 | { 140 | // The user should never try to give us non-existent work or try 141 | // to wait() twice. 142 | timpi_assert (item); 143 | item->run(); 144 | delete item; 145 | item = nullptr; 146 | } 147 | post_wait_work->first.clear(); 148 | } 149 | 150 | return stat; 151 | } 152 | 153 | bool Request::test () 154 | { 155 | #ifdef TIMPI_HAVE_MPI 156 | int val=0; 157 | 158 | timpi_call_mpi 159 | (MPI_Test (&_request, &val, MPI_STATUS_IGNORE)); 160 | 161 | if (val) 162 | { 163 | timpi_assert (_request == null_request); 164 | timpi_assert_equal_to (val, 1); 165 | } 166 | 167 | return val; 168 | #else 169 | return true; 170 | #endif 171 | } 172 | 173 | #ifdef TIMPI_HAVE_MPI 174 | bool Request::test (status & stat) 175 | { 176 | int val=0; 177 | 178 | timpi_call_mpi 179 | (MPI_Test (&_request, &val, &stat)); 180 | 181 | return val; 182 | } 183 | #else 184 | bool Request::test (status &) 185 | { 186 | return true; 187 | } 188 | #endif 189 | 190 | void Request::add_prior_request(const Request & req) 191 | { 192 | // We're making a chain of prior requests, not a tree 193 | timpi_assert(!req._prior_request.get()); 194 | 195 | Request * new_prior_req = new Request(req); 196 | 197 | // new_prior_req takes ownership of our existing _prior_request 198 | new_prior_req->_prior_request.reset(this->_prior_request.release()); 199 | 200 | // Our _prior_request now manages the new resource we just set up 201 | this->_prior_request.reset(new_prior_req); 202 | } 203 | 204 | void Request::add_post_wait_work(PostWaitWork * work) 205 | { 206 | if (!post_wait_work) 207 | post_wait_work = new 208 | std::pair, unsigned int> 209 | (std::vector (), 1); 210 | post_wait_work->first.push_back(work); 211 | } 212 | 213 | void wait (std::vector & r) 214 | { 215 | for (auto & req : r) 216 | req.wait(); 217 | } 218 | 219 | std::size_t waitany (std::vector & r) 220 | { 221 | timpi_assert(!r.empty()); 222 | 223 | int r_size = cast_int(r.size()); 224 | std::vector raw(r_size); 225 | int non_null = r_size; 226 | for (int i=0; i != r_size; ++i) 227 | { 228 | Request * root = &r[i]; 229 | // If we have prior requests, we need to complete the first one 230 | // first 231 | while (root->_prior_request.get()) 232 | root = root->_prior_request.get(); 233 | raw[i] = *root->get(); 234 | 235 | if (raw[i] != Request::null_request) 236 | non_null = std::min(non_null,i); 237 | } 238 | 239 | if (non_null == r_size) 240 | return std::size_t(-1); 241 | 242 | int index = non_null; 243 | 244 | #ifdef TIMPI_HAVE_MPI 245 | bool only_priors_completed = false; 246 | Request * next; 247 | 248 | do 249 | { 250 | timpi_call_mpi 251 | (MPI_Waitany(r_size, raw.data(), &index, MPI_STATUS_IGNORE)); 252 | 253 | timpi_assert_not_equal_to(index, MPI_UNDEFINED); 254 | 255 | timpi_assert_less(index, r_size); 256 | 257 | Request * completed = &r[index]; 258 | next = completed; 259 | 260 | // If we completed a prior request, we're not really done yet, 261 | // so find the next in that line to try again. 262 | while (completed->_prior_request.get()) 263 | { 264 | only_priors_completed = true; 265 | next = completed; 266 | completed = completed->_prior_request.get(); 267 | } 268 | 269 | // MPI sets a completed MPI_Request to MPI_REQUEST_NULL; we want 270 | // to preserve that 271 | completed->_request = raw[index]; 272 | 273 | // Do any post-wait work for the completed request 274 | if (completed->post_wait_work) 275 | for (auto & item : completed->post_wait_work->first) 276 | { 277 | // The user should never try to give us non-existent work or try 278 | // to wait() twice. 279 | timpi_assert (item); 280 | item->run(); 281 | delete item; 282 | item = nullptr; 283 | } 284 | 285 | next->_prior_request.reset(nullptr); 286 | raw[index] = *next->get(); 287 | 288 | } while(only_priors_completed); 289 | #else 290 | r[index]._request = Request::null_request; 291 | #endif 292 | 293 | return index; 294 | } 295 | 296 | } // namespace TIMPI 297 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/ignore_warnings.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Note: no include guards! We want to be able to #include this 20 | // header multiple times. 21 | 22 | #include "timpi/timpi_config.h" 23 | 24 | // TODO: icpc options 25 | #ifdef __clang__ 26 | #pragma clang diagnostic push 27 | #pragma clang diagnostic ignored "-Wunused-parameter" 28 | #pragma clang diagnostic ignored "-Wextra-semi" 29 | #pragma clang diagnostic ignored "-Wvariadic-macros" 30 | #pragma clang diagnostic ignored "-Wc++11-extensions" 31 | #pragma clang diagnostic ignored "-Wnested-anon-types" 32 | #pragma clang diagnostic ignored "-Wsign-compare" 33 | #pragma clang diagnostic ignored "-Wunused-private-field" 34 | #pragma clang diagnostic ignored "-Wextra" 35 | #pragma clang diagnostic ignored "-Wredundant-decls" 36 | #pragma clang diagnostic ignored "-Wcast-align" 37 | #pragma clang diagnostic ignored "-Wcast-qual" 38 | #pragma clang diagnostic ignored "-Wswitch-default" 39 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 40 | #pragma clang diagnostic ignored "-Woverloaded-virtual" 41 | // This isn't supported in 3.4.2 at least 42 | #if (__clang_major__ > 3) 43 | #pragma clang diagnostic ignored "-Wmacro-redefined" 44 | #endif 45 | #if (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 5) 46 | // This was introduced in 3.6 47 | #pragma clang diagnostic ignored "-Winconsistent-missing-override" 48 | #endif // clang > 3.5 49 | #endif 50 | 51 | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) 52 | // GCC > 4.5 supports diagnostic pragmas with push/pop 53 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) 54 | #pragma GCC diagnostic push 55 | // These two don't work? 56 | #pragma GCC diagnostic ignored "-Wpedantic" 57 | #pragma GCC diagnostic ignored "-Wdeprecated" 58 | // But this is helpful with some MPI stacks 59 | #pragma GCC diagnostic ignored "-Wunused-parameter" 60 | // And these are for cppunit 61 | #pragma GCC diagnostic ignored "-Woverloaded-virtual" 62 | #pragma GCC diagnostic ignored "-Wundef" 63 | // And these are for Trilinos 64 | #pragma GCC diagnostic ignored "-Wextra" 65 | #pragma GCC diagnostic ignored "-Wshadow" 66 | // And these are for PETSc 67 | #pragma GCC diagnostic ignored "-Wredundant-decls" 68 | #pragma GCC diagnostic ignored "-Wcast-qual" 69 | #pragma GCC diagnostic ignored "-Wswitch-default" 70 | // And these are for Eigen 71 | #pragma GCC diagnostic ignored "-Wconversion" 72 | #pragma GCC diagnostic ignored "-Wstack-protector" 73 | // And this for VTK 74 | #pragma GCC diagnostic ignored "-Wlogical-op" 75 | // Ignore warnings from code that uses deprecated members of std, like std::auto_ptr. 76 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 77 | #if (__GNUC__ > 5) 78 | // Ignore this for VTK 79 | #pragma GCC diagnostic ignored "-Wfloat-conversion" 80 | // Ignore warnings from code that does "if (foo) bar();" 81 | #pragma GCC diagnostic ignored "-Wmisleading-indentation" 82 | // Ignore warnings from bad placement new use 83 | #pragma GCC diagnostic ignored "-Wplacement-new" 84 | #if (__GNUC__ > 6) 85 | #pragma GCC diagnostic ignored "-Wint-in-bool-context" 86 | #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" 87 | #if (__GNUC__ > 7) 88 | #pragma GCC diagnostic ignored "-Wparentheses" 89 | #pragma GCC diagnostic ignored "-Wcast-function-type" 90 | #if (__GNUC__ > 8) 91 | #pragma GCC diagnostic ignored "-Wdeprecated-copy" 92 | #endif // GCC > 8 93 | #endif // GCC > 7 94 | #endif // GCC > 6 95 | #endif // GCC > 5 96 | #endif // GCC > 4.5 97 | #endif // __GNUC__ && !__INTEL_COMPILER 98 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/restore_warnings.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Note: no include guards! We want to be able to #include this 20 | // header multiple times. 21 | 22 | #include "timpi/timpi_config.h" 23 | 24 | #ifdef __clang__ 25 | #pragma clang diagnostic pop 26 | #endif 27 | 28 | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) 29 | // GCC > 4.5 supports diagnostic pragmas with push/pop 30 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) 31 | #pragma GCC diagnostic pop 32 | #endif // GCC > 4.5 33 | #endif // __GNUC__ && !__INTEL_COMPILER 34 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/semipermanent.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | 20 | #ifndef TIMPI_SEMIPERMANENT_H 21 | #define TIMPI_SEMIPERMANENT_H 22 | 23 | 24 | // Local includes 25 | #include "timpi/timpi_config.h" 26 | 27 | // C/C++ includes 28 | 29 | #include 30 | #include 31 | 32 | namespace TIMPI 33 | { 34 | 35 | // Forward declare friend 36 | class TIMPIInit; 37 | 38 | /** 39 | * The \p SemiPermanent "class" is basically just a place for a 40 | * destructor vtable. Derive from it and pass a unique_ptr to your 41 | * derived object to SemiPermanent::add() whenever you have 42 | * something that ought to be *almost* permanent: that should be 43 | * cleaned up eventually to avoid resource leaks, but that should not 44 | * be cleaned up until the last TIMPIInit object exits, just before 45 | * the MPI_Finalize call if TIMPI initialized MPI. 46 | */ 47 | 48 | class SemiPermanent 49 | { 50 | public: 51 | SemiPermanent() = default; 52 | virtual ~SemiPermanent() = default; 53 | 54 | /* 55 | * Transfer ownership of a pointer to some "SemiPermanent" objects, 56 | * to be destroyed (and thereby do any necessary cleanup work) 57 | * whenever the last TIMPIInit is destroyed, before MPI is 58 | * finalized. 59 | */ 60 | static void add(std::unique_ptr obj); 61 | 62 | // Class to hold a reference to the SemiPermanent objects; they will 63 | // only be destructed when the last Ref is. 64 | struct Ref { 65 | Ref() { _ref_count++; } 66 | ~Ref(); 67 | }; 68 | 69 | private: 70 | 71 | // Mechanisms to avoid leaks after every TIMPIInit has been 72 | // destroyed 73 | static int _ref_count; 74 | static std::vector> _stuff_to_clean; 75 | }; 76 | 77 | 78 | } // namespace TIMPI 79 | 80 | #endif // TIMPI_SEMIPERMANENT_H 81 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/timpi.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_PARALLEL_H 20 | #define TIMPI_PARALLEL_H 21 | 22 | // TIMPI includes 23 | #include "timpi/attributes.h" 24 | #include "timpi/communicator.h" 25 | #include "timpi/data_type.h" 26 | #include "timpi/message_tag.h" 27 | #include "timpi/op_function.h" 28 | #include "timpi/packing.h" 29 | #include "timpi/timpi_call_mpi.h" 30 | #include "timpi/timpi_init.h" 31 | #include "timpi/post_wait_copy_buffer.h" 32 | #include "timpi/post_wait_delete_buffer.h" 33 | #include "timpi/post_wait_dereference_shared_ptr.h" 34 | #include "timpi/post_wait_dereference_tag.h" 35 | #include "timpi/post_wait_free_buffer.h" 36 | #include "timpi/post_wait_unpack_buffer.h" 37 | #include "timpi/post_wait_work.h" 38 | #include "timpi/request.h" 39 | #include "timpi/status.h" 40 | #include "timpi/standard_type.h" 41 | 42 | // Define all the implementations separately; users might want to look 43 | // through this file for APIs, and it's long enough already. 44 | 45 | #include "timpi/parallel_implementation.h" 46 | 47 | #endif // TIMPI_PARALLEL_H 48 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/timpi_call_mpi.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | #ifndef TIMPI_CALL_MPI_H 20 | #define TIMPI_CALL_MPI_H 21 | 22 | // TIMPI includes 23 | #include "timpi/timpi_assert.h" 24 | #include "timpi/timpi_config.h" 25 | 26 | // C/C++ includes 27 | #ifdef TIMPI_HAVE_MPI 28 | # include "timpi/ignore_warnings.h" 29 | # include "mpi.h" 30 | # include "timpi/restore_warnings.h" 31 | 32 | /** 33 | * Macro to use arguments only when MPI is in use 34 | */ 35 | #define timpi_mpi_var(var) var 36 | 37 | /** 38 | * Macros to test MPI return values 39 | */ 40 | #ifndef NDEBUG 41 | #define timpi_assert_mpi_success(error_code) \ 42 | do \ 43 | { \ 44 | if (error_code != MPI_SUCCESS) \ 45 | { \ 46 | char timpi_mpi_error_string[MPI_MAX_ERROR_STRING+1]; \ 47 | int timpi_mpi_error_string_len; \ 48 | MPI_Error_string(error_code, timpi_mpi_error_string, \ 49 | &timpi_mpi_error_string_len); \ 50 | timpi_assert_equal_to_msg(error_code, MPI_SUCCESS, \ 51 | timpi_mpi_error_string); \ 52 | } \ 53 | } \ 54 | while (0) 55 | 56 | #else 57 | 58 | #define timpi_assert_mpi_success(error_code) ((void) 0) 59 | 60 | #endif 61 | 62 | 63 | 64 | // Only catch MPI return values when asserts are active. 65 | #ifndef NDEBUG 66 | #define timpi_call_mpi(mpi_call) \ 67 | do \ 68 | { \ 69 | int timpi_mpi_error_code = mpi_call; \ 70 | timpi_assert_mpi_success (timpi_mpi_error_code); \ 71 | } \ 72 | while (0) 73 | 74 | #else 75 | 76 | #define timpi_call_mpi(mpi_call) \ 77 | do \ 78 | { \ 79 | mpi_call; \ 80 | } \ 81 | while (0) 82 | #endif 83 | 84 | #else // TIMPI_HAVE_MPI 85 | 86 | #define timpi_mpi_var(var) 87 | 88 | #define timpi_call_mpi(mpi_call) \ 89 | do {} \ 90 | while (0) 91 | 92 | #endif // TIMPI_HAVE_MPI 93 | 94 | 95 | #endif // TIMPI_CALL_MPI_H 96 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/timpi_init.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | 20 | #ifndef TIMPI_INIT_H 21 | #define TIMPI_INIT_H 22 | 23 | 24 | // Local includes 25 | #include "timpi/timpi_config.h" 26 | 27 | #include "timpi/semipermanent.h" 28 | 29 | // C/C++ includes 30 | 31 | #ifdef TIMPI_HAVE_MPI 32 | # include "timpi/ignore_warnings.h" 33 | # include 34 | # include "timpi/restore_warnings.h" 35 | #endif // #ifdef TIMPI_HAVE_MPI 36 | 37 | #include 38 | 39 | namespace TIMPI 40 | { 41 | 42 | // Forward declarations 43 | class Communicator; 44 | 45 | /** 46 | * The \p TIMPIInit class, when constructed, initializes 47 | * any dependent libraries (e.g. MPI). 48 | * 49 | * For many users, a single TIMPIInit object should be created at 50 | * the start of your main() function. 51 | * 52 | * Since "it is best not to perform much more than a return rc after 53 | * calling MPI_Finalize", applications which want to do anything after 54 | * TIMPIInit destruction should manage MPI initialization and 55 | * finalization manually. 56 | */ 57 | class TIMPIInit 58 | { 59 | public: 60 | #ifdef TIMPI_HAVE_MPI 61 | /** 62 | * Initialize the library for use, with the command line options 63 | * provided. This will e.g. call MPI_Init_thread if MPI is 64 | * available and enabled and has not already been initialized. 65 | * 66 | * mpi_thread_requested should be set to 0 when MPI_THREAD_SINGLE is 67 | * desired, 1 when MPI_THREAD_FUNNELED initialization is desired, 2 68 | * when MPI_THREAD_SERIALIZED is desaired, and 3 when 69 | * MPI_THREAD_MULTIPLE is desired 70 | * 71 | * handle_mpi_errors should be set to true to use the 72 | * "timpi_not_implemented()" behavior (e.g. throwing an 73 | * exception) as an MPI error handler, which can aid in debugging. 74 | * 75 | * When building with MPI, this method may take an optional 76 | * parameter to use a user-specified MPI communicator. 77 | */ 78 | TIMPIInit(int argc, const char * const * argv, 79 | int mpi_thread_requested=0, 80 | bool handle_mpi_errors=false, 81 | MPI_Comm COMM_WORLD_IN=MPI_COMM_WORLD); 82 | #else 83 | TIMPIInit(int argc, const char * const * argv, 84 | int mpi_thread_requested=0, 85 | bool handle_mpi_errors=false); 86 | #endif 87 | 88 | /** 89 | * Destructor. 90 | * Finalizes MPI if that was initialized by TIMPIInit. 91 | */ 92 | virtual ~TIMPIInit(); 93 | 94 | /** 95 | * Returns the Communicator created by this object, which will be a 96 | * compatibility shim if MPI is not enabled, or a wrapper for the 97 | * user-input MPI_Comm if we were constructed with one, or a wrapper 98 | * for MPI_COMM_WORLD by default. 99 | */ 100 | const Communicator & comm() const { return *_comm; } 101 | 102 | Communicator & comm() { return *_comm; } 103 | 104 | private: 105 | std::unique_ptr _comm; 106 | 107 | // unique_ptr so we can free it *before* we MPI_Finalize 108 | std::unique_ptr _ref; 109 | 110 | #ifdef TIMPI_HAVE_MPI 111 | bool i_initialized_mpi; 112 | 113 | MPI_Errhandler my_errhandler; 114 | bool err_handler_set; 115 | #endif 116 | }; 117 | 118 | 119 | } // namespace TIMPI 120 | 121 | #endif // TIMPI_INIT_H 122 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/timpi_macros.h: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | 20 | #ifndef TIMPI_MACROS_H 21 | #define TIMPI_MACROS_H 22 | 23 | 24 | // Local includes 25 | #include "timpi/timpi_config.h" 26 | 27 | #ifdef TIMPI_HAVE_CXX20 28 | # define timpi_pure [[nodiscard("Pure-function return values should not be discarded")]] 29 | #elif defined(TIMPI_HAVE_CXX17) 30 | # define timpi_pure [[nodiscard]] 31 | #else 32 | # define timpi_pure 33 | #endif 34 | 35 | #endif // TIMPI_MACROS_H 36 | -------------------------------------------------------------------------------- /src/utilities/include/timpi/timpi_version.h.in: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | #ifndef TIMPI_VERSION_H 19 | #define TIMPI_VERSION_H 20 | 21 | #define TIMPI_MAJOR_VERSION @GENERIC_MAJOR_VERSION@ 22 | #define TIMPI_MINOR_VERSION @GENERIC_MINOR_VERSION@ 23 | #define TIMPI_MICRO_VERSION @GENERIC_MICRO_VERSION@ 24 | 25 | #define TIMPI_LIB_VERSION "@VERSION@" 26 | #define TIMPI_LIB_RELEASE "@BUILD_DEVSTATUS@" 27 | 28 | #define TIMPI_CXX "@CXX@" 29 | #define TIMPI_CXXFLAGS "@CXXFLAGS@" 30 | 31 | #include "timpi/timpi_config.h" 32 | 33 | #include 34 | #include 35 | 36 | namespace TIMPI 37 | { 38 | void timpi_version_stdout(); 39 | std::string timpi_version_string(); 40 | int get_timpi_version(); 41 | } // end namespace TIMPI 42 | 43 | #endif // TIMPI_VERISON_H 44 | -------------------------------------------------------------------------------- /src/utilities/src/semipermanent.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Local includes 20 | #include "timpi/semipermanent.h" 21 | 22 | #include "timpi/timpi_assert.h" 23 | 24 | namespace TIMPI 25 | { 26 | 27 | int SemiPermanent::_ref_count = 0; 28 | 29 | std::vector> SemiPermanent::_stuff_to_clean; 30 | 31 | 32 | SemiPermanent::Ref::~Ref() 33 | { 34 | _ref_count--; 35 | 36 | // Last one to leave turns out the lights 37 | if (_ref_count <= 0) 38 | _stuff_to_clean.clear(); 39 | } 40 | 41 | 42 | void SemiPermanent::add(std::unique_ptr obj) 43 | { 44 | timpi_assert_greater(_ref_count, 0); 45 | 46 | _stuff_to_clean.push_back(std::move(obj)); 47 | } 48 | 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/utilities/src/timpi_assert.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Local includes 20 | #include "timpi/timpi_assert.h" 21 | 22 | // TIMPI includes 23 | #include "timpi/timpi_config.h" 24 | #include "timpi/communicator.h" 25 | 26 | namespace TIMPI 27 | { 28 | 29 | void report_here(const char * file, int line, const char * date, const char * time) 30 | { 31 | std::ostringstream here_msg; // Build in one buffer to reduce interleaving 32 | #ifdef TIMPI_HAVE_MPI 33 | TIMPI::Communicator commworld(MPI_COMM_WORLD); 34 | const std::size_t proc_id = commworld.rank(); 35 | here_msg << "[" << proc_id << "] "; 36 | #endif 37 | here_msg << file << ", line " << line << ", compiled " 38 | << date << " at " << time << std::endl; 39 | std::cerr << here_msg.str(); 40 | } 41 | 42 | 43 | void report_error(const char * file, int line, const char * date, const char * time) 44 | { 45 | // It is possible to have an error *inside* report_error; e.g. when 46 | // we start using a TIMPI::print_trace. Don't infinitely recurse. 47 | static bool reporting_error = false; 48 | if (reporting_error) 49 | { 50 | // I heard you like error reporting, so we put an error report 51 | // in report_error() so you can report errors from the report. 52 | std::cerr << "TIMPI encountered an error while attempting to report_error." << std::endl; 53 | return; 54 | } 55 | reporting_error = true; 56 | 57 | report_here(file, line, date, time); 58 | 59 | reporting_error = false; 60 | } 61 | 62 | } // namespace TIMPI 63 | -------------------------------------------------------------------------------- /src/utilities/src/timpi_init.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | // Local includes 20 | #include "timpi/timpi_init.h" 21 | 22 | #include "timpi/semipermanent.h" 23 | 24 | // TIMPI includes 25 | #include "timpi/communicator.h" 26 | #include "timpi/timpi_assert.h" 27 | 28 | 29 | #ifdef TIMPI_HAVE_MPI 30 | void TIMPI_MPI_Handler (MPI_Comm *, int *, ...) 31 | { 32 | timpi_not_implemented(); 33 | } 34 | #endif 35 | 36 | 37 | namespace TIMPI 38 | { 39 | 40 | #ifdef TIMPI_HAVE_MPI 41 | TIMPIInit::TIMPIInit (int argc, const char * const * argv, 42 | int mpi_thread_requested, 43 | bool handle_mpi_errors, 44 | MPI_Comm COMM_WORLD_IN) : 45 | i_initialized_mpi(false), 46 | err_handler_set(false) 47 | { 48 | // Check whether the calling program has already initialized 49 | // MPI, and avoid duplicate Init/Finalize 50 | int flag; 51 | timpi_call_mpi(MPI_Initialized (&flag)); 52 | 53 | if (!flag) 54 | { 55 | int mpi_thread_provided; 56 | 57 | timpi_call_mpi 58 | (MPI_Init_thread (&argc, const_cast(&argv), 59 | mpi_thread_requested, &mpi_thread_provided)); 60 | 61 | if (mpi_thread_provided < mpi_thread_requested) 62 | { 63 | // Ideally, if an MPI stack tells us it's unsafe for us 64 | // to use threads, we should scream and die or at least 65 | // disable threads. 66 | // 67 | // In practice, we've encountered one MPI stack (an mvapich2 68 | // configuration) that returned MPI_THREAD_SINGLE as a 69 | // proper warning, two stacks that handle 70 | // MPI_THREAD_FUNNELED properly, and two current stacks plus 71 | // a couple old stacks that return MPI_THREAD_SINGLE but 72 | // support threaded runs anyway, so we just emit a warning. 73 | // 74 | std::string thread_type; 75 | switch (mpi_thread_requested) 76 | { 77 | case 0: 78 | thread_type = "MPI_THREAD_SINGLE"; 79 | break; 80 | case 1: 81 | thread_type = "MPI_THREAD_FUNNELED"; 82 | break; 83 | case 2: 84 | thread_type = "MPI_THREAD_SERIALIZED"; 85 | break; 86 | case 3: 87 | thread_type = "MPI_THREAD_MULTIPLE"; 88 | break; 89 | default: 90 | timpi_error_msg("Unsupported mpi thread requested '" << mpi_thread_requested << "'"); 91 | } 92 | 93 | timpi_warning("Warning: MPI failed to guarantee " << thread_type << "\n" 94 | << "for a threaded run.\n" 95 | << std::endl); 96 | } 97 | this->i_initialized_mpi = true; 98 | } 99 | 100 | // Duplicate the input communicator for internal use 101 | // And get a Communicator copy too, to use 102 | // as a default for that API 103 | this->_comm = std::make_unique(COMM_WORLD_IN); 104 | 105 | // Let SemiPermanent know we need its objects for a while 106 | this->_ref = std::make_unique(); 107 | 108 | // Set up an MPI error handler if requested. This helps us get 109 | // into a debugger with a proper stack when an MPI error occurs. 110 | if (handle_mpi_errors) 111 | { 112 | timpi_call_mpi 113 | (MPI_Comm_create_errhandler(TIMPI_MPI_Handler, &my_errhandler)); 114 | timpi_call_mpi 115 | (MPI_Comm_set_errhandler(COMM_WORLD_IN, my_errhandler)); 116 | timpi_call_mpi 117 | (MPI_Comm_set_errhandler(MPI_COMM_WORLD, my_errhandler)); 118 | err_handler_set = true; 119 | } 120 | } 121 | #else 122 | TIMPIInit::TIMPIInit (int /* argc */, const char * const * /* argv */, 123 | int /* mpi_thread_requested */, 124 | bool /* handle_mpi_errors */) 125 | { 126 | this->_comm = std::make_unique(); // So comm() doesn't dereference null 127 | this->_ref = std::make_unique(); 128 | } 129 | #endif 130 | 131 | 132 | 133 | TIMPIInit::~TIMPIInit() 134 | { 135 | // Every processor had better be ready to exit at the same time. 136 | // This would be a timpi_parallel_only() function, except that 137 | // timpi_parallel_only() uses timpi_assert() which throws an 138 | // exception which causes compilers to scream about exceptions 139 | // inside destructors. 140 | 141 | // Even if we're not doing parallel_only debugging, we don't want 142 | // one processor to try to exit until all others are done working. 143 | this->comm().barrier(); 144 | 145 | // Trigger any SemiPermanent cleanup before potentially finalizing MPI 146 | _ref.reset(); 147 | 148 | #ifdef TIMPI_HAVE_MPI 149 | if (err_handler_set) 150 | { 151 | unsigned int error_code = 152 | MPI_Errhandler_free(&my_errhandler); 153 | if (error_code != MPI_SUCCESS) 154 | { 155 | std::cerr << 156 | "Failure when freeing MPI_Errhandler! Continuing..." << 157 | std::endl; 158 | } 159 | } 160 | 161 | this->_comm.reset(); 162 | 163 | if (this->i_initialized_mpi) 164 | { 165 | // We can't just timpi_assert here because destructor, 166 | // but we ought to report any errors 167 | int error_code = MPI_Finalize(); 168 | if (error_code != MPI_SUCCESS) 169 | { 170 | char error_string[MPI_MAX_ERROR_STRING+1]; 171 | int error_string_len; 172 | MPI_Error_string(error_code, error_string, 173 | &error_string_len); 174 | std::cerr << "Failure from MPI_Finalize():\n" 175 | << error_string << std::endl; 176 | } 177 | } 178 | #else 179 | this->_comm.reset(); 180 | #endif 181 | } 182 | 183 | 184 | } // namespace TIMPI 185 | -------------------------------------------------------------------------------- /src/utilities/src/timpi_version.C: -------------------------------------------------------------------------------- 1 | // The TIMPI Message-Passing Parallelism Library. 2 | // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 | 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | #include "timpi/timpi_version.h" 19 | 20 | #include 21 | #include 22 | 23 | namespace TIMPI 24 | { 25 | 26 | void timpi_version_stdout() 27 | { 28 | std::cout << timpi_version_string() << std::flush; 29 | } 30 | 31 | std::string timpi_version_string() 32 | { 33 | std::ostringstream oss; 34 | 35 | oss << "--------------------------------------------------------" << std::endl; 36 | oss << "TIMPI Package: Version = " << TIMPI_LIB_VERSION; 37 | oss << " (" << get_timpi_version() << ")" << std::endl << std::endl; 38 | 39 | oss << TIMPI_LIB_RELEASE << std::endl << std::endl; 40 | 41 | oss << "Build Date = " << TIMPI_BUILD_DATE << std::endl; 42 | oss << "Build Host = " << TIMPI_BUILD_HOST << std::endl; 43 | oss << "Build User = " << TIMPI_BUILD_USER << std::endl; 44 | oss << "Build Arch = " << TIMPI_BUILD_ARCH << std::endl; 45 | oss << "Build Rev = " << TIMPI_BUILD_VERSION << std::endl << std::endl; 46 | 47 | oss << "C++ Config = " << TIMPI_CXX << " " << TIMPI_CXXFLAGS << std::endl; 48 | oss << "--------------------------------------------------------" << std::endl; 49 | 50 | return oss.str(); 51 | } 52 | 53 | int get_timpi_version() 54 | { 55 | /* Note: return format follows the versioning convention xx.yy.zz where 56 | 57 | xx = major version number 58 | yy = minor version number 59 | zz = micro version number 60 | 61 | For example: 62 | v. 0.23 -> 002300 = 2300 63 | v 0.23.1 -> 002301 = 2301 64 | v. 10.23.2 -> 102302 */ 65 | 66 | int major_version = 0; 67 | int minor_version = 0; 68 | int micro_version = 0; 69 | 70 | #ifdef TIMPI_MAJOR_VERSION 71 | major_version = TIMPI_MAJOR_VERSION; 72 | #endif 73 | 74 | #ifdef TIMPI_MINOR_VERSION 75 | minor_version = TIMPI_MINOR_VERSION; 76 | #endif 77 | 78 | #ifdef TIMPI_MICRO_VERSION 79 | micro_version = TIMPI_MICRO_VERSION; 80 | #endif 81 | 82 | return major_version*10000 + minor_version*100 + micro_version; 83 | } 84 | 85 | } // end namespace TIMPI 86 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | AM_CPPFLAGS = $(timpi_optional_INCLUDES) 3 | AM_CPPFLAGS += -I$(top_srcdir)/src/algorithms/include 4 | AM_CPPFLAGS += -I$(top_srcdir)/src/parallel/include 5 | AM_CPPFLAGS += -I$(top_srcdir)/src/utilities/include 6 | AM_CPPFLAGS += -I$(top_builddir)/src/utilities/include #timpi_version.h, timpi_config.h 7 | 8 | CXXFLAGS_DBG += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 9 | CXXFLAGS_DEVEL += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 10 | CXXFLAGS_OPROF += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 11 | CXXFLAGS_OPT += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 12 | CXXFLAGS_PROF += $(ACSM_ANY_WERROR_FLAG) $(ACSM_ANY_PARANOID_FLAGS) 13 | 14 | LIBS = $(timpi_optional_LIBS) 15 | 16 | #Script to run underlying tests 17 | TESTS = run_unit_tests.sh 18 | check_PROGRAMS = 19 | 20 | if BUILD_DBG_MODE 21 | message_tag_unit_dbg_SOURCES = message_tag_unit.C 22 | message_tag_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 23 | message_tag_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 24 | message_tag_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 25 | 26 | packed_range_unit_dbg_SOURCES = packed_range_unit.C 27 | packed_range_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 28 | packed_range_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 29 | packed_range_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 30 | 31 | parallel_sync_unit_dbg_SOURCES = parallel_sync_unit.C 32 | parallel_sync_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 33 | parallel_sync_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 34 | parallel_sync_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 35 | 36 | parallel_unit_dbg_SOURCES = parallel_unit.C 37 | parallel_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 38 | parallel_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 39 | parallel_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 40 | 41 | set_unit_dbg_SOURCES = set_unit.C 42 | set_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 43 | set_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 44 | set_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 45 | 46 | dispatch_to_packed_unit_dbg_SOURCES = dispatch_to_packed_unit.C 47 | dispatch_to_packed_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 48 | dispatch_to_packed_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 49 | dispatch_to_packed_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 50 | 51 | utility_unit_dbg_SOURCES = utility_unit.C 52 | utility_unit_dbg_LDFLAGS = $(top_builddir)/src/libtimpi_dbg.la 53 | utility_unit_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) 54 | utility_unit_dbg_CXXFLAGS = $(CXXFLAGS_DBG) 55 | 56 | check_PROGRAMS += message_tag_unit-dbg 57 | check_PROGRAMS += packed_range_unit-dbg 58 | check_PROGRAMS += parallel_sync_unit-dbg 59 | check_PROGRAMS += parallel_unit-dbg 60 | check_PROGRAMS += set_unit-dbg 61 | check_PROGRAMS += dispatch_to_packed_unit-dbg 62 | check_PROGRAMS += utility_unit-dbg 63 | endif 64 | 65 | if BUILD_DEVEL_MODE 66 | message_tag_unit_devel_SOURCES = message_tag_unit.C 67 | message_tag_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 68 | message_tag_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 69 | message_tag_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 70 | 71 | packed_range_unit_devel_SOURCES = packed_range_unit.C 72 | packed_range_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 73 | packed_range_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 74 | packed_range_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 75 | 76 | parallel_sync_unit_devel_SOURCES = parallel_sync_unit.C 77 | parallel_sync_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 78 | parallel_sync_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 79 | parallel_sync_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 80 | 81 | parallel_unit_devel_SOURCES = parallel_unit.C 82 | parallel_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 83 | parallel_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 84 | parallel_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 85 | 86 | set_unit_devel_SOURCES = set_unit.C 87 | set_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 88 | set_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 89 | set_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 90 | 91 | dispatch_to_packed_unit_devel_SOURCES = dispatch_to_packed_unit.C 92 | dispatch_to_packed_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 93 | dispatch_to_packed_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 94 | dispatch_to_packed_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 95 | 96 | utility_unit_devel_SOURCES = utility_unit.C 97 | utility_unit_devel_LDFLAGS = $(top_builddir)/src/libtimpi_devel.la 98 | utility_unit_devel_CPPFLAGS = $(CPPFLAGS_DEVEL) $(AM_CPPFLAGS) 99 | utility_unit_devel_CXXFLAGS = $(CXXFLAGS_DEVEL) 100 | 101 | check_PROGRAMS += message_tag_unit-devel 102 | check_PROGRAMS += packed_range_unit-devel 103 | check_PROGRAMS += parallel_sync_unit-devel 104 | check_PROGRAMS += parallel_unit-devel 105 | check_PROGRAMS += set_unit-devel 106 | check_PROGRAMS += dispatch_to_packed_unit-devel 107 | check_PROGRAMS += utility_unit-devel 108 | endif 109 | 110 | if BUILD_OPT_MODE 111 | message_tag_unit_opt_SOURCES = message_tag_unit.C 112 | message_tag_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 113 | message_tag_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 114 | message_tag_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 115 | 116 | packed_range_unit_opt_SOURCES = packed_range_unit.C 117 | packed_range_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 118 | packed_range_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 119 | packed_range_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 120 | 121 | parallel_sync_unit_opt_SOURCES = parallel_sync_unit.C 122 | parallel_sync_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 123 | parallel_sync_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 124 | parallel_sync_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 125 | 126 | parallel_unit_opt_SOURCES = parallel_unit.C 127 | parallel_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 128 | parallel_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 129 | parallel_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 130 | 131 | set_unit_opt_SOURCES = set_unit.C 132 | set_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 133 | set_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 134 | set_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 135 | 136 | dispatch_to_packed_unit_opt_SOURCES = dispatch_to_packed_unit.C 137 | dispatch_to_packed_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 138 | dispatch_to_packed_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 139 | dispatch_to_packed_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 140 | 141 | utility_unit_opt_SOURCES = utility_unit.C 142 | utility_unit_opt_LDFLAGS = $(top_builddir)/src/libtimpi_opt.la 143 | utility_unit_opt_CPPFLAGS = $(CPPFLAGS_OPT) $(AM_CPPFLAGS) 144 | utility_unit_opt_CXXFLAGS = $(CXXFLAGS_OPT) 145 | 146 | check_PROGRAMS += message_tag_unit-opt 147 | check_PROGRAMS += packed_range_unit-opt 148 | check_PROGRAMS += parallel_sync_unit-opt 149 | check_PROGRAMS += parallel_unit-opt 150 | check_PROGRAMS += set_unit-opt 151 | check_PROGRAMS += dispatch_to_packed_unit-opt 152 | check_PROGRAMS += utility_unit-opt 153 | endif 154 | 155 | if BUILD_OPROF_MODE 156 | message_tag_unit_oprof_SOURCES = message_tag_unit.C 157 | message_tag_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 158 | message_tag_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 159 | message_tag_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 160 | 161 | packed_range_unit_oprof_SOURCES = packed_range_unit.C 162 | packed_range_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 163 | packed_range_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 164 | packed_range_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 165 | 166 | parallel_sync_unit_oprof_SOURCES = parallel_sync_unit.C 167 | parallel_sync_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 168 | parallel_sync_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 169 | parallel_sync_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 170 | 171 | parallel_unit_oprof_SOURCES = parallel_unit.C 172 | parallel_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 173 | parallel_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 174 | parallel_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 175 | 176 | set_unit_oprof_SOURCES = set_unit.C 177 | set_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 178 | set_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 179 | set_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 180 | 181 | dispatch_to_packed_unit_oprof_SOURCES = dispatch_to_packed_unit.C 182 | dispatch_to_packed_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 183 | dispatch_to_packed_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 184 | dispatch_to_packed_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 185 | 186 | utility_unit_oprof_SOURCES = utility_unit.C 187 | utility_unit_oprof_LDFLAGS = $(top_builddir)/src/libtimpi_oprof.la 188 | utility_unit_oprof_CPPFLAGS = $(CPPFLAGS_OPROF) $(AM_CPPFLAGS) 189 | utility_unit_oprof_CXXFLAGS = $(CXXFLAGS_OPROF) 190 | 191 | check_PROGRAMS += message_tag_unit-oprof 192 | check_PROGRAMS += packed_range_unit-oprof 193 | check_PROGRAMS += parallel_sync_unit-oprof 194 | check_PROGRAMS += parallel_unit-oprof 195 | check_PROGRAMS += set_unit-oprof 196 | check_PROGRAMS += dispatch_to_packed_unit-oprof 197 | check_PROGRAMS += utility_unit-oprof 198 | endif 199 | 200 | if BUILD_PROF_MODE 201 | message_tag_unit_prof_SOURCES = message_tag_unit.C 202 | message_tag_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 203 | message_tag_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 204 | message_tag_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 205 | 206 | packed_range_unit_prof_SOURCES = packed_range_unit.C 207 | packed_range_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 208 | packed_range_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 209 | packed_range_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 210 | 211 | parallel_sync_unit_prof_SOURCES = parallel_sync_unit.C 212 | parallel_sync_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 213 | parallel_sync_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 214 | parallel_sync_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 215 | 216 | parallel_unit_prof_SOURCES = parallel_unit.C 217 | parallel_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 218 | parallel_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 219 | parallel_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 220 | 221 | set_unit_prof_SOURCES = set_unit.C 222 | set_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 223 | set_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 224 | set_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 225 | 226 | dispatch_to_packed_unit_prof_SOURCES = dispatch_to_packed_unit.C 227 | dispatch_to_packed_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 228 | dispatch_to_packed_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 229 | dispatch_to_packed_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 230 | 231 | utility_unit_prof_SOURCES = utility_unit.C 232 | utility_unit_prof_LDFLAGS = $(top_builddir)/src/libtimpi_prof.la 233 | utility_unit_prof_CPPFLAGS = $(CPPFLAGS_PROF) $(AM_CPPFLAGS) 234 | utility_unit_prof_CXXFLAGS = $(CXXFLAGS_PROF) 235 | 236 | check_PROGRAMS += message_tag_unit-prof 237 | check_PROGRAMS += packed_range_unit-prof 238 | check_PROGRAMS += parallel_sync_unit-prof 239 | check_PROGRAMS += parallel_unit-prof 240 | check_PROGRAMS += set_unit-prof 241 | check_PROGRAMS += dispatch_to_packed_unit-prof 242 | check_PROGRAMS += utility_unit-prof 243 | endif 244 | 245 | ###################################################################### 246 | # 247 | # Don't leave code coverage outputs lying around 248 | if CODE_COVERAGE_ENABLED 249 | CLEANFILES = *.gcda *.gcno 250 | endif 251 | 252 | # Required for AX_AM_MACROS 253 | ###@INC_AMINCLUDE@ 254 | -------------------------------------------------------------------------------- /test/message_tag_unit.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TIMPI_UNIT_ASSERT(expr) \ 6 | if (!(expr)) \ 7 | timpi_error(); 8 | 9 | using namespace TIMPI; 10 | 11 | Communicator *TestCommWorld; 12 | 13 | void testGetUniqueTagAuto() 14 | { 15 | // We need to duplicate the communicator first, because the 16 | // original might already have tags used by other unit tests 17 | 18 | TIMPI::Communicator newcomm; 19 | 20 | TestCommWorld->duplicate(newcomm); 21 | 22 | const int n_vals = 5; 23 | const int n_vals_in_scope = 3; 24 | std::vector vals(n_vals); 25 | 26 | { 27 | std::vector tags(n_vals_in_scope); 28 | for (int i=0; i != n_vals_in_scope; ++i) 29 | { 30 | tags[i] = newcomm.get_unique_tag(); 31 | vals[i] = tags[i].value(); 32 | for (int j=0; j != i; ++j) 33 | { 34 | TIMPI_UNIT_ASSERT(vals[i] != vals[j]); 35 | } 36 | } 37 | } 38 | 39 | // Even after we go out of scope those values should be used up 40 | for (int i=n_vals_in_scope; i != n_vals; ++i) 41 | { 42 | TIMPI::MessageTag another_tag = newcomm.get_unique_tag(); 43 | vals[i] = another_tag.value(); 44 | for (int j=0; j != i; ++j) 45 | { 46 | TIMPI_UNIT_ASSERT(vals[i] != vals[j]); 47 | } 48 | } 49 | } 50 | 51 | 52 | 53 | void testGetUniqueTagManual() 54 | { 55 | // Here we'll use the standard communicator, because even if it 56 | // used these tags in other contexts it should have freed them for 57 | // reuse later. 58 | 59 | const int requests[] = {2, 4, 6, 8, 8, 6, 8, 123, 3141, 3142}; 60 | 61 | for (const int i : requests) 62 | { 63 | TIMPI::MessageTag manual_tag = 64 | TestCommWorld->get_unique_tag(i); 65 | TIMPI_UNIT_ASSERT(i == manual_tag.value()); 66 | 67 | TIMPI::MessageTag tag_copy = manual_tag; 68 | TIMPI_UNIT_ASSERT(i == tag_copy.value()); 69 | 70 | TIMPI::MessageTag tag_move = std::move(tag_copy); 71 | TIMPI_UNIT_ASSERT(i == tag_move.value()); 72 | 73 | TIMPI::MessageTag stupidly_manual_tag(i); 74 | TIMPI_UNIT_ASSERT(i == stupidly_manual_tag.value()); 75 | } 76 | } 77 | 78 | 79 | void testGetUniqueTagOverlap() 80 | { 81 | // Try to request the same tag twice, make sure we don't get it 82 | // the second time. 83 | 84 | const int requests[] = {2, 4, 6, 8, 8, 6, 8, 123, 3141, 3142}; 85 | 86 | for (const int i : requests) 87 | { 88 | TIMPI::MessageTag manual_tag = 89 | TestCommWorld->get_unique_tag(i); 90 | TIMPI_UNIT_ASSERT(i == manual_tag.value()); 91 | 92 | TIMPI::MessageTag dup_manual_tag = 93 | TestCommWorld->get_unique_tag(i); 94 | TIMPI_UNIT_ASSERT(i != dup_manual_tag.value()); 95 | 96 | TIMPI::MessageTag tag_copy = manual_tag; 97 | TIMPI_UNIT_ASSERT(i == tag_copy.value()); 98 | 99 | TIMPI::MessageTag tag_move = std::move(tag_copy); 100 | TIMPI_UNIT_ASSERT(i == tag_move.value()); 101 | } 102 | } 103 | 104 | int main(int argc, const char * const * argv) 105 | { 106 | TIMPI::TIMPIInit init(argc, argv); 107 | TestCommWorld = &init.comm(); 108 | 109 | testGetUniqueTagAuto(); 110 | testGetUniqueTagManual(); 111 | testGetUniqueTagOverlap(); 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /test/run_unit_tests.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # Run executables from most-debugging-enabled to least-, so if 6 | # there's a failure we get the most informative death possible 7 | ORDERED_METHODS="dbg debug devel profiling pro prof oprofile oprof optimized opt" 8 | 9 | for method in ${ORDERED_METHODS}; do 10 | for mymethod in @METHODS@; do 11 | if (test "x${mymethod}" = "x${method}"); then 12 | MY_METHODS="${MY_METHODS} ${mymethod}" 13 | fi 14 | done 15 | done 16 | 17 | for method in ${MY_METHODS}; do 18 | for prog in message_tag packed_range parallel_sync parallel dispatch_to_packed set; do 19 | echo $TIMPI_RUN ./${prog}_unit-$method 20 | $TIMPI_RUN ./${prog}_unit-$method 21 | done 22 | done 23 | -------------------------------------------------------------------------------- /test/set_unit.C: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define TIMPI_UNIT_ASSERT(expr) \ 10 | if (!(expr)) \ 11 | timpi_error(); 12 | 13 | using namespace TIMPI; 14 | 15 | Communicator *TestCommWorld; 16 | 17 | void my_inserter(std::set & s, int i) 18 | { s.insert(i); } 19 | 20 | void my_inserter(std::multiset & s, int i) 21 | { 22 | s.insert(-1); 23 | s.insert(3*i+1); 24 | s.insert(3*i+2); 25 | } 26 | 27 | void my_inserter(std::unordered_multiset & s, int i) 28 | { 29 | s.insert(-1); 30 | s.insert(3*i+1); 31 | s.insert(3*i+2); 32 | } 33 | 34 | void my_inserter(std::set> & s, int i) 35 | { s.insert(std::vector(i,i)); } 36 | 37 | void my_inserter(std::unordered_set & s, int i) 38 | { s.insert(i); } 39 | 40 | void my_inserter(std::map & m, int i) 41 | { m.insert(std::make_pair(i,2*i+3)); } 42 | 43 | void my_inserter(std::multimap & m, int i) 44 | { 45 | m.insert(std::make_pair(-1,-1)); 46 | m.insert(std::make_pair(i,3*i+1)); 47 | m.insert(std::make_pair(i,3*i+2)); 48 | } 49 | 50 | void my_inserter(std::unordered_multimap & m, int i) 51 | { 52 | m.insert(std::make_pair(-1,-1)); 53 | m.insert(std::make_pair(i,3*i+1)); 54 | m.insert(std::make_pair(i,3*i+2)); 55 | } 56 | 57 | void my_inserter(std::map> & m, int i) 58 | { m.insert(std::make_pair(i,std::vector(i,2*i+3))); } 59 | 60 | void my_inserter(std::unordered_map & m, int i) 61 | { m.insert(std::make_pair(i,2*i+3)); } 62 | 63 | void my_inserter(std::unordered_map> & m, int i) 64 | { m.insert(std::make_pair(i,std::vector(i,2*i+3))); } 65 | 66 | 67 | void tester(const std::set & s, int i) 68 | { TIMPI_UNIT_ASSERT( s.count(i) == std::size_t(1) ); } 69 | 70 | void tester(const std::multiset & s, int i) 71 | { 72 | TIMPI_UNIT_ASSERT( s.count(-1) * 3 == s.size() ); 73 | TIMPI_UNIT_ASSERT( s.count(3*i+1) == std::size_t(1) ); 74 | TIMPI_UNIT_ASSERT( s.count(3*i+2) == std::size_t(1) ); 75 | } 76 | 77 | void tester(const std::unordered_multiset & s, int i) 78 | { 79 | TIMPI_UNIT_ASSERT( s.count(-1) * 3 == s.size() ); 80 | TIMPI_UNIT_ASSERT( s.count(3*i+1) == std::size_t(1) ); 81 | TIMPI_UNIT_ASSERT( s.count(3*i+2) == std::size_t(1) ); 82 | } 83 | 84 | void tester(const std::set> & s, int i) 85 | { TIMPI_UNIT_ASSERT( s.count(std::vector(i,i)) == std::size_t(1) ); } 86 | 87 | void tester(const std::unordered_set & s, int i) 88 | { TIMPI_UNIT_ASSERT( s.count(i) == std::size_t(1) ); } 89 | 90 | void tester(const std::map & m, int i) 91 | { 92 | TIMPI_UNIT_ASSERT( m.count(i) == std::size_t(1) ); 93 | TIMPI_UNIT_ASSERT( m.at(i) == 2*i+3 ); 94 | } 95 | 96 | void tester(const std::multimap & m, int i) 97 | { 98 | TIMPI_UNIT_ASSERT( m.count(-1) * 3 == m.size() ); 99 | 100 | std::bitset<2> found; 101 | auto pr = m.equal_range(i); 102 | for (auto it = pr.first; it != pr.second; ++it) 103 | { 104 | auto val = it->second; 105 | TIMPI_UNIT_ASSERT( val > 3*i && val < 3*i+3 ); 106 | TIMPI_UNIT_ASSERT( !found[val-3*i-1] ); 107 | found[val-3*i-1] = true; 108 | } 109 | TIMPI_UNIT_ASSERT( found.count() == 2 ); 110 | } 111 | 112 | void tester(const std::unordered_multimap & m, int i) 113 | { 114 | TIMPI_UNIT_ASSERT( m.count(-1) * 3 == m.size() ); 115 | 116 | std::bitset<2> found; 117 | const auto pr = m.equal_range(i); 118 | for (auto it = pr.first; it != pr.second; ++it) 119 | { 120 | auto val = it->second; 121 | TIMPI_UNIT_ASSERT( val > 3*i && val < 3*i+3 ); 122 | TIMPI_UNIT_ASSERT( !found[val-3*i-1] ); 123 | found[val-3*i-1] = true; 124 | } 125 | TIMPI_UNIT_ASSERT( found.count() == 2 ); 126 | } 127 | 128 | void tester(const std::map> & m, int i) 129 | { 130 | TIMPI_UNIT_ASSERT( m.count(i) == std::size_t(1) ); 131 | TIMPI_UNIT_ASSERT( m.at(i).size() == std::size_t(i) ); 132 | for (auto val : m.at(i)) 133 | TIMPI_UNIT_ASSERT( val == 2*i+3 ); 134 | } 135 | 136 | void tester(const std::unordered_map & m, int i) 137 | { 138 | TIMPI_UNIT_ASSERT( m.count(i) == std::size_t(1) ); 139 | TIMPI_UNIT_ASSERT( m.at(i) == 2*i+3 ); 140 | } 141 | 142 | void tester(const std::unordered_map> & m, int i) 143 | { 144 | TIMPI_UNIT_ASSERT( m.count(i) == std::size_t(1) ); 145 | TIMPI_UNIT_ASSERT( m.at(i).size() == std::size_t(i) ); 146 | for (auto val : m.at(i)) 147 | TIMPI_UNIT_ASSERT( val == 2*i+3 ); 148 | } 149 | 150 | 151 | template 152 | void testBigUnion(int n_multi = 1) 153 | { 154 | Set data; 155 | 156 | const int N = TestCommWorld->size(); 157 | 158 | my_inserter(data, 150*N + TestCommWorld->rank()); 159 | 160 | TestCommWorld->set_union(data); 161 | 162 | // The real assertions here are the internal ones in that 163 | // set_union 164 | TIMPI_UNIT_ASSERT( data.size() == n_multi * std::size_t(N) ); 165 | for (int p=0; p 174 | void testUnion() 175 | { 176 | Set data; 177 | 178 | const int N = TestCommWorld->size(); 179 | 180 | my_inserter(data, TestCommWorld->rank()); 181 | my_inserter(data, 2*N); 182 | my_inserter(data, 3*N + TestCommWorld->rank()); 183 | 184 | TestCommWorld->set_union(data); 185 | 186 | TIMPI_UNIT_ASSERT( data.size() == std::size_t(2*N+1) ); 187 | tester(data, 2*N); 188 | for (int p=0; p> mapset; 199 | 200 | // Values on all procs 201 | mapset[0].insert(20201); 202 | 203 | // Insert extra values on procs 0 and 2 204 | switch (TestCommWorld->rank()) 205 | { 206 | case 0: 207 | case 2: 208 | mapset[0].insert(60201); 209 | break; 210 | default: 211 | break; 212 | } 213 | 214 | TestCommWorld->set_union(mapset); 215 | 216 | // Check results on all procs. In a broken 4-processor run what we 217 | // saw was: 218 | // key = 0, surface_ids = 20201 60201 219 | // key = 0, surface_ids = 20201 220 | // key = 0, surface_ids = 20201 60201 221 | // key = 0, surface_ids = 20201 222 | // whereas what we expect to see is that all procs have the 223 | // same surface_ids, the ones from pid 0. 224 | TIMPI_UNIT_ASSERT( mapset.size() == 1 ); 225 | const std::set goodset {20201, 60201}; 226 | for (const auto & pr : mapset) 227 | { 228 | const auto & key = pr.first; 229 | const auto & boundary_id_set = pr.second; 230 | TIMPI_UNIT_ASSERT( key == 0 ); 231 | TIMPI_UNIT_ASSERT( boundary_id_set == goodset ); 232 | } 233 | } 234 | 235 | 236 | void testMapMap() 237 | { 238 | std::map> mapmap; 239 | 240 | // Values on all procs 241 | mapmap[0].emplace(20201, 0.8); 242 | 243 | // Insert extra values on procs 0 and 2 244 | switch (TestCommWorld->rank()) 245 | { 246 | case 0: 247 | case 2: 248 | mapmap[0].emplace(60201, 1.); 249 | break; 250 | default: 251 | break; 252 | } 253 | 254 | TestCommWorld->set_union(mapmap); 255 | 256 | TIMPI_UNIT_ASSERT( mapmap.size() == 1 ); 257 | const std::map goodmap {{20201, 0.8}, 258 | {60201, 1}}; 259 | for (const auto & pr : mapmap) 260 | { 261 | const auto & key = pr.first; 262 | const auto & boundary_id_map = pr.second; 263 | TIMPI_UNIT_ASSERT( key == 0 ); 264 | TIMPI_UNIT_ASSERT( boundary_id_map == goodmap ); 265 | } 266 | } 267 | 268 | 269 | int main(int argc, const char * const * argv) 270 | { 271 | TIMPI::TIMPIInit init(argc, argv); 272 | TestCommWorld = &init.comm(); 273 | 274 | testBigUnion>(); 275 | testBigUnion>(3); 276 | testBigUnion>(3); 277 | testBigUnion>(); 278 | testBigUnion>(); 279 | testBigUnion>(3); 280 | testBigUnion>(3); 281 | testBigUnion>(); 282 | 283 | testUnion>(); 284 | testUnion>(); 285 | testUnion>(); 286 | testUnion>(); 287 | 288 | // TODO: allgather(vector) 289 | // testUnion>>(); 290 | 291 | // No std::hash> 292 | // testUnion>>(); 293 | 294 | testUnion>>(); 295 | testUnion>>(); 296 | 297 | testMapSet(); 298 | testMapMap(); 299 | 300 | return 0; 301 | } 302 | -------------------------------------------------------------------------------- /test/utility_unit.C: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #define TIMPI_UNIT_ASSERT(expr) \ 6 | if (!(expr)) \ 7 | timpi_error(); 8 | 9 | using namespace TIMPI; 10 | 11 | Communicator *TestCommWorld; 12 | 13 | void testVersionString() 14 | { 15 | std::string build_string = timpi_version_string(); 16 | TIMPI_UNIT_ASSERT(build_string.find("Version = 1.8.5") != std::string::npos); 17 | TIMPI_UNIT_ASSERT(build_string.find("Build Date") != std::string::npos); 18 | TIMPI_UNIT_ASSERT(build_string.find("C++ Config") != std::string::npos); 19 | TIMPI_UNIT_ASSERT(build_string.find("Using find correctly") == std::string::npos); 20 | } 21 | 22 | void testVersionNumber() 23 | { 24 | int version = get_timpi_version(); 25 | TIMPI_UNIT_ASSERT(version == 10805); 26 | } 27 | 28 | 29 | int main(int argc, const char * const * argv) 30 | { 31 | TIMPI::TIMPIInit init(argc, argv); 32 | TestCommWorld = &init.comm(); 33 | 34 | testVersionString(); 35 | testVersionNumber(); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /timpi.pc.in: -------------------------------------------------------------------------------- 1 | # @PACKAGE_NAME@ installation details 2 | prefix=@prefix@ 3 | exec_prefix=@exec_prefix@ 4 | libdir=@libdir@ 5 | includedir=@includedir@ 6 | 7 | Name: @PACKAGE_TARNAME@ 8 | Description: @PACKAGE_DESCRIPTION@ 9 | URL: @PACKAGE_URL@ 10 | Requires: 11 | Version: @VERSION@ 12 | Libs: -L${libdir} -l@PACKAGE_TARNAME@ 13 | Cflags: -I${includedir} 14 | --------------------------------------------------------------------------------