diff --git a/.travis.yml b/.travis.yml index 2682a86a9..8becb2261 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,14 @@ matrix: - IMG=nvcc-9 - CMAKE_EXTRA_FLAGS="-DENABLE_CUDA=On" - DO_TEST=no + - compiler: hcc + env: + - COMPILER=hcc + - IMG=rocm + - CMAKE_EXTRA_FLAGS="-C ../host-configs/rocm.cmake -DCMAKE_CXX_COMPILER=/opt/rocm/bin/hcc -DENABLE_ROCM=On -DENABLE_OPENMP=Off -DENABLE_CUDA=Off -DENABLE_BENCHMARKS=Off -DENABLE_WARNINGS_AS_ERRORS=Off" + - DO_TEST=no -script: +script: - docker run --rm --user='root' -v ${TRAVIS_BUILD_DIR}:/home/axom axom/compilers:$IMG chown -R axom /home/axom - docker run --rm -v ${TRAVIS_BUILD_DIR}:/home/axom -e COMPILER -e DO_BUILD -e DO_TEST -e CMAKE_EXTRA_FLAGS axom/compilers:$IMG ./scripts/travis/build_and_test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 28d542304..e9dba1e60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,12 +13,13 @@ # Please also see the LICENSE file for MIT license. ############################################################################## +cmake_policy(SET CMP0025 NEW) cmake_policy(SET CMP0048 NEW) cmake_policy(SET CMP0057 NEW) project(Umpire LANGUAGES CXX C - VERSION 0.2.4) + VERSION 0.3.0) set(ENABLE_OPENMP On CACHE Bool "") set(ENABLE_CUDA On CACHE Bool "") @@ -26,6 +27,10 @@ set(ENABLE_COPY_HEADERS Off CACHE Bool "") set(ENABLE_TESTS On CACHE Bool "") set(ENABLE_BENCHMARKS On CACHE Bool "") set(ENABLE_GMOCK On CACHE Bool "") +set(ENABLE_DOCS Off CACHE Bool "") +option(ENABLE_FORTRAN_API "Build FORTRAN API" Off) +option(ENABLE_C_API "Build C API" Off) +set(ENABLE_WARNINGS_AS_ERRORS On CACHE Bool "") option(ENABLE_EXAMPLES "Build Umpire examples" On) option(ENABLE_LOGGING "Build Umpire with Logging enabled" On) option(ENABLE_SLIC "Build Umpire with SLIC logging" Off) @@ -33,6 +38,7 @@ option(ENABLE_ASSERTS "Build Umpire with assert() enabled" On) set(ENABLE_GTEST_DEATH_TESTS ${ENABLE_ASSERTS} CACHE Bool "") option(ENABLE_STATISTICS "Track statistics for allocations and operations" Off) option(ENABLE_COVERAGE "Enable code coverage (with GCC)" Off) +option(ENABLE_TOOLS "Enable Umpire Development Tools" On) if (ENABLE_CUDA) cmake_minimum_required(VERSION 3.9) @@ -42,6 +48,11 @@ endif () message(STATUS "Using CMake version ${CMAKE_VERSION}") +if (ENABLE_FORTRAN_API) + set(ENABLE_FORTRAN On) + set(ENABLE_C_API On) +endif() + ################################ # BLT ################################ @@ -93,4 +104,10 @@ if (ENABLE_EXAMPLES) add_subdirectory(examples) endif () -add_subdirectory(docs) +if (ENABLE_TOOLS) +add_subdirectory(tools) +endif () + +if (ENABLE_DOCS) + add_subdirectory(docs) +endif () diff --git a/README.md b/README.md index c2617f150..8bea4537d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Umpire Umpire v0.2.4 +# Umpire Umpire v0.3.0 [![Build Status](https://travis-ci.com/LLNL/Umpire.svg?branch=develop)](https://travis-ci.com/LLNL/Umpire) [![Documentation Status](https://readthedocs.org/projects/umpire/badge/?version=develop)](https://umpire.readthedocs.io/en/develop/?badge=develop) @@ -29,6 +29,28 @@ For more advanced configuration you can use standard CMake variables. Both user and code documentation is available [here](http://umpire.readthedocs.io/). +The Umpire [tutorial](https://umpire.readthedocs.io/en/develop/tutorial.html) provides a step by step introduction to Umpire features. + +If you have build problems, we have comprehensive [build sytem documentation](https://umpire.readthedocs.io/en/develop/advanced_configuration.html) too! + +# Getting Involved + +Umpire is an open-source project, and we welcome contributions from the community. + +## Mailing List + +The Umpire mailing list is hosted on Google Groups, and is a great place to ask questions: +- [Umpire Users Google Group](https://groups.google.com/forum/#!forum/umpire-users) + +## Contributions + +We welcome all kinds of contributions: new features, bug fixes, documentation edits; it's all great! + +To contribute, make a [pull request](https://github.com/LLNL/Umpire/compare), with `develop` as the destination branch. +We use Travis to run CI tests, and your branch must pass these tests before being merged. + +For more information, see the [contributing guide](https://github.com/LLNL/Umpire/blob/develop/CONTRIBUTING.md). + # Authors Thanks to all of Umpire's diff --git a/RELEASE b/RELEASE index e5dec840b..1969a10eb 100644 --- a/RELEASE +++ b/RELEASE @@ -1,4 +1,4 @@ -Umpire Version 0.2 +Umpire Version 0.3 Copyright (c) 2016-17, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory. diff --git a/blt b/blt index d298777de..062ee3ff5 160000 --- a/blt +++ b/blt @@ -1 +1 @@ -Subproject commit d298777de4f95db9201ba18d7443fff48d2b9867 +Subproject commit 062ee3ff58e23713b9cd4d2daa2f9b5fca02d3bc diff --git a/docs/sphinx/advanced_configuration.rst b/docs/sphinx/advanced_configuration.rst index 47ea3f53f..acb5eba6c 100644 --- a/docs/sphinx/advanced_configuration.rst +++ b/docs/sphinx/advanced_configuration.rst @@ -18,19 +18,27 @@ Here is a summary of the configuration options, their default value, and meaning Variable Default Meaning =========================== ======== =============================================================================== ``ENABLE_CUDA`` On Enable CUDA support + ``ENABLE_ROCM`` Off Enable ROCm support ``ENABLE_STATISTICS`` Off Enable collection of memory statistics ``ENABLE_TESTING`` On Build test executables ``ENABLE_BENCHMARKS`` On Build benchmark programs ``ENABLE_LOGGING`` On Enable Logging within Umpire ``ENABLE_SLIC`` Off Enable SLIC logging ``ENABLE_ASSERTS`` On Enable UMPIRE_ASSERT() within Umpire + ``ENABLE_TOOLS`` On Enable tools like replay + ``ENABLE_DOCS`` Off Build documentation (requires Sphinx and/or Doxygen) =========================== ======== =============================================================================== These arguments are explained in more detail below: * ``ENABLE_CUDA`` - This option enables support for GPUs. If Umpire is built without CUDA support, - then only the ``HOST`` allocator is available for use. + This option enables support for NVIDIA GPUs. If Umpire is built without CUDA + or ROCM support, then only the ``HOST`` allocator is available for use. + +* ``ENABLE_ROCM`` + This option enables support for AMD GPUs using the ROCm stack and HCC + programming model. If Umpire is built without CUDA or ROCM support, then only + the ``HOST`` allocator is available for use. * ``ENABLE_STATISTICS`` This option enables collection of memory statistics. If Umpire is built with @@ -50,3 +58,9 @@ These arguments are explained in more detail below: * ``ENABLE_ASSERTS`` Enable assert() within Umpire + +* ``ENABLE_TOOLS`` + Enable development tools for Umpire (replay, etc.) + +* ``ENABLE_DOCS`` + Build user documentation (with Sphinx) and code documentation (with Doxygen) diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 0a98309c2..a0b684889 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -104,9 +104,9 @@ # built documents. # # The short X.Y version. -version = u'0.2' +version = u'0.3' # The full version, including alpha/beta/rc tags. -release = u'0.2.4' +release = u'0.3.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 864cdc35b..6be3459fc 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -24,7 +24,7 @@ blt_add_executable( DEPENDS_ON umpire) -if (ENABLE_FORTRAN) +if (ENABLE_C_API) blt_add_executable( NAME allocator_c SOURCES allocator.c @@ -39,6 +39,12 @@ blt_add_executable( DEPENDS_ON umpire) +blt_add_executable( + NAME size_limiter + SOURCES size_limiter.cpp + DEPENDS_ON + umpire) + if (ENABLE_STATISTICS) blt_add_executable( NAME statistics_example diff --git a/examples/allocator.c b/examples/allocator.c index c04cf0cd3..72d236f37 100644 --- a/examples/allocator.c +++ b/examples/allocator.c @@ -21,8 +21,11 @@ int main(int argc, char* argv[]) { (void)(argc); (void)(argv); - UMPIRE_resourcemanager* rm = UMPIRE_resourcemanager_get(); - UMPIRE_allocator* allocator = UMPIRE_resourcemanager_get_allocator(rm, "HOST"); + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + umpire_allocator allocator; + umpire_resourcemanager_get_allocator_by_name(&rm, "HOST", &allocator); double* alloc_one; double* alloc_two; @@ -31,14 +34,14 @@ int main(int argc, char* argv[]) { int i; printf("Allocating memory on HOST..."); - alloc_one = (double*) UMPIRE_allocator_allocate(allocator, sizeof(double)*ELEMS); - alloc_two = (double*) UMPIRE_allocator_allocate(allocator, sizeof(double)*ELEMS); + alloc_one = (double*) umpire_allocator_allocate(&allocator, sizeof(double)*ELEMS); + alloc_two = (double*) umpire_allocator_allocate(&allocator, sizeof(double)*ELEMS); for (i = 0; i < ELEMS; i++) { alloc_one[i] = 1.0*i; } - UMPIRE_resourcemanager_copy(rm, alloc_one, alloc_two); + umpire_resourcemanager_copy_all(&rm, alloc_one, alloc_two); for (i = 0; i < ELEMS; i++) { if (alloc_one[i] == alloc_two[i]) { @@ -48,8 +51,8 @@ int main(int argc, char* argv[]) { } printf("Deallocating memory on HOST..."); - UMPIRE_allocator_deallocate(allocator, alloc_one); - UMPIRE_allocator_deallocate(allocator, alloc_two); + umpire_allocator_deallocate(&allocator, alloc_one); + umpire_allocator_deallocate(&allocator, alloc_two); printf("done.\n"); return 0; diff --git a/examples/size_limiter.cpp b/examples/size_limiter.cpp new file mode 100644 index 000000000..15fe805ce --- /dev/null +++ b/examples/size_limiter.cpp @@ -0,0 +1,38 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include + +#include "umpire/ResourceManager.hpp" + +#include "umpire/strategy/SizeLimiter.hpp" +#include "umpire/strategy/DynamicPool.hpp" + +#include "umpire/util/Macros.hpp" + +int main(int, char**) +{ + auto& rm = umpire::ResourceManager::getInstance(); + auto size_limited_alloc = rm.makeAllocator( + "size_limited_alloc", rm.getAllocator("HOST"), 1024); + + auto pool = rm.makeAllocator( + "pool", size_limited_alloc, 64, 64); + + // This will throw an exception because the pool is limited to 1024 bytes. + void* data = pool.allocate(2048); + UMPIRE_USE_VAR(data); + + return 0; +} diff --git a/host-configs/rocm.cmake b/host-configs/rocm.cmake new file mode 100644 index 000000000..a82cf3a3e --- /dev/null +++ b/host-configs/rocm.cmake @@ -0,0 +1,48 @@ +#cmake \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DENABLE_ROCM=ON -DBLT_SOURCE_DIR=${BLT_DIR} \ +# -DROCM_ARCH=gfx900 \ +# -C ${BLT_DIR}/cmake/blt-test/host-configs/rocm.cmake \ +# -DCMAKE_INSTALL_PREFIX=../install-rocm-release \ + + +set(ENABLE_ROCM ON CACHE BOOL "") +set(ENABLE_OPENMP OFF CACHE BOOL "") +set(ENABLE_CUDA Off CACHE BOOL "") +set(ENABLE_GMOCK Off CACHE BOOL "") + +set(ROCM_ROOT_DIR "/opt/rocm/" CACHE PATH "ROCm ROOT directory path") + +set(ROCM_INCLUDE_PATH "${ROCM_ROOT_DIR}/hcc/include" CACHE PATH "") +set(ROCM_CXX_LIBRARIES "-L${ROCM_ROOT_DIR}/hcc/lib -lhc_am" CACHE STRING "") + +set(ROCM_ARCH "gfx900" CACHE STRING "") + +########################################################### +# specify the target architecture +# Default with ROCm 1.7 is gfx803 (Fiji) +# Other options: +# gfx700 Hawaii +# gfx803 Polaris (RX580) +# gfx900 Vega +# gfx901 +########################################################### +set(ROCM_ARCH_FLAG "-amdgpu-target=${ROCM_ARCH}" CACHE STRING "") + +########################################################### +# get compile/link flags from hcc-config +########################################################### +execute_process(COMMAND ${ROCM_ROOT_DIR}/hcc/bin/hcc-config --cxxflags OUTPUT_VARIABLE ROCM_CXX_COMPILE_FLAGS) +execute_process(COMMAND ${ROCM_ROOT_DIR}/hcc/bin/hcc-config --ldflags OUTPUT_VARIABLE ROCM_CXX_LINK_FLAGS) + +#set(ROCM_CXX_COMPILE_FLAGS "${ROCM_CXX_COMPILE_FLAGS} -Wno-unused-command-line-argument -DHCC_ENABLE_ACCELERATOR_PRINTF" CACHE STRING "") +set(ROCM_CXX_LINK_FLAGS "${ROCM_CXX_LINK_FLAGS} ${ROCM_ARCH_FLAG} ${ROCM_CXX_LIBRARIES}" CACHE STRING "") + +########################################################### +# set CMake cache variables +########################################################### +set(CMAKE_CXX_COMPILER "${ROCM_ROOT_DIR}/bin/hcc" CACHE FILEPATH "ROCm HCC compiler") +set(BLT_CXX_FLAGS "${ROCM_CXX_COMPILE_FLAGS}" CACHE STRING "HCC compiler flags") +set(BLT_EXE_LINKER_FLAGS ${ROCM_CXX_LINK_FLAGS} CACHE STRING "") + +#set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_COMPILER} ${ROCM_CXX_LINK_FLAGS} -o " CACHE STRING "HCC linker command line") diff --git a/scripts/make_release_tarball.sh b/scripts/make_release_tarball.sh index 19f1b5427..93d59483f 100755 --- a/scripts/make_release_tarball.sh +++ b/scripts/make_release_tarball.sh @@ -15,7 +15,7 @@ ############################################################################## TAR_CMD=gtar -VERSION=0.2.4 +VERSION=0.3.0 git archive --prefix=umpire-${VERSION}/ -o umpire-${VERSION}.tar HEAD 2> /dev/null diff --git a/scripts/travis/build_and_test.sh b/scripts/travis/build_and_test.sh index 1be3b835c..30fe28a88 100755 --- a/scripts/travis/build_and_test.sh +++ b/scripts/travis/build_and_test.sh @@ -34,7 +34,7 @@ if [[ "$DO_BUILD" == "yes" ]] ; then or_die make -j 3 VERBOSE=1 fi if [[ "${DO_TEST}" == "yes" ]] ; then - or_die ctest -V + or_die ctest --output-on-failure -V fi fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f0e2da66..782db3ba0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,4 +12,5 @@ # For details, see https://github.com/LLNL/Umpire # Please also see the LICENSE file for MIT license. ############################################################################## + add_subdirectory(umpire) diff --git a/src/umpire/Allocator.cpp b/src/umpire/Allocator.cpp index 392560c05..9552f80d0 100644 --- a/src/umpire/Allocator.cpp +++ b/src/umpire/Allocator.cpp @@ -16,6 +16,7 @@ #include "umpire/ResourceManager.hpp" #include "umpire/util/Macros.hpp" +#include "umpire/Replay.hpp" #if defined(UMPIRE_ENABLE_STATISTICS) #include "umpire/util/StatisticsDatabase.hpp" @@ -24,7 +25,7 @@ namespace umpire { -Allocator::Allocator(std::shared_ptr allocator): +Allocator::Allocator(std::shared_ptr allocator) noexcept: m_allocator(allocator) { } @@ -33,8 +34,12 @@ void* Allocator::allocate(size_t bytes) { void* ret = nullptr; + UMPIRE_LOG(Debug, "(" << bytes << ")"); + + UMPIRE_REPLAY( "allocate," << bytes << "," << m_allocator); ret = m_allocator->allocate(bytes); + UMPIRE_REPLAY_CONT( ret << "\n"); UMPIRE_RECORD_STATISTIC(getName(), "ptr", reinterpret_cast(ret), "size", bytes, "event", "allocate"); return ret; @@ -43,8 +48,9 @@ Allocator::allocate(size_t bytes) void Allocator::deallocate(void* ptr) { - UMPIRE_LOG(Debug, "(" << ptr << ")"); + UMPIRE_REPLAY( "deallocate," << ptr << "," << m_allocator << "\n"); + UMPIRE_LOG(Debug, "(" << ptr << ")"); UMPIRE_RECORD_STATISTIC(getName(), "ptr", reinterpret_cast(ptr), "size", 0x0, "event", "deallocate"); @@ -56,6 +62,16 @@ Allocator::deallocate(void* ptr) } } +void +Allocator::release() +{ + UMPIRE_REPLAY("release," << m_allocator << "\n"); + + UMPIRE_LOG(Debug, ""); + + m_allocator->release(); +} + size_t Allocator::getSize(void* ptr) { @@ -64,44 +80,44 @@ Allocator::getSize(void* ptr) } size_t -Allocator::getHighWatermark() +Allocator::getHighWatermark() noexcept { return m_allocator->getHighWatermark(); } size_t -Allocator::getCurrentSize() +Allocator::getCurrentSize() noexcept { return m_allocator->getCurrentSize(); } size_t -Allocator::getActualSize() +Allocator::getActualSize() noexcept { return m_allocator->getActualSize(); } std::string -Allocator::getName() +Allocator::getName() const noexcept { return m_allocator->getName(); } int -Allocator::getId() +Allocator::getId() const noexcept { return m_allocator->getId(); } std::shared_ptr -Allocator::getAllocationStrategy() +Allocator::getAllocationStrategy() noexcept { UMPIRE_LOG(Debug, "() returning " << m_allocator); return m_allocator; } Platform -Allocator::getPlatform() +Allocator::getPlatform() noexcept { return m_allocator->getPlatform(); } diff --git a/src/umpire/Allocator.hpp b/src/umpire/Allocator.hpp index 3f074e2cc..f41d57051 100644 --- a/src/umpire/Allocator.hpp +++ b/src/umpire/Allocator.hpp @@ -70,6 +70,11 @@ class Allocator { */ void deallocate(void* ptr); + /*! + * \brief Release any and all unused memory held by this Allocator. + */ + void release(); + /*! * \brief Return number of bytes allocated for allocation * @@ -88,7 +93,7 @@ class Allocator { * * \return Memory high watermark. */ - size_t getHighWatermark(); + size_t getHighWatermark() noexcept; /*! * \brief Return the current size of this Allocator. @@ -98,7 +103,7 @@ class Allocator { * * \return current size of Allocator. */ - size_t getCurrentSize(); + size_t getCurrentSize() noexcept; /*! * \brief Return the actual size of this Allocator. @@ -110,7 +115,7 @@ class Allocator { * * \return actual size of Allocator. */ - size_t getActualSize(); + size_t getActualSize() noexcept; /*! * \brief Get the name of this Allocator. @@ -122,7 +127,7 @@ class Allocator { * * \return name of Allocator. */ - std::string getName(); + std::string getName() const noexcept; /*! * \brief Get the integer ID of this Allocator. @@ -135,7 +140,7 @@ class Allocator { * * \return integer id of Allocator. */ - int getId(); + int getId() const noexcept; /*! * \brief Get the AllocationStrategy object used by this Allocator. @@ -144,14 +149,16 @@ class Allocator { * * \return Pointer to the AllocationStrategy. */ - std::shared_ptr getAllocationStrategy(); + std::shared_ptr getAllocationStrategy() noexcept; /*! * \brief Get the Platform object appropriate for this Allocator. * * \return Platform for this Allocator. */ - Platform getPlatform(); + Platform getPlatform() noexcept; + + Allocator() = default; private: /*! @@ -163,9 +170,8 @@ class Allocator { * \param allocator Pointer to the AllocationStrategy object to use for * Allocations. */ - Allocator(std::shared_ptr allocator); + Allocator(std::shared_ptr allocator) noexcept; - Allocator() = delete; /*! * \brief Pointer to the AllocationStrategy used by this Allocator. diff --git a/src/umpire/CMakeLists.txt b/src/umpire/CMakeLists.txt index 6f52308ce..9ff30d292 100644 --- a/src/umpire/CMakeLists.txt +++ b/src/umpire/CMakeLists.txt @@ -14,6 +14,7 @@ ############################################################################## set (umpire_headers Allocator.hpp + Replay.hpp ResourceManager.hpp ResourceManager.inl TypedAllocator.hpp @@ -22,9 +23,10 @@ set (umpire_headers set (umpire_sources Allocator.cpp + Replay.cpp ResourceManager.cpp) -if (ENABLE_FORTRAN) +if (ENABLE_FORTRAN_API OR ENABLE_C_API) set (umpire_headers ${umpire_headers} interface/umpire.h @@ -33,18 +35,27 @@ if (ENABLE_FORTRAN) interface/c_fortran/wrapResourceManager.h ) - set (umpire_sources - ${umpire_sources} - interface/c_fortran/shroudrt.cpp - interface/c_fortran/wrapAllocator.cpp - interface/c_fortran/wrapResourceManager.cpp - interface/c_fortran/wrapfumpire.f90 - ) + if (ENABLE_C_API) + set (umpire_sources + ${umpire_sources} + interface/c_fortran/shroudrt.cpp + interface/c_fortran/wrapAllocator.cpp + interface/c_fortran/wrapResourceManager.cpp + interface/c_fortran/wrapUmpire.cpp + ) + + if (ENABLE_FORTRAN_API) + set (umpire_sources + ${umpire_sources} + interface/c_fortran/wrapfumpire.f + ) - set_source_files_properties( - interface/c_fortran/wrapfumpire.f90 - PROPERTIES - Fortran_FORMAT FREE) + set_source_files_properties( + interface/c_fortran/wrapfumpire.f + PROPERTIES + Fortran_FORMAT FREE) + endif () + endif () endif () blt_add_library( @@ -59,6 +70,21 @@ set(UMPIRE_ENABLE_LOGGING ${ENABLE_LOGGING}) set(UMPIRE_ENABLE_SLIC ${ENABLE_SLIC}) set(UMPIRE_ENABLE_ASSERTS ${ENABLE_ASSERTS}) set(UMPIRE_ENABLE_STATISTICS ${ENABLE_STATISTICS}) +set(UMPIRE_ENABLE_ROCM ${ENABLE_ROCM}) + +if (ENABLE_CUDA OR ENABLE_ROCM) + set(UMPIRE_ENABLE_DEVICE On) + set(UMPIRE_ENABLE_PINNED On) +else () + set(UMPIRE_ENABLE_DEVICE Off) + set(UMPIRE_ENABLE_PINNED Off) +endif() + +if (ENABLE_CUDA) + set(UMPIRE_ENABLE_UM On) +else () + set(UMPIRE_ENABLE_UM Off) +endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.in diff --git a/src/umpire/Replay.cpp b/src/umpire/Replay.cpp new file mode 100644 index 000000000..dec1a64d2 --- /dev/null +++ b/src/umpire/Replay.cpp @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// + +#include // for std::cout, std::cerr +#include // for getenv() +#include // for strcasecmp() +#include "umpire/Allocator.hpp" +#include "umpire/Replay.hpp" + +namespace umpire { +namespace replay { + +static const char* env_name = "UMPIRE_REPLAY"; +Replay* Replay::s_Replay = nullptr; + +Replay::Replay(bool enable_replay) : replayEnabled(enable_replay) +{ +} + +Replay::~Replay() +{ +} + +void Replay::logMessage( const std::string& message ) +{ + if ( !replayEnabled ) + return; /* short-circuit */ + + std::cout << message; +} + +bool Replay::replayLoggingEnabled() +{ + return replayEnabled; +} + +void Replay::initialize() +{ + if ( s_Replay != nullptr ) + return; + + char* enval = getenv(env_name); + bool enable_replay = ( enval != NULL ); + + s_Replay = new Replay(enable_replay); +} + +void Replay::finalize() +{ + delete s_Replay; + s_Replay = nullptr; +} + +Replay* Replay::getReplayLogger() +{ + if ( s_Replay == nullptr ) + Replay::initialize(); + + return s_Replay; +} + +std::ostream& operator<< (std::ostream& out, umpire::Allocator& alloc) { + out << alloc.getName(); + return out; +} + +} /* namespace replay */ +} /* namespace umpire */ diff --git a/src/umpire/Replay.hpp b/src/umpire/Replay.hpp new file mode 100644 index 000000000..aaaf382fd --- /dev/null +++ b/src/umpire/Replay.hpp @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_Replay_HPP +#define UMPIRE_Replay_HPP + +#include +#include +#include +#include "umpire/Allocator.hpp" + +#define UMPIRE_REPLAY( msg ) \ +{ \ + if (umpire::replay::Replay::getReplayLogger()->replayLoggingEnabled()) { \ + std::ostringstream local_msg; \ + local_msg << "REPLAY," << msg; \ + umpire::replay::Replay::getReplayLogger()->logMessage(local_msg.str());\ + } \ +} + +#define UMPIRE_REPLAY_CONT( msg ) \ +{ \ + if (umpire::replay::Replay::getReplayLogger()->replayLoggingEnabled()) { \ + std::ostringstream local_msg; \ + local_msg << "," << msg; \ + umpire::replay::Replay::getReplayLogger()->logMessage(local_msg.str());\ + } \ +} + +namespace umpire { +namespace replay { +std::ostream& operator<< (std::ostream& out, umpire::Allocator& alloc); +class Replay { +public: + static void initialize(); + static void finalize(); + + void logMessage( const std::string& message ); + static Replay* getReplayLogger(); + bool replayLoggingEnabled(); + + static std::string printReplayAllocator( void ) { + return std::string(""); + } + + template + static std::string printReplayAllocator(T&& firstArg, Args&&... args) { + std::stringstream ss; + ss << "," << firstArg << printReplayAllocator(std::forward(args)...); + return ss.str(); + } +private: + Replay(bool enable_replay); + ~Replay(); + + bool replayEnabled; + static Replay* s_Replay; +}; + +} /* namespace replay */ +} /* namespace umpire */ + +#endif /* UMPIRE_Replay_HPP */ diff --git a/src/umpire/ResourceManager.cpp b/src/umpire/ResourceManager.cpp index 12188abbf..0da615b14 100644 --- a/src/umpire/ResourceManager.cpp +++ b/src/umpire/ResourceManager.cpp @@ -19,14 +19,24 @@ #include "umpire/resource/MemoryResourceRegistry.hpp" #include "umpire/resource/HostResourceFactory.hpp" + #if defined(UMPIRE_ENABLE_CUDA) -#include "umpire/resource/DeviceResourceFactory.hpp" -#include "umpire/resource/UnifiedMemoryResourceFactory.hpp" -#include "umpire/resource/PinnedMemoryResourceFactory.hpp" -#include "umpire/resource/DeviceConstResourceFactory.hpp" +#include "umpire/resource/CudaDeviceResourceFactory.hpp" +#include "umpire/resource/CudaUnifiedMemoryResourceFactory.hpp" +#include "umpire/resource/CudaPinnedMemoryResourceFactory.hpp" +#include "umpire/resource/CudaConstantMemoryResourceFactory.hpp" +#endif + +#if defined(UMPIRE_ENABLE_ROCM) +#include "umpire/resource/RocmDeviceResourceFactory.hpp" +#include "umpire/resource/RocmPinnedMemoryResourceFactory.hpp" #endif + #include "umpire/op/MemoryOperationRegistry.hpp" +#include "umpire/strategy/DynamicPool.hpp" +#include "umpire/strategy/AllocationTracker.hpp" + #include "umpire/util/Macros.hpp" namespace umpire { @@ -63,16 +73,24 @@ ResourceManager::ResourceManager() : #if defined(UMPIRE_ENABLE_CUDA) registry.registerMemoryResource( - std::make_shared()); + std::make_shared()); + + registry.registerMemoryResource( + std::make_shared()); + + registry.registerMemoryResource( + std::make_shared()); registry.registerMemoryResource( - std::make_shared()); + std::make_shared()); +#endif +#if defined(UMPIRE_ENABLE_ROCM) registry.registerMemoryResource( - std::make_shared()); + std::make_shared()); registry.registerMemoryResource( - std::make_shared()); + std::make_shared()); #endif initialize(); @@ -88,11 +106,20 @@ ResourceManager::initialize() m_memory_resources[resource::Host] = registry.makeMemoryResource("HOST", getNextId()); -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) m_memory_resources[resource::Device] = registry.makeMemoryResource("DEVICE", getNextId()); - m_memory_resources[resource::UnifiedMemory] = registry.makeMemoryResource("UM", getNextId()); - m_memory_resources[resource::PinnedMemory] = registry.makeMemoryResource("PINNED", getNextId()); - m_memory_resources[resource::DeviceConst] = registry.makeMemoryResource("DEVICE_CONST", getNextId()); +#endif + +#if defined(UMPIRE_ENABLE_PINNED) + m_memory_resources[resource::Pinned] = registry.makeMemoryResource("PINNED", getNextId()); +#endif + +#if defined(UMPIRE_ENABLE_UM) + m_memory_resources[resource::Unified] = registry.makeMemoryResource("UM", getNextId()); +#endif + +#if defined(UMPIRE_ENABLE_CUDA) + m_memory_resources[resource::Constant] = registry.makeMemoryResource("DEVICE_CONST", getNextId()); #endif /* @@ -104,23 +131,30 @@ ResourceManager::initialize() m_default_allocator = host_allocator; -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) auto device_allocator = m_memory_resources[resource::Device]; m_allocators_by_name["DEVICE"] = device_allocator; m_allocators_by_id[device_allocator->getId()] = device_allocator; +#endif - auto um_allocator = m_memory_resources[resource::UnifiedMemory]; - m_allocators_by_name["UM"] = um_allocator; - m_allocators_by_id[um_allocator->getId()] = um_allocator; - - auto pinned_allocator = m_memory_resources[resource::PinnedMemory]; +#if defined(UMPIRE_ENABLE_PINNED) + auto pinned_allocator = m_memory_resources[resource::Pinned]; m_allocators_by_name["PINNED"] = pinned_allocator; m_allocators_by_id[pinned_allocator->getId()] = pinned_allocator; +#endif - auto device_const_allocator = m_memory_resources[resource::DeviceConst]; +#if defined(UMPIRE_ENABLE_UM) + auto um_allocator = m_memory_resources[resource::Unified]; + m_allocators_by_name["UM"] = um_allocator; + m_allocators_by_id[um_allocator->getId()] = um_allocator; +#endif + +#if defined(UMPIRE_ENABLE_CUDA) + auto device_const_allocator = m_memory_resources[resource::Constant]; m_allocators_by_name["DEVICE_CONST"] = device_const_allocator; m_allocators_by_id[device_const_allocator->getId()] = device_const_allocator; #endif + UMPIRE_LOG(Debug, "() leaving"); } @@ -182,7 +216,7 @@ ResourceManager::getDefaultAllocator() } void -ResourceManager::setDefaultAllocator(Allocator allocator) +ResourceManager::setDefaultAllocator(Allocator allocator) noexcept { UMPIRE_LOG(Debug, "(\"" << allocator.getName() << "\")"); @@ -207,7 +241,7 @@ ResourceManager::getAllocator(void* ptr) } bool -ResourceManager::isAllocator(const std::string& name) +ResourceManager::isAllocator(const std::string& name) noexcept { return (m_allocators_by_name.find(name) != m_allocators_by_name.end()); } @@ -259,8 +293,8 @@ void ResourceManager::copy(void* dst_ptr, void* src_ptr, size_t size) UMPIRE_ERROR("Not enough resource in destination for copy: " << size << " -> " << dst_size); } - auto op = op_registry.find("COPY", - src_alloc_record->m_strategy, + auto op = op_registry.find("COPY", + src_alloc_record->m_strategy, dst_alloc_record->m_strategy); op->transform(src_ptr, &dst_ptr, src_alloc_record, dst_alloc_record, size); @@ -284,8 +318,8 @@ void ResourceManager::memset(void* ptr, int value, size_t length) UMPIRE_ERROR("Cannot memset over the end of allocation: " << length << " -> " << src_size); } - auto op = op_registry.find("MEMSET", - alloc_record->m_strategy, + auto op = op_registry.find("MEMSET", + alloc_record->m_strategy, alloc_record->m_strategy); op->apply(ptr, alloc_record, value, length); @@ -309,8 +343,8 @@ ResourceManager::reallocate(void* src_ptr, size_t size) UMPIRE_ERROR("Cannot reallocate an offset ptr (ptr=" << src_ptr << ", base=" << alloc_record->m_ptr); } - auto op = op_registry.find("REALLOCATE", - alloc_record->m_strategy, + auto op = op_registry.find("REALLOCATE", + alloc_record->m_strategy, alloc_record->m_strategy); @@ -384,6 +418,39 @@ ResourceManager::getSize(void* ptr) return record->m_size; } +void +ResourceManager::coalesce(Allocator allocator) +{ + auto strategy = allocator.getAllocationStrategy(); + + auto tracker = std::dynamic_pointer_cast(strategy); + + if (tracker) { + strategy = tracker->getAllocationStrategy(); + + } + + auto dynamic_pool = std::dynamic_pointer_cast(strategy); + + if (dynamic_pool) { + dynamic_pool->coalesce(); + } else { + UMPIRE_ERROR(allocator.getName() << " is not a DynamicPool, cannot coalesce!"); + } +} + +std::shared_ptr& ResourceManager::findAllocatorForId(int id) +{ + auto allocator_i = m_allocators_by_id.find(id); + + if ( allocator_i == m_allocators_by_id.end() ) { + UMPIRE_ERROR("Cannot find allocator for ID " << id); + } + + UMPIRE_LOG(Debug, "(id=" << id << ") returning " << allocator_i->second ); + return allocator_i->second; +} + std::shared_ptr& ResourceManager::findAllocatorForPointer(void* ptr) { auto allocation_record = m_allocations.find(ptr); @@ -397,7 +464,7 @@ std::shared_ptr& ResourceManager::findAllocatorFor } std::vector -ResourceManager::getAvailableAllocators() +ResourceManager::getAvailableAllocators() noexcept { std::vector names; for(auto it = m_allocators_by_name.begin(); it != m_allocators_by_name.end(); ++it) { @@ -409,7 +476,7 @@ ResourceManager::getAvailableAllocators() } int -ResourceManager::getNextId() +ResourceManager::getNextId() noexcept { return m_id++; } diff --git a/src/umpire/ResourceManager.hpp b/src/umpire/ResourceManager.hpp index 7f8b30ef1..b069532a1 100644 --- a/src/umpire/ResourceManager.hpp +++ b/src/umpire/ResourceManager.hpp @@ -27,16 +27,17 @@ #include "umpire/util/AllocationMap.hpp" #include "umpire/resource/MemoryResourceTypes.hpp" +#include "umpire/resource/MemoryResourceTraits.hpp" namespace umpire { /*! - * \brief + * \brief */ class ResourceManager { - public: + public: /*! - * \brief + * \brief */ static ResourceManager& getInstance(); @@ -48,11 +49,11 @@ class ResourceManager { void initialize(); void finalize(); - + /*! * \brief Get the names of all available Allocator objects. */ - std::vector getAvailableAllocators(); + std::vector getAvailableAllocators() noexcept; /*! * \brief Get the Allocator with the given name. @@ -87,7 +88,7 @@ class ResourceManager { * * \param allocator The Allocator to use as the default. */ - void setDefaultAllocator(Allocator allocator); + void setDefaultAllocator(Allocator allocator) noexcept; /*! * \brief Construct a new Allocator. @@ -106,7 +107,7 @@ class ResourceManager { * * The same Allocator can be registered under multiple names. * - * \param name Name to register Allocator with. + * \param name Name to register Allocator with. * \param allocator Allocator to register. */ void registerAllocator(const std::string& name, Allocator allocator); @@ -121,7 +122,7 @@ class ResourceManager { */ Allocator getAllocator(void* ptr); - bool isAllocator(const std::string& name); + bool isAllocator(const std::string& name) noexcept; /*! * \brief Does the given pointer have an associated Allocator. @@ -129,7 +130,7 @@ class ResourceManager { * \return True if the pointer has an associated Allocator. */ bool hasAllocator(void* ptr); - + void registerAllocation(void* ptr, util::AllocationRecord* record); util::AllocationRecord* deregisterAllocation(void* ptr); @@ -144,7 +145,7 @@ class ResourceManager { * \brief Copy size bytes of data from src_ptr to dst_ptr. * * Both the src_ptr and dst_ptr addresses must be allocated by Umpire. They - * can be offset from any Umpire-managed base address. + * can be offset from any Umpire-managed base address. * * The dst_ptr must be large enough to accommodate size bytes of data. * @@ -217,6 +218,16 @@ class ResourceManager { */ size_t getSize(void* ptr); + /*! + * \brief If allocator is some kind of memory pool, try and coalesce + * memory. + * + * \param allocator Allocator to coalesce memory. + * + * \throws umpire::util::Exception if allocator doesn't support coalescing. + */ + void coalesce(Allocator allocator); + private: ResourceManager(); @@ -225,9 +236,10 @@ class ResourceManager { ResourceManager& operator= (const ResourceManager&) = delete; std::shared_ptr& findAllocatorForPointer(void* ptr); + std::shared_ptr& findAllocatorForId(int id); std::shared_ptr& getAllocationStrategy(const std::string& name); - int getNextId(); + int getNextId() noexcept; static ResourceManager* s_resource_manager_instance; diff --git a/src/umpire/ResourceManager.inl b/src/umpire/ResourceManager.inl index f450481c1..625181806 100644 --- a/src/umpire/ResourceManager.inl +++ b/src/umpire/ResourceManager.inl @@ -18,8 +18,10 @@ #include "umpire/ResourceManager.hpp" #include +#include #include "umpire/util/Macros.hpp" +#include "umpire/Replay.hpp" #include "umpire/strategy/AllocationTracker.hpp" namespace umpire { @@ -38,6 +40,13 @@ Allocator ResourceManager::makeAllocator( UMPIRE_LOG(Debug, "(name=\"" << name << "\")"); + UMPIRE_REPLAY("makeAllocator," + << abi::__cxa_demangle(typeid(Strategy).name(),nullptr,nullptr,nullptr) + << "," << (introspection ? "true" : "false") + << "," << name + << umpire::replay::Replay::printReplayAllocator(std::forward(args)...) + ); + if (isAllocator(name)) { UMPIRE_ERROR("Allocator with name " << name << " is already registered."); } @@ -51,7 +60,6 @@ Allocator ResourceManager::makeAllocator( std::stringstream base_name; base_name << name << "_base"; - auto base_allocator = std::make_shared(base_name.str(), getNextId(), std::forward(args)...); allocator = std::make_shared(name, getNextId(), Allocator(base_allocator)); @@ -61,6 +69,8 @@ Allocator ResourceManager::makeAllocator( } + UMPIRE_REPLAY_CONT("" << allocator << "\n"); + UMPIRE_UNLOCK; } catch (...) { UMPIRE_UNLOCK; diff --git a/src/umpire/alloc/AmAllocAllocator.hpp b/src/umpire/alloc/AmAllocAllocator.hpp new file mode 100644 index 000000000..f662b675f --- /dev/null +++ b/src/umpire/alloc/AmAllocAllocator.hpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_AmAllocAllocator_HPP +#define UMPIRE_AmAllocAllocator_HPP + +#include + +namespace umpire { +namespace alloc { + +/*! + * \brief Uses hcAlloc and hcAlloc to allocate and deallocate memory on + * AMD GPUs that support ROCm. + */ +struct AmAllocAllocator { + /*! + * \brief Allocate bytes of memory using hcAlloc + * + * \param bytes Number of bytes to allocate. + * \return Pointer to start of the allocation. + * + * \throws umpire::util::Exception if memory cannot be allocated. + */ + void* allocate(size_t bytes) + { + /* Default accelerator */ + hc::accelerator acc; + void* ret = hc::am_alloc(bytes, acc, 0); + + UMPIRE_LOG(Debug, "(size=" << bytes << ") returning " << ret); + + if (ret == nullptr) { + UMPIRE_ERROR("hc::am_alloc(bytes = " << bytes << ") failed"); + } else { + return ret; + } + } + + /*! + * \brief Deallocate memory using hcFree. + * + * \param ptr Address to deallocate. + * + * \throws umpire::util::Exception if memory cannot be free'd. + */ + void deallocate(void* ptr) + { + UMPIRE_LOG(Debug, "(ptr=" << ptr << ")"); + auto status = hc::am_free(ptr); + } +}; + +} // end of namespace alloc +} // end of namespace umpire + +#endif // UMPIRE_AmAllocAllocator_HPP diff --git a/src/umpire/alloc/AmPinnedAllocator.hpp b/src/umpire/alloc/AmPinnedAllocator.hpp new file mode 100644 index 000000000..08795f2ff --- /dev/null +++ b/src/umpire/alloc/AmPinnedAllocator.hpp @@ -0,0 +1,70 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_AmPinnedAllocator_HPP +#define UMPIRE_AmPinnedAllocator_HPP + +#include + +namespace umpire { +namespace alloc { + +/*! + * \brief Uses hcAlloc and hcAlloc to allocate and deallocate memory on + * AMD GPUs that support ROCm. + */ +struct AmPinnedAllocator { + /*! + * \brief Allocate bytes of pinned memory using am_alloc + * + * \param bytes Number of bytes to allocate. + * \return Pointer to start of the allocation. + * + * \throws umpire::util::Exception if memory cannot be allocated. + */ + void* allocate(size_t bytes) + { + /* Default accelerator */ + hc::accelerator acc; + void* ret = hc::am_alloc(bytes, acc, amHostPinned); + + UMPIRE_LOG(Debug, "(size=" << bytes << ") returning " << ret); + + if (ret == nullptr) { + UMPIRE_ERROR("hc::am_alloc(bytes = " << bytes + << ", acc=" << 0 + << ", hc::amHostPinned) failed"); + } else { + return ret; + } + } + + /*! + * \brief Deallocate memory using am_free. + * + * \param ptr Address to deallocate. + * + * \throws umpire::util::Exception if memory cannot be free'd. + */ + void deallocate(void* ptr) + { + UMPIRE_LOG(Debug, "(ptr=" << ptr << ")"); + auto status = hc::am_free(ptr); + } +}; + +} // end of namespace alloc +} // end of namespace umpire + +#endif // UMPIRE_AmPinnedAllocator_HPP diff --git a/src/umpire/alloc/CMakeLists.txt b/src/umpire/alloc/CMakeLists.txt index 96ed7760d..fbb2a289d 100644 --- a/src/umpire/alloc/CMakeLists.txt +++ b/src/umpire/alloc/CMakeLists.txt @@ -27,6 +27,12 @@ if (ENABLE_CUDA) CudaPinnedAllocator.hpp) endif () +if (ENABLE_ROCM) + set (umpire_alloc_headers + ${umpire_alloc_headers} + AmAllocAllocator.hpp) +endif () + blt_add_library( NAME umpire_alloc HEADERS ${umpire_alloc_headers} diff --git a/src/umpire/config.hpp.in b/src/umpire/config.hpp.in index f918eff23..987028df0 100644 --- a/src/umpire/config.hpp.in +++ b/src/umpire/config.hpp.in @@ -20,6 +20,11 @@ #cmakedefine UMPIRE_ENABLE_LOGGING #cmakedefine UMPIRE_ENABLE_ASSERTS #cmakedefine UMPIRE_ENABLE_STATISTICS +#cmakedefine UMPIRE_ENABLE_ROCM + +#cmakedefine UMPIRE_ENABLE_DEVICE +#cmakedefine UMPIRE_ENABLE_PINNED +#cmakedefine UMPIRE_ENABLE_UM constexpr int UMPIRE_VERSION_MAJOR = @Umpire_VERSION_MAJOR@; constexpr int UMPIRE_VERSION_MINOR = @Umpire_VERSION_MINOR@; diff --git a/src/umpire/interface/c_fortran/typesUmpire.h b/src/umpire/interface/c_fortran/typesUmpire.h new file mode 100644 index 000000000..b24c87d47 --- /dev/null +++ b/src/umpire/interface/c_fortran/typesUmpire.h @@ -0,0 +1,68 @@ +// typesUmpire.h +// This is generated code, do not edit +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +// For C users and C++ implementation + +#ifndef TYPESUMPIRE_H +#define TYPESUMPIRE_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_UMP_SHROUD_capsule_data { + void *addr; /* address of C++ memory */ + int idtor; /* index of destructor */ +}; +typedef struct s_UMP_SHROUD_capsule_data UMP_SHROUD_capsule_data; + +struct s_umpire_allocator { + void *addr; /* address of C++ memory */ + int idtor; /* index of destructor */ +}; +typedef struct s_umpire_allocator umpire_allocator; + +struct s_umpire_dynamicpool { + void *addr; /* address of C++ memory */ + int idtor; /* index of destructor */ +}; +typedef struct s_umpire_dynamicpool umpire_dynamicpool; + +struct s_umpire_resourcemanager { + void *addr; /* address of C++ memory */ + int idtor; /* index of destructor */ +}; +typedef struct s_umpire_resourcemanager umpire_resourcemanager; + +struct s_UMP_SHROUD_array { + UMP_SHROUD_capsule_data cxx; /* address of C++ memory */ + union { + const void * cvoidp; + const char * ccharp; + } addr; + size_t len; /* bytes-per-item or character len of data in cxx */ + size_t size; /* size of data in cxx */ +}; +typedef struct s_UMP_SHROUD_array UMP_SHROUD_array; + +void umpire_SHROUD_memory_destructor(UMP_SHROUD_capsule_data *cap); + +#ifdef __cplusplus +} +#endif + +#endif // TYPESUMPIRE_H diff --git a/src/umpire/interface/c_fortran/wrapAllocator.cpp b/src/umpire/interface/c_fortran/wrapAllocator.cpp index dd7468e27..bd16df072 100644 --- a/src/umpire/interface/c_fortran/wrapAllocator.cpp +++ b/src/umpire/interface/c_fortran/wrapAllocator.cpp @@ -1,4 +1,5 @@ -////////////////////////////////////////////////////////////////////////////// +// wrapAllocator.cpp +// This is generated code, do not edit // Copyright (c) 2018, Lawrence Livermore National Security, LLC. // Produced at the Lawrence Livermore National Laboratory // @@ -11,41 +12,111 @@ // // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. -////////////////////////////////////////////////////////////////////////////// -// wrapAllocator.cpp -// This is generated code, do not edit -// wrapAllocator.cpp #include "wrapAllocator.h" +#include +#include #include "umpire/Allocator.hpp" -namespace umpire { - // splicer begin class.Allocator.CXX_definitions // splicer end class.Allocator.CXX_definitions extern "C" { + +// helper function +// Copy the char* or std::string in context into c_var. +// Called by Fortran to deal with allocatable character. +void umpire_ShroudCopyStringAndFree(UMP_SHROUD_array *data, char *c_var, size_t c_var_len) { + const char *cxx_var = data->addr.ccharp; + size_t n = c_var_len; + if (data->len < n) n = data->len; + strncpy(c_var, cxx_var, n); + umpire_SHROUD_memory_destructor(&data->cxx); // delete data->cxx.addr +} + // splicer begin class.Allocator.C_definitions // splicer end class.Allocator.C_definitions -void * UMPIRE_allocator_allocate(UMPIRE_allocator * self, size_t bytes) +void * umpire_allocator_allocate(umpire_allocator * self, size_t bytes) { // splicer begin class.Allocator.method.allocate - Allocator *SH_this = static_cast(static_cast(self)); - void * SH_rv = SH_this->allocate(bytes); - return SH_rv; + umpire::Allocator *SH_this = + static_cast(self->addr); + void * SHC_rv = SH_this->allocate(bytes); + return SHC_rv; // splicer end class.Allocator.method.allocate } -void UMPIRE_allocator_deallocate(UMPIRE_allocator * self, void * ptr) +void umpire_allocator_deallocate(umpire_allocator * self, void * ptr) { // splicer begin class.Allocator.method.deallocate - Allocator *SH_this = static_cast(static_cast(self)); + umpire::Allocator *SH_this = + static_cast(self->addr); SH_this->deallocate(ptr); return; // splicer end class.Allocator.method.deallocate } -} // extern "C" +size_t umpire_allocator_get_size(umpire_allocator * self, void * ptr) +{ +// splicer begin class.Allocator.method.get_size + umpire::Allocator *SH_this = + static_cast(self->addr); + size_t SHC_rv = SH_this->getSize(ptr); + return SHC_rv; +// splicer end class.Allocator.method.get_size +} + +size_t umpire_allocator_get_high_watermark(umpire_allocator * self) +{ +// splicer begin class.Allocator.method.get_high_watermark + umpire::Allocator *SH_this = + static_cast(self->addr); + size_t SHC_rv = SH_this->getHighWatermark(); + return SHC_rv; +// splicer end class.Allocator.method.get_high_watermark +} -} // namespace umpire +size_t umpire_allocator_get_current_size(umpire_allocator * self) +{ +// splicer begin class.Allocator.method.get_current_size + umpire::Allocator *SH_this = + static_cast(self->addr); + size_t SHC_rv = SH_this->getCurrentSize(); + return SHC_rv; +// splicer end class.Allocator.method.get_current_size +} + +void umpire_allocator_get_name_bufferify(umpire_allocator * self, + UMP_SHROUD_array *DSHF_rv) +{ +// splicer begin class.Allocator.method.get_name_bufferify + umpire::Allocator *SH_this = + static_cast(self->addr); + std::string * SHCXX_rv = new std::string; + *SHCXX_rv = SH_this->getName(); + DSHF_rv->cxx.addr = static_cast(SHCXX_rv); + DSHF_rv->cxx.idtor = 1; + if (SHCXX_rv->empty()) { + DSHF_rv->addr.ccharp = NULL; + DSHF_rv->len = 0; + } else { + DSHF_rv->addr.ccharp = SHCXX_rv->data(); + DSHF_rv->len = SHCXX_rv->size(); + } + DSHF_rv->size = 1; + return; +// splicer end class.Allocator.method.get_name_bufferify +} + +size_t umpire_allocator_get_id(umpire_allocator * self) +{ +// splicer begin class.Allocator.method.get_id + umpire::Allocator *SH_this = + static_cast(self->addr); + size_t SHC_rv = SH_this->getId(); + return SHC_rv; +// splicer end class.Allocator.method.get_id +} + +} // extern "C" diff --git a/src/umpire/interface/c_fortran/wrapAllocator.h b/src/umpire/interface/c_fortran/wrapAllocator.h index 2819d1d6f..3b0c9faee 100644 --- a/src/umpire/interface/c_fortran/wrapAllocator.h +++ b/src/umpire/interface/c_fortran/wrapAllocator.h @@ -1,4 +1,5 @@ -////////////////////////////////////////////////////////////////////////////// +// wrapAllocator.h +// This is generated code, do not edit // Copyright (c) 2018, Lawrence Livermore National Security, LLC. // Produced at the Lawrence Livermore National Laboratory // @@ -11,9 +12,6 @@ // // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. -////////////////////////////////////////////////////////////////////////////// -// wrapAllocator.h -// This is generated code, do not edit /** * \file wrapAllocator.h * \brief Shroud generated wrapper for Allocator class @@ -23,25 +21,36 @@ #ifndef WRAPALLOCATOR_H #define WRAPALLOCATOR_H -#include "stdlib.h" +#include +#include "typesUmpire.h" // splicer begin class.Allocator.CXX_declarations +#ifdef __cplusplus +#include +#endif // splicer end class.Allocator.CXX_declarations #ifdef __cplusplus extern "C" { #endif -// declaration of wrapped types -struct s_UMPIRE_allocator; -typedef struct s_UMPIRE_allocator UMPIRE_allocator; - // splicer begin class.Allocator.C_declarations // splicer end class.Allocator.C_declarations -void * UMPIRE_allocator_allocate(UMPIRE_allocator * self, size_t bytes); +void * umpire_allocator_allocate(umpire_allocator * self, size_t bytes); + +void umpire_allocator_deallocate(umpire_allocator * self, void * ptr); + +size_t umpire_allocator_get_size(umpire_allocator * self, void * ptr); + +size_t umpire_allocator_get_high_watermark(umpire_allocator * self); + +size_t umpire_allocator_get_current_size(umpire_allocator * self); + +void umpire_allocator_get_name_bufferify(umpire_allocator * self, + UMP_SHROUD_array *DSHF_rv); -void UMPIRE_allocator_deallocate(UMPIRE_allocator * self, void * ptr); +size_t umpire_allocator_get_id(umpire_allocator * self); #ifdef __cplusplus } diff --git a/src/umpire/interface/c_fortran/wrapResourceManager.cpp b/src/umpire/interface/c_fortran/wrapResourceManager.cpp index 589aca653..5f1499002 100644 --- a/src/umpire/interface/c_fortran/wrapResourceManager.cpp +++ b/src/umpire/interface/c_fortran/wrapResourceManager.cpp @@ -1,4 +1,5 @@ -////////////////////////////////////////////////////////////////////////////// +// wrapResourceManager.cpp +// This is generated code, do not edit // Copyright (c) 2018, Lawrence Livermore National Security, LLC. // Produced at the Lawrence Livermore National Laboratory // @@ -11,16 +12,12 @@ // // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. -////////////////////////////////////////////////////////////////////////////// -// wrapResourceManager.cpp -// This is generated code, do not edit -// wrapResourceManager.cpp #include "wrapResourceManager.h" +#include #include +#include "umpire/Allocator.hpp" #include "umpire/ResourceManager.hpp" -namespace umpire { - // splicer begin class.ResourceManager.CXX_definitions // splicer end class.ResourceManager.CXX_definitions @@ -29,53 +26,156 @@ extern "C" { // splicer begin class.ResourceManager.C_definitions // splicer end class.ResourceManager.C_definitions -UMPIRE_resourcemanager * UMPIRE_resourcemanager_get() +umpire_resourcemanager * umpire_resourcemanager_get_instance( + umpire_resourcemanager * SHC_rv) +{ +// splicer begin class.ResourceManager.method.get_instance + umpire::ResourceManager & SHCXX_rv = + umpire::ResourceManager::getInstance(); + SHC_rv->addr = static_cast(&SHCXX_rv); + SHC_rv->idtor = 0; + return SHC_rv; +// splicer end class.ResourceManager.method.get_instance +} + +umpire_allocator * umpire_resourcemanager_get_allocator_by_name( + umpire_resourcemanager * self, const char * name, + umpire_allocator * SHC_rv) +{ +// splicer begin class.ResourceManager.method.get_allocator_by_name + umpire::ResourceManager *SH_this = + static_cast(self->addr); + umpire::Allocator * SHCXX_rv = new umpire::Allocator; + const std::string SH_name(name); + *SHCXX_rv = SH_this->getAllocator(SH_name); + SHC_rv->addr = static_cast(SHCXX_rv); + SHC_rv->idtor = 0; + return SHC_rv; +// splicer end class.ResourceManager.method.get_allocator_by_name +} + +umpire_allocator * umpire_resourcemanager_get_allocator_by_name_bufferify( + umpire_resourcemanager * self, const char * name, int Lname, + umpire_allocator * SHC_rv) { -// splicer begin class.ResourceManager.method.get - auto& SH_rv = ResourceManager::getInstance(); return static_cast(static_cast(&SH_rv)); -// splicer end class.ResourceManager.method.get +// splicer begin class.ResourceManager.method.get_allocator_by_name_bufferify + umpire::ResourceManager *SH_this = + static_cast(self->addr); + umpire::Allocator * SHCXX_rv = new umpire::Allocator; + const std::string SH_name(name, Lname); + *SHCXX_rv = SH_this->getAllocator(SH_name); + SHC_rv->addr = static_cast(SHCXX_rv); + SHC_rv->idtor = 0; + return SHC_rv; +// splicer end class.ResourceManager.method.get_allocator_by_name_bufferify } -UMPIRE_allocator * UMPIRE_resourcemanager_get_allocator(UMPIRE_resourcemanager * self, const char * space) +umpire_allocator * umpire_resourcemanager_get_allocator_by_id( + umpire_resourcemanager * self, const int id, + umpire_allocator * SHC_rv) { -// splicer begin class.ResourceManager.method.get_allocator - ResourceManager *SH_this = static_cast(static_cast(self)); - const std::string SH_space(space); - Allocator * SH_rv = new Allocator(SH_this->getAllocator(SH_space)); - UMPIRE_allocator * XSH_rv = static_cast(static_cast(SH_rv)); - return XSH_rv; -// splicer end class.ResourceManager.method.get_allocator +// splicer begin class.ResourceManager.method.get_allocator_by_id + umpire::ResourceManager *SH_this = + static_cast(self->addr); + umpire::Allocator * SHCXX_rv = new umpire::Allocator; + *SHCXX_rv = SH_this->getAllocator(id); + SHC_rv->addr = static_cast(SHCXX_rv); + SHC_rv->idtor = 0; + return SHC_rv; +// splicer end class.ResourceManager.method.get_allocator_by_id } -UMPIRE_allocator * UMPIRE_resourcemanager_get_allocator_bufferify(UMPIRE_resourcemanager * self, const char * space, int Lspace) +umpire_allocator * umpire_resourcemanager_get_allocatorfor_ptr( + umpire_resourcemanager * self, void * ptr, + umpire_allocator * SHC_rv) { -// splicer begin class.ResourceManager.method.get_allocator_bufferify - ResourceManager *SH_this = static_cast(static_cast(self)); - const std::string SH_space(space, Lspace); - Allocator * SH_rv = new Allocator(SH_this->getAllocator(SH_space)); - UMPIRE_allocator * XSH_rv = static_cast(static_cast(SH_rv)); - return XSH_rv; -// splicer end class.ResourceManager.method.get_allocator_bufferify +// splicer begin class.ResourceManager.method.get_allocatorfor_ptr + umpire::ResourceManager *SH_this = + static_cast(self->addr); + umpire::Allocator * SHCXX_rv = new umpire::Allocator; + *SHCXX_rv = SH_this->getAllocator(ptr); + SHC_rv->addr = static_cast(SHCXX_rv); + SHC_rv->idtor = 0; + return SHC_rv; +// splicer end class.ResourceManager.method.get_allocatorfor_ptr } -void UMPIRE_resourcemanager_copy(UMPIRE_resourcemanager * self, void * src_ptr, void * dst_ptr) +void umpire_resourcemanager_copy_all(umpire_resourcemanager * self, + void * src_ptr, void * dst_ptr) { -// splicer begin class.ResourceManager.method.copy - ResourceManager *SH_this = static_cast(static_cast(self)); +// splicer begin class.ResourceManager.method.copy_all + umpire::ResourceManager *SH_this = + static_cast(self->addr); SH_this->copy(src_ptr, dst_ptr); return; -// splicer end class.ResourceManager.method.copy +// splicer end class.ResourceManager.method.copy_all +} + +void umpire_resourcemanager_copy_with_size( + umpire_resourcemanager * self, void * src_ptr, void * dst_ptr, + size_t size) +{ +// splicer begin class.ResourceManager.method.copy_with_size + umpire::ResourceManager *SH_this = + static_cast(self->addr); + SH_this->copy(src_ptr, dst_ptr, size); + return; +// splicer end class.ResourceManager.method.copy_with_size } -void UMPIRE_resourcemanager_deallocate(UMPIRE_resourcemanager * self, void * ptr) +void umpire_resourcemanager_memset_all(umpire_resourcemanager * self, + void * ptr, int val) +{ +// splicer begin class.ResourceManager.method.memset_all + umpire::ResourceManager *SH_this = + static_cast(self->addr); + SH_this->memset(ptr, val); + return; +// splicer end class.ResourceManager.method.memset_all +} + +void umpire_resourcemanager_memset_with_size( + umpire_resourcemanager * self, void * ptr, int val, size_t length) +{ +// splicer begin class.ResourceManager.method.memset_with_size + umpire::ResourceManager *SH_this = + static_cast(self->addr); + SH_this->memset(ptr, val, length); + return; +// splicer end class.ResourceManager.method.memset_with_size +} + +void * umpire_resourcemanager_reallocate(umpire_resourcemanager * self, + void * src_ptr, size_t size) +{ +// splicer begin class.ResourceManager.method.reallocate + umpire::ResourceManager *SH_this = + static_cast(self->addr); + void * SHC_rv = SH_this->reallocate(src_ptr, size); + return SHC_rv; +// splicer end class.ResourceManager.method.reallocate +} + +void umpire_resourcemanager_deallocate(umpire_resourcemanager * self, + void * ptr) { // splicer begin class.ResourceManager.method.deallocate - ResourceManager *SH_this = static_cast(static_cast(self)); + umpire::ResourceManager *SH_this = + static_cast(self->addr); SH_this->deallocate(ptr); return; // splicer end class.ResourceManager.method.deallocate } -} // extern "C" +size_t umpire_resourcemanager_get_size(umpire_resourcemanager * self, + void * ptr) +{ +// splicer begin class.ResourceManager.method.get_size + umpire::ResourceManager *SH_this = + static_cast(self->addr); + size_t SHC_rv = SH_this->getSize(ptr); + return SHC_rv; +// splicer end class.ResourceManager.method.get_size +} -} // namespace umpire +} // extern "C" diff --git a/src/umpire/interface/c_fortran/wrapResourceManager.h b/src/umpire/interface/c_fortran/wrapResourceManager.h index 4a38ed67e..1c59602d4 100644 --- a/src/umpire/interface/c_fortran/wrapResourceManager.h +++ b/src/umpire/interface/c_fortran/wrapResourceManager.h @@ -1,4 +1,5 @@ -////////////////////////////////////////////////////////////////////////////// +// wrapResourceManager.h +// This is generated code, do not edit // Copyright (c) 2018, Lawrence Livermore National Security, LLC. // Produced at the Lawrence Livermore National Laboratory // @@ -11,9 +12,6 @@ // // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. -////////////////////////////////////////////////////////////////////////////// -// wrapResourceManager.h -// This is generated code, do not edit /** * \file wrapResourceManager.h * \brief Shroud generated wrapper for ResourceManager class @@ -23,6 +21,9 @@ #ifndef WRAPRESOURCEMANAGER_H #define WRAPRESOURCEMANAGER_H +#include +#include "typesUmpire.h" + // splicer begin class.ResourceManager.CXX_declarations // splicer end class.ResourceManager.CXX_declarations @@ -30,24 +31,49 @@ extern "C" { #endif -// declaration of wrapped types -struct s_UMPIRE_allocator; -typedef struct s_UMPIRE_allocator UMPIRE_allocator; -struct s_UMPIRE_resourcemanager; -typedef struct s_UMPIRE_resourcemanager UMPIRE_resourcemanager; - // splicer begin class.ResourceManager.C_declarations // splicer end class.ResourceManager.C_declarations -UMPIRE_resourcemanager * UMPIRE_resourcemanager_get(); +umpire_resourcemanager * umpire_resourcemanager_get_instance( + umpire_resourcemanager * SHC_rv); + +umpire_allocator * umpire_resourcemanager_get_allocator_by_name( + umpire_resourcemanager * self, const char * name, + umpire_allocator * SHC_rv); + +umpire_allocator * umpire_resourcemanager_get_allocator_by_name_bufferify( + umpire_resourcemanager * self, const char * name, int Lname, + umpire_allocator * SHC_rv); + +umpire_allocator * umpire_resourcemanager_get_allocator_by_id( + umpire_resourcemanager * self, const int id, + umpire_allocator * SHC_rv); + +umpire_allocator * umpire_resourcemanager_get_allocatorfor_ptr( + umpire_resourcemanager * self, void * ptr, + umpire_allocator * SHC_rv); + +void umpire_resourcemanager_copy_all(umpire_resourcemanager * self, + void * src_ptr, void * dst_ptr); + +void umpire_resourcemanager_copy_with_size( + umpire_resourcemanager * self, void * src_ptr, void * dst_ptr, + size_t size); + +void umpire_resourcemanager_memset_all(umpire_resourcemanager * self, + void * ptr, int val); -UMPIRE_allocator * UMPIRE_resourcemanager_get_allocator(UMPIRE_resourcemanager * self, const char * space); +void umpire_resourcemanager_memset_with_size( + umpire_resourcemanager * self, void * ptr, int val, size_t length); -UMPIRE_allocator * UMPIRE_resourcemanager_get_allocator_bufferify(UMPIRE_resourcemanager * self, const char * space, int Lspace); +void * umpire_resourcemanager_reallocate(umpire_resourcemanager * self, + void * src_ptr, size_t size); -void UMPIRE_resourcemanager_copy(UMPIRE_resourcemanager * self, void * src_ptr, void * dst_ptr); +void umpire_resourcemanager_deallocate(umpire_resourcemanager * self, + void * ptr); -void UMPIRE_resourcemanager_deallocate(UMPIRE_resourcemanager * self, void * ptr); +size_t umpire_resourcemanager_get_size(umpire_resourcemanager * self, + void * ptr); #ifdef __cplusplus } diff --git a/src/umpire/interface/c_fortran/wrapUmpire.cpp b/src/umpire/interface/c_fortran/wrapUmpire.cpp new file mode 100644 index 000000000..6ed85be69 --- /dev/null +++ b/src/umpire/interface/c_fortran/wrapUmpire.cpp @@ -0,0 +1,53 @@ +// wrapUmpire.cpp +// This is generated code, do not edit +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +#include +#include +#include "typesUmpire.h" + +// splicer begin CXX_definitions +// splicer end CXX_definitions + +extern "C" { + +// splicer begin C_definitions +// splicer end C_definitions + +// Release C++ allocated memory. +void umpire_SHROUD_memory_destructor(UMP_SHROUD_capsule_data *cap) +{ + void *ptr = cap->addr; + switch (cap->idtor) { + case 0: // --none-- + { + // Nothing to delete + break; + } + case 1: // new_string + { + std::string *cxx_ptr = reinterpret_cast(ptr); + delete cxx_ptr; + break; + } + default: + { + // Unexpected case in destructor + break; + } + } + cap->addr = NULL; + cap->idtor = 0; // avoid deleting again +} + +} // extern "C" diff --git a/src/umpire/interface/c_fortran/wrapfumpire.f b/src/umpire/interface/c_fortran/wrapfumpire.f new file mode 100644 index 000000000..fcb3e3a17 --- /dev/null +++ b/src/umpire/interface/c_fortran/wrapfumpire.f @@ -0,0 +1,696 @@ +! wrapfumpire.f +! This is generated code, do not edit +! Copyright (c) 2018, Lawrence Livermore National Security, LLC. +! Produced at the Lawrence Livermore National Laboratory +! +! Created by David Beckingsale, david@llnl.gov +! LLNL-CODE-747640 +! +! All rights reserved. +! +! This file is part of Umpire. +! +! For details, see https://github.com/LLNL/Umpire +! Please also see the LICENSE file for MIT license. +!> +!! \file wrapfumpire.f +!! \brief Shroud generated wrapper for Umpire library +!< +! splicer begin file_top +! splicer end file_top +module umpire_mod + use iso_c_binding, only : C_INT, C_NULL_PTR, C_PTR, C_SIZE_T + ! splicer begin module_use + ! splicer end module_use + implicit none + + ! splicer begin module_top + ! splicer end module_top + + type, bind(C) :: SHROUD_capsule_data + type(C_PTR) :: addr = C_NULL_PTR ! address of C++ memory + integer(C_INT) :: idtor = 0 ! index of destructor + end type SHROUD_capsule_data + + type, bind(C) :: SHROUD_array + type(SHROUD_capsule_data) :: cxx ! address of C++ memory + type(C_PTR) :: addr = C_NULL_PTR ! address of data in cxx + integer(C_SIZE_T) :: len = 0_C_SIZE_T ! bytes-per-item or character len of data in cxx + integer(C_SIZE_T) :: size = 0_C_SIZE_T ! size of data in cxx + end type SHROUD_array + + ! splicer begin class.DynamicPool.module_top + ! splicer end class.DynamicPool.module_top + + type, bind(C) :: SHROUD_dynamicpool_capsule + type(C_PTR) :: addr = C_NULL_PTR ! address of C++ memory + integer(C_INT) :: idtor = 0 ! index of destructor + end type SHROUD_dynamicpool_capsule + + type dynamicpool + type(SHROUD_dynamicpool_capsule) :: cxxmem + ! splicer begin class.DynamicPool.component_part + ! splicer end class.DynamicPool.component_part + contains + procedure :: get_instance => dynamicpool_get_instance + procedure :: set_instance => dynamicpool_set_instance + procedure :: associated => dynamicpool_associated + ! splicer begin class.DynamicPool.type_bound_procedure_part + ! splicer end class.DynamicPool.type_bound_procedure_part + end type dynamicpool + + ! splicer begin class.Allocator.module_top + ! splicer end class.Allocator.module_top + + type, bind(C) :: SHROUD_allocator_capsule + type(C_PTR) :: addr = C_NULL_PTR ! address of C++ memory + integer(C_INT) :: idtor = 0 ! index of destructor + end type SHROUD_allocator_capsule + + type UmpireAllocator + type(SHROUD_allocator_capsule) :: cxxmem + ! splicer begin class.Allocator.component_part + ! splicer end class.Allocator.component_part + contains + procedure :: allocate => allocator_allocate + procedure :: deallocate => allocator_deallocate + procedure :: get_size => allocator_get_size + procedure :: get_high_watermark => allocator_get_high_watermark + procedure :: get_current_size => allocator_get_current_size + procedure :: get_name => allocator_get_name + procedure :: get_id => allocator_get_id + procedure :: get_instance => allocator_get_instance + procedure :: set_instance => allocator_set_instance + procedure :: associated => allocator_associated + ! splicer begin class.Allocator.type_bound_procedure_part + ! splicer end class.Allocator.type_bound_procedure_part + end type UmpireAllocator + + ! splicer begin class.ResourceManager.module_top + ! splicer end class.ResourceManager.module_top + + type, bind(C) :: SHROUD_resourcemanager_capsule + type(C_PTR) :: addr = C_NULL_PTR ! address of C++ memory + integer(C_INT) :: idtor = 0 ! index of destructor + end type SHROUD_resourcemanager_capsule + + type UmpireResourceManager + type(SHROUD_resourcemanager_capsule) :: cxxmem + ! splicer begin class.ResourceManager.component_part + ! splicer end class.ResourceManager.component_part + contains + procedure, nopass :: get_instance => resourcemanager_get_instance + procedure :: get_allocator_by_name => resourcemanager_get_allocator_by_name + procedure :: get_allocator_by_id => resourcemanager_get_allocator_by_id + procedure :: get_allocatorfor_ptr => resourcemanager_get_allocatorfor_ptr + procedure :: copy_all => resourcemanager_copy_all + procedure :: copy_with_size => resourcemanager_copy_with_size + procedure :: memset_all => resourcemanager_memset_all + procedure :: memset_with_size => resourcemanager_memset_with_size + procedure :: reallocate => resourcemanager_reallocate + procedure :: deallocate => resourcemanager_deallocate + procedure :: get_size => resourcemanager_get_size + procedure :: associated => resourcemanager_associated + generic :: copy => copy_all, copy_with_size + generic :: get_allocator => get_allocator_by_name, & + get_allocator_by_id, get_allocatorfor_ptr + generic :: memset => memset_all, memset_with_size + ! splicer begin class.ResourceManager.type_bound_procedure_part + ! splicer end class.ResourceManager.type_bound_procedure_part + end type UmpireResourceManager + + interface operator (.eq.) + module procedure dynamicpool_eq + module procedure allocator_eq + module procedure resourcemanager_eq + end interface + + interface operator (.ne.) + module procedure dynamicpool_ne + module procedure allocator_ne + module procedure resourcemanager_ne + end interface + + interface + + ! splicer begin class.DynamicPool.additional_interfaces + ! splicer end class.DynamicPool.additional_interfaces + + function c_allocator_allocate(self, bytes) & + result(SHT_rv) & + bind(C, name="umpire_allocator_allocate") + use iso_c_binding, only : C_PTR, C_SIZE_T + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + integer(C_SIZE_T), value, intent(IN) :: bytes + type(C_PTR) :: SHT_rv + end function c_allocator_allocate + + subroutine c_allocator_deallocate(self, ptr) & + bind(C, name="umpire_allocator_deallocate") + use iso_c_binding, only : C_PTR + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + end subroutine c_allocator_deallocate + + function c_allocator_get_size(self, ptr) & + result(SHT_rv) & + bind(C, name="umpire_allocator_get_size") + use iso_c_binding, only : C_PTR, C_SIZE_T + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + integer(C_SIZE_T) :: SHT_rv + end function c_allocator_get_size + + function c_allocator_get_high_watermark(self) & + result(SHT_rv) & + bind(C, name="umpire_allocator_get_high_watermark") + use iso_c_binding, only : C_SIZE_T + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + integer(C_SIZE_T) :: SHT_rv + end function c_allocator_get_high_watermark + + function c_allocator_get_current_size(self) & + result(SHT_rv) & + bind(C, name="umpire_allocator_get_current_size") + use iso_c_binding, only : C_SIZE_T + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + integer(C_SIZE_T) :: SHT_rv + end function c_allocator_get_current_size + + subroutine c_allocator_get_name_bufferify(self, DSHF_rv) & + bind(C, name="umpire_allocator_get_name_bufferify") + import :: SHROUD_allocator_capsule, SHROUD_array + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + type(SHROUD_array), intent(INOUT) :: DSHF_rv + end subroutine c_allocator_get_name_bufferify + + function c_allocator_get_id(self) & + result(SHT_rv) & + bind(C, name="umpire_allocator_get_id") + use iso_c_binding, only : C_SIZE_T + import :: SHROUD_allocator_capsule + implicit none + type(SHROUD_allocator_capsule), intent(IN) :: self + integer(C_SIZE_T) :: SHT_rv + end function c_allocator_get_id + + ! splicer begin class.Allocator.additional_interfaces + ! splicer end class.Allocator.additional_interfaces + + function c_resourcemanager_get_instance(SHT_crv) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_instance") + use iso_c_binding, only : C_PTR + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(OUT) :: SHT_crv + type(C_PTR) SHT_rv + end function c_resourcemanager_get_instance + + function c_resourcemanager_get_allocator_by_name(self, name, & + SHT_crv) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_allocator_by_name") + use iso_c_binding, only : C_CHAR, C_PTR + import :: SHROUD_allocator_capsule, SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + character(kind=C_CHAR), intent(IN) :: name(*) + type(SHROUD_allocator_capsule), intent(OUT) :: SHT_crv + type(C_PTR) SHT_rv + end function c_resourcemanager_get_allocator_by_name + + function c_resourcemanager_get_allocator_by_name_bufferify(self, & + name, Lname, SHT_crv) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_allocator_by_name_bufferify") + use iso_c_binding, only : C_CHAR, C_INT, C_PTR + import :: SHROUD_allocator_capsule, SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + character(kind=C_CHAR), intent(IN) :: name(*) + integer(C_INT), value, intent(IN) :: Lname + type(SHROUD_allocator_capsule), intent(OUT) :: SHT_crv + type(C_PTR) SHT_rv + end function c_resourcemanager_get_allocator_by_name_bufferify + + function c_resourcemanager_get_allocator_by_id(self, id, & + SHT_crv) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_allocator_by_id") + use iso_c_binding, only : C_INT, C_PTR + import :: SHROUD_allocator_capsule, SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + integer(C_INT), value, intent(IN) :: id + type(SHROUD_allocator_capsule), intent(OUT) :: SHT_crv + type(C_PTR) SHT_rv + end function c_resourcemanager_get_allocator_by_id + + function c_resourcemanager_get_allocatorfor_ptr(self, ptr, & + SHT_crv) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_allocatorfor_ptr") + use iso_c_binding, only : C_PTR + import :: SHROUD_allocator_capsule, SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + type(SHROUD_allocator_capsule), intent(OUT) :: SHT_crv + type(C_PTR) SHT_rv + end function c_resourcemanager_get_allocatorfor_ptr + + subroutine c_resourcemanager_copy_all(self, src_ptr, dst_ptr) & + bind(C, name="umpire_resourcemanager_copy_all") + use iso_c_binding, only : C_PTR + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: src_ptr + type(C_PTR), value, intent(IN) :: dst_ptr + end subroutine c_resourcemanager_copy_all + + subroutine c_resourcemanager_copy_with_size(self, src_ptr, & + dst_ptr, size) & + bind(C, name="umpire_resourcemanager_copy_with_size") + use iso_c_binding, only : C_PTR, C_SIZE_T + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: src_ptr + type(C_PTR), value, intent(IN) :: dst_ptr + integer(C_SIZE_T), value, intent(IN) :: size + end subroutine c_resourcemanager_copy_with_size + + subroutine c_resourcemanager_memset_all(self, ptr, val) & + bind(C, name="umpire_resourcemanager_memset_all") + use iso_c_binding, only : C_INT, C_PTR + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + integer(C_INT), value, intent(IN) :: val + end subroutine c_resourcemanager_memset_all + + subroutine c_resourcemanager_memset_with_size(self, ptr, val, & + length) & + bind(C, name="umpire_resourcemanager_memset_with_size") + use iso_c_binding, only : C_INT, C_PTR, C_SIZE_T + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + integer(C_INT), value, intent(IN) :: val + integer(C_SIZE_T), value, intent(IN) :: length + end subroutine c_resourcemanager_memset_with_size + + function c_resourcemanager_reallocate(self, src_ptr, size) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_reallocate") + use iso_c_binding, only : C_PTR, C_SIZE_T + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: src_ptr + integer(C_SIZE_T), value, intent(IN) :: size + type(C_PTR) :: SHT_rv + end function c_resourcemanager_reallocate + + subroutine c_resourcemanager_deallocate(self, ptr) & + bind(C, name="umpire_resourcemanager_deallocate") + use iso_c_binding, only : C_PTR + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + end subroutine c_resourcemanager_deallocate + + function c_resourcemanager_get_size(self, ptr) & + result(SHT_rv) & + bind(C, name="umpire_resourcemanager_get_size") + use iso_c_binding, only : C_PTR, C_SIZE_T + import :: SHROUD_resourcemanager_capsule + implicit none + type(SHROUD_resourcemanager_capsule), intent(IN) :: self + type(C_PTR), value, intent(IN) :: ptr + integer(C_SIZE_T) :: SHT_rv + end function c_resourcemanager_get_size + + ! splicer begin class.ResourceManager.additional_interfaces + ! splicer end class.ResourceManager.additional_interfaces + end interface + + interface + ! helper function + ! Copy the char* or std::string in context into c_var. + subroutine SHROUD_copy_string_and_free(context, c_var, c_var_size) & + bind(c,name="umpire_ShroudCopyStringAndFree") + use, intrinsic :: iso_c_binding, only : C_CHAR, C_SIZE_T + import SHROUD_array + type(SHROUD_array), intent(IN) :: context + character(kind=C_CHAR), intent(OUT) :: c_var(*) + integer(C_SIZE_T), value :: c_var_size + end subroutine SHROUD_copy_string_and_free + end interface + +contains + + ! Return pointer to C++ memory. + function dynamicpool_get_instance(obj) result (cxxptr) + use iso_c_binding, only: C_PTR + class(dynamicpool), intent(IN) :: obj + type(C_PTR) :: cxxptr + cxxptr = obj%cxxmem%addr + end function dynamicpool_get_instance + + subroutine dynamicpool_set_instance(obj, cxxmem) + use iso_c_binding, only: C_PTR + class(dynamicpool), intent(INOUT) :: obj + type(C_PTR), intent(IN) :: cxxmem + obj%cxxmem%addr = cxxmem + obj%cxxmem%idtor = 0 + end subroutine dynamicpool_set_instance + + function dynamicpool_associated(obj) result (rv) + use iso_c_binding, only: c_associated + class(dynamicpool), intent(IN) :: obj + logical rv + rv = c_associated(obj%cxxmem%addr) + end function dynamicpool_associated + + ! splicer begin class.DynamicPool.additional_functions + ! splicer end class.DynamicPool.additional_functions + + function allocator_allocate(obj, bytes) & + result(SHT_rv) + use iso_c_binding, only : C_PTR, C_SIZE_T + class(UmpireAllocator) :: obj + integer(C_SIZE_T), value, intent(IN) :: bytes + type(C_PTR) :: SHT_rv + ! splicer begin class.Allocator.method.allocate + SHT_rv = c_allocator_allocate(obj%cxxmem, bytes) + ! splicer end class.Allocator.method.allocate + end function allocator_allocate + + subroutine allocator_deallocate(obj, ptr) + use iso_c_binding, only : C_PTR + class(UmpireAllocator) :: obj + type(C_PTR), value, intent(IN) :: ptr + ! splicer begin class.Allocator.method.deallocate + call c_allocator_deallocate(obj%cxxmem, ptr) + ! splicer end class.Allocator.method.deallocate + end subroutine allocator_deallocate + + function allocator_get_size(obj, ptr) & + result(SHT_rv) + use iso_c_binding, only : C_PTR, C_SIZE_T + class(UmpireAllocator) :: obj + type(C_PTR), value, intent(IN) :: ptr + integer(C_SIZE_T) :: SHT_rv + ! splicer begin class.Allocator.method.get_size + SHT_rv = c_allocator_get_size(obj%cxxmem, ptr) + ! splicer end class.Allocator.method.get_size + end function allocator_get_size + + function allocator_get_high_watermark(obj) & + result(SHT_rv) + use iso_c_binding, only : C_SIZE_T + class(UmpireAllocator) :: obj + integer(C_SIZE_T) :: SHT_rv + ! splicer begin class.Allocator.method.get_high_watermark + SHT_rv = c_allocator_get_high_watermark(obj%cxxmem) + ! splicer end class.Allocator.method.get_high_watermark + end function allocator_get_high_watermark + + function allocator_get_current_size(obj) & + result(SHT_rv) + use iso_c_binding, only : C_SIZE_T + class(UmpireAllocator) :: obj + integer(C_SIZE_T) :: SHT_rv + ! splicer begin class.Allocator.method.get_current_size + SHT_rv = c_allocator_get_current_size(obj%cxxmem) + ! splicer end class.Allocator.method.get_current_size + end function allocator_get_current_size + + function allocator_get_name(obj) & + result(SHT_rv) + class(UmpireAllocator) :: obj + type(SHROUD_array) :: DSHF_rv + character(len=:), allocatable :: SHT_rv + ! splicer begin class.Allocator.method.get_name + call c_allocator_get_name_bufferify(obj%cxxmem, DSHF_rv) + ! splicer end class.Allocator.method.get_name + allocate(character(len=DSHF_rv%len):: SHT_rv) + call SHROUD_copy_string_and_free(DSHF_rv, SHT_rv, DSHF_rv%len) + end function allocator_get_name + + function allocator_get_id(obj) & + result(SHT_rv) + use iso_c_binding, only : C_SIZE_T + class(UmpireAllocator) :: obj + integer(C_SIZE_T) :: SHT_rv + ! splicer begin class.Allocator.method.get_id + SHT_rv = c_allocator_get_id(obj%cxxmem) + ! splicer end class.Allocator.method.get_id + end function allocator_get_id + + ! Return pointer to C++ memory. + function allocator_get_instance(obj) result (cxxptr) + use iso_c_binding, only: C_PTR + class(UmpireAllocator), intent(IN) :: obj + type(C_PTR) :: cxxptr + cxxptr = obj%cxxmem%addr + end function allocator_get_instance + + subroutine allocator_set_instance(obj, cxxmem) + use iso_c_binding, only: C_PTR + class(UmpireAllocator), intent(INOUT) :: obj + type(C_PTR), intent(IN) :: cxxmem + obj%cxxmem%addr = cxxmem + obj%cxxmem%idtor = 0 + end subroutine allocator_set_instance + + function allocator_associated(obj) result (rv) + use iso_c_binding, only: c_associated + class(UmpireAllocator), intent(IN) :: obj + logical rv + rv = c_associated(obj%cxxmem%addr) + end function allocator_associated + + ! splicer begin class.Allocator.additional_functions + ! splicer end class.Allocator.additional_functions + + function resourcemanager_get_instance() & + result(SHT_rv) + use iso_c_binding, only : C_PTR + type(C_PTR) :: SHT_prv + type(UmpireResourceManager) :: SHT_rv + ! splicer begin class.ResourceManager.method.get_instance + SHT_prv = c_resourcemanager_get_instance(SHT_rv%cxxmem) + ! splicer end class.ResourceManager.method.get_instance + end function resourcemanager_get_instance + + function resourcemanager_get_allocator_by_name(obj, name) & + result(SHT_rv) + use iso_c_binding, only : C_INT, C_PTR + class(UmpireResourceManager) :: obj + character(len=*), intent(IN) :: name + type(C_PTR) :: SHT_prv + type(UmpireAllocator) :: SHT_rv + ! splicer begin class.ResourceManager.method.get_allocator_by_name + SHT_prv = c_resourcemanager_get_allocator_by_name_bufferify(obj%cxxmem, & + name, len_trim(name, kind=C_INT), SHT_rv%cxxmem) + ! splicer end class.ResourceManager.method.get_allocator_by_name + end function resourcemanager_get_allocator_by_name + + function resourcemanager_get_allocator_by_id(obj, id) & + result(SHT_rv) + use iso_c_binding, only : C_INT, C_PTR + class(UmpireResourceManager) :: obj + integer(C_INT), value, intent(IN) :: id + type(C_PTR) :: SHT_prv + type(UmpireAllocator) :: SHT_rv + ! splicer begin class.ResourceManager.method.get_allocator_by_id + SHT_prv = c_resourcemanager_get_allocator_by_id(obj%cxxmem, id, & + SHT_rv%cxxmem) + ! splicer end class.ResourceManager.method.get_allocator_by_id + end function resourcemanager_get_allocator_by_id + + function resourcemanager_get_allocatorfor_ptr(obj, ptr) & + result(SHT_rv) + use iso_c_binding, only : C_PTR + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: ptr + type(C_PTR) :: SHT_prv + type(UmpireAllocator) :: SHT_rv + ! splicer begin class.ResourceManager.method.get_allocatorfor_ptr + SHT_prv = c_resourcemanager_get_allocatorfor_ptr(obj%cxxmem, & + ptr, SHT_rv%cxxmem) + ! splicer end class.ResourceManager.method.get_allocatorfor_ptr + end function resourcemanager_get_allocatorfor_ptr + + subroutine resourcemanager_copy_all(obj, src_ptr, dst_ptr) + use iso_c_binding, only : C_PTR + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: src_ptr + type(C_PTR), value, intent(IN) :: dst_ptr + ! splicer begin class.ResourceManager.method.copy_all + call c_resourcemanager_copy_all(obj%cxxmem, src_ptr, dst_ptr) + ! splicer end class.ResourceManager.method.copy_all + end subroutine resourcemanager_copy_all + + subroutine resourcemanager_copy_with_size(obj, src_ptr, dst_ptr, & + size) + use iso_c_binding, only : C_PTR, C_SIZE_T + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: src_ptr + type(C_PTR), value, intent(IN) :: dst_ptr + integer(C_SIZE_T), value, intent(IN) :: size + ! splicer begin class.ResourceManager.method.copy_with_size + call c_resourcemanager_copy_with_size(obj%cxxmem, src_ptr, & + dst_ptr, size) + ! splicer end class.ResourceManager.method.copy_with_size + end subroutine resourcemanager_copy_with_size + + subroutine resourcemanager_memset_all(obj, ptr, val) + use iso_c_binding, only : C_INT, C_PTR + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: ptr + integer(C_INT), value, intent(IN) :: val + ! splicer begin class.ResourceManager.method.memset_all + call c_resourcemanager_memset_all(obj%cxxmem, ptr, val) + ! splicer end class.ResourceManager.method.memset_all + end subroutine resourcemanager_memset_all + + subroutine resourcemanager_memset_with_size(obj, ptr, val, length) + use iso_c_binding, only : C_INT, C_PTR, C_SIZE_T + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: ptr + integer(C_INT), value, intent(IN) :: val + integer(C_SIZE_T), value, intent(IN) :: length + ! splicer begin class.ResourceManager.method.memset_with_size + call c_resourcemanager_memset_with_size(obj%cxxmem, ptr, val, & + length) + ! splicer end class.ResourceManager.method.memset_with_size + end subroutine resourcemanager_memset_with_size + + function resourcemanager_reallocate(obj, src_ptr, size) & + result(SHT_rv) + use iso_c_binding, only : C_PTR, C_SIZE_T + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: src_ptr + integer(C_SIZE_T), value, intent(IN) :: size + type(C_PTR) :: SHT_rv + ! splicer begin class.ResourceManager.method.reallocate + SHT_rv = c_resourcemanager_reallocate(obj%cxxmem, src_ptr, size) + ! splicer end class.ResourceManager.method.reallocate + end function resourcemanager_reallocate + + subroutine resourcemanager_deallocate(obj, ptr) + use iso_c_binding, only : C_PTR + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: ptr + ! splicer begin class.ResourceManager.method.deallocate + call c_resourcemanager_deallocate(obj%cxxmem, ptr) + ! splicer end class.ResourceManager.method.deallocate + end subroutine resourcemanager_deallocate + + function resourcemanager_get_size(obj, ptr) & + result(SHT_rv) + use iso_c_binding, only : C_PTR, C_SIZE_T + class(UmpireResourceManager) :: obj + type(C_PTR), value, intent(IN) :: ptr + integer(C_SIZE_T) :: SHT_rv + ! splicer begin class.ResourceManager.method.get_size + SHT_rv = c_resourcemanager_get_size(obj%cxxmem, ptr) + ! splicer end class.ResourceManager.method.get_size + end function resourcemanager_get_size + + function resourcemanager_associated(obj) result (rv) + use iso_c_binding, only: c_associated + class(UmpireResourceManager), intent(IN) :: obj + logical rv + rv = c_associated(obj%cxxmem%addr) + end function resourcemanager_associated + + ! splicer begin class.ResourceManager.additional_functions + ! splicer end class.ResourceManager.additional_functions + + function dynamicpool_eq(a,b) result (rv) + use iso_c_binding, only: c_associated + type(dynamicpool), intent(IN) ::a,b + logical :: rv + if (c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function dynamicpool_eq + + function dynamicpool_ne(a,b) result (rv) + use iso_c_binding, only: c_associated + type(dynamicpool), intent(IN) ::a,b + logical :: rv + if (.not. c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function dynamicpool_ne + + function allocator_eq(a,b) result (rv) + use iso_c_binding, only: c_associated + type(UmpireAllocator), intent(IN) ::a,b + logical :: rv + if (c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function allocator_eq + + function allocator_ne(a,b) result (rv) + use iso_c_binding, only: c_associated + type(UmpireAllocator), intent(IN) ::a,b + logical :: rv + if (.not. c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function allocator_ne + + function resourcemanager_eq(a,b) result (rv) + use iso_c_binding, only: c_associated + type(UmpireResourceManager), intent(IN) ::a,b + logical :: rv + if (c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function resourcemanager_eq + + function resourcemanager_ne(a,b) result (rv) + use iso_c_binding, only: c_associated + type(UmpireResourceManager), intent(IN) ::a,b + logical :: rv + if (.not. c_associated(a%cxxmem%addr, b%cxxmem%addr)) then + rv = .true. + else + rv = .false. + endif + end function resourcemanager_ne + +end module umpire_mod diff --git a/src/umpire/interface/c_fortran/wrapfumpire.f90 b/src/umpire/interface/c_fortran/wrapfumpire.f90 deleted file mode 100644 index 328505058..000000000 --- a/src/umpire/interface/c_fortran/wrapfumpire.f90 +++ /dev/null @@ -1,326 +0,0 @@ -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! Copyright (c) 2018, Lawrence Livermore National Security, LLC. -! Produced at the Lawrence Livermore National Laboratory -! -! Created by David Beckingsale, david@llnl.gov -! LLNL-CODE-747640 -! -! All rights reserved. -! -! This file is part of Umpire. -! -! For details, see https://github.com/LLNL/Umpire -! Please also see the LICENSE file for MIT license. -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! wrapfumpire.f -! This is generated code, do not edit -!> -!! \file wrapfumpire.f -!! \brief Shroud generated wrapper for Umpire library -!< -! splicer begin file_top -! splicer end file_top -module umpire_mod - use, intrinsic :: iso_c_binding, only : C_PTR - ! splicer begin module_use - ! splicer end module_use - ! splicer begin class.ResourceManager.module_use - ! splicer end class.ResourceManager.module_use - ! splicer begin class.Allocator.module_use - ! splicer end class.Allocator.module_use - implicit none - - ! splicer begin module_top - ! splicer end module_top - - ! splicer begin class.ResourceManager.module_top - ! splicer end class.ResourceManager.module_top - - type UmpireResourceManager - type(C_PTR), private :: voidptr - ! splicer begin class.ResourceManager.component_part - ! splicer end class.ResourceManager.component_part - contains - procedure :: get_allocator => resourcemanager_get_allocator - procedure :: copy => resourcemanager_copy - procedure :: deallocate => resourcemanager_deallocate - procedure :: get_instance => resourcemanager_get_instance - procedure :: set_instance => resourcemanager_set_instance - procedure :: associated => resourcemanager_associated - ! splicer begin class.ResourceManager.type_bound_procedure_part - ! splicer end class.ResourceManager.type_bound_procedure_part - end type UmpireResourceManager - - ! splicer begin class.Allocator.module_top - ! splicer end class.Allocator.module_top - - type UmpireAllocator - type(C_PTR), private :: voidptr - ! splicer begin class.Allocator.component_part - ! splicer end class.Allocator.component_part - contains - procedure :: allocate => allocator_allocate - procedure :: deallocate => allocator_deallocate - procedure :: get_instance => allocator_get_instance - procedure :: set_instance => allocator_set_instance - procedure :: associated => allocator_associated - ! splicer begin class.Allocator.type_bound_procedure_part - ! splicer end class.Allocator.type_bound_procedure_part - end type UmpireAllocator - - - interface operator (.eq.) - module procedure resourcemanager_eq - module procedure allocator_eq - end interface - - interface operator (.ne.) - module procedure resourcemanager_ne - module procedure allocator_ne - end interface - - interface - - function c_resourcemanager_get() & - result(SH_rv) & - bind(C, name="UMPIRE_resourcemanager_get") - use iso_c_binding, only : C_PTR - implicit none - type(C_PTR) :: SH_rv - end function c_resourcemanager_get - - function c_resourcemanager_get_allocator(self, space) & - result(SH_rv) & - bind(C, name="UMPIRE_resourcemanager_get_allocator") - use iso_c_binding, only : C_CHAR, C_PTR - implicit none - type(C_PTR), value, intent(IN) :: self - character(kind=C_CHAR), intent(IN) :: space(*) - type(C_PTR) :: SH_rv - end function c_resourcemanager_get_allocator - - function c_resourcemanager_get_allocator_bufferify(self, space, Lspace) & - result(SH_rv) & - bind(C, name="UMPIRE_resourcemanager_get_allocator_bufferify") - use iso_c_binding, only : C_CHAR, C_INT, C_PTR - implicit none - type(C_PTR), value, intent(IN) :: self - character(kind=C_CHAR), intent(IN) :: space(*) - integer(C_INT), value, intent(IN) :: Lspace - type(C_PTR) :: SH_rv - end function c_resourcemanager_get_allocator_bufferify - - subroutine c_resourcemanager_copy(self, src_ptr, dst_ptr) & - bind(C, name="UMPIRE_resourcemanager_copy") - use iso_c_binding, only : C_PTR - implicit none - type(C_PTR), value, intent(IN) :: self - type(C_PTR), value, intent(IN) :: src_ptr - type(C_PTR), value, intent(IN) :: dst_ptr - end subroutine c_resourcemanager_copy - - subroutine c_resourcemanager_deallocate(self, ptr) & - bind(C, name="UMPIRE_resourcemanager_deallocate") - use iso_c_binding, only : C_PTR - implicit none - type(C_PTR), value, intent(IN) :: self - type(C_PTR), value, intent(IN) :: ptr - end subroutine c_resourcemanager_deallocate - - ! splicer begin class.ResourceManager.additional_interfaces - ! splicer end class.ResourceManager.additional_interfaces - - function c_allocator_allocate(self, bytes) & - result(SH_rv) & - bind(C, name="UMPIRE_allocator_allocate") - use iso_c_binding, only : C_PTR, C_SIZE_T - implicit none - type(C_PTR), value, intent(IN) :: self - integer(C_SIZE_T), value, intent(IN) :: bytes - type(C_PTR) :: SH_rv - end function c_allocator_allocate - - subroutine c_allocator_deallocate(self, ptr) & - bind(C, name="UMPIRE_allocator_deallocate") - use iso_c_binding, only : C_PTR - implicit none - type(C_PTR), value, intent(IN) :: self - type(C_PTR), value, intent(IN) :: ptr - end subroutine c_allocator_deallocate - - ! splicer begin class.Allocator.additional_interfaces - ! splicer end class.Allocator.additional_interfaces - end interface - -contains - - function resourcemanager_get() result(SH_rv) - type(UmpireResourceManager) :: SH_rv - ! splicer begin class.ResourceManager.method.get - SH_rv%voidptr = c_resourcemanager_get() - ! splicer end class.ResourceManager.method.get - end function resourcemanager_get - - function resourcemanager_get_allocator(obj, space) result(SH_rv) - use iso_c_binding, only : C_INT - class(UmpireResourceManager) :: obj - character(*), intent(IN) :: space - type(UmpireAllocator) :: SH_rv - ! splicer begin class.ResourceManager.method.get_allocator - SH_rv%voidptr = c_resourcemanager_get_allocator_bufferify( & - obj%voidptr, & - space, & - len_trim(space, kind=C_INT)) - ! splicer end class.ResourceManager.method.get_allocator - end function resourcemanager_get_allocator - - subroutine resourcemanager_copy(obj, src_ptr, dst_ptr) - use iso_c_binding, only : C_PTR - class(UmpireResourceManager) :: obj - type(C_PTR), value, intent(IN) :: src_ptr - type(C_PTR), value, intent(IN) :: dst_ptr - ! splicer begin class.ResourceManager.method.copy - call c_resourcemanager_copy( & - obj%voidptr, & - src_ptr, & - dst_ptr) - ! splicer end class.ResourceManager.method.copy - end subroutine resourcemanager_copy - - subroutine resourcemanager_deallocate(obj, ptr) - use iso_c_binding, only : C_PTR - class(UmpireResourceManager) :: obj - type(C_PTR), value, intent(IN) :: ptr - ! splicer begin class.ResourceManager.method.deallocate - call c_resourcemanager_deallocate( & - obj%voidptr, & - ptr) - ! splicer end class.ResourceManager.method.deallocate - end subroutine resourcemanager_deallocate - - function resourcemanager_get_instance(obj) result (voidptr) - use iso_c_binding, only: C_PTR - implicit none - class(UmpireResourceManager), intent(IN) :: obj - type(C_PTR) :: voidptr - voidptr = obj%voidptr - end function resourcemanager_get_instance - - subroutine resourcemanager_set_instance(obj, voidptr) - use iso_c_binding, only: C_PTR - implicit none - class(UmpireResourceManager), intent(INOUT) :: obj - type(C_PTR), intent(IN) :: voidptr - obj%voidptr = voidptr - end subroutine resourcemanager_set_instance - - function resourcemanager_associated(obj) result (rv) - use iso_c_binding, only: c_associated - implicit none - class(UmpireResourceManager), intent(IN) :: obj - logical rv - rv = c_associated(obj%voidptr) - end function resourcemanager_associated - - ! splicer begin class.ResourceManager.additional_functions - ! splicer end class.ResourceManager.additional_functions - - function allocator_allocate(obj, bytes) result(SH_rv) - use iso_c_binding, only : C_PTR, C_SIZE_T - class(UmpireAllocator) :: obj - integer(C_SIZE_T), value, intent(IN) :: bytes - type(C_PTR) :: SH_rv - ! splicer begin class.Allocator.method.allocate - SH_rv = c_allocator_allocate( & - obj%voidptr, & - bytes) - ! splicer end class.Allocator.method.allocate - end function allocator_allocate - - subroutine allocator_deallocate(obj, ptr) - use iso_c_binding, only : C_PTR - class(UmpireAllocator) :: obj - type(C_PTR), value, intent(IN) :: ptr - ! splicer begin class.Allocator.method.deallocate - call c_allocator_deallocate( & - obj%voidptr, & - ptr) - ! splicer end class.Allocator.method.deallocate - end subroutine allocator_deallocate - - function allocator_get_instance(obj) result (voidptr) - use iso_c_binding, only: C_PTR - implicit none - class(UmpireAllocator), intent(IN) :: obj - type(C_PTR) :: voidptr - voidptr = obj%voidptr - end function allocator_get_instance - - subroutine allocator_set_instance(obj, voidptr) - use iso_c_binding, only: C_PTR - implicit none - class(UmpireAllocator), intent(INOUT) :: obj - type(C_PTR), intent(IN) :: voidptr - obj%voidptr = voidptr - end subroutine allocator_set_instance - - function allocator_associated(obj) result (rv) - use iso_c_binding, only: c_associated - implicit none - class(UmpireAllocator), intent(IN) :: obj - logical rv - rv = c_associated(obj%voidptr) - end function allocator_associated - - ! splicer begin class.Allocator.additional_functions - ! splicer end class.Allocator.additional_functions - - function resourcemanager_eq(a,b) result (rv) - use iso_c_binding, only: c_associated - implicit none - type(UmpireResourceManager), intent(IN) ::a,b - logical :: rv - if (c_associated(a%voidptr, b%voidptr)) then - rv = .true. - else - rv = .false. - endif - end function resourcemanager_eq - - function resourcemanager_ne(a,b) result (rv) - use iso_c_binding, only: c_associated - implicit none - type(UmpireResourceManager), intent(IN) ::a,b - logical :: rv - if (.not. c_associated(a%voidptr, b%voidptr)) then - rv = .true. - else - rv = .false. - endif - end function resourcemanager_ne - - function allocator_eq(a,b) result (rv) - use iso_c_binding, only: c_associated - implicit none - type(UmpireAllocator), intent(IN) ::a,b - logical :: rv - if (c_associated(a%voidptr, b%voidptr)) then - rv = .true. - else - rv = .false. - endif - end function allocator_eq - - function allocator_ne(a,b) result (rv) - use iso_c_binding, only: c_associated - implicit none - type(UmpireAllocator), intent(IN) ::a,b - logical :: rv - if (.not. c_associated(a%voidptr, b%voidptr)) then - rv = .true. - else - rv = .false. - endif - end function allocator_ne - -end module umpire_mod diff --git a/src/umpire/interface/umpire.h b/src/umpire/interface/umpire.h index 184cc3923..351671ee4 100644 --- a/src/umpire/interface/umpire.h +++ b/src/umpire/interface/umpire.h @@ -18,7 +18,6 @@ #include "umpire/interface/c_fortran/shroudrt.hpp" #include "umpire/interface/c_fortran/wrapAllocator.h" - #include "umpire/interface/c_fortran/wrapResourceManager.h" #endif // UMPIRE_H_ diff --git a/src/umpire/interface/umpire_shroud.yaml b/src/umpire/interface/umpire_shroud.yaml index c6ccebc79..9c5a39a2a 100644 --- a/src/umpire/interface/umpire_shroud.yaml +++ b/src/umpire/interface/umpire_shroud.yaml @@ -13,6 +13,21 @@ # Please also see the LICENSE file for MIT license. ############################################################################## +copyright: + - Copyright (c) 2018, Lawrence Livermore National Security, LLC. + - Produced at the Lawrence Livermore National Laboratory + - + - Created by David Beckingsale, david@llnl.gov + - LLNL-CODE-747640 + - + - All rights reserved. + - + - This file is part of Umpire. + - + - For details, see https://github.com/LLNL/Umpire + - Please also see the LICENSE file for MIT license. + + library: Umpire options: @@ -24,6 +39,9 @@ format: declarations: - decl: namespace umpire declarations: + - decl: namespace strategy + declarations: + - decl: class DynamicPool - decl: class Allocator cxx_header: umpire/Allocator.hpp @@ -33,18 +51,65 @@ declarations: declarations: - decl: void* allocate(size_t bytes) - decl: void deallocate (void* ptr) + - decl: size_t getSize(void* ptr) + - decl: size_t getHighWatermark() + - decl: size_t getCurrentSize() + - decl: std::string getName() + - decl: size_t getId() - decl: class ResourceManager cxx_header: umpire/ResourceManager.hpp format: F_derived_name: UmpireResourceManager + F_name_instance_set: + F_name_instance_get: declarations: - - decl: ResourceManager& get() +constructor + - decl: static ResourceManager& getInstance() + + - decl: Allocator getAllocator(const std::string& name) format: - C_code: auto& SH_rv = ResourceManager::getInstance(); - return static_cast(static_cast(&SH_rv)); + function_suffix: _by_name + + - decl: Allocator getAllocator(const int id) + format: + function_suffix: _by_id + + - decl: Allocator getAllocator(void* ptr) + format: + function_suffix: for_ptr + + # - decl: void registerAllocator(const std::string& name, Allocator allocator) + + - decl: void copy(void* src_ptr, void* dst_ptr, size_t size=0) + default_arg_suffix: + - _all + - _with_size + + - decl: void memset(void* ptr, int val, size_t length=0) + default_arg_suffix: + - _all + - _with_size + + - decl: void* reallocate(void* src_ptr, size_t size) + + #- decl: void* reallocate(void* src_ptr, size_t size, Allocator allocator) + # format: + # function_suffix: _with_allocator - - decl: Allocator * getAllocator(const std::string& resource) - - decl: void copy(void* src_ptr, void* dst_ptr) - decl: void deallocate(void* ptr) + + - decl: size_t getSize(void* ptr) + + # - decl: template Allocator makeAllocator(const std::string& name); + # cxx_template: + # - instantiation: + +splicer_code: + c: + class: + Allocator: + CXX_declarations: + - "#ifdef __cplusplus" + - "#include " + - "#endif" diff --git a/src/umpire/interface/yaml/umpire_types.yaml b/src/umpire/interface/yaml/umpire_types.yaml index d59c0b6dc..9c3f764fc 100644 --- a/src/umpire/interface/yaml/umpire_types.yaml +++ b/src/umpire/interface/yaml/umpire_types.yaml @@ -1,4 +1,5 @@ -############################################################################## +# umpire_types.yaml +# This is generated code, do not edit # Copyright (c) 2018, Lawrence Livermore National Security, LLC. # Produced at the Lawrence Livermore National Laboratory # @@ -11,28 +12,38 @@ # # For details, see https://github.com/LLNL/Umpire # Please also see the LICENSE file for MIT license. -############################################################################## -# umpire_types.yaml -# This is generated code, do not edit -# Types generated by Shroud for class Umpire -types: - - ResourceManager: - base: wrapped - cpp_type: ResourceManager - c_type: UMPIRE_resourcemanager - f_derived_type: UmpireResourceManager - f_to_c: "{f_var}%get_instance()" - f_module: - umpire_mod: - - resourcemanager - - Allocator: - base: wrapped - cpp_type: Allocator - c_type: UMPIRE_allocator - f_derived_type: UmpireAllocator - f_to_c: "{f_var}%get_instance()" - f_module: - umpire_mod: - - allocator +# Types generated by Shroud for library Umpire +declarations: + - namespace: umpire + declarations: umpire + - type: Allocator + fields: + base: shadow + cxx_header: umpire/Allocator.hpp + cxx_type: umpire::Allocator + c_type: umpire_allocator + f_module_name: umpire_mod + f_derived_type: UmpireAllocator + f_capsule_data_type: SHROUD_allocator_capsule + f_to_c: "{f_var}%cxxmem" + - type: ResourceManager + fields: + base: shadow + cxx_header: umpire/ResourceManager.hpp + cxx_type: umpire::ResourceManager + c_type: umpire_resourcemanager + f_module_name: umpire_mod + f_derived_type: UmpireResourceManager + f_capsule_data_type: SHROUD_resourcemanager_capsule + f_to_c: "{f_var}%cxxmem" + - namespace: strategy + declarations: strategy + - type: DynamicPool + fields: + base: shadow + cxx_type: umpire::strategy::DynamicPool + c_type: umpire_dynamicpool + f_module_name: umpire_mod + f_derived_type: dynamicpool + f_capsule_data_type: SHROUD_dynamicpool_capsule + f_to_c: "{f_var}%cxxmem" diff --git a/src/umpire/op/CMakeLists.txt b/src/umpire/op/CMakeLists.txt index 5fbfe5aa0..3c2e71566 100644 --- a/src/umpire/op/CMakeLists.txt +++ b/src/umpire/op/CMakeLists.txt @@ -20,6 +20,17 @@ set (umpire_op_headers MemoryOperation.hpp MemoryOperationRegistry.hpp) +set (umpire_op_sources + GenericReallocateOperation.cpp + HostCopyOperation.cpp + HostMemsetOperation.cpp + HostReallocateOperation.cpp + MemoryOperation.cpp + MemoryOperationRegistry.cpp) + +set (umpire_op_depends + umpire_util) + if (ENABLE_CUDA) set (umpire_op_headers ${umpire_op_headers} @@ -30,17 +41,7 @@ if (ENABLE_CUDA) CudaCopyFromOperation.hpp CudaCopyToOperation.hpp CudaMemsetOperation.hpp) -endif () -set (umpire_op_sources - GenericReallocateOperation.cpp - HostCopyOperation.cpp - HostMemsetOperation.cpp - HostReallocateOperation.cpp - MemoryOperation.cpp - MemoryOperationRegistry.cpp) - -if (ENABLE_CUDA) set (umpire_op_sources ${umpire_op_sources} CudaAdviseAccessedByOperation.cpp @@ -50,17 +51,29 @@ if (ENABLE_CUDA) CudaCopyFromOperation.cpp CudaCopyToOperation.cpp CudaMemsetOperation.cpp) + + set (umpire_op_depends + ${umpire_op_depends} + cuda_runtime) endif () -set (umpire_op_depends - umpire_util) +if (ENABLE_ROCM) + set (umpire_op_headers + ${umpire_op_headers} + RocmCopyOperation.hpp + RocmMemsetOperation.hpp) + + set (umpire_op_sources + ${umpire_op_sources} + RocmCopyOperation.cpp + RocmMemsetOperation.cpp) -if (ENABLE_CUDA) set (umpire_op_depends ${umpire_op_depends} - cuda_runtime) + rocm) endif () + blt_add_library( NAME umpire_op HEADERS ${umpire_op_headers} diff --git a/src/umpire/op/HostReallocateOperation.hpp b/src/umpire/op/HostReallocateOperation.hpp index dfd474f42..501b886bb 100644 --- a/src/umpire/op/HostReallocateOperation.hpp +++ b/src/umpire/op/HostReallocateOperation.hpp @@ -23,7 +23,7 @@ namespace op { /*! * \brief Reallocate data in CPU memory. */ -class HostReallocateOperation : +class HostReallocateOperation : public MemoryOperation { public: /*! @@ -45,4 +45,3 @@ class HostReallocateOperation : } // end of namespace umpire #endif // UMPIRE_HostReallocateOperation_HPP - diff --git a/src/umpire/op/MemoryOperationRegistry.cpp b/src/umpire/op/MemoryOperationRegistry.cpp index 06e422d8d..0cba92d18 100644 --- a/src/umpire/op/MemoryOperationRegistry.cpp +++ b/src/umpire/op/MemoryOperationRegistry.cpp @@ -34,6 +34,11 @@ #include "umpire/op/CudaAdviseReadMostlyOperation.hpp" #endif +#if defined(UMPIRE_ENABLE_ROCM) +#include "umpire/op/RocmCopyOperation.hpp" +#include "umpire/op/RocmMemsetOperation.hpp" +#endif + #include "umpire/util/Macros.hpp" namespace umpire { @@ -43,7 +48,7 @@ MemoryOperationRegistry* MemoryOperationRegistry::s_memory_operation_registry_instance = nullptr; MemoryOperationRegistry& -MemoryOperationRegistry::getInstance() +MemoryOperationRegistry::getInstance() noexcept { if (!s_memory_operation_registry_instance) { s_memory_operation_registry_instance = new MemoryOperationRegistry(); @@ -53,7 +58,7 @@ MemoryOperationRegistry::getInstance() return *s_memory_operation_registry_instance; } -MemoryOperationRegistry::MemoryOperationRegistry() +MemoryOperationRegistry::MemoryOperationRegistry() noexcept { registerOperation( "COPY", @@ -117,13 +122,40 @@ MemoryOperationRegistry::MemoryOperationRegistry() std::make_shared()); #endif + +#if defined(UMPIRE_ENABLE_ROCM) + registerOperation( + "COPY", + std::make_pair(Platform::rocm, Platform::cpu), + std::make_shared()); + + registerOperation( + "COPY", + std::make_pair(Platform::cpu, Platform::rocm), + std::make_shared()); + + registerOperation( + "COPY", + std::make_pair(Platform::rocm, Platform::rocm), + std::make_shared()); + + registerOperation( + "MEMSET", + std::make_pair(Platform::rocm, Platform::rocm), + std::make_shared()); + + registerOperation( + "REALLOCATE", + std::make_pair(Platform::rocm, Platform::rocm), + std::make_shared()); +#endif } void MemoryOperationRegistry::registerOperation( const std::string& name, std::pair platforms, - std::shared_ptr&& operation) + std::shared_ptr&& operation) noexcept { auto operations = m_operators.find(name); @@ -150,7 +182,7 @@ MemoryOperationRegistry::find( auto operations = m_operators.find(name); if (operations == m_operators.end()) { - UMPIRE_ERROR("Cannot find operator " << name); + UMPIRE_ERROR("Cannot find operator " << name); } auto op = operations->second.find(platforms); diff --git a/src/umpire/op/MemoryOperationRegistry.hpp b/src/umpire/op/MemoryOperationRegistry.hpp index 4698d34f9..4682ea861 100644 --- a/src/umpire/op/MemoryOperationRegistry.hpp +++ b/src/umpire/op/MemoryOperationRegistry.hpp @@ -28,7 +28,7 @@ namespace umpire { namespace op { struct pair_hash { - std::size_t operator () (const std::pair &p) const { + std::size_t operator () (const std::pair &p) const noexcept { auto h1 = std::hash{}(static_cast(p.first)); auto h2 = std::hash{}(static_cast(p.second)); @@ -64,7 +64,7 @@ class MemoryOperationRegistry { /*! * \brief Get the MemoryOperationRegistry singleton instance. */ - static MemoryOperationRegistry& getInstance(); + static MemoryOperationRegistry& getInstance() noexcept; /*! * \brief Function to find a MemoryOperation object @@ -98,10 +98,10 @@ class MemoryOperationRegistry { void registerOperation( const std::string& name, std::pair platforms, - std::shared_ptr&& operation); + std::shared_ptr&& operation) noexcept; protected: - MemoryOperationRegistry(); + MemoryOperationRegistry() noexcept; MemoryOperationRegistry (const MemoryOperationRegistry&) = delete; MemoryOperationRegistry& operator= (const MemoryOperationRegistry&) = delete; @@ -114,8 +114,8 @@ class MemoryOperationRegistry { */ std::unordered_map< std::string, - std::unordered_map< std::pair, - std::shared_ptr, + std::unordered_map< std::pair, + std::shared_ptr, pair_hash > > m_operators; }; diff --git a/src/umpire/op/RocmCopyOperation.cpp b/src/umpire/op/RocmCopyOperation.cpp new file mode 100644 index 000000000..e6a100cea --- /dev/null +++ b/src/umpire/op/RocmCopyOperation.cpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "umpire/op/RocmCopyOperation.hpp" + +#include + +#include "umpire/util/Macros.hpp" + +namespace umpire { +namespace op { + +void RocmCopyOperation::transform( + void* src_ptr, + void** dst_ptr, + umpire::util::AllocationRecord* UMPIRE_UNUSED_ARG(src_allocation), + umpire::util::AllocationRecord* UMPIRE_UNUSED_ARG(dst_allocation), + size_t length) +{ + hc::accelerator acc; + hc::accelerator_view av = acc.get_default_view(); + + av.copy(src_ptr, *dst_ptr, length); + + av.wait(); + + UMPIRE_RECORD_STATISTIC( + "RocmCopyOperation", + "src_ptr", reinterpret_cast(src_ptr), + "dst_ptr", reinterpret_cast(dst_ptr), + "size", length, + "event", "copy"); +} + +} // end of namespace op +} // end of namespace umpire diff --git a/src/umpire/op/RocmCopyOperation.hpp b/src/umpire/op/RocmCopyOperation.hpp new file mode 100644 index 000000000..00310bb69 --- /dev/null +++ b/src/umpire/op/RocmCopyOperation.hpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_RocmCopyOperation_HPP +#define UMPIRE_RocmCopyOperation_HPP + +#include "umpire/op/MemoryOperation.hpp" + +namespace umpire { +namespace op { + +/*! + * \brief Copy operation to move data between two GPU addresses. + */ +class RocmCopyOperation : public MemoryOperation { + public: + /*! + * @copybrief MemoryOperation::transform + * + * Uses hc::accelerator_view::copy to move data when either src_ptr and + * dst_ptr are on AMD GPUs. + * + * @copydetails MemoryOperation::transform + */ + void transform( + void* src_ptr, + void** dst_ptr, + umpire::util::AllocationRecord *src_allocation, + umpire::util::AllocationRecord *dst_allocation, + size_t length); +}; + +} // end of namespace op +} // end of namespace umpire + +#endif // UMPIRE_RocmCopyOperation_HPP diff --git a/src/umpire/op/RocmMemsetOperation.cpp b/src/umpire/op/RocmMemsetOperation.cpp new file mode 100644 index 000000000..5e422b66a --- /dev/null +++ b/src/umpire/op/RocmMemsetOperation.cpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "umpire/op/RocmMemsetOperation.hpp" + + +#include + +#include "umpire/util/Macros.hpp" + +namespace umpire { +namespace op { + +void +RocmMemsetOperation::apply( + void* src_ptr, + util::AllocationRecord* UMPIRE_UNUSED_ARG(allocation), + int value, + size_t length) +{ + unsigned char * cptr = static_cast(src_ptr); + uint32_t * wptr = static_cast(src_ptr); + + char c = static_cast(value); + + uint32_t fill = + static_cast(value + + (static_cast(value)<<8) + + (static_cast(value)<<16) + + (static_cast(value)<<24)); + + int n = length/4; + int r = length - n*4; + + if(n+r) { + hc::extent<1> e(n + (r ? r : 0)); + + hc::parallel_for_each(e, [=] (hc::index<1> idx) [[hc]] { + if(idx[0] < n) { + wptr[idx[0]] = fill; + } + if(r) { + if(idx[0] < r) { + cptr[n*4+idx[0]] = value; + } + } + }).wait(); + } + + + UMPIRE_RECORD_STATISTIC( + "RocmMemsetOperation", + "src_ptr", reinterpret_cast(src_ptr), + "value", value, + "size", length, + "event", "memset"); +} + +} // end of namespace op +} // end of namespace umpire diff --git a/src/umpire/op/RocmMemsetOperation.hpp b/src/umpire/op/RocmMemsetOperation.hpp new file mode 100644 index 000000000..00a81b0f5 --- /dev/null +++ b/src/umpire/op/RocmMemsetOperation.hpp @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_RocmMemsetOperation_HPP +#define UMPIRE_RocmMemsetOperation_HPP + +#include "umpire/op/MemoryOperation.hpp" + +namespace umpire { +namespace op { + +/*! + * \brief Memset an allocation in CPU memory. + */ +class RocmMemsetOperation : public MemoryOperation { + public: + /*! + * \copybrief MemoryOperation::apply + * + * Uses std::memset to set the first length bytes of src_ptr to value. + * + * \copydetails MemoryOperation::apply + */ + void apply( + void* src_ptr, + util::AllocationRecord* allocation, + int value, + size_t length); +}; + +} // end of namespace op +} // end of namespace umpire + +#endif // UMPIRE_RocmMemsetOperation_HPP diff --git a/src/umpire/resource/CMakeLists.txt b/src/umpire/resource/CMakeLists.txt index 183c655de..128bb1ef8 100644 --- a/src/umpire/resource/CMakeLists.txt +++ b/src/umpire/resource/CMakeLists.txt @@ -20,6 +20,7 @@ set (umpire_resource_headers MemoryResourceFactory.hpp MemoryResourceRegistry.hpp MemoryResourceTypes.hpp + MemoryResourceTraits.hpp ) set (umpire_resource_sources @@ -34,25 +35,47 @@ set (umpire_resource_depends if (ENABLE_CUDA) set (umpire_resource_headers ${umpire_resource_headers} - DeviceConstResourceFactory.hpp - ConstantMemoryResource.hpp - DeviceResourceFactory.hpp - PinnedMemoryResourceFactory.hpp - UnifiedMemoryResourceFactory.hpp) + CudaDeviceResourceFactory.hpp + CudaPinnedMemoryResourceFactory.hpp + CudaUnifiedMemoryResourceFactory.hpp + + CudaConstantMemoryResourceFactory.hpp + CudaConstantMemoryResource.hpp + ) set (umpire_resource_sources ${umpire_resource_sources} - DeviceConstResourceFactory.cpp - ConstantMemoryResource.cu - DeviceResourceFactory.cpp - PinnedMemoryResourceFactory.cpp - UnifiedMemoryResourceFactory.cpp) + + + CudaConstantMemoryResourceFactory.cpp + CudaConstantMemoryResource.cu + + CudaDeviceResourceFactory.cpp + CudaPinnedMemoryResourceFactory.cpp + CudaUnifiedMemoryResourceFactory.cpp) + set(umpire_resource_depends ${umpire_resource_depends} cuda_runtime) endif () +if (ENABLE_ROCM) + set (umpire_resource_headers + ${umpire_resource_headers} + RocmDeviceResourceFactory.hpp + RocmPinnedMemoryResourceFactory.hpp) + + set (umpire_resource_sources + ${umpire_resource_sources} + RocmDeviceResourceFactory.cpp + RocmPinnedMemoryResourceFactory.cpp) + + set (umpire_resource_depends + ${umpire_resource_depends} + rocm) +endif () + blt_add_library( NAME umpire_resource HEADERS ${umpire_resource_headers} diff --git a/src/umpire/resource/ConstantMemoryResource.cu b/src/umpire/resource/CudaConstantMemoryResource.cu similarity index 74% rename from src/umpire/resource/ConstantMemoryResource.cu rename to src/umpire/resource/CudaConstantMemoryResource.cu index d5e10d212..c688b926a 100644 --- a/src/umpire/resource/ConstantMemoryResource.cu +++ b/src/umpire/resource/CudaConstantMemoryResource.cu @@ -13,7 +13,7 @@ // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#include "umpire/resource/ConstantMemoryResource.hpp" +#include "umpire/resource/CudaConstantMemoryResource.hpp" #include "umpire/ResourceManager.hpp" #include "umpire/util/Macros.hpp" @@ -24,8 +24,8 @@ namespace umpire { namespace resource { -ConstantMemoryResource::ConstantMemoryResource(const std::string& name, int id) : - MemoryResource(name, id), +CudaConstantMemoryResource::CudaConstantMemoryResource(const std::string& name, int id, MemoryResourceTraits traits) : + MemoryResource(name, id, traits), m_current_size(0l), m_highwatermark(0l), m_platform(Platform::cuda), @@ -33,9 +33,13 @@ ConstantMemoryResource::ConstantMemoryResource(const std::string& name, int id) m_ptr(nullptr) { cudaError_t error = ::cudaGetSymbolAddress((void**)&m_ptr, umpire_internal_device_constant_memory); + + if (error != cudaSuccess) { + UMPIRE_ERROR("cudaGetSymbolAddress failed with error: " << cudaGetErrorString(error)); + } } -void* ConstantMemoryResource::allocate(size_t bytes) +void* CudaConstantMemoryResource::allocate(size_t bytes) { char* ptr = static_cast(m_ptr) + m_offset; m_offset += bytes; @@ -59,36 +63,36 @@ void* ConstantMemoryResource::allocate(size_t bytes) return ret; } -void ConstantMemoryResource::deallocate(void* ptr) +void CudaConstantMemoryResource::deallocate(void* ptr) { UMPIRE_LOG(Debug, "(ptr=" << ptr << ")"); util::AllocationRecord* record = ResourceManager::getInstance().deregisterAllocation(ptr); m_current_size -= record->m_size; - if ( (static_cast(m_ptr) + (m_offset - record->m_size)) + if ( (static_cast(m_ptr) + (m_offset - record->m_size)) == static_cast(ptr)) { m_offset -= record->m_size; } else { - UMPIRE_ERROR("ConstantMemory deallocations must be in reverse order"); + UMPIRE_ERROR("CudaConstantMemory deallocations must be in reverse order"); } delete record; } -long ConstantMemoryResource::getCurrentSize() +long CudaConstantMemoryResource::getCurrentSize() noexcept { UMPIRE_LOG(Debug, "() returning " << m_current_size); return m_current_size; } -long ConstantMemoryResource::getHighWatermark() +long CudaConstantMemoryResource::getHighWatermark() noexcept { UMPIRE_LOG(Debug, "() returning " << m_highwatermark); return m_highwatermark; } -Platform ConstantMemoryResource::getPlatform() +Platform CudaConstantMemoryResource::getPlatform() noexcept { return m_platform; } diff --git a/src/umpire/resource/ConstantMemoryResource.hpp b/src/umpire/resource/CudaConstantMemoryResource.hpp similarity index 72% rename from src/umpire/resource/ConstantMemoryResource.hpp rename to src/umpire/resource/CudaConstantMemoryResource.hpp index 6e2c06039..f3e066873 100644 --- a/src/umpire/resource/ConstantMemoryResource.hpp +++ b/src/umpire/resource/CudaConstantMemoryResource.hpp @@ -12,8 +12,8 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#ifndef UMPIRE_ConstantMemoryResource_HPP -#define UMPIRE_ConstantMemoryResource_HPP +#ifndef UMPIRE_CudaConstantMemoryResource_HPP +#define UMPIRE_CudaConstantMemoryResource_HPP #include "umpire/resource/MemoryResource.hpp" @@ -28,21 +28,21 @@ namespace umpire { namespace resource { -class ConstantMemoryResource : +class CudaConstantMemoryResource : public MemoryResource { - public: - ConstantMemoryResource(const std::string& name, int id); + public: + CudaConstantMemoryResource(const std::string& name, int id, MemoryResourceTraits traits); void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; - private: + private: long m_current_size; long m_highwatermark; @@ -55,4 +55,4 @@ class ConstantMemoryResource : } // end of namespace resource } // end of namespace umpire -#endif // UMPIRE_ConstantMemoryResource_HPP +#endif // UMPIRE_CudaConstantMemoryResource_HPP diff --git a/src/umpire/resource/DeviceConstResourceFactory.cpp b/src/umpire/resource/CudaConstantMemoryResourceFactory.cpp similarity index 54% rename from src/umpire/resource/DeviceConstResourceFactory.cpp rename to src/umpire/resource/CudaConstantMemoryResourceFactory.cpp index 0737e24ff..34c8a4a7e 100644 --- a/src/umpire/resource/DeviceConstResourceFactory.cpp +++ b/src/umpire/resource/CudaConstantMemoryResourceFactory.cpp @@ -12,9 +12,9 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#include "umpire/resource/DeviceConstResourceFactory.hpp" +#include "umpire/resource/CudaConstantMemoryResourceFactory.hpp" -#include "umpire/resource/ConstantMemoryResource.hpp" +#include "umpire/resource/CudaConstantMemoryResource.hpp" #include "umpire/util/Macros.hpp" @@ -22,7 +22,8 @@ namespace umpire { namespace resource { bool -DeviceConstResourceFactory::isValidMemoryResourceFor(const std::string& name) +CudaConstantMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept { if (name.compare("DEVICE_CONST") == 0) { return true; @@ -32,9 +33,19 @@ DeviceConstResourceFactory::isValidMemoryResourceFor(const std::string& name) } std::shared_ptr -DeviceConstResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +CudaConstantMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) { - return std::make_shared("DEVICE_CONST", id); + MemoryResourceTraits traits; + + traits.unified = false; + traits.size = 64*1024; + + traits.vendor = MemoryResourceTraits::vendor_type::NVIDIA; + traits.kind = MemoryResourceTraits::memory_type::GDDR; + + traits.used_for = MemoryResourceTraits::optimized_for::any; + + return std::make_shared("DEVICE_CONST", id, traits); } } // end of namespace resource diff --git a/src/umpire/resource/CudaConstantMemoryResourceFactory.hpp b/src/umpire/resource/CudaConstantMemoryResourceFactory.hpp new file mode 100644 index 000000000..32ec9098f --- /dev/null +++ b/src/umpire/resource/CudaConstantMemoryResourceFactory.hpp @@ -0,0 +1,38 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_CudaConstantMemoryResourceFactory_HPP +#define UMPIRE_CudaConstantMemoryResourceFactory_HPP + +#include "umpire/resource/MemoryResourceFactory.hpp" + +namespace umpire { +namespace resource { + +/*! + * \brief Factory class for constructing MemoryResource objects that use GPU + * memory. + */ +class CudaConstantMemoryResourceFactory : + public MemoryResourceFactory +{ + bool isValidMemoryResourceFor(const std::string& name) noexcept; + + std::shared_ptr create(const std::string& name, int id); +}; + +} // end of namespace resource +} // end of namespace umpire + +#endif // UMPIRE_CudaConstantMemoryResourceFactory_HPP diff --git a/src/umpire/resource/CudaDeviceResourceFactory.cpp b/src/umpire/resource/CudaDeviceResourceFactory.cpp new file mode 100644 index 000000000..21dc4263c --- /dev/null +++ b/src/umpire/resource/CudaDeviceResourceFactory.cpp @@ -0,0 +1,59 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "umpire/resource/CudaDeviceResourceFactory.hpp" + +#include "umpire/resource/DefaultMemoryResource.hpp" +#include "umpire/alloc/CudaMallocAllocator.hpp" + +#include + +namespace umpire { +namespace resource { + +bool +CudaDeviceResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept +{ + if (name.compare("DEVICE") == 0) { + return true; + } else { + return false; + } +} + +std::shared_ptr +CudaDeviceResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +{ + MemoryResourceTraits traits; + + cudaDeviceProp properties; + auto error = ::cudaGetDeviceProperties(&properties, 0); + + if (error != cudaSuccess) { + UMPIRE_ERROR("cudaGetDeviceProperties failed with error: " << cudaGetErrorString(error)); + } + + traits.unified = false; + traits.size = properties.totalGlobalMem; + + traits.vendor = MemoryResourceTraits::vendor_type::NVIDIA; + traits.kind = MemoryResourceTraits::memory_type::GDDR; + traits.used_for = MemoryResourceTraits::optimized_for::any; + + return std::make_shared >(Platform::cuda, "DEVICE", id, traits); +} + +} // end of namespace resource +} // end of namespace umpire diff --git a/src/umpire/resource/DeviceResourceFactory.hpp b/src/umpire/resource/CudaDeviceResourceFactory.hpp similarity index 78% rename from src/umpire/resource/DeviceResourceFactory.hpp rename to src/umpire/resource/CudaDeviceResourceFactory.hpp index 816ea64ae..9f393c1e0 100644 --- a/src/umpire/resource/DeviceResourceFactory.hpp +++ b/src/umpire/resource/CudaDeviceResourceFactory.hpp @@ -12,8 +12,8 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#ifndef UMPIRE_DeviceResourceFactory_HPP -#define UMPIRE_DeviceResourceFactory_HPP +#ifndef UMPIRE_CudaDeviceResourceFactory_HPP +#define UMPIRE_CudaDeviceResourceFactory_HPP #include "umpire/resource/MemoryResourceFactory.hpp" @@ -25,10 +25,10 @@ namespace resource { * \brief Factory class for constructing MemoryResource objects that use GPU * memory. */ -class DeviceResourceFactory : +class CudaDeviceResourceFactory : public MemoryResourceFactory { - bool isValidMemoryResourceFor(const std::string& name); + bool isValidMemoryResourceFor(const std::string& name) noexcept; std::shared_ptr create(const std::string& name, int id); }; @@ -36,4 +36,4 @@ class DeviceResourceFactory : } // end of namespace resource } // end of namespace umpire -#endif // UMPIRE_DeviceResourceFactory_HPP +#endif // UMPIRE_CudaDeviceResourceFactory_HPP diff --git a/src/umpire/resource/PinnedMemoryResourceFactory.cpp b/src/umpire/resource/CudaPinnedMemoryResourceFactory.cpp similarity index 60% rename from src/umpire/resource/PinnedMemoryResourceFactory.cpp rename to src/umpire/resource/CudaPinnedMemoryResourceFactory.cpp index c6aecbe63..d20e9f2e8 100644 --- a/src/umpire/resource/PinnedMemoryResourceFactory.cpp +++ b/src/umpire/resource/CudaPinnedMemoryResourceFactory.cpp @@ -12,7 +12,7 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#include "umpire/resource/PinnedMemoryResourceFactory.hpp" +#include "umpire/resource/CudaPinnedMemoryResourceFactory.hpp" #include "umpire/resource/DefaultMemoryResource.hpp" @@ -22,7 +22,8 @@ namespace umpire { namespace resource { bool -PinnedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) +CudaPinnedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept { if (name.compare("PINNED") == 0) { return true; @@ -32,9 +33,18 @@ PinnedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) } std::shared_ptr -PinnedMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +CudaPinnedMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) { - return std::make_shared >(Platform::cuda, "PINNED", id); + MemoryResourceTraits traits; + + traits.unified = false; + traits.size = 0; // size of system memory? + + traits.vendor = MemoryResourceTraits::vendor_type::NVIDIA; + traits.kind = MemoryResourceTraits::memory_type::DDR; + traits.used_for = MemoryResourceTraits::optimized_for::access; + + return std::make_shared >(Platform::cuda, "PINNED", id, traits); } } // end of namespace resource diff --git a/src/umpire/resource/PinnedMemoryResourceFactory.hpp b/src/umpire/resource/CudaPinnedMemoryResourceFactory.hpp similarity index 75% rename from src/umpire/resource/PinnedMemoryResourceFactory.hpp rename to src/umpire/resource/CudaPinnedMemoryResourceFactory.hpp index f2c5925d8..d2bb69653 100644 --- a/src/umpire/resource/PinnedMemoryResourceFactory.hpp +++ b/src/umpire/resource/CudaPinnedMemoryResourceFactory.hpp @@ -12,22 +12,22 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#ifndef UMPIRE_PinnedMemoryResourceFactory_HPP -#define UMPIRE_PinnedMemoryResourceFactory_HPP +#ifndef UMPIRE_CudaPinnedMemoryResourceFactory_HPP +#define UMPIRE_CudaPinnedMemoryResourceFactory_HPP #include "umpire/resource/MemoryResourceFactory.hpp" namespace umpire { namespace resource { -class PinnedMemoryResourceFactory : +class CudaPinnedMemoryResourceFactory : public MemoryResourceFactory { - bool isValidMemoryResourceFor(const std::string& name); + bool isValidMemoryResourceFor(const std::string& name) noexcept; std::shared_ptr create(const std::string& name, int id); }; } // end of namespace resource } // end of namespace umpire -#endif // UMPIRE_PinnedMemoryResourceFactory_HPP +#endif // UMPIRE_CudaPinnedMemoryResourceFactory_HPP diff --git a/src/umpire/resource/CudaUnifiedMemoryResourceFactory.cpp b/src/umpire/resource/CudaUnifiedMemoryResourceFactory.cpp new file mode 100644 index 000000000..7dddff86f --- /dev/null +++ b/src/umpire/resource/CudaUnifiedMemoryResourceFactory.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "umpire/resource/CudaUnifiedMemoryResourceFactory.hpp" + +#include "umpire/resource/DefaultMemoryResource.hpp" + +#include "umpire/alloc/CudaMallocManagedAllocator.hpp" + +#include + +namespace umpire { +namespace resource { + +bool +CudaUnifiedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept +{ + if (name.compare("UM") == 0) { + return true; + } else { + return false; + } +} + +std::shared_ptr +CudaUnifiedMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +{ + MemoryResourceTraits traits; + + cudaDeviceProp properties; + auto error = ::cudaGetDeviceProperties(&properties, 0); + + if (error != cudaSuccess) { + UMPIRE_ERROR("cudaGetDeviceProperties failed with error: " << cudaGetErrorString(error)); + } + + traits.unified = true; + traits.size = properties.totalGlobalMem; // plus system size? + + traits.vendor = MemoryResourceTraits::vendor_type::NVIDIA; + traits.kind = MemoryResourceTraits::memory_type::GDDR; + traits.used_for = MemoryResourceTraits::optimized_for::any; + + return std::make_shared >(Platform::cuda, "UM", id, traits); +} + +} // end of namespace resource +} // end of namespace umpire diff --git a/src/umpire/resource/UnifiedMemoryResourceFactory.hpp b/src/umpire/resource/CudaUnifiedMemoryResourceFactory.hpp similarity index 77% rename from src/umpire/resource/UnifiedMemoryResourceFactory.hpp rename to src/umpire/resource/CudaUnifiedMemoryResourceFactory.hpp index 18c337608..4aaa0de18 100644 --- a/src/umpire/resource/UnifiedMemoryResourceFactory.hpp +++ b/src/umpire/resource/CudaUnifiedMemoryResourceFactory.hpp @@ -12,8 +12,8 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#ifndef UMPIRE_UnifiedMemoryResourceFactory_HPP -#define UMPIRE_UnifiedMemoryResourceFactory_HPP +#ifndef UMPIRE_CudaUnifiedMemoryResourceFactory_HPP +#define UMPIRE_CudaUnifiedMemoryResourceFactory_HPP #include "umpire/resource/MemoryResourceFactory.hpp" @@ -24,14 +24,14 @@ namespace resource { * \brief Factory class to construct a MemoryResource that uses NVIDIA * "unified" memory, accesible from both the CPU and NVIDIA GPUs. */ -class UnifiedMemoryResourceFactory : +class CudaUnifiedMemoryResourceFactory : public MemoryResourceFactory { - bool isValidMemoryResourceFor(const std::string& name); + bool isValidMemoryResourceFor(const std::string& name) noexcept; std::shared_ptr create(const std::string& name, int id); }; } // end of namespace resource } // end of namespace umpire -#endif // UMPIRE_UnifiedMemoryResourceFactory_HPP +#endif // UMPIRE_CudaUnifiedMemoryResourceFactory_HPP diff --git a/src/umpire/resource/DefaultMemoryResource.hpp b/src/umpire/resource/DefaultMemoryResource.hpp index 3f123b07b..abeee8d20 100644 --- a/src/umpire/resource/DefaultMemoryResource.hpp +++ b/src/umpire/resource/DefaultMemoryResource.hpp @@ -35,17 +35,17 @@ class DefaultMemoryResource : private umpire::strategy::mixins::Inspector { public: - DefaultMemoryResource(Platform platform, const std::string& name, int id); + DefaultMemoryResource(Platform platform, const std::string& name, int id, MemoryResourceTraits traits); void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; - protected: + protected: _allocator m_allocator; Platform m_platform; diff --git a/src/umpire/resource/DefaultMemoryResource.inl b/src/umpire/resource/DefaultMemoryResource.inl index e5f561b76..c5f9079d0 100644 --- a/src/umpire/resource/DefaultMemoryResource.inl +++ b/src/umpire/resource/DefaultMemoryResource.inl @@ -27,8 +27,8 @@ namespace umpire { namespace resource { template -DefaultMemoryResource<_allocator>::DefaultMemoryResource(Platform platform, const std::string& name, int id) : - MemoryResource(name, id), +DefaultMemoryResource<_allocator>::DefaultMemoryResource(Platform platform, const std::string& name, int id, MemoryResourceTraits traits) : + MemoryResource(name, id, traits), umpire::strategy::mixins::Inspector(), m_allocator(), m_platform(platform) @@ -60,21 +60,21 @@ void DefaultMemoryResource<_allocator>::deallocate(void* ptr) } template -long DefaultMemoryResource<_allocator>::getCurrentSize() +long DefaultMemoryResource<_allocator>::getCurrentSize() noexcept { UMPIRE_LOG(Debug, "() returning " << m_current_size); return m_current_size; } template -long DefaultMemoryResource<_allocator>::getHighWatermark() +long DefaultMemoryResource<_allocator>::getHighWatermark() noexcept { UMPIRE_LOG(Debug, "() returning " << m_high_watermark); return m_high_watermark; } template -Platform DefaultMemoryResource<_allocator>::getPlatform() +Platform DefaultMemoryResource<_allocator>::getPlatform() noexcept { return m_platform; } diff --git a/src/umpire/resource/HostResourceFactory.cpp b/src/umpire/resource/HostResourceFactory.cpp index 3282a343a..ad3bbe663 100644 --- a/src/umpire/resource/HostResourceFactory.cpp +++ b/src/umpire/resource/HostResourceFactory.cpp @@ -21,7 +21,7 @@ namespace umpire { namespace resource { bool -HostResourceFactory::isValidMemoryResourceFor(const std::string& name) +HostResourceFactory::isValidMemoryResourceFor(const std::string& name) noexcept { if (name.compare("HOST") == 0) { return true; @@ -33,7 +33,24 @@ HostResourceFactory::isValidMemoryResourceFor(const std::string& name) std::shared_ptr HostResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) { - return std::make_shared >(Platform::cpu, "HOST", id); + MemoryResourceTraits traits; + + // int mib[2]; + // mib[0] = CTL_HW; + // mib[1] = HW_MEMSIZE; + + // size_t mem_size; + // size_t returnSize = sizeof(mem_size); + // sysctl(mib, 2, &physicalMem, &returnSize, NULL, 0); + + traits.unified = false; + traits.size = 0; + + traits.vendor = MemoryResourceTraits::vendor_type::IBM; + traits.kind = MemoryResourceTraits::memory_type::GDDR; + traits.used_for = MemoryResourceTraits::optimized_for::any; + + return std::make_shared >(Platform::cpu, "HOST", id, traits); } } // end of namespace resource diff --git a/src/umpire/resource/HostResourceFactory.hpp b/src/umpire/resource/HostResourceFactory.hpp index bde8806ad..ea0d70a05 100644 --- a/src/umpire/resource/HostResourceFactory.hpp +++ b/src/umpire/resource/HostResourceFactory.hpp @@ -27,7 +27,7 @@ namespace resource { class HostResourceFactory : public MemoryResourceFactory { - bool isValidMemoryResourceFor(const std::string& name); + bool isValidMemoryResourceFor(const std::string& name) noexcept; std::shared_ptr create(const std::string& name, int id); }; diff --git a/src/umpire/resource/MemoryResource.cpp b/src/umpire/resource/MemoryResource.cpp index 4bc55f3f6..f079ac505 100644 --- a/src/umpire/resource/MemoryResource.cpp +++ b/src/umpire/resource/MemoryResource.cpp @@ -17,10 +17,17 @@ namespace umpire { namespace resource { -MemoryResource::MemoryResource(const std::string& name, int id) : - strategy::AllocationStrategy(name, id) +MemoryResource::MemoryResource(const std::string& name, int id, MemoryResourceTraits traits) : + strategy::AllocationStrategy(name, id), + m_traits(traits) { } +MemoryResourceTraits +MemoryResource::getTraits() +{ + return m_traits; +} + } // end of namespace resource } // end of namespace umpire diff --git a/src/umpire/resource/MemoryResource.hpp b/src/umpire/resource/MemoryResource.hpp index 6018b56a0..fe84f62ca 100644 --- a/src/umpire/resource/MemoryResource.hpp +++ b/src/umpire/resource/MemoryResource.hpp @@ -15,6 +15,8 @@ #ifndef UMPIRE_MemoryResource_HPP #define UMPIRE_MemoryResource_HPP +#include "umpire/resource/MemoryResourceTraits.hpp" + #include "umpire/strategy/AllocationStrategy.hpp" namespace umpire { @@ -38,7 +40,7 @@ class MemoryResource : * \param id ID of the MemoryResource (must be unique). * */ - MemoryResource(const std::string& name, int id); + MemoryResource(const std::string& name, int id, MemoryResourceTraits traits); virtual ~MemoryResource() = default; @@ -72,7 +74,7 @@ class MemoryResource : * * \return current total size of active allocations in this MemoryResource. */ - virtual long getCurrentSize() = 0; + virtual long getCurrentSize() noexcept = 0; /*! * \brief Return the memory high watermark for this MemoryResource. @@ -83,7 +85,7 @@ class MemoryResource : * * \return Memory high watermark. */ - virtual long getHighWatermark() = 0; + virtual long getHighWatermark() noexcept = 0; /*! @@ -94,7 +96,11 @@ class MemoryResource : * * \return Platform associated with this MemoryResource. */ - virtual Platform getPlatform() = 0; + virtual Platform getPlatform() noexcept = 0; + + MemoryResourceTraits getTraits(); + protected: + MemoryResourceTraits m_traits; }; } // end of namespace strategy diff --git a/src/umpire/resource/MemoryResourceFactory.hpp b/src/umpire/resource/MemoryResourceFactory.hpp index 8901d94ec..888276fd7 100644 --- a/src/umpire/resource/MemoryResourceFactory.hpp +++ b/src/umpire/resource/MemoryResourceFactory.hpp @@ -34,14 +34,14 @@ namespace resource { class MemoryResourceFactory { public: virtual ~MemoryResourceFactory() = default; - + /* * \brief Check whether the MemoryResource constructed by this factory is * valid for the given name * * \return true if the MemoryResource matches name. */ - virtual bool isValidMemoryResourceFor(const std::string& name) = 0; + virtual bool isValidMemoryResourceFor(const std::string& name) noexcept = 0; /*! * \brief Construct a MemoryResource with the given name and id. diff --git a/src/umpire/resource/MemoryResourceRegistry.cpp b/src/umpire/resource/MemoryResourceRegistry.cpp index a94d0a6c9..8c1affde1 100644 --- a/src/umpire/resource/MemoryResourceRegistry.cpp +++ b/src/umpire/resource/MemoryResourceRegistry.cpp @@ -22,7 +22,7 @@ namespace resource { MemoryResourceRegistry* MemoryResourceRegistry::s_allocator_registry_instance = nullptr; MemoryResourceRegistry& -MemoryResourceRegistry::getInstance() +MemoryResourceRegistry::getInstance() noexcept { if (!s_allocator_registry_instance) { s_allocator_registry_instance = new MemoryResourceRegistry(); @@ -31,7 +31,7 @@ MemoryResourceRegistry::getInstance() return *s_allocator_registry_instance; } -MemoryResourceRegistry::MemoryResourceRegistry() : +MemoryResourceRegistry::MemoryResourceRegistry() noexcept : m_allocator_factories() { } diff --git a/src/umpire/resource/MemoryResourceRegistry.hpp b/src/umpire/resource/MemoryResourceRegistry.hpp index 0c6fe70ba..af584381f 100644 --- a/src/umpire/resource/MemoryResourceRegistry.hpp +++ b/src/umpire/resource/MemoryResourceRegistry.hpp @@ -26,14 +26,14 @@ namespace resource { class MemoryResourceRegistry { public: - static MemoryResourceRegistry& getInstance(); + static MemoryResourceRegistry& getInstance() noexcept; std::shared_ptr makeMemoryResource(const std::string& name, int id); void registerMemoryResource(std::shared_ptr&& factory); protected: - MemoryResourceRegistry(); + MemoryResourceRegistry() noexcept; private: static MemoryResourceRegistry* s_allocator_registry_instance; diff --git a/src/umpire/resource/MemoryResourceTraits.hpp b/src/umpire/resource/MemoryResourceTraits.hpp new file mode 100644 index 000000000..b986b8644 --- /dev/null +++ b/src/umpire/resource/MemoryResourceTraits.hpp @@ -0,0 +1,59 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_MemoryResourceTraits_HPP +#define UMPIRE_MemoryResourceTraits_HPP + +#include + +namespace umpire { +namespace resource { + +struct MemoryResourceTraits { + + enum class optimized_for { + any, + latency, + bandwidth, + access + }; + + enum class vendor_type { + UNKNOWN, + AMD, + IBM, + INTEL, + NVIDIA + }; + + enum class memory_type { + UNKNOWN, + DDR, + GDDR, + HBM, + NVME + }; + + bool unified = false; + size_t size = 0; + + vendor_type vendor = vendor_type::UNKNOWN; + memory_type kind = memory_type::UNKNOWN; + optimized_for used_for = optimized_for::any; +}; + +} // end of namespace resource +} // end of namespace umpire + +#endif // UMPIRE_MemoryResourceTraits_HPP diff --git a/src/umpire/resource/MemoryResourceTypes.hpp b/src/umpire/resource/MemoryResourceTypes.hpp index aa3895f78..5ebbd0123 100644 --- a/src/umpire/resource/MemoryResourceTypes.hpp +++ b/src/umpire/resource/MemoryResourceTypes.hpp @@ -21,7 +21,7 @@ namespace resource { struct MemoryResourceTypeHash { template - std::size_t operator()(T t) const + std::size_t operator()(T t) const noexcept { return static_cast(t); } @@ -31,9 +31,9 @@ struct MemoryResourceTypeHash enum MemoryResourceType { Host, Device, - UnifiedMemory, - PinnedMemory, - DeviceConst + Unified, + Pinned, + Constant }; } // end of namespace resource diff --git a/src/umpire/resource/DeviceResourceFactory.cpp b/src/umpire/resource/RocmDeviceResourceFactory.cpp similarity index 60% rename from src/umpire/resource/DeviceResourceFactory.cpp rename to src/umpire/resource/RocmDeviceResourceFactory.cpp index 06aa2edac..b3616cc8a 100644 --- a/src/umpire/resource/DeviceResourceFactory.cpp +++ b/src/umpire/resource/RocmDeviceResourceFactory.cpp @@ -12,16 +12,17 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#include "umpire/resource/DeviceResourceFactory.hpp" +#include "umpire/resource/RocmDeviceResourceFactory.hpp" #include "umpire/resource/DefaultMemoryResource.hpp" -#include "umpire/alloc/CudaMallocAllocator.hpp" +#include "umpire/alloc/AmAllocAllocator.hpp" namespace umpire { namespace resource { bool -DeviceResourceFactory::isValidMemoryResourceFor(const std::string& name) +RocmDeviceResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept { if (name.compare("DEVICE") == 0) { return true; @@ -31,9 +32,16 @@ DeviceResourceFactory::isValidMemoryResourceFor(const std::string& name) } std::shared_ptr -DeviceResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +RocmDeviceResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) { - return std::make_shared >(Platform::cuda, "DEVICE", id); + MemoryResourceTraits traits; + + traits.unified = false; + traits.vendor = MemoryResourceTraits::vendor_type::AMD; + traits.kind = MemoryResourceTraits::memory_type::GDDR; + traits.used_for = MemoryResourceTraits::optimized_for::any; + + return std::make_shared >(Platform::rocm, "DEVICE", id, traits); } } // end of namespace resource diff --git a/src/umpire/resource/DeviceConstResourceFactory.hpp b/src/umpire/resource/RocmDeviceResourceFactory.hpp similarity index 78% rename from src/umpire/resource/DeviceConstResourceFactory.hpp rename to src/umpire/resource/RocmDeviceResourceFactory.hpp index 4eec2c7e4..a1e6ca32a 100644 --- a/src/umpire/resource/DeviceConstResourceFactory.hpp +++ b/src/umpire/resource/RocmDeviceResourceFactory.hpp @@ -12,22 +12,23 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#ifndef UMPIRE_DeviceConstResourceFactory_HPP -#define UMPIRE_DeviceConstResourceFactory_HPP +#ifndef UMPIRE_RocmDeviceResourceFactory_HPP +#define UMPIRE_RocmDeviceResourceFactory_HPP #include "umpire/resource/MemoryResourceFactory.hpp" namespace umpire { namespace resource { + /*! * \brief Factory class for constructing MemoryResource objects that use GPU * memory. */ -class DeviceConstResourceFactory : +class RocmDeviceResourceFactory : public MemoryResourceFactory { - bool isValidMemoryResourceFor(const std::string& name); + bool isValidMemoryResourceFor(const std::string& name) noexcept; std::shared_ptr create(const std::string& name, int id); }; @@ -35,4 +36,4 @@ class DeviceConstResourceFactory : } // end of namespace resource } // end of namespace umpire -#endif // UMPIRE_DeviceConstResourceFactory_HPP +#endif // UMPIRE_RocmDeviceResourceFactory_HPP diff --git a/src/umpire/resource/UnifiedMemoryResourceFactory.cpp b/src/umpire/resource/RocmPinnedMemoryResourceFactory.cpp similarity index 57% rename from src/umpire/resource/UnifiedMemoryResourceFactory.cpp rename to src/umpire/resource/RocmPinnedMemoryResourceFactory.cpp index 1f135f275..41fcccf46 100644 --- a/src/umpire/resource/UnifiedMemoryResourceFactory.cpp +++ b/src/umpire/resource/RocmPinnedMemoryResourceFactory.cpp @@ -12,19 +12,19 @@ // For details, see https://github.com/LLNL/Umpire // Please also see the LICENSE file for MIT license. ////////////////////////////////////////////////////////////////////////////// -#include "umpire/resource/UnifiedMemoryResourceFactory.hpp" +#include "umpire/resource/RocmPinnedMemoryResourceFactory.hpp" #include "umpire/resource/DefaultMemoryResource.hpp" - -#include "umpire/alloc/CudaMallocManagedAllocator.hpp" +#include "umpire/alloc/AmPinnedAllocator.hpp" namespace umpire { namespace resource { bool -UnifiedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) +RocmPinnedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) + noexcept { - if (name.compare("UM") == 0) { + if (name.compare("PINNED") == 0) { return true; } else { return false; @@ -32,9 +32,16 @@ UnifiedMemoryResourceFactory::isValidMemoryResourceFor(const std::string& name) } std::shared_ptr -UnifiedMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) +RocmPinnedMemoryResourceFactory::create(const std::string& UMPIRE_UNUSED_ARG(name), int id) { - return std::make_shared >(Platform::cuda, "UM", id); + MemoryResourceTraits traits; + + traits.unified = true; + traits.vendor = MemoryResourceTraits::vendor_type::AMD; + traits.kind = MemoryResourceTraits::memory_type::DDR; + traits.used_for = MemoryResourceTraits::optimized_for::access; + + return std::make_shared >(Platform::rocm, "PINNED", id, traits); } } // end of namespace resource diff --git a/src/umpire/resource/RocmPinnedMemoryResourceFactory.hpp b/src/umpire/resource/RocmPinnedMemoryResourceFactory.hpp new file mode 100644 index 000000000..7e07ca785 --- /dev/null +++ b/src/umpire/resource/RocmPinnedMemoryResourceFactory.hpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_RocmPinnedMemoryResourceFactory_HPP +#define UMPIRE_RocmPinnedMemoryResourceFactory_HPP + +#include "umpire/resource/MemoryResourceFactory.hpp" + +namespace umpire { +namespace resource { + + +/*! + * \brief Factory class for constructing MemoryResource objects that use GPU + * memory. + */ +class RocmPinnedMemoryResourceFactory : + public MemoryResourceFactory +{ + bool isValidMemoryResourceFor(const std::string& name) noexcept; + + std::shared_ptr create(const std::string& name, int id); +}; + +} // end of namespace resource +} // end of namespace umpire + +#endif // UMPIRE_RocmPinnedMemoryResourceFactory_HPP diff --git a/src/umpire/strategy/AllocationAdvisor.cpp b/src/umpire/strategy/AllocationAdvisor.cpp index 97f1bd7d1..3fc4d379e 100644 --- a/src/umpire/strategy/AllocationAdvisor.cpp +++ b/src/umpire/strategy/AllocationAdvisor.cpp @@ -67,9 +67,9 @@ void* AllocationAdvisor::allocate(size_t bytes) auto alloc_record = new util::AllocationRecord{ptr, bytes, this->shared_from_this()}; m_advice_operation->apply( - ptr, + ptr, alloc_record, - m_device, + m_device, bytes); return ptr; @@ -81,17 +81,17 @@ void AllocationAdvisor::deallocate(void* ptr) } -long AllocationAdvisor::getCurrentSize() +long AllocationAdvisor::getCurrentSize() noexcept { return 0; } -long AllocationAdvisor::getHighWatermark() +long AllocationAdvisor::getHighWatermark() noexcept { return 0; } -Platform AllocationAdvisor::getPlatform() +Platform AllocationAdvisor::getPlatform() noexcept { return m_allocator->getPlatform(); } diff --git a/src/umpire/strategy/AllocationAdvisor.hpp b/src/umpire/strategy/AllocationAdvisor.hpp index 7f9c22622..838adc025 100644 --- a/src/umpire/strategy/AllocationAdvisor.hpp +++ b/src/umpire/strategy/AllocationAdvisor.hpp @@ -58,10 +58,10 @@ class AllocationAdvisor : void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; private: std::shared_ptr m_advice_operation; diff --git a/src/umpire/strategy/AllocationStrategy.cpp b/src/umpire/strategy/AllocationStrategy.cpp index fd7818255..87e99106e 100644 --- a/src/umpire/strategy/AllocationStrategy.cpp +++ b/src/umpire/strategy/AllocationStrategy.cpp @@ -14,29 +14,37 @@ ////////////////////////////////////////////////////////////////////////////// #include "umpire/strategy/AllocationStrategy.hpp" +#include "umpire/util/Macros.hpp" + namespace umpire { namespace strategy { -AllocationStrategy::AllocationStrategy(const std::string& name, int id) : +AllocationStrategy::AllocationStrategy(const std::string& name, int id) noexcept : m_name(name), m_id(id) { } +void +AllocationStrategy::release() +{ + UMPIRE_LOG(Info, "AllocationStrategy::release in a no-op"); +} + std::string -AllocationStrategy::getName() +AllocationStrategy::getName() noexcept { return m_name; } int -AllocationStrategy::getId() +AllocationStrategy::getId() noexcept { return m_id; } long -AllocationStrategy::getActualSize() +AllocationStrategy::getActualSize() noexcept { return getCurrentSize(); } diff --git a/src/umpire/strategy/AllocationStrategy.hpp b/src/umpire/strategy/AllocationStrategy.hpp index c1fa3a1ac..a3fe8b2d6 100644 --- a/src/umpire/strategy/AllocationStrategy.hpp +++ b/src/umpire/strategy/AllocationStrategy.hpp @@ -41,7 +41,7 @@ class AllocationStrategy : * \param name The name of this AllocationStrategy object. * \param id The id of this AllocationStrategy object. */ - AllocationStrategy(const std::string& name, int id); + AllocationStrategy(const std::string& name, int id) noexcept; virtual ~AllocationStrategy() = default; @@ -61,6 +61,11 @@ class AllocationStrategy : */ virtual void deallocate(void* ptr) = 0; + /*! + * \brief Release any and all unused memory held by this AllocationStrategy + */ + virtual void release(); + /*! * \brief Get current (total) size of the allocated memory. * @@ -69,7 +74,7 @@ class AllocationStrategy : * * \return Current total size of allocations. */ - virtual long getCurrentSize() = 0; + virtual long getCurrentSize() noexcept = 0; /*! * \brief Get the high watermark of the total allocated size. @@ -77,7 +82,7 @@ class AllocationStrategy : * This is equivalent to the highest observed value of getCurrentSize. * \return High watermark allocation size. */ - virtual long getHighWatermark() = 0; + virtual long getHighWatermark() noexcept = 0; /*! * \brief Get the current amount of memory allocated by this allocator. @@ -87,7 +92,7 @@ class AllocationStrategy : * * \return The total size of all the memory this object has allocated. */ - virtual long getActualSize(); + virtual long getActualSize() noexcept; /*! * \brief Get the platform associated with this AllocationStrategy. @@ -97,14 +102,14 @@ class AllocationStrategy : * * \return The platform associated with this AllocationStrategy. */ - virtual Platform getPlatform() = 0; + virtual Platform getPlatform() noexcept = 0; /*! * \brief Get the name of this AllocationStrategy. * * \return The name of this AllocationStrategy. */ - std::string getName(); + std::string getName() noexcept; /*! @@ -112,7 +117,7 @@ class AllocationStrategy : * * \return The id of this AllocationStrategy. */ - int getId(); + int getId() noexcept; protected: std::string m_name; diff --git a/src/umpire/strategy/AllocationTracker.cpp b/src/umpire/strategy/AllocationTracker.cpp index 7fc908238..72855c40a 100644 --- a/src/umpire/strategy/AllocationTracker.cpp +++ b/src/umpire/strategy/AllocationTracker.cpp @@ -20,14 +20,14 @@ namespace strategy { AllocationTracker::AllocationTracker( const std::string& name, int id, - Allocator allocator) : + Allocator allocator) noexcept : AllocationStrategy(name, id), mixins::Inspector(), m_allocator(allocator.getAllocationStrategy()) { } -void* +void* AllocationTracker::allocate(size_t bytes) { void* ptr = m_allocator->allocate(bytes); @@ -37,36 +37,42 @@ AllocationTracker::allocate(size_t bytes) return ptr; } -void +void AllocationTracker::deallocate(void* ptr) { deregisterAllocation(ptr); m_allocator->deallocate(ptr); } -long -AllocationTracker::getCurrentSize() +long +AllocationTracker::getCurrentSize() noexcept { return m_current_size; } -long -AllocationTracker::getHighWatermark() +long +AllocationTracker::getHighWatermark() noexcept { return m_high_watermark; } long -AllocationTracker::getActualSize() +AllocationTracker::getActualSize() noexcept { return m_allocator->getActualSize(); } -Platform -AllocationTracker::getPlatform() +Platform +AllocationTracker::getPlatform() noexcept { return m_allocator->getPlatform(); } +std::shared_ptr +AllocationTracker::getAllocationStrategy() +{ + return m_allocator; +} + } // end of namespace umpire } // end of namespace strategy diff --git a/src/umpire/strategy/AllocationTracker.hpp b/src/umpire/strategy/AllocationTracker.hpp index b588a672f..0b570f279 100644 --- a/src/umpire/strategy/AllocationTracker.hpp +++ b/src/umpire/strategy/AllocationTracker.hpp @@ -24,7 +24,7 @@ namespace umpire { namespace strategy { -class AllocationTracker : +class AllocationTracker : public AllocationStrategy, private mixins::Inspector { @@ -32,17 +32,19 @@ class AllocationTracker : AllocationTracker( const std::string& name, int id, - Allocator allocator); + Allocator allocator) noexcept; void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); - long getActualSize(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; + long getActualSize() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; + + std::shared_ptr getAllocationStrategy(); private: std::shared_ptr m_allocator; diff --git a/src/umpire/strategy/CMakeLists.txt b/src/umpire/strategy/CMakeLists.txt index fa0c93206..3c57b3c9e 100644 --- a/src/umpire/strategy/CMakeLists.txt +++ b/src/umpire/strategy/CMakeLists.txt @@ -18,6 +18,7 @@ set (umpire_strategy_headers AllocationTracker.hpp MonotonicAllocationStrategy.hpp SlotPool.hpp + SizeLimiter.hpp ThreadSafeAllocator.hpp DynamicPool.hpp FixedPool.hpp @@ -32,6 +33,7 @@ set (umpire_stategy_sources AllocationTracker.cpp MonotonicAllocationStrategy.cpp SlotPool.cpp + SizeLimiter.cpp ThreadSafeAllocator.cpp DynamicPool.cpp mixins/Inspector.cpp) diff --git a/src/umpire/strategy/DynamicPool.cpp b/src/umpire/strategy/DynamicPool.cpp index 022195ec7..a06d127b7 100644 --- a/src/umpire/strategy/DynamicPool.cpp +++ b/src/umpire/strategy/DynamicPool.cpp @@ -26,7 +26,7 @@ DynamicPool::DynamicPool( int id, Allocator allocator, const std::size_t min_initial_alloc_size, - const std::size_t min_alloc_size) : + const std::size_t min_alloc_size) noexcept : AllocationStrategy(name, id), dpa(nullptr), m_allocator(allocator.getAllocationStrategy()) @@ -42,40 +42,50 @@ DynamicPool::allocate(size_t bytes) return ptr; } -void +void DynamicPool::deallocate(void* ptr) { UMPIRE_LOG(Debug, "(ptr=" << ptr << ")"); dpa->deallocate(ptr); } -long -DynamicPool::getCurrentSize() -{ - UMPIRE_LOG(Debug, "() returning " << m_current_size); +void +DynamicPool::release() +{ + dpa->release(); +} + +long +DynamicPool::getCurrentSize() noexcept +{ return 0; } -long -DynamicPool::getHighWatermark() -{ - UMPIRE_LOG(Debug, "() returning " << m_highwatermark); +long +DynamicPool::getHighWatermark() noexcept +{ return 0; } -long -DynamicPool::getActualSize() -{ +long +DynamicPool::getActualSize() noexcept +{ long totalSize = dpa->totalSize(); UMPIRE_LOG(Debug, "() returning " << totalSize); return totalSize; } -Platform -DynamicPool::getPlatform() -{ +Platform +DynamicPool::getPlatform() noexcept +{ return m_allocator->getPlatform(); } +void +DynamicPool::coalesce() noexcept +{ + dpa->coalesce(); +} + } // end of namespace strategy } // end of namespace umpire diff --git a/src/umpire/strategy/DynamicPool.hpp b/src/umpire/strategy/DynamicPool.hpp index 77b82e9d5..da022e2b2 100644 --- a/src/umpire/strategy/DynamicPool.hpp +++ b/src/umpire/strategy/DynamicPool.hpp @@ -56,24 +56,25 @@ class DynamicPool : int id, Allocator allocator, const std::size_t min_initial_alloc_size = (512 * 1024 * 1024), - const std::size_t min_alloc_size = (1 * 1024 *1024)); + const std::size_t min_alloc_size = (1 * 1024 *1024)) noexcept; - void* allocate(size_t bytes); + void* allocate(size_t bytes) override; - void deallocate(void* ptr); + void deallocate(void* ptr) override; - long getCurrentSize(); - long getHighWatermark(); - long getActualSize(); + void release() override; - Platform getPlatform(); + long getCurrentSize() noexcept override; + long getHighWatermark() noexcept override; + long getActualSize() noexcept override; + + Platform getPlatform() noexcept override; + + void coalesce() noexcept; private: DynamicSizePool<>* dpa; - long m_current_size; - long m_highwatermark; - std::shared_ptr m_allocator; }; diff --git a/src/umpire/strategy/FixedPool.hpp b/src/umpire/strategy/FixedPool.hpp index f25bcdb4a..2fe8984ce 100644 --- a/src/umpire/strategy/FixedPool.hpp +++ b/src/umpire/strategy/FixedPool.hpp @@ -35,7 +35,7 @@ namespace strategy { * used to quickly allocate and deallocate objects. */ template -class FixedPool +class FixedPool : public AllocationStrategy { @@ -51,11 +51,11 @@ class FixedPool void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); - long getActualSize(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; + long getActualSize() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; private: struct Pool @@ -70,7 +70,7 @@ class FixedPool T* allocInPool(struct Pool *p); - size_t numPools() const; + size_t numPools() const noexcept; struct Pool *m_pool; diff --git a/src/umpire/strategy/FixedPool.inl b/src/umpire/strategy/FixedPool.inl index 24153d779..d1c53f56d 100644 --- a/src/umpire/strategy/FixedPool.inl +++ b/src/umpire/strategy/FixedPool.inl @@ -23,7 +23,7 @@ namespace umpire { namespace strategy { template -void +void FixedPool::newPool(struct Pool **pnew) { struct Pool *p = static_cast(IA::allocate(sizeof(struct Pool) + NP * sizeof(unsigned int))); p->numAvail = m_num_per_pool; @@ -42,7 +42,7 @@ FixedPool::newPool(struct Pool **pnew) { } template -T* +T* FixedPool::allocInPool(struct Pool *p) { if (!p->numAvail) return NULL; @@ -63,7 +63,7 @@ template FixedPool::FixedPool( const std::string& name, int id, - Allocator allocator) : + Allocator allocator) : AllocationStrategy(name, id), m_num_per_pool(NP * sizeof(unsigned int) * 8), m_total_pool_size(sizeof(struct Pool) + m_num_per_pool * sizeof(T) + NP * sizeof(unsigned int)), @@ -71,8 +71,8 @@ FixedPool::FixedPool( m_highwatermark(0), m_current_size(0), m_allocator(allocator.getAllocationStrategy()) -{ - newPool(&m_pool); +{ + newPool(&m_pool); } template @@ -86,7 +86,7 @@ FixedPool::~FixedPool() { } template -void* +void* FixedPool::allocate(size_t bytes) { T* ptr = NULL; @@ -111,7 +111,7 @@ FixedPool::allocate(size_t bytes) { } template -void +void FixedPool::deallocate(void* ptr) { T* t_ptr = static_cast(ptr); @@ -142,35 +142,35 @@ FixedPool::deallocate(void* ptr) { } template -long -FixedPool::getCurrentSize() { +long +FixedPool::getCurrentSize() noexcept { return m_current_size; } template -long -FixedPool::getActualSize() { +long +FixedPool::getActualSize() noexcept { return m_total_pool_size; } template -long -FixedPool::getHighWatermark() { +long +FixedPool::getHighWatermark() noexcept { return m_highwatermark; } template size_t -FixedPool::numPools() const { +FixedPool::numPools() const noexcept { std::size_t np = 0; for (struct Pool *curr = m_pool; curr; curr = curr->next) np++; return np; } template -Platform -FixedPool::getPlatform() -{ +Platform +FixedPool::getPlatform() noexcept +{ return m_allocator->getPlatform(); } diff --git a/src/umpire/strategy/MonotonicAllocationStrategy.cpp b/src/umpire/strategy/MonotonicAllocationStrategy.cpp index 35cc6ab01..f50730dc5 100644 --- a/src/umpire/strategy/MonotonicAllocationStrategy.cpp +++ b/src/umpire/strategy/MonotonicAllocationStrategy.cpp @@ -34,7 +34,7 @@ MonotonicAllocationStrategy::MonotonicAllocationStrategy( m_block = m_allocator->allocate(m_capacity); } -void* +void* MonotonicAllocationStrategy::allocate(size_t bytes) { void* ret = static_cast(m_block) + bytes; @@ -49,28 +49,28 @@ MonotonicAllocationStrategy::allocate(size_t bytes) return ret; } -void +void MonotonicAllocationStrategy::deallocate(void* UMPIRE_UNUSED_ARG(ptr)) { UMPIRE_LOG(Info, "() doesn't do anything"); } -long -MonotonicAllocationStrategy::getCurrentSize() +long +MonotonicAllocationStrategy::getCurrentSize() noexcept { UMPIRE_LOG(Debug, "() returning " << m_size); return m_size; } -long -MonotonicAllocationStrategy::getHighWatermark() +long +MonotonicAllocationStrategy::getHighWatermark() noexcept { UMPIRE_LOG(Debug, "() returning " << m_capacity); return m_capacity; } -Platform -MonotonicAllocationStrategy::getPlatform() +Platform +MonotonicAllocationStrategy::getPlatform() noexcept { return m_allocator->getPlatform(); } diff --git a/src/umpire/strategy/MonotonicAllocationStrategy.hpp b/src/umpire/strategy/MonotonicAllocationStrategy.hpp index 77c0b1345..5bf72dc38 100644 --- a/src/umpire/strategy/MonotonicAllocationStrategy.hpp +++ b/src/umpire/strategy/MonotonicAllocationStrategy.hpp @@ -38,12 +38,10 @@ class MonotonicAllocationStrategy : void* allocate(size_t bytes); void deallocate(void* ptr); - size_t getSize(void* ptr); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - long getCurrentSize(); - long getHighWatermark(); - - Platform getPlatform(); + Platform getPlatform() noexcept; private: void* m_block; @@ -58,4 +56,3 @@ class MonotonicAllocationStrategy : } // end of namespace umpire #endif // UMPIRE_MonotonicAllocationStrategy_HPP - diff --git a/src/umpire/strategy/SizeLimiter.cpp b/src/umpire/strategy/SizeLimiter.cpp new file mode 100644 index 000000000..b0746997a --- /dev/null +++ b/src/umpire/strategy/SizeLimiter.cpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// + +#include "umpire/strategy/SizeLimiter.hpp" + +#include "umpire/ResourceManager.hpp" + +namespace umpire { +namespace strategy { + +SizeLimiter::SizeLimiter( + const std::string& name, + int id, + Allocator allocator, + size_t size_limit) : + AllocationStrategy(name, id), + m_allocator(allocator.getAllocationStrategy()), + m_size_limit(size_limit), + m_total_size(0) +{ +} + +void* SizeLimiter::allocate(size_t bytes) +{ + m_total_size += bytes; + + if (m_total_size > m_size_limit) { + m_total_size -= bytes; + UMPIRE_ERROR("Size limit exceeded."); + } + + return m_allocator->allocate(bytes); + +} + +void SizeLimiter::deallocate(void* ptr) +{ + m_total_size -= ResourceManager::getInstance().getSize(ptr); + m_allocator->deallocate(ptr); + +} + +long SizeLimiter::getCurrentSize() noexcept +{ + return 0; +} + +long SizeLimiter::getHighWatermark() noexcept +{ + return 0; +} + +Platform SizeLimiter::getPlatform() noexcept +{ + return m_allocator->getPlatform(); +} + +} // end of namespace strategy +} // end of namespace umpire diff --git a/src/umpire/strategy/SizeLimiter.hpp b/src/umpire/strategy/SizeLimiter.hpp new file mode 100644 index 000000000..59f247f39 --- /dev/null +++ b/src/umpire/strategy/SizeLimiter.hpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#ifndef UMPIRE_SizeLimiter_HPP +#define UMPIRE_SizeLimiter_HPP + +#include + +#include "umpire/strategy/AllocationStrategy.hpp" +#include "umpire/Allocator.hpp" + +namespace umpire { +namespace strategy { + +/*! + * + * \brief An allocator with a limited total size. + * + * Using this AllocationStrategy with another can be a good way to limit the + * total size of allocations made on a particular resource or from a particular + * context. + * */ +class SizeLimiter : + public AllocationStrategy +{ + public: + SizeLimiter( + const std::string& name, + int id, + Allocator allocator, + size_t size_limit); + + void* allocate(size_t bytes); + void deallocate(void* ptr); + + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; + + Platform getPlatform() noexcept; + private: + std::shared_ptr m_allocator; + + size_t m_size_limit; + size_t m_total_size; +}; + +} // end of namespace strategy +} // end namespace umpire + +#endif // UMPIRE_SizeLimiter_HPP diff --git a/src/umpire/strategy/SlotPool.cpp b/src/umpire/strategy/SlotPool.cpp index 34bde63ba..d88f8bbe5 100644 --- a/src/umpire/strategy/SlotPool.cpp +++ b/src/umpire/strategy/SlotPool.cpp @@ -77,22 +77,22 @@ SlotPool::deallocate(void* ptr) } } -long -SlotPool::getCurrentSize() +long +SlotPool::getCurrentSize() noexcept { UMPIRE_LOG(Debug, "() returning " << m_current_size); return m_current_size; } -long -SlotPool::getHighWatermark() +long +SlotPool::getHighWatermark() noexcept { UMPIRE_LOG(Debug, "() returning " << m_highwatermark); return m_highwatermark; } Platform -SlotPool::getPlatform() +SlotPool::getPlatform() noexcept { return m_allocator->getPlatform(); } diff --git a/src/umpire/strategy/SlotPool.hpp b/src/umpire/strategy/SlotPool.hpp index 4338bb192..21e24fdd8 100644 --- a/src/umpire/strategy/SlotPool.hpp +++ b/src/umpire/strategy/SlotPool.hpp @@ -37,10 +37,10 @@ class SlotPool : void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; private: void init(); diff --git a/src/umpire/strategy/ThreadSafeAllocator.cpp b/src/umpire/strategy/ThreadSafeAllocator.cpp index a639b0a87..a58b6128a 100644 --- a/src/umpire/strategy/ThreadSafeAllocator.cpp +++ b/src/umpire/strategy/ThreadSafeAllocator.cpp @@ -30,8 +30,8 @@ ThreadSafeAllocator::ThreadSafeAllocator( { } -void* -ThreadSafeAllocator::allocate(size_t bytes) +void* +ThreadSafeAllocator::allocate(size_t bytes) { void* ret = nullptr; @@ -49,7 +49,7 @@ ThreadSafeAllocator::allocate(size_t bytes) return ret; } -void +void ThreadSafeAllocator::deallocate(void* ptr) { try { @@ -65,20 +65,19 @@ ThreadSafeAllocator::deallocate(void* ptr) } long -ThreadSafeAllocator::getCurrentSize() +ThreadSafeAllocator::getCurrentSize() noexcept { return 0; } long -ThreadSafeAllocator::getHighWatermark() +ThreadSafeAllocator::getHighWatermark() noexcept { return 0; } - Platform -ThreadSafeAllocator::getPlatform() +ThreadSafeAllocator::getPlatform() noexcept { return m_allocator->getPlatform(); diff --git a/src/umpire/strategy/ThreadSafeAllocator.hpp b/src/umpire/strategy/ThreadSafeAllocator.hpp index 64620ecad..844a7c010 100644 --- a/src/umpire/strategy/ThreadSafeAllocator.hpp +++ b/src/umpire/strategy/ThreadSafeAllocator.hpp @@ -28,17 +28,17 @@ class ThreadSafeAllocator : { public: ThreadSafeAllocator( - const std::string& name, + const std::string& name, int id, Allocator allocator); void* allocate(size_t bytes); void deallocate(void* ptr); - long getCurrentSize(); - long getHighWatermark(); + long getCurrentSize() noexcept; + long getHighWatermark() noexcept; - Platform getPlatform(); + Platform getPlatform() noexcept; protected: std::shared_ptr m_allocator; diff --git a/src/umpire/tpl/judy/judy.c b/src/umpire/tpl/judy/judy.c index 008a575c8..b50669c2b 100644 --- a/src/umpire/tpl/judy/judy.c +++ b/src/umpire/tpl/judy/judy.c @@ -1233,7 +1233,8 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max judyvalue * src = ( judyvalue * )buff; int size, idx, slot, cnt, tst; JudySlot * next = judy->root; - judyvalue test, value; + judyvalue test = 0; + judyvalue value = 0; unsigned int off = 0, start; JudySlot * table; JudySlot * node; diff --git a/src/umpire/tpl/simpool b/src/umpire/tpl/simpool index ff7d25c8b..2ca2a06fa 160000 --- a/src/umpire/tpl/simpool +++ b/src/umpire/tpl/simpool @@ -1 +1 @@ -Subproject commit ff7d25c8b368fa16ddee23afbf293c811c6d9092 +Subproject commit 2ca2a06fa409f568e23af02da3a59b50bd200b28 diff --git a/src/umpire/util/Logger.cpp b/src/umpire/util/Logger.cpp index bd4a7d81c..8ae8f03ac 100644 --- a/src/umpire/util/Logger.cpp +++ b/src/umpire/util/Logger.cpp @@ -32,18 +32,18 @@ static const std::string MessageLevelName[ message::Num_Levels ] = { "DEBUG" }; -Logger::Logger() +Logger::Logger() noexcept { // by default, all message streams are disabled for ( int i=0 ; i < message::Num_Levels ; ++i ) m_isEnabled[ i ] = false; } -Logger::~Logger() +Logger::~Logger() noexcept { } -void Logger::setLoggingMsgLevel( message::Level level ) +void Logger::setLoggingMsgLevel( message::Level level ) noexcept { for ( int i=0 ; i < message::Num_Levels ; ++i ) m_isEnabled[ i ] = (i<= level) ? true : false; @@ -52,15 +52,15 @@ void Logger::setLoggingMsgLevel( message::Level level ) void Logger::logMessage( message::Level level, const std::string& message, const std::string& fileName, - int line ) + int line ) noexcept { if ( !logLevelEnabled( level ) ) return; /* short-circuit */ - std::cout + std::cout << "[" << MessageLevelName[ level ] << "]" - << "[" << fileName << ":" << line << "]:" - << message + << "[" << fileName << ":" << line << "]:" + << message << std::endl; } diff --git a/src/umpire/util/Logger.hpp b/src/umpire/util/Logger.hpp index ba490392a..b39557156 100644 --- a/src/umpire/util/Logger.hpp +++ b/src/umpire/util/Logger.hpp @@ -41,12 +41,12 @@ static const std::string MessageLevelName[ Level::Num_Levels ] = { class Logger { public: - void setLoggingMsgLevel( message::Level level ); + void setLoggingMsgLevel( message::Level level ) noexcept; void logMessage( message::Level level, const std::string& message, const std::string& fileName, - int line ); + int line ) noexcept; static void initialize(); @@ -65,8 +65,8 @@ class Logger { }; private: - Logger(); - ~Logger(); + Logger() noexcept; + ~Logger() noexcept; bool m_isEnabled[ message::Num_Levels ]; static Logger* s_Logger; diff --git a/src/umpire/util/Platform.hpp b/src/umpire/util/Platform.hpp index 033eb89e0..5883e0118 100644 --- a/src/umpire/util/Platform.hpp +++ b/src/umpire/util/Platform.hpp @@ -19,7 +19,8 @@ namespace umpire { enum class Platform { cpu, - cuda + cuda, + rocm }; } // end of namespace umpire diff --git a/src/umpire/util/Statistic.cpp b/src/umpire/util/Statistic.cpp index 4518e2e35..b0b99f898 100644 --- a/src/umpire/util/Statistic.cpp +++ b/src/umpire/util/Statistic.cpp @@ -24,7 +24,7 @@ namespace umpire { namespace util { -Statistic::Statistic(const std::string& name) : +Statistic::Statistic(const std::string& name) noexcept: m_name(name), m_counter(), m_data() @@ -32,7 +32,7 @@ Statistic::Statistic(const std::string& name) : m_data["name"] = name; } -Statistic::~Statistic() +Statistic::~Statistic() noexcept { } @@ -46,7 +46,7 @@ Statistic::recordStatistic(conduit::Node&& stat) } void -Statistic::printData(std::ostream& stream) +Statistic::printData(std::ostream& stream) noexcept { m_data.print(); } diff --git a/src/umpire/util/Statistic.hpp b/src/umpire/util/Statistic.hpp index 9c9589981..d9a58d239 100644 --- a/src/umpire/util/Statistic.hpp +++ b/src/umpire/util/Statistic.hpp @@ -29,14 +29,14 @@ class StatisticsDatabase; class Statistic { friend class StatisticsDatabase; public: - ~Statistic(); + ~Statistic() noexcept; void recordStatistic(conduit::Node&& n); - void printData(std::ostream& stream); + void printData(std::ostream& stream) noexcept; protected: - Statistic(const std::string& name); + Statistic(const std::string& name) noexcept; private: std::string m_name; diff --git a/src/umpire/util/StatisticsDatabase.cpp b/src/umpire/util/StatisticsDatabase.cpp index a7f84bab5..13752a4c0 100644 --- a/src/umpire/util/StatisticsDatabase.cpp +++ b/src/umpire/util/StatisticsDatabase.cpp @@ -30,7 +30,7 @@ StatisticsDatabase* StatisticsDatabase::getDatabase() return s_statistics_database_instance; } -std::shared_ptr +std::shared_ptr StatisticsDatabase::getStatistic(const std::string& name) { auto statistic = m_statistics.find(name); @@ -46,13 +46,13 @@ StatisticsDatabase::getStatistic(const std::string& name) return stat; } -StatisticsDatabase::StatisticsDatabase() : +StatisticsDatabase::StatisticsDatabase() noexcept: m_statistics() { } void -StatisticsDatabase::printStatistics(std::ostream& stream) +StatisticsDatabase::printStatistics(std::ostream& stream) noexcept { stream << "umpire::util::StatisticsDatabase contains " << m_statistics.size() << " statistics" << std::endl; for (auto& stat : m_statistics) { diff --git a/src/umpire/util/StatisticsDatabase.hpp b/src/umpire/util/StatisticsDatabase.hpp index d406c4782..3a9107c6d 100644 --- a/src/umpire/util/StatisticsDatabase.hpp +++ b/src/umpire/util/StatisticsDatabase.hpp @@ -31,9 +31,9 @@ class StatisticsDatabase { std::shared_ptr getStatistic( const std::string& name); - void printStatistics(std::ostream& stream); + void printStatistics(std::ostream& stream) noexcept; private: - StatisticsDatabase(); + StatisticsDatabase() noexcept; StatisticsDatabase (const StatisticsDatabase&) = delete; StatisticsDatabase& operator= (const StatisticsDatabase&) = delete; diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 99617527e..bda60dba8 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -89,3 +89,24 @@ target_include_directories( blt_add_test( NAME free_functions_integration_tests COMMAND free_functions_integration_tests) + +# blt_add_executable( +# NAME memory_resource_traits_tests +# SOURCES memory_resource_traits_tests.cpp +# DEPENDS_ON umpire gtest +# OUTPUT_DIR ${UMPIRE_TEST_OUTPUT_DIR}) +# +# target_include_directories( +# memory_resource_traits_tests +# PRIVATE +# ${PROJECT_BINARY_DIR}/include) +# +# blt_add_test( +# NAME memory_resource_traits_tests +# COMMAND memory_resource_traits_tests) + +add_subdirectory(replay) + +if (ENABLE_C_API OR ENABLE_FORTRAN_API) + add_subdirectory(interface) +endif() diff --git a/tests/integration/allocator_integration_tests.cpp b/tests/integration/allocator_integration_tests.cpp index a8a333353..f1b8e7d9b 100644 --- a/tests/integration/allocator_integration_tests.cpp +++ b/tests/integration/allocator_integration_tests.cpp @@ -65,7 +65,8 @@ TEST_P(AllocatorTest, AllocateDeallocateSmall) TEST_P(AllocatorTest, AllocateDeallocateNothing) { // CUDA doesn't support allocating 0 bytes - if (m_allocator->getPlatform() == umpire::Platform::cuda) { + if (m_allocator->getPlatform() == umpire::Platform::cuda || + m_allocator->getPlatform() == umpire::Platform::rocm) { SUCCEED(); } else { double* data = static_cast( @@ -125,12 +126,18 @@ TEST_P(AllocatorTest, GetById) const std::string allocator_strings[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) , "UM" - , "PINNED" +#endif +#if defined(UMPIRE_ENABLE_CUDA) , "DEVICE_CONST" #endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif }; INSTANTIATE_TEST_CASE_P( @@ -153,7 +160,7 @@ TEST(Allocator, registerAllocator) rm.registerAllocator("my_host_allocator_copy", rm.getAllocator("HOST")); - ASSERT_EQ(rm.getAllocator("HOST").getAllocationStrategy(), + ASSERT_EQ(rm.getAllocator("HOST").getAllocationStrategy(), rm.getAllocator("my_host_allocator_copy").getAllocationStrategy()); ASSERT_ANY_THROW( @@ -207,11 +214,17 @@ TEST_P(AllocatorByResourceTest, AllocateDeallocate) const umpire::resource::MemoryResourceType resource_types[] = { umpire::resource::Host -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , umpire::resource::Device - , umpire::resource::UnifiedMemory - , umpire::resource::PinnedMemory - , umpire::resource::DeviceConst +#endif +#if defined(UMPIRE_ENABLE_UM) + , umpire::resource::Unified + #endif +#if defined(UMPIRE_ENABLE_PINNED) + , umpire::resource::Pinned +#endif +#if defined(UMPIRE_ENABLE_CUDA) + , umpire::resource::Constant #endif }; diff --git a/tests/integration/interface/CMakeLists.txt b/tests/integration/interface/CMakeLists.txt new file mode 100644 index 000000000..76b3dc2ab --- /dev/null +++ b/tests/integration/interface/CMakeLists.txt @@ -0,0 +1,60 @@ +############################################################################## +# Copyright (c) 2018, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory +# +# Created by David Beckingsale, david@llnl.gov +# LLNL-CODE-747640 +# +# All rights reserved. +# +# This file is part of Umpire. +# +# For details, see https://github.com/LLNL/Umpire +# Please also see the LICENSE file for MIT license. +############################################################################## + +if (ENABLE_C_API) + blt_add_executable( + NAME allocator_c_tests + SOURCES allocator_c_tests.cpp + DEPENDS_ON umpire gtest + OUTPUT_DIR ${UMPIRE_TEST_OUTPUT_DIR}) + + target_include_directories( + allocator_c_tests + PRIVATE + ${PROJECT_BINARY_DIR}/include) + + blt_add_test( + NAME allocator_c_tests + COMMAND allocator_c_tests) + + blt_add_executable( + NAME operation_c_tests + SOURCES operation_c_tests.cpp + DEPENDS_ON umpire gtest + OUTPUT_DIR ${UMPIRE_TEST_OUTPUT_DIR}) + + target_include_directories( + operation_c_tests + PRIVATE + ${PROJECT_BINARY_DIR}/include) + + blt_add_test( + NAME operation_c_tests + COMMAND operation_c_tests) + + if (ENABLE_FORTRAN_API) + blt_add_executable( + NAME fortran_interface_tests + SOURCES umpire_fortran_interface.f + DEPENDS_ON fruit umpire + ) + + set_source_files_properties( + umpire_fortran_interface.f + PROPERTIES + Fortran_FORMAT FREE) + endif() +endif() + diff --git a/tests/integration/interface/allocator_c_tests.cpp b/tests/integration/interface/allocator_c_tests.cpp new file mode 100644 index 000000000..991c4a84f --- /dev/null +++ b/tests/integration/interface/allocator_c_tests.cpp @@ -0,0 +1,160 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "gtest/gtest.h" + +#include "umpire/interface/umpire.h" + +class AllocatorCTest : + public ::testing::TestWithParam< const char* > +{ + public: + virtual void SetUp() + { + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + umpire_resourcemanager_get_allocator_by_name(&rm, GetParam(), &m_allocator);; + } + + virtual void TearDown() + { + } + + umpire_allocator m_allocator; + + const size_t m_big = 64; + const size_t m_small = 8; + const size_t m_nothing = 0; +}; + +TEST_P(AllocatorCTest, AllocateDeallocateBig) +{ + double* data = (double*) umpire_allocator_allocate(&m_allocator, m_big*sizeof(double)); + ASSERT_NE(nullptr, data); + + umpire_allocator_deallocate(&m_allocator, data); +} + +TEST_P(AllocatorCTest, AllocateDeallocateSmall) +{ + double* data = (double*) umpire_allocator_allocate(&m_allocator, m_small*sizeof(double)); + ASSERT_NE(nullptr, data); + + umpire_allocator_deallocate(&m_allocator, data); +} + +TEST_P(AllocatorCTest, AllocateDeallocateNothing) +{ + double* data = (double*) umpire_allocator_allocate(&m_allocator, m_nothing*sizeof(double)); + ASSERT_NE(nullptr, data); + + umpire_allocator_deallocate(&m_allocator, data); +} + +TEST_P(AllocatorCTest, GetSize) +{ + const size_t size = m_big * sizeof(double); + + double* data = (double*) umpire_allocator_allocate(&m_allocator, m_big*sizeof(double)); + + ASSERT_EQ(size, umpire_allocator_get_size(&m_allocator, data)); + + umpire_allocator_deallocate(&m_allocator, data); +} + +TEST_P(AllocatorCTest, GetAllocatorById) +{ + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + int alloc_id = umpire_allocator_get_id(&m_allocator); + + umpire_allocator alloc_two; + umpire_resourcemanager_get_allocator_by_id(&rm, alloc_id, &alloc_two); + ASSERT_EQ(alloc_id, umpire_allocator_get_id(&alloc_two)); +} + +TEST_P(AllocatorCTest, SizeAndHighWatermark) +{ + double* data_one = (double*) umpire_allocator_allocate(&m_allocator, m_big*sizeof(double)); + ASSERT_NE(nullptr, data_one); + + double* data_two = (double*) umpire_allocator_allocate(&m_allocator, m_big*sizeof(double)); + ASSERT_NE(nullptr, data_two); + + double* data_three = (double*) umpire_allocator_allocate(&m_allocator, m_big*sizeof(double)); + ASSERT_NE(nullptr, data_three); + + size_t total_size = 3*m_big*sizeof(double); + + ASSERT_EQ(total_size, umpire_allocator_get_current_size(&m_allocator)); + ASSERT_EQ(total_size, umpire_allocator_get_high_watermark(&m_allocator)); + + umpire_allocator_deallocate(&m_allocator, data_one); + ASSERT_EQ((2*m_big*sizeof(double)), umpire_allocator_get_current_size(&m_allocator)); + ASSERT_EQ(total_size, umpire_allocator_get_high_watermark(&m_allocator)); + + umpire_allocator_deallocate(&m_allocator, data_two); + ASSERT_EQ((m_big*sizeof(double)), umpire_allocator_get_current_size(&m_allocator)); + ASSERT_EQ(total_size, umpire_allocator_get_high_watermark(&m_allocator)); + + umpire_allocator_deallocate(&m_allocator, data_three); + ASSERT_EQ(0, umpire_allocator_get_current_size(&m_allocator)); + ASSERT_EQ(total_size, umpire_allocator_get_high_watermark(&m_allocator)); +} + +const char* allocator_names[] = { + "HOST" +#if defined(UMPIRE_ENABLE_DEVICE) + , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) + , "UM" +#endif +#if defined(UMPIRE_ENABLE_CUDA) + , "DEVICE_CONST" +#endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif +}; + +INSTANTIATE_TEST_CASE_P( + Allocators, + AllocatorCTest, + ::testing::ValuesIn(allocator_names)); + +//TEST(AllocatorC, RegisterAllocator) +//{ +// umpire_resourcemanager rm; +// umpire_resourcemanager_get_instance(&rm); +// +// umpire_allocator alloc; +// umpire_resourcemanager_get_allocator_by_name(&rm, "HOST", &alloc); +// +// umpire_resourcemanager_register_allocator( +// "my_host_allocator_copy", +// &alloc); +// +// SUCCEED(); +//} + +// TEST(Allocator, DeallocateThrow) +// { +// umpire_resourcemanager* rm = umpire_resourcemanager_get_instance(); +// double* ptr = new double[20]; +// ASSERT_ANY_THROW( umpire_resourcemanager_deallocate(rm, ptr) ); +// +// delete[] ptr; +// } +// diff --git a/tests/integration/interface/operation_c_tests.cpp b/tests/integration/interface/operation_c_tests.cpp new file mode 100644 index 000000000..27ebd8aed --- /dev/null +++ b/tests/integration/interface/operation_c_tests.cpp @@ -0,0 +1,444 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "gtest/gtest.h" + +#include "umpire/interface/umpire.h" + +#if defined(UMPIRE_ENABLE_CUDA) +#include +#endif + +class OperationTest : + public ::testing::TestWithParam< ::testing::tuple > +{ + public: + virtual void SetUp() { + + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + umpire_resourcemanager_get_allocator_by_name(&rm, ::testing::get<0>(GetParam()), &source_allocator);; + umpire_resourcemanager_get_allocator_by_name(&rm, ::testing::get<1>(GetParam()), &dest_allocator);; + + source_array = (float*) umpire_allocator_allocate(&source_allocator, m_size*sizeof(float)); + dest_array = (float*) umpire_allocator_allocate(&dest_allocator, m_size*sizeof(float)); + + umpire_allocator host_allocator; + umpire_resourcemanager_get_allocator_by_name(&rm, "HOST", &host_allocator);; + + check_array = (float*) umpire_allocator_allocate(&host_allocator, m_size*sizeof(float)); + } + + virtual void TearDown() { + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + umpire_allocator host_allocator; + umpire_resourcemanager_get_allocator_by_name(&rm, "HOST", &host_allocator);; + + if (source_array) + umpire_allocator_deallocate(&source_allocator, source_array); + + if (dest_array) + umpire_allocator_deallocate(&dest_allocator, dest_array); + + if (check_array) + umpire_allocator_deallocate(&host_allocator, check_array); + } + + float* source_array; + float* dest_array; + float* check_array; + + const size_t m_size = 1024; + + umpire_allocator source_allocator; + umpire_allocator dest_allocator; +}; + +class CopyTest : + public OperationTest +{ +}; + +TEST_P(CopyTest, Copy) { + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + for (size_t i = 0; i < m_size; i++) { + source_array[i] = i; + } + + umpire_resourcemanager_copy_all(&rm, dest_array, source_array); + umpire_resourcemanager_copy_all(&rm, check_array, dest_array); + + for (size_t i = 0; i < m_size; i++) { + ASSERT_FLOAT_EQ(source_array[i], check_array[i]); + } +} + +TEST_P(CopyTest, CopyOffset) +{ + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + check_array[10] = 3.14; + + umpire_resourcemanager_copy_with_size(&rm, &dest_array[11], &check_array[10], sizeof(float)); + umpire_resourcemanager_copy_with_size(&rm, &check_array[0], &dest_array[11], sizeof(float)); + + ASSERT_EQ(check_array[0], check_array[10]); +} + +const char* copy_sources[] = { + "HOST" +#if defined(UMPIRE_ENABLE_UM) + , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif +}; + +const char* copy_dests[] = { + "HOST" +#if defined(UMPIRE_ENABLE_DEVICE) + , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) + , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif +}; + + +INSTANTIATE_TEST_CASE_P( + Copies, + CopyTest, + ::testing::Combine( + ::testing::ValuesIn(copy_sources), + ::testing::ValuesIn(copy_dests) +)); + +class MemsetTest : + public OperationTest +{ +}; + +TEST_P(MemsetTest, Memset) { + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + umpire_resourcemanager_memset_all(&rm, source_array, 0); + + umpire_resourcemanager_copy_all(&rm, check_array, source_array); + + for (size_t i = 0; i < m_size; i++) { + ASSERT_EQ(0, check_array[i]); + } +} + +const char* memset_sources[] = { + "HOST" +#if defined(UMPIRE_ENABLE_DEVICE) + , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) + , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif +}; + +const char* memset_dests[] = { + "HOST" +}; + +INSTANTIATE_TEST_CASE_P( + Sets, + MemsetTest, + ::testing::Combine( + ::testing::ValuesIn(memset_sources), + ::testing::ValuesIn(memset_dests) +)); + +class ReallocateTest : + public OperationTest +{ +}; + +TEST_P(ReallocateTest, Reallocate) +{ + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + const size_t reallocated_size = (m_size/2); + + umpire_resourcemanager_memset_all(&rm, source_array, 0); + + float* reallocated_array = + (float*) umpire_resourcemanager_reallocate(&rm, source_array, reallocated_size*sizeof(float)); + + ASSERT_EQ( + umpire_allocator_get_size(&source_allocator, reallocated_array), + reallocated_size*sizeof(float)); + + umpire_resourcemanager_copy_with_size(&rm, check_array, reallocated_array, reallocated_size*sizeof(float)); + + for (size_t i = 0; i < reallocated_size; i++) { + ASSERT_FLOAT_EQ(check_array[i], 0); + } + + source_array = nullptr; +} + +TEST_P(ReallocateTest, ReallocateLarger) +{ + umpire_resourcemanager rm; + umpire_resourcemanager_get_instance(&rm); + + const size_t reallocated_size = (m_size+50); + + umpire_resourcemanager_memset_all(&rm, source_array, 0); + + float* reallocated_array = + (float*) umpire_resourcemanager_reallocate(&rm, source_array, reallocated_size*sizeof(float)); + + ASSERT_EQ( + umpire_allocator_get_size(&source_allocator, reallocated_array), + reallocated_size*sizeof(float)); + + float* reallocated_check_array = + (float*) umpire_resourcemanager_reallocate(&rm, check_array, reallocated_size*sizeof(float)); + + umpire_resourcemanager_copy_with_size(&rm, reallocated_check_array, reallocated_array, reallocated_size*sizeof(float)); + + for (size_t i = 0; i < m_size; i++) { + ASSERT_FLOAT_EQ(reallocated_check_array[i], 0); + } + + umpire_resourcemanager_deallocate(&rm, reallocated_check_array); + + source_array = nullptr; + check_array = nullptr; +} + +// TEST_P(ReallocateTest, ReallocateWithAllocator) +// { +// umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); +// +// const size_t reallocated_size = (m_size+50); +// +// float* reallocated_array = +// static_cast( +// rm.reallocate(source_array, reallocated_size*sizeof(float), *source_allocator)); +// +// ASSERT_EQ( +// source_allocator->getSize(reallocated_array), +// reallocated_size*sizeof(float)); +// +// rm.deallocate(reallocated_array); +// source_array = nullptr; +// } + +const char* reallocate_sources[] = { + "HOST" +#if defined(UMPIRE_ENABLE_UM) + , "UM" +#endif +#if defined(UMPIRE_ENABLE_DEVICE) + , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_PINNED) + , "PINNED" +#endif +}; + +const char* reallocate_dests[] = { + "HOST" +}; + +INSTANTIATE_TEST_CASE_P( + Reallocate, + ReallocateTest, + ::testing::Combine( + ::testing::ValuesIn(reallocate_sources), + ::testing::ValuesIn(reallocate_dests) +)); + +// class MoveTest : +// public OperationTest +// { +// }; +// +// TEST_P(MoveTest, Move) +// { +// auto& rm = umpire::ResourceManager::getInstance(); +// +// // this works because source should always be host! +// for (size_t i = 0; i < m_size; i++) { +// source_array[i] = i; +// } +// +// float* moved_array = static_cast(rm.move(source_array, *dest_allocator)); +// +// if ( dest_allocator->getAllocationStrategy() +// == source_allocator->getAllocationStrategy()) { +// ASSERT_EQ(moved_array, source_array); +// } +// +// rm.copy(check_array, moved_array); +// +// for (size_t i = 0; i < m_size; i++) { +// ASSERT_FLOAT_EQ(check_array[i], i); +// } +// +// dest_allocator->deallocate(moved_array); +// source_array = nullptr; +// } +// +// const std::string move_sources[] = { +// "HOST" +// #if defined(UMPIRE_ENABLE_UM) +// , "UM" +// #endif +// #if defined(UMPIRE_ENABLE_PINNED) +// , "PINNED" +// #endif +// }; +// +// const std::string move_dests[] = { +// "HOST" +// #if defined(UMPIRE_ENABLE_DEVICE) +// , "DEVICE" +// #endif +// #if defined(UMPIRE_ENABLE_UM) +// , "UM" +// #endif +// #if defined(UMPIRE_ENABLE_PINNED) +// , "PINNED" +// #endif +// }; +// +// INSTANTIATE_TEST_CASE_P( +// Move, +// MoveTest, +// ::testing::Combine( +// ::testing::ValuesIn(move_sources), +// ::testing::ValuesIn(move_dests) +// )); +// +// #if defined(UMPIRE_ENABLE_CUDA) +// class AdviceTest : +// public OperationTest +// { +// }; +// +// TEST_P(AdviceTest, ReadMostly) +// { +// auto& op_registry = umpire::op::MemoryOperationRegistry::getInstance(); +// auto strategy = source_allocator->getAllocationStrategy(); +// +// int device = 0; +// +// auto m_advice_operation = op_registry.find( +// "READ_MOSTLY", +// strategy, +// strategy); +// +// if (dest_allocator->getPlatform() == umpire::Platform::cpu) { +// device = cudaCpuDeviceId; +// } +// +// ASSERT_NO_THROW({ +// m_advice_operation->apply( +// source_array, +// nullptr, +// device, +// m_size); +// }); +// } +// +// TEST_P(AdviceTest, PreferredLocation) +// { +// auto& op_registry = umpire::op::MemoryOperationRegistry::getInstance(); +// auto strategy = source_allocator->getAllocationStrategy(); +// +// int device = 0; +// +// auto m_advice_operation = op_registry.find( +// "PREFERRED_LOCATION", +// strategy, +// strategy); +// +// if (dest_allocator->getPlatform() == umpire::Platform::cpu) { +// device = cudaCpuDeviceId; +// } +// +// ASSERT_NO_THROW({ +// m_advice_operation->apply( +// source_array, +// nullptr, +// device, +// m_size); +// }); +// } +// +// TEST_P(AdviceTest, AccessedBy) +// { +// auto& op_registry = umpire::op::MemoryOperationRegistry::getInstance(); +// auto strategy = source_allocator->getAllocationStrategy(); +// +// int device = 0; +// +// auto m_advice_operation = op_registry.find( +// "ACCESSED_BY", +// strategy, +// strategy); +// +// if (dest_allocator->getPlatform() == umpire::Platform::cpu) { +// device = cudaCpuDeviceId; +// } +// +// ASSERT_NO_THROW({ +// m_advice_operation->apply( +// source_array, +// nullptr, +// device, +// m_size); +// }); +// } +// +// const std::string advice_sources[] = { +// "UM" +// }; +// +// const std::string advice_dests[] = { +// "HOST" +// , "DEVICE" +// }; +// +// INSTANTIATE_TEST_CASE_P( +// Advice, +// AdviceTest, +// ::testing::Combine( +// ::testing::ValuesIn(advice_sources), +// ::testing::ValuesIn(advice_dests) +// )); +// +// #endif diff --git a/tests/integration/interface/umpire_fortran_interface.f b/tests/integration/interface/umpire_fortran_interface.f new file mode 100644 index 000000000..a21ebea5e --- /dev/null +++ b/tests/integration/interface/umpire_fortran_interface.f @@ -0,0 +1,51 @@ + +module umpire_fortran_test + use iso_c_binding + use fruit + use umpire_mod + implicit none + +contains + subroutine allocate_sixty_four + integer(C_INT), pointer :: array(:) + type(C_PTR) data_ptr + integer i + + type(UmpireAllocator) allocator + type(UmpireResourceManager) rm + + rm = rm%get_instance() + + allocator = rm%get_allocator_by_id(0) + + data_ptr = allocator%allocate(c_sizeof(i)*10); + call c_f_pointer(data_ptr, array, [ 10 ]) + + do i = 1, 10 + array(i) = i*i + enddo + + write(*, *) (array(i), i=1,10) + + end subroutine allocate_sixty_four + +end module umpire_fortran_test + +program fortran_test + use fruit + use umpire_fortran_test + implicit none + logical ok + + call init_fruit + + call allocate_sixty_four + + call fruit_summary + call fruit_finalize + + call is_all_successful(ok) + if (.not. ok) then + call exit(1) + endif +end program fortran_test diff --git a/tests/integration/memory_resource_traits_tests.cpp b/tests/integration/memory_resource_traits_tests.cpp new file mode 100644 index 000000000..4f3fa96a0 --- /dev/null +++ b/tests/integration/memory_resource_traits_tests.cpp @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include "gtest/gtest.h" + +#include "umpire/config.hpp" + +#include "umpire/ResourceManager.hpp" +#include "umpire/resource/MemoryResourceTraits.hpp" + +TEST(Traits, DDR) { + umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); + + using namespace umpire::resource; + + MemoryResourceTraits traits; + traits.kind = MemoryResourceTraits::memory_type::DDR; + + auto allocator = rm.getAllocator(traits); + + float* data = static_cast(allocator.allocate(sizeof(float)*1024)); + + for (int i = 0; i < 1024; i++) { + data[i] = 3.14; + } + + for (int i = 0; i < 1024; i++) { + EXPECT_FLOAT_EQ(data[i], 3.14); + } +} diff --git a/tests/integration/operation_tests.cpp b/tests/integration/operation_tests.cpp index a7d1fcd60..636c022b6 100644 --- a/tests/integration/operation_tests.cpp +++ b/tests/integration/operation_tests.cpp @@ -118,17 +118,23 @@ TEST_P(CopyTest, InvalidSize) const std::string copy_sources[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; const std::string copy_dests[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; @@ -179,9 +185,13 @@ TEST_P(MemsetTest, InvalidPointer) const std::string memset_sources[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; @@ -335,9 +345,13 @@ TEST_P(ReallocateTest, ReallocateWithAllocatorFail) const std::string reallocate_sources[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; @@ -387,17 +401,23 @@ TEST_P(MoveTest, Move) const std::string move_sources[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; const std::string move_dests[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; diff --git a/tests/integration/replay/CMakeLists.txt b/tests/integration/replay/CMakeLists.txt new file mode 100644 index 000000000..91965e0f3 --- /dev/null +++ b/tests/integration/replay/CMakeLists.txt @@ -0,0 +1,31 @@ +############################################################################## +# Copyright (c) 2018, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory +# +# Created by David Beckingsale, david@llnl.gov +# LLNL-CODE-747640 +# +# All rights reserved. +# +# This file is part of Umpire. +# +# For details, see https://github.com/LLNL/Umpire +# Please also see the LICENSE file for MIT license. +############################################################################## +find_program (BASH_PROGRAM bash) + +set (replay_integration_tests_depends + umpire) + +if (BASH_PROGRAM) + blt_add_executable( + NAME replay_tests + SOURCES replay_tests.cpp + DEPENDS_ON ${replay_integration_tests_depends}) + + add_test( + NAME replay_tests + COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/replay_tests.bash ${CMAKE_BINARY_DIR}/bin + ) + +endif() diff --git a/tests/integration/replay/replay_tests.bash b/tests/integration/replay/replay_tests.bash new file mode 100644 index 000000000..4e94d8116 --- /dev/null +++ b/tests/integration/replay/replay_tests.bash @@ -0,0 +1,28 @@ +#!/bin/bash +testprogram=$1/replay_tests +replayprogram=$1/replay + +# +# The following program will generate a CSV file of Umpire activity that +# may be replayed. +# +UMPIRE_REPLAY="On" $testprogram >& replay_test1.csv +if [ $? -nq 0 ]; then + echo FAIL + exit 1 +fi + +# +# Now replay from the activity captured in the replay_test1.csv file +# +UMPIRE_REPLAY="On" $replayprogram replay_test1.csv >& replay_test2.csv +if [ $? -nq 0 ]; then + echo FAIL + exit 1 +fi + +# +# Now, compare the results being careful to allow for different object +# references (everything else should be the same). +# +exit 0 diff --git a/tests/integration/replay/replay_tests.cpp b/tests/integration/replay/replay_tests.cpp new file mode 100644 index 000000000..ec64ed3c2 --- /dev/null +++ b/tests/integration/replay/replay_tests.cpp @@ -0,0 +1,110 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include "umpire/ResourceManager.hpp" +#include "umpire/strategy/SlotPool.hpp" +#include "umpire/strategy/MonotonicAllocationStrategy.hpp" +#include "umpire/strategy/DynamicPool.hpp" +#include "umpire/strategy/AllocationStrategy.hpp" +#include "umpire/Allocator.hpp" +#include "umpire/op/MemoryOperation.hpp" +#include "umpire/strategy/AllocationAdvisor.hpp" +#include "umpire/strategy/ThreadSafeAllocator.hpp" +#include "umpire/strategy/FixedPool.hpp" + +class replayTest { +public: + replayTest() : testAllocations(3), allocationSize(16) + { + auto& rm = umpire::ResourceManager::getInstance(); + + rm.makeAllocator( + "host_simpool_defaults", rm.getAllocator("HOST")); + allocatorNames.push_back("host_simpool_defaults"); + + rm.makeAllocator( + "host_simpool_spec1", rm.getAllocator("HOST"), 9876, 1234); + allocatorNames.push_back("host_simpool_spec1"); + + rm.makeAllocator( + "host_simpool_spec2", rm.getAllocator("HOST"), 9876, 1234); + allocatorNames.push_back("host_simpool_spec2"); + + rm.makeAllocator( + "read_only_um", rm.getAllocator("UM"), "READ_MOSTLY"); + allocatorNames.push_back("read_only_um"); + + rm.makeAllocator( + "preferred_location_host", rm.getAllocator("UM"), + "PREFERRED_LOCATION", rm.getAllocator("HOST")); + allocatorNames.push_back("preferred_location_host"); + + rm.makeAllocator( + "MONOTONIC 1024", 1024, rm.getAllocator("HOST")); + allocatorNames.push_back("MONOTONIC 1024"); + + rm.makeAllocator( + "host_slot_pool", 64, rm.getAllocator("HOST")); + allocatorNames.push_back("host_slot_pool"); + + rm.makeAllocator( + "thread_safe_allocator", rm.getAllocator("HOST")); + allocatorNames.push_back("thread_safe_allocator"); + + struct data { char _[1024*1024]; }; + + rm.makeAllocator>( + "fixed_pool_allocator", rm.getAllocator("HOST")); + allocatorNames.push_back("fixed_pool_allocator"); + } + + ~replayTest( void ) + { + } + + void runTest() + { + for ( int i = 0; i < testAllocations; ++i ) { + for ( auto n : allocatorNames ) { + auto& rm = umpire::ResourceManager::getInstance(); + auto alloc = rm.getAllocator(n); + allocations.push_back( std::make_pair(alloc.allocate( ++allocationSize ), n) ); + } + } + + for ( auto ptr : allocations ) { + auto& rm = umpire::ResourceManager::getInstance(); + auto alloc = rm.getAllocator(ptr.second); + alloc.deallocate( ptr.first ); + } + } +private: + const int testAllocations; + std::size_t allocationSize; + std::vector allocatorNames; + std::vector> allocations; +}; + + +int main(int , char** ) +{ + replayTest test; + + test.runTest(); + + return 0; +} diff --git a/tests/integration/strategy_tests.cpp b/tests/integration/strategy_tests.cpp index b2d44106c..b6395cd24 100644 --- a/tests/integration/strategy_tests.cpp +++ b/tests/integration/strategy_tests.cpp @@ -26,6 +26,7 @@ #include "umpire/strategy/ThreadSafeAllocator.hpp" #include "umpire/strategy/FixedPool.hpp" #include "umpire/strategy/AllocationAdvisor.hpp" +#include "umpire/strategy/SizeLimiter.hpp" #if defined(_OPENMP) #include @@ -37,9 +38,13 @@ static int subsequent_min_size = 512; const char* AllocationDevices[] = { "HOST" -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) , "DEVICE" +#endif +#if defined(UMPIRE_ENABLE_UM) , "UM" +#endif +#if defined(UMPIRE_ENABLE_PINNED) , "PINNED" #endif }; @@ -97,7 +102,7 @@ TEST_P(StrategyTest, Duplicate) auto& rm = umpire::ResourceManager::getInstance(); ASSERT_TRUE(rm.isAllocator(allocatorName)); - + ASSERT_EQ(allocator->getName(), poolName.str()); ASSERT_ANY_THROW( @@ -107,7 +112,7 @@ TEST_P(StrategyTest, Duplicate) INSTANTIATE_TEST_CASE_P(Allocations, StrategyTest, ::testing::ValuesIn(AllocationDevices)); -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) TEST(SimpoolStrategy, Device) { auto& rm = umpire::ResourceManager::getInstance(); @@ -177,7 +182,7 @@ TEST(MonotonicStrategy, Host) ASSERT_EQ(allocator.getName(), "host_monotonic_pool"); } -#if defined(UMPIRE_ENABLE_CUDA) +#if defined(UMPIRE_ENABLE_DEVICE) TEST(MonotonicStrategy, Device) { auto& rm = umpire::ResourceManager::getInstance(); @@ -192,7 +197,9 @@ TEST(MonotonicStrategy, Device) ASSERT_GE(allocator.getHighWatermark(), 100); ASSERT_EQ(allocator.getName(), "device_monotonic_pool"); } +#endif // defined(UMPIRE_ENABLE_DEVICE) +#if defined(UMPIRE_ENABLE_UM) TEST(MonotonicStrategy, UM) { auto& rm = umpire::ResourceManager::getInstance(); @@ -207,18 +214,20 @@ TEST(MonotonicStrategy, UM) ASSERT_GE(allocator.getHighWatermark(), 100); ASSERT_EQ(allocator.getName(), "um_monotonic_pool"); } +#endif // defined(UMPIRE_ENABLE_UM) +#if defined(UMPIRE_ENABLE_CUDA) TEST(AllocationAdvisor, Create) { auto& rm = umpire::ResourceManager::getInstance(); ASSERT_NO_THROW( - auto read_only_alloc = + auto read_only_alloc = rm.makeAllocator( "read_only_um", rm.getAllocator("UM"), "READ_MOSTLY")); ASSERT_ANY_THROW( - auto failed_alloc = + auto failed_alloc = rm.makeAllocator( "read_only_um", rm.getAllocator("UM"), "FOOBAR")); } @@ -229,7 +238,7 @@ TEST(AllocationAdvisor, Host) auto um_allocator = rm.getAllocator("UM"); auto host_allocator = rm.getAllocator("HOST"); - auto read_only_alloc = + auto read_only_alloc = rm.makeAllocator( "preferred_location_host", um_allocator, "PREFERRED_LOCATION", host_allocator); @@ -240,7 +249,7 @@ TEST(AllocationAdvisor, Host) }); } -#endif +#endif // defined(UMPIRE_ENABLE_CUDA) TEST(FixedPool, Host) { @@ -282,3 +291,65 @@ TEST(ThreadSafeAllocator, Host) } #endif + +TEST(SizeLimiter, Host) +{ + auto& rm = umpire::ResourceManager::getInstance(); + + auto alloc = rm.makeAllocator( + "size_limited_alloc", rm.getAllocator("HOST"), 64); + + void* data = nullptr; + + EXPECT_NO_THROW(data = alloc.allocate(64)); + + EXPECT_THROW({ + void* tmp_data = alloc.allocate(1024); + UMPIRE_USE_VAR(tmp_data); + }, umpire::util::Exception); + + EXPECT_NO_THROW( + alloc.deallocate(data)); +} + + +TEST(CoalesceTest, CanCoalesce) +{ + auto& rm = umpire::ResourceManager::getInstance(); + + auto alloc = rm.makeAllocator( + "host_simpool", rm.getAllocator("HOST"), 64, 64); + + void* ptr_one = alloc.allocate(62); + void* ptr_two = alloc.allocate(1024); + alloc.deallocate(ptr_two); + + EXPECT_NO_THROW(rm.coalesce(alloc)); + + alloc.deallocate(ptr_one); +} + +TEST(CoalesceTest, Unsupported) +{ + auto& rm = umpire::ResourceManager::getInstance(); + + EXPECT_THROW( + rm.coalesce(rm.getAllocator("HOST")), + umpire::util::Exception); +} + +TEST(ReleaseTest, Works) +{ + auto& rm = umpire::ResourceManager::getInstance(); + + auto alloc = rm.makeAllocator( + "host_simpool_for_release", rm.getAllocator("HOST"), 64, 64); + + void* ptr_one = alloc.allocate(62); + void* ptr_two = alloc.allocate(1024); + alloc.deallocate(ptr_two); + + EXPECT_NO_THROW(alloc.release()); + + alloc.deallocate(ptr_one); +} diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 376df5bf2..f3dde531a 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -21,16 +21,6 @@ blt_add_test( NAME resource_manager_tests COMMAND resource_manager_tests) -blt_add_executable( - NAME allocator_tests - SOURCES allocator_tests.cpp - OUTPUT_DIR ${UMPIRE_TEST_OUTPUT_DIR} - DEPENDS_ON umpire gtest gmock) - -blt_add_test( - NAME allocator_tests - COMMAND allocator_tests) - add_subdirectory(alloc) add_subdirectory(op) add_subdirectory(resource) diff --git a/tests/unit/alloc/memory_allocator_tests.cpp b/tests/unit/alloc/memory_allocator_tests.cpp index 765797b1c..fc4d87126 100644 --- a/tests/unit/alloc/memory_allocator_tests.cpp +++ b/tests/unit/alloc/memory_allocator_tests.cpp @@ -24,6 +24,11 @@ using namespace umpire::alloc; #include "umpire/alloc/CudaPinnedAllocator.hpp" #endif +#if defined(UMPIRE_ENABLE_ROCM) +#include "umpire/alloc/AmAllocAllocator.hpp" +#include "umpire/alloc/AmPinnedAllocator.hpp" +#endif + #include "gtest/gtest.h" template @@ -46,6 +51,8 @@ REGISTER_TYPED_TEST_CASE_P( #if defined(UMPIRE_ENABLE_CUDA) using test_types = ::testing::Types; +#elif defined(UMPIRE_ENABLE_ROCM) +using test_types = ::testing::Types; #else using test_types = ::testing::Types; #endif diff --git a/tests/unit/allocator_tests.cpp b/tests/unit/allocator_tests.cpp index 159de0edc..95f6a6665 100644 --- a/tests/unit/allocator_tests.cpp +++ b/tests/unit/allocator_tests.cpp @@ -31,9 +31,9 @@ class MockAllocationStrategy : public umpire::strategy::AllocationStrategy MOCK_METHOD1(allocate, void*(size_t bytes)); MOCK_METHOD1(deallocate, void(void* ptr)); - MOCK_METHOD0(getCurrentSize, long()); - MOCK_METHOD0(getHighWatermark, long()); - MOCK_METHOD0(getPlatform, umpire::Platform()); + MOCK_METHOD0(getCurrentSize, long() noexcept); + MOCK_METHOD0(getHighWatermark, long() noexcept); + MOCK_METHOD0(getPlatform, umpire::Platform() noexcept); }; class AllocatorTest : public ::testing::Test diff --git a/tests/unit/resource/CMakeLists.txt b/tests/unit/resource/CMakeLists.txt index 94661bea3..372f6bff6 100644 --- a/tests/unit/resource/CMakeLists.txt +++ b/tests/unit/resource/CMakeLists.txt @@ -12,11 +12,13 @@ # For details, see https://github.com/LLNL/Umpire # Please also see the LICENSE file for MIT license. ############################################################################## -blt_add_executable( - NAME resource_tests - SOURCES resource_tests.cpp - DEPENDS_ON umpire umpire_resource umpire_util umpire gtest gmock) +if (ENABLE_GMOCK) + blt_add_executable( + NAME resource_tests + SOURCES resource_tests.cpp + DEPENDS_ON umpire umpire_resource umpire_util umpire gtest gmock) -blt_add_test( - NAME resource_tests - COMMAND resource_tests) + blt_add_test( + NAME resource_tests + COMMAND resource_tests) +endif () diff --git a/tests/unit/resource/resource_tests.cpp b/tests/unit/resource/resource_tests.cpp index 0398bb496..3d409d533 100644 --- a/tests/unit/resource/resource_tests.cpp +++ b/tests/unit/resource/resource_tests.cpp @@ -32,21 +32,21 @@ struct TestAllocator TEST(DefaultMemoryResource, Constructor) { - auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0); + auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0, umpire::resource::MemoryResourceTraits{}); SUCCEED(); } TEST(DefaultMemoryResource, AllocateDeallocate) { - auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0); + auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0, umpire::resource::MemoryResourceTraits{}); double* pointer = (double*)alloc->allocate(10*sizeof(double)); ASSERT_NE(pointer, nullptr); } TEST(DefaultMemoryResource, GetSize) { - auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0); + auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0, umpire::resource::MemoryResourceTraits{}); double* pointer = (double*) alloc->allocate(10); ASSERT_EQ(alloc->getCurrentSize(), 10); @@ -62,7 +62,7 @@ TEST(DefaultMemoryResource, GetSize) TEST(DefaultMemoryResource, GetHighWatermark) { - auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0); + auto alloc = std::make_shared >(umpire::Platform::cpu, "TEST", 0, umpire::resource::MemoryResourceTraits{}); ASSERT_EQ(alloc->getHighWatermark(), 0); double* pointer = (double*)alloc->allocate(10); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 000000000..a928ca68b --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,19 @@ +############################################################################## +# Copyright (c) 2018, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory +# +# Created by David Beckingsale, david@llnl.gov +# LLNL-CODE-747640 +# +# All rights reserved. +# +# This file is part of Umpire. +# +# For details, see https://github.com/LLNL/Umpire +# Please also see the LICENSE file for MIT license. +############################################################################## +blt_add_executable( + NAME replay + SOURCES replay.cpp + DEPENDS_ON + umpire) diff --git a/tools/replay.cpp b/tools/replay.cpp new file mode 100644 index 000000000..259acc542 --- /dev/null +++ b/tools/replay.cpp @@ -0,0 +1,285 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory +// +// Created by David Beckingsale, david@llnl.gov +// LLNL-CODE-747640 +// +// All rights reserved. +// +// This file is part of Umpire. +// +// For details, see https://github.com/LLNL/Umpire +// Please also see the LICENSE file for MIT license. +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "umpire/ResourceManager.hpp" +#include "umpire/strategy/SlotPool.hpp" +#include "umpire/strategy/MonotonicAllocationStrategy.hpp" +#include "umpire/strategy/DynamicPool.hpp" +#include "umpire/strategy/AllocationStrategy.hpp" +#include "umpire/Allocator.hpp" +#include "umpire/op/MemoryOperation.hpp" +#include "umpire/strategy/AllocationAdvisor.hpp" +#include "umpire/strategy/SizeLimiter.hpp" +#include "umpire/strategy/ThreadSafeAllocator.hpp" +#include "umpire/strategy/FixedPool.hpp" + +class CSVRow { +public: + std::string const& operator[](std::size_t index) const { return m_data[index]; } + std::size_t size() const { return m_data.size(); } + void readNextRow(std::istream& str) { + std::string line; + std::getline(str, line); + + std::stringstream lineStream(line); + std::string cell; + + m_data.clear(); + while ( std::getline(lineStream, cell, ',') ) { + m_data.push_back(cell); + } + + // This checks for a trailing comma with no data after it. + if (!lineStream && cell.empty()) { + // If there was a trailing comma then add an empty element. + m_data.push_back(""); + } + } +private: + std::vector m_data; +}; + +std::istream& operator>>(std::istream& str, CSVRow& data) +{ + data.readNextRow(str); + return str; +} + +class Replay { + public: + // Replay( const std::string& filename ) : + Replay( const char* _fname ) : + m_filename(_fname) + , m_file(m_filename) + , m_rm(umpire::ResourceManager::getInstance()) + { + if ( ! m_file.is_open() ) + usage_and_exit( "Unable to open file " + m_filename ); + } + + static void usage_and_exit( const std::string& errorMessage ) { + std::cerr << errorMessage + << std::endl + << "Usage: replay " + << std::endl; + exit (1); + } + + void run(void) + { + while ( m_file >> m_row ) { + if ( m_row[0] != "REPLAY" ) + continue; + + if ( m_row[1] == "makeAllocator" ) { + replay_makeAllocator(); + } + else if ( m_row[1] == "allocate" ) { + replay_allocate(); + } + else if ( m_row[1] == "deallocate" ) { + replay_deallocate(); + } + else { + std::cout << m_row[1] << "\n"; + } + } + } + + private: + std::string m_filename; + std::ifstream m_file; + umpire::ResourceManager& m_rm; + std::unordered_map m_allocators; // key(alloc_obj), val(alloc name) + std::unordered_map m_allocated_ptrs; // key(alloc_ptr), val(replay_alloc_ptr) + CSVRow m_row; + + template + void get_from_string( const std::string& s, T& val ) + { + std::istringstream ss(s); + ss >> val; + } + + void replay_allocate( void ) + { + void* alloc_obj_ref; + std::size_t alloc_size; + void* alloc_ptr; + void* replay_alloc_ptr; + + get_from_string(m_row[m_row.size() - 1], alloc_ptr); + get_from_string(m_row[m_row.size() - 2], alloc_obj_ref); + get_from_string(m_row[m_row.size() - 3], alloc_size); + + auto n_iter = m_allocators.find(alloc_obj_ref); + + if ( n_iter == m_allocators.end() ) + return; // Just skip unknown allocators + + const std::string& allocName = n_iter->second; + + auto alloc = m_rm.getAllocator(allocName); + replay_alloc_ptr = alloc.allocate(alloc_size); + + m_allocated_ptrs[alloc_ptr] = replay_alloc_ptr; + } + + void replay_deallocate( void ) + { + void* alloc_obj_ref; + void* alloc_ptr; + + get_from_string(m_row[m_row.size() - 1], alloc_obj_ref); + get_from_string(m_row[m_row.size() - 2], alloc_ptr); + + auto n_iter = m_allocators.find(alloc_obj_ref); + + if ( n_iter == m_allocators.end() ) + return; // Just skip unknown allocators + + auto p_iter = m_allocated_ptrs.find(alloc_ptr); + if ( p_iter == m_allocated_ptrs.end() ) { + std::cerr << "Unable to find pointer to free\n"; + return; // Just skip unknown allocators + } + + void* replay_alloc_ptr = p_iter->second; + m_allocated_ptrs.erase(p_iter); + + const std::string& allocName = n_iter->second; + + auto alloc = m_rm.getAllocator(allocName); + alloc.deallocate(replay_alloc_ptr); + } + + void replay_makeAllocator( void ) + { + bool introspection = ( m_row[3] == "true" ); + const std::string& name = m_row[4]; + void* alloc_obj_ref; + + get_from_string(m_row[m_row.size() - 1], alloc_obj_ref); + + if ( m_row[2] == "umpire::strategy::AllocationAdvisor" ) { + const std::string& allocName = m_row[5]; + const std::string& adviceOperation = m_row[6]; + // Now grab the optional fields + if (m_row.size() > 8) { + const std::string& accessingAllocatorName = m_row[7]; + if ( introspection ) m_rm.makeAllocator( name, m_rm.getAllocator(allocName), adviceOperation, m_rm.getAllocator(accessingAllocatorName)); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName), adviceOperation, m_rm.getAllocator(accessingAllocatorName)); + } + else { + if ( introspection ) m_rm.makeAllocator( name, m_rm.getAllocator(allocName), adviceOperation); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName), adviceOperation); + } + } + else if ( m_row[2] == "umpire::strategy::DynamicPool" ) { + const std::string& allocName = m_row[5]; + std::size_t min_initial_alloc_size; // Optional: m_row[6] + std::size_t min_alloc_size; // Optional: m_row[7] + + // Now grab the optional fields + if (m_row.size() > 8) { + get_from_string(m_row[6], min_initial_alloc_size); + get_from_string(m_row[7], min_alloc_size); + if ( introspection ) m_rm.makeAllocator(name, m_rm.getAllocator(allocName), min_initial_alloc_size, min_alloc_size); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName), min_initial_alloc_size, min_alloc_size); + } + else if ( m_row.size() > 7 ) { + get_from_string(m_row[6], min_initial_alloc_size); + if ( introspection ) m_rm.makeAllocator(name, m_rm.getAllocator(allocName), min_initial_alloc_size); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName), min_initial_alloc_size); + } + else { + if ( introspection ) m_rm.makeAllocator(name, m_rm.getAllocator(allocName)); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName)); + } + } + else if ( m_row[2] == "umpire::strategy::MonotonicAllocationStrategy" ) { + std::size_t capacity; + get_from_string(m_row[5], capacity); + + const std::string& allocName = m_row[6]; + + if ( introspection ) m_rm.makeAllocator(name, capacity, m_rm.getAllocator(allocName)); + else m_rm.makeAllocator(name, capacity, m_rm.getAllocator(allocName)); + } + else if ( m_row[2] == "umpire::strategy::SizeLimiter" ) { + const std::string& allocName = m_row[5]; + std::size_t size_limit; + get_from_string(m_row[6], size_limit); + + if ( introspection ) m_rm.makeAllocator(name, m_rm.getAllocator(allocName), size_limit); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName), size_limit); + } + else if ( m_row[2] == "umpire::strategy::SlotPool" ) { + const std::string& allocName = m_row[6]; + std::size_t slots; + get_from_string(m_row[5], slots); + + if ( introspection ) m_rm.makeAllocator(name, slots, m_rm.getAllocator(allocName)); + else m_rm.makeAllocator(name, slots, m_rm.getAllocator(allocName)); + } + else if ( m_row[2] == "umpire::strategy::ThreadSafeAllocator" ) { + const std::string& allocName = m_row[5]; + + if ( introspection ) m_rm.makeAllocator(name, m_rm.getAllocator(allocName)); + else m_rm.makeAllocator(name, m_rm.getAllocator(allocName)); + } + else if ( m_row[2] == "umpire::strategy::FixedPool" ) { + // + // Need to skip FixedPool for now since I haven't figured out how to + // dynamically parse/creat the data type parameter + // + return; +#if 0 + const std::string& allocName = m_row[5]; + std::size_t PoolSize = hmm... + + if ( introspection ) m_rm.makeAllocator, true>(name, m_rm.getAllocator(allocName)); + else m_rm.makeAllocator, false>(name, m_rm.getAllocator(allocName)); +#endif + } + else { + std::cerr << "Unknown class (" << m_row[2] << "), skipping.\n"; + return; + } + + m_allocators[alloc_obj_ref] = name; + } +}; + +int main(int ac, char** av) +{ + if ( ac != 2 ) + Replay::usage_and_exit( "Incorrect number of program arguments" ); + + Replay replay(av[1]); + + replay.run(); + + return 0; +}