├── .gitignore ├── .readthedocs.yml ├── .travis.yml ├── CHANGELOG.md ├── CMakeLists.txt ├── COPYRIGHT ├── Dockerfile ├── LICENSE ├── NOTICE ├── README.md ├── RELEASE ├── cmake ├── BuildEnv.cmake ├── BuildType.cmake └── SetupUmapThirdParty.cmake ├── config └── config.h.in ├── docs ├── doxygen │ └── Doxyfile └── sphinx │ ├── advanced_configuration.rst │ ├── caliper.rst │ ├── conf.py │ ├── contribution_guide.rst │ ├── environment_variables.rst │ ├── getting_started.rst │ ├── index.rst │ ├── requirements.txt │ └── sparse_store.rst ├── examples ├── CMakeLists.txt ├── bfs │ ├── CMakeLists.txt │ ├── README.md │ ├── bfs_kernel.hpp │ ├── data │ │ ├── bfs_level_reference │ │ ├── edge_list_rmat_s10_0_of_4 │ │ ├── edge_list_rmat_s10_1_of_4 │ │ ├── edge_list_rmat_s10_2_of_4 │ │ └── edge_list_rmat_s10_3_of_4 │ ├── main.cpp │ ├── rmat_graph_generator │ │ ├── CMakeLists.txt │ │ ├── generate_edge_list.cpp │ │ ├── hash.hpp │ │ ├── ingest_edge_list.cpp │ │ └── rmat_edge_generator.hpp │ ├── run_bfs.sh │ └── utility │ │ ├── bitmap.hpp │ │ ├── commandline.hpp │ │ ├── file.hpp │ │ ├── map_file.hpp │ │ ├── mmap.hpp │ │ ├── open_mp.hpp │ │ ├── time.hpp │ │ └── umap_fits_file.hpp ├── stream │ ├── CMakeLists.txt │ ├── run_stream.sh │ └── stream.c └── umapsort │ ├── CMakeLists.txt │ ├── commandline.hpp │ ├── main.cpp │ ├── map_file.hpp │ ├── run_umapsort.sh │ └── time.hpp ├── host-configs └── toss_3_x86_64 │ └── gcc_4_8_5.cmake ├── scripts ├── apply-license-info.sh ├── bamboo │ └── build_and_test.sh ├── check-license-info.sh ├── make_release_tarball.sh ├── travis │ └── build_and_test.sh └── umap-license.txt ├── src ├── CMakeLists.txt └── umap │ ├── Buffer.cpp │ ├── Buffer.hpp │ ├── CMakeLists.txt │ ├── EvictManager.cpp │ ├── EvictManager.hpp │ ├── EvictWorkers.cpp │ ├── EvictWorkers.hpp │ ├── FillWorkers.cpp │ ├── FillWorkers.hpp │ ├── PageDescriptor.cpp │ ├── PageDescriptor.hpp │ ├── RegionDescriptor.hpp │ ├── RegionManager.cpp │ ├── RegionManager.hpp │ ├── Uffd.cpp │ ├── Uffd.hpp │ ├── WorkQueue.hpp │ ├── WorkerPool.hpp │ ├── store │ ├── SparseStore.cpp │ ├── SparseStore.h │ ├── Store.cpp │ ├── Store.hpp │ ├── StoreFile.cpp │ └── StoreFile.h │ ├── umap.cpp │ ├── umap.h │ └── util │ ├── Exception.cpp │ ├── Exception.hpp │ ├── Logger.cpp │ ├── Logger.hpp │ └── Macros.hpp ├── tests ├── CMakeLists.txt ├── caliper_trace │ ├── CMakeLists.txt │ └── caliper_trace.cpp ├── churn │ ├── CMakeLists.txt │ ├── churn.cpp │ ├── churntest_umap.sh │ ├── options.cpp │ └── options.h ├── flush_buffer │ ├── CMakeLists.txt │ └── flush_buffer.cpp ├── multi_thread │ ├── CMakeLists.txt │ └── multi_thread.cpp ├── pfbenchmark │ ├── CMakeLists.txt │ ├── nvmebenchmark.cpp │ ├── pfbenchmark.cpp │ └── test_results │ │ ├── data.csv │ │ ├── data.xlsx │ │ ├── runbenchmarks.sh │ │ └── sysinfo ├── tools │ ├── adjust_free_mem │ ├── flush_cache │ ├── freemem │ └── waste_memory ├── umap-sparsestore │ ├── CMakeLists.txt │ └── umap-sparsestore.cpp └── utility │ ├── commandline.hpp │ ├── file.hpp │ └── umap_file.hpp └── thirdparty_licenses.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.12" 13 | # You can also specify other tool versions: 14 | # nodejs: "20" 15 | # rust: "1.70" 16 | # golang: "1.20" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: docs/sphinx/conf.py 21 | 22 | # Build documentation with MkDocs 23 | #mkdocs: 24 | # configuration: mkdocs.yml 25 | 26 | # Optionally build your docs in additional formats such as PDF and ePub 27 | formats: all 28 | 29 | # Optionally set the version of Python and requirements required to build your docs 30 | python: 31 | install: 32 | - requirements: docs/sphinx/requirements.txt 33 | 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | services: docker 2 | dist: trusty 3 | language: cpp 4 | env: 5 | global: 6 | - DO_BUILD=yes 7 | - DO_TEST=no 8 | - GTEST_COLOR=1 9 | matrix: 10 | include: 11 | - compiler: gcc5 12 | env: 13 | - COMPILER=g++ 14 | - IMG=gcc-5 15 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 16 | - DO_MEMCHECK=no 17 | - compiler: gcc6 18 | env: 19 | - COMPILER=g++ 20 | - IMG=gcc-6 21 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 22 | - compiler: gcc7 23 | env: 24 | - COMPILER=g++ 25 | - IMG=gcc-7 26 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 27 | - compiler: gcc8 28 | env: 29 | - COMPILER=g++ 30 | - IMG=gcc-8 31 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 32 | - compiler: gcc8 33 | env: 34 | - COMPILER=g++ 35 | - IMG=gcc-8 36 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=On" 37 | - compiler: clang4 38 | env: 39 | - COMPILER=clang++ 40 | - IMG=clang-4 41 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 42 | - compiler: clang5 43 | env: 44 | - COMPILER=clang++ 45 | - IMG=clang-5 46 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 47 | - compiler: clang6 48 | env: 49 | - COMPILER=clang++ 50 | - IMG=clang-6 51 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=Off" 52 | - compiler: clang6 53 | env: 54 | - COMPILER=clang++ 55 | - IMG=clang-6 56 | - CMAKE_EXTRA_FLAGS="-DENABLE_DEBUG_LOGGING=On" 57 | 58 | script: 59 | - docker run --rm --user='root' -v ${TRAVIS_BUILD_DIR}:/home/axom axom/compilers:$IMG chown -R axom /home/axom 60 | - docker run --rm -v ${TRAVIS_BUILD_DIR}:/home/axom -e COMPILER -e DO_BUILD -e DO_TEST -e DO_MEMCHECK -e CMAKE_EXTRA_FLAGS -e GTEST_COLOR axom/compilers:$IMG ./scripts/travis/build_and_test.sh 61 | 62 | after_success: 63 | - if [[ "${CMAKE_EXTRA_FLAGS}" == *"ENABLE_COVERAGE"* ]] ; then bash <(curl -s https://codecov.io/bash) -a "-f" >& /dev/null; fi 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ## [2.1.0] 9 | ### Added 10 | - SparseStore: A sparse multi-file backing store interface included [Details](https://llnl-umap.readthedocs.io/en/latest/sparse_store.html) 11 | - Build Option: -DENABLE_DISPLAY_STATS: option to display statistics before uunmap returns [Details](https://llnl-umap.readthedocs.io/en/latest/advanced_configuration.html) 12 | - Build Option: -DENABLE_TESTS_LINK_STATIC_UMAP: This allows test binaries to link Umap statically or dynamically [Details](https://llnl-umap.readthedocs.io/en/latest/advanced_configuration.html) 13 | - Flush Buffer: umap_flush() allows users to explicitly flush dirty pages [#2b36757] 14 | 15 | ### Fixed 16 | - Fixed C-compatibility of umap.h [#c489653] 17 | - Duplicate stats removed [#3b59db9] 18 | - deadlock in evict_region [#aeb4e6b] 19 | - Thread-safe umap_ex() and uunmap() API calls ([#13863a6],[#12a740b]) 20 | 21 | ## [2.0.0] 22 | 23 | [Unreleased]: https://github.com/LLNL/umap/tree/develop 24 | [2.1.0]: https://github.com/LLNL/umap/tree/release-test 25 | [2.0.0]: https://github.com/LLNL/umap/tree/release-2.0.0 26 | [#13863a6]: https://github.com/LLNL/umap/commit/13863a60121072660bb459d03f1a185b082a37c8 27 | [#aeb4e6b]: https://github.com/LLNL/umap/commit/86fd5937aeb4e6bb73dd689a6975cb225a4b3725 28 | [#12a740b]: https://github.com/LLNL/umap/commit/12a740bd85ddd57d50a00071644d4d654176375c 29 | [#c489653]: https://github.com/LLNL/umap/commit/c4896535eacd9266a0c00744f9c14c389a3c89a0 30 | [#3b59db9]: https://github.com/LLNL/umap/commit/3b59db93d29bca092e702ea93f9712e8cc5f147f 31 | [#2b36757]: https://github.com/LLNL/umap/commit/2b36757ae5f83836dafc63702b12bda480f17540 32 | 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | cmake_minimum_required (VERSION 3.5.1) 8 | project(umap 9 | VERSION 2.1.0 10 | LANGUAGES CXX C 11 | ) 12 | 13 | OPTION (ENABLE_TESTS "Selects whether tests are built." On) 14 | OPTION (ENABLE_LOGGING "Build umap with Logging enabled" On) 15 | OPTION (ENABLE_DISPLAY_STATS "Display umap statistics when closing" Off) 16 | OPTION (ENABLE_TESTS_LINK_STATIC_UMAP "Build tests statically linked to umap" Off) 17 | 18 | include(cmake/BuildEnv.cmake) 19 | include(cmake/BuildType.cmake) 20 | include(cmake/SetupUmapThirdParty.cmake) 21 | 22 | set(UMAP_DEBUG_LOGGING ${ENABLE_LOGGING}) 23 | set(UMAP_DISPLAY_STATS ${ENABLE_DISPLAY_STATS}) 24 | configure_file( 25 | ${PROJECT_SOURCE_DIR}/config/config.h.in 26 | ${PROJECT_BINARY_DIR}/src/umap/config.h) 27 | 28 | include_directories ( "${CMAKE_SOURCE_DIR}/src" "${CMAKE_BINARY_DIR}/src") 29 | 30 | add_subdirectory(src) 31 | 32 | if (ENABLE_TESTS) 33 | #set(STATIC_UMAP_LINK ${ENABLE_TESTS_LINK_STATIC_UMAP} CACHE BOOL "Linking option for Umap binaries" FORCE) 34 | add_subdirectory(examples) 35 | add_subdirectory(tests) 36 | endif() 37 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Intellectual Property Notice 2 | ------------------------------ 3 | 4 | Umap is licensed under the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, 5 | Ferbruary 1999 (LICENSE-LGPL 6 | or https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt). 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License (as published by the Free 10 | Software Foundation) version 2.1 dated February 1999. This program is 11 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A 13 | PARTICULAR PURPOSE. See the terms and conditions of the GNU Lesser General 14 | Public License for more details. You should have received a copy of the GNU 15 | Lesser General Public License along with this program; if not, write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 | MA 02111-1307 USA. 18 | 19 | SPDX usage 20 | ------------ 21 | 22 | Individual files contain SPDX tags instead of the full license text. 23 | This enables machine processing of license information based on the SPDX 24 | License Identifiers that are available here: https://spdx.org/licenses/ 25 | 26 | SPDX-License-Identifier: LGPL-2.1-only 27 | 28 | External Packages 29 | ------------------- 30 | 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/ubuntu:22.04 2 | RUN apt update && apt full-upgrade -y && apt install -y git cmake g++ linux-headers-generic 3 | RUN adduser --disabled-password umap && mkdir ~umap/umap 4 | COPY . /home/umap/umap/ 5 | RUN cd ~umap/umap \ 6 | && cmake . && make && make install \ 7 | && ldconfig \ 8 | && chown -R umap:umap ~umap 9 | USER umap 10 | WORKDIR /home/umap 11 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of 2 | Energy by Lawrence Livermore National Laboratory under Contract 3 | DE-AC52-07NA27344. 4 | 5 | This work was prepared as an account of work sponsored by an agency of 6 | the United States Government. Neither the United States Government nor 7 | Lawrence Livermore National Security, LLC, nor any of their employees 8 | makes any warranty, expressed or implied, or assumes any legal liability 9 | or responsibility for the accuracy, completeness, or usefulness of any 10 | information, apparatus, product, or process disclosed, or represents that 11 | its use would not infringe privately owned rights. 12 | 13 | Reference herein to any specific commercial product, process, or service 14 | by trade name, trademark, manufacturer, or otherwise does not necessarily 15 | constitute or imply its endorsement, recommendation, or favoring by the 16 | United States Government or Lawrence Livermore National Security, LLC. 17 | 18 | The views and opinions of authors expressed herein do not necessarily 19 | state or reflect those of the United States Government or Lawrence 20 | Livermore National Security, LLC, and shall not be used for advertising 21 | or product endorsement purposes. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UMAP v2.1.0 2 | 3 | [![Travis Build Status](https://travis-ci.com/LLNL/umap.svg?branch=develop)](https://travis-ci.com/LLNL/umap) 4 | [![Documentation Status](https://readthedocs.org/projects/llnl-umap/badge/?version=develop)](https://llnl-umap.readthedocs.io/en/develop/?badge=develop) 5 | 6 | Umap is a library that provides an mmap()-like interface to a simple, user- 7 | space page fault handler based on the userfaultfd Linux feature (starting with 8 | 4.3 linux kernel). The use case is to have an application specific buffer of 9 | pages cached from a large file, i.e. out-of-core execution using memory map. 10 | 11 | The src directory in the top level contains the source code for the library. 12 | 13 | The tests directory contains various tests written to test the library 14 | including a hello world program for userfaultfd based upon code from the 15 | [userfaultfd-hello-world project](http://noahdesu.github.io/2016/10/10/userfaultfd-hello-world.html). 16 | 17 | `LLNL-CODE-733797` 18 | 19 | ## Quick Start 20 | 21 | *Building umap* is trivial. In the root directory of the repo 22 | 23 | ```bash 24 | mkdir build 25 | cd build 26 | cmake -DCMAKE_INSTALL_PREFIX= .. 27 | make install 28 | ``` 29 | 30 | The default for cmake is to build a Debug version of the software. If you 31 | would like to build an optimized (-O3) version, simply run 32 | ```bash 33 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= .. 34 | ``` 35 | 36 | ### Docker Container 37 | There is a `Dockerfile` included in the repository to make it easier to build a container image with a basic Umap development environment. 38 | 39 | A few caveats: 40 | The [runtime requirements](#runtime-requirements) of the Docker container are the same as the non-containerized Umap. Additionally, it's important to note that Umap checks the kernel headers present in the build-time environment to decide whether or not WP mode should be enabled. The included `Dockerfile` will always build Umap with WP support enabled because the Ubuntu 22.04 kernel headers included in the the container indicate that WP is supported, even if the host kernel doesn't actually support that feature. Umap will return an error at runtime if it's built with WP enabled but run on a kernel without WP support. 41 | 42 | Docker, as a security measure, uses a `seccomp` profile to restrict the syscalls allowed to be made by an application running inside a container to a minimal subset. Umap relies on being able to make host kernel syscalls that are otherwise blocked by Docker's default `seccomp` profile. Specifically, Umap relies on the `userfaultfd` syscall. See [here](https://docs.docker.com/engine/security/seccomp/#significant-syscalls-blocked-by-the-default-profile]) for more information about which syscalls are blocked by Docker's default `seccomp` profile. 43 | 44 | #### Example: Building and running the Umap Docker container 45 | ```bash 46 | docker build -t umap . 47 | docker run --security-opt seccomp=unconfined -it umap bash 48 | ``` 49 | 50 | #### Example: Running the Umap container with a `seccomp` whitelist 51 | It's also possible to run the container with a `seccomp` whitelist rather than disabling confinement entirely. 52 | First, create a `userfaultfd.json` file: 53 | ```json 54 | {"names": ["userfaultfd"], "action": "SCMP_ACT_ALLOW"} 55 | ``` 56 | 57 | When running the container: 58 | ```bash 59 | docker run --security-opt seccomp=userfaultfd.json -it umap bash 60 | ``` 61 | 62 | ## Build Requirements 63 | Building Umap requires a C++ compiler, CMake >= 3.5.1, as well as the Linux kernel headers. 64 | 65 | Additionally, Umap will automatically enable read/write mode *at library compile time* if it detects that the installed kernel supports it by looking at the defined symbols in the kernel headers. Some Linux distributions, such as Ubuntu 20.04.2, provide a 5.8 kernel that supports read/write mode but don't ship with headers that define these symbols. 66 | 67 | Read-only mode: Linux kernel >= 4.3 68 | 69 | Read/write mode: Linux kernel >= 5.7 (>= 5.10 preferred) 70 | 71 | Note: Some early mainline releases of Linux that included support for read/write mode (between 5.7 and 5.9) contain a known bug that causes an application to hang indefinitely when performing a write. It's recommended to update to a 5.10 kernel if this bug is encountered. 72 | 73 | ## Runtime Requirements 74 | At runtime, Umap requires a kernel that supports the same features as it was built against. For example, running a version of Umap compiled against kernel 5.10 on a system with kernel 4.18 will result in runtime errors caused by write functionality not being present in the 4.18 kernel. 75 | 76 | On Linux >= 5.4, the `sysctl` variable `vm.unprivileged_userfaultfd` needs to be set to `1` in order to use Umap in both read-only and read/write modes as a non-root user. The value of this variable may be determined by running `sysctl vm.unprivileged_userfaultfd` or `cat /proc/sys/vm/unprivileged_userfaultfd`. 77 | 78 | ## Applications 79 | 80 | Applications can be found at https://github.com/LLNL/umap-apps. 81 | 82 | ## Documentation 83 | 84 | Both user and code documentation is available 85 | [here](http://llnl-umap.readthedocs.io/). 86 | 87 | If you have build problems, we have comprehensive 88 | [build sytem documentation](https://llnl-umap.readthedocs.io/en/develop/advanced_configuration.html) too! 89 | 90 | ## Publications 91 | 92 | ```Peng, I.B., Gokhale, M., Youssef, K., Iwabuchi, K. and Pearce, R., 2021. Enabling Scalable and Extensible Memory-mapped Datastores in Userspace. IEEE Transactions on Parallel and Distributed Systems. doi: 10.1109/TPDS.2021.3086302.``` 93 | 94 | ```Peng, I.B., McFadden, M., Green, E., Iwabuchi, K., Wu, K., Li, D., Pearce, R. and Gokhale, M., 2019, November. UMap: Enabling application-driven optimizations for page management. In 2019 IEEE/ACM Workshop on Memory Centric High Performance Computing (MCHPC) (pp. 71-78). IEEE.``` 95 | 96 | ## License 97 | 98 | - The license is [LGPL](/LICENSE). 99 | - [thirdparty_licenses.md](/thirdparty_licenses.md) 100 | 101 | ## Contact 102 | 103 | - Ivy Peng (ivybopeng@gmail.com) 104 | - Maya Gokhale (gokhale2@llnl.gov) 105 | - Eric Green (green77@llnl.gov) 106 | -------------------------------------------------------------------------------- /RELEASE: -------------------------------------------------------------------------------- 1 | Umap Version 2.1 2 | 3 | Copyright (c) 2016-20, Lawrence Livermore National Security, LLC. and other 4 | UMAP Project Developers. Produced at the Lawrence Livermore National 5 | Laboratory. All rights reserved. See details in umap/LICENSE. 6 | 7 | Open Source – LGPL-2.1-only 8 | LLNL-CODE-733797 9 | 10 | Created by Abhik Sarkar (sarkar6@llnl.gov) 11 | 12 | Contributors: 13 | - Marty McFadden (mcfadden8@llnl.gov) 14 | - Eric Green (green77@llnl.gov) 15 | - Ivy Peng (peng8@llnl.gov) 16 | - Maya Gokhale (gokhale2@llnl.gov) 17 | - Abhik Sarkar (sarkar6@llnl.gov) 18 | -------------------------------------------------------------------------------- /cmake/BuildEnv.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2019 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | 8 | # Set up the language supported for the build environment 9 | set (CMAKE_CXX_STANDARD 11) 10 | set (CMAKE_C_STANDARD 99) 11 | -------------------------------------------------------------------------------- /cmake/BuildType.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | # Set a default build type if none was specified 8 | set( default_build_type "Release" ) 9 | if ( EXISTS "${CMAKE_SOURCE_DIR}/.git" ) 10 | set( default_build_type "Debug" ) 11 | endif() 12 | 13 | if ( NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES ) 14 | message(STATUS "Setting build type to '${default_build_type}' as none was specified.") 15 | set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE 16 | STRING "Choose the type of build." FORCE) 17 | # Set the possible values of build type for cmake-gui 18 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" 19 | "MinSizeRel" "RelWithDebInfo") 20 | endif() 21 | -------------------------------------------------------------------------------- /cmake/SetupUmapThirdParty.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | 8 | -------------------------------------------------------------------------------- /config/config.h.in: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | #ifndef _UMAP_UMAPCONFIG_H 9 | #define _UMAP_UMAPCONFIG_H 10 | #define UMAP_VERSION_MAJOR @umap_VERSION_MAJOR@ 11 | #define UMAP_VERSION_MINOR @umap_VERSION_MINOR@ 12 | #define UMAP_VERSION_PATCH @umap_VERSION_PATCH@ 13 | #cmakedefine UMAP_DEBUG_LOGGING 14 | #cmakedefine UMAP_DISPLAY_STATS 15 | #endif 16 | -------------------------------------------------------------------------------- /docs/sphinx/advanced_configuration.rst: -------------------------------------------------------------------------------- 1 | .. _advanced_configuration: 2 | 3 | ====================== 4 | Advanced Configuration 5 | ====================== 6 | 7 | Listed below are the umap-specific options which may be used when configuring 8 | your build directory with cmake. Some CMake-specific options have also been 9 | added to show how to make additional changes to the build configuration. 10 | 11 | .. code-block:: bash 12 | 13 | cmake -DENABLE_LOGGING=Off 14 | 15 | Here is a summary of the configuration options, their default value, and meaning: 16 | 17 | =========================== ======== ========================================== 18 | Variable Default Meaning 19 | =========================== ======== ========================================== 20 | ``ENABLE_LOGGING`` On Enable Logging within umap 21 | ``ENABLE_DISPLAY_STATS`` Off Enable Displaying umap stats at close 22 | ``ENABLE_TESTS`` On Enable building and installation of tests 23 | ``ENABLE_TESTS_LINK_STATIC_UMAP`` Off Generate tests statically linked with Umap 24 | ``CMAKE_CXX_COMPILER`` not set Specify C++ compiler to use 25 | ``DCMAKE_CC_COMPILER`` not set Specify C compiler to use 26 | =========================== ======== ========================================== 27 | 28 | These arguments are explained in more detail below: 29 | 30 | * ``ENABLE_LOGGING`` 31 | This option enables usage of Logging services for umap. When this support is 32 | enabled, you may cause umap library to emit log files by setting the ``UMAP_LOG_LEVEL`` 33 | environment variable to "INFO" (for information-only logs), "WARNING" (for warning info 34 | logs), "ERROR" for (for errors only logs), and "DEBUG" for all debug messages to be emitted to a log file. 35 | 36 | * ``ENABLE_DISPLAY_STATS`` 37 | When this option is turned on, the umap library will display its runtime 38 | statistics before unmap() completes. 39 | 40 | * ``ENABLE_TESTS`` 41 | This option enables the compilation of the programs under the tests directory 42 | of the umap source code. 43 | 44 | * ``ENABLE_TESTS_LINK_STATIC_UMAP`` 45 | This option enables the compilation of the programs under the tests directory 46 | of the umap source code against static umap library. 47 | -------------------------------------------------------------------------------- /docs/sphinx/caliper.rst: -------------------------------------------------------------------------------- 1 | .. _caliper 2 | 3 | ========================================== 4 | Integration within Caliper 5 | ========================================== 6 | 7 | UMap can be integrated into the Caliper: A Performance Analysis Toolbox in a Library for providing page access pattern profiling. 8 | We describe the steps for leveraging UMap in Caliper as follows: 9 | 10 | * Install Caliper from https://github.com/LLNL/Caliper.git to 11 | 12 | * Build UMap by running cmake with -Dcaliper_DIR=/share/cmake/caliper 13 | 14 | * An example application is provided in /tests/caliper_trace. Make sure it is compiled 15 | 16 | * Enable the page fault tracing before running the program to be profiled as follows 17 | 18 | .. code:: bash 19 | 20 | export CALI_SERVICES_ENABLE=alloc,event,trace,recorder 21 | export CALI_ALLOC_TRACK_ALLOCATIONS=true 22 | export CALI_ALLOC_RESOLVE_ADDRESSES=true 23 | 24 | * This should produce a .cali output file with an automatically generated filename, e.g., "200611-155825_69978_QSZC2zryxwRh.cali". 25 | 26 | 27 | Now we describe how to analyze the profiling results. To simply print all records captured from Caliper, simply use: 28 | 29 | .. code:: bash 30 | 31 | cali-query -t 32 | 33 | 34 | For advanced queries, e.g. count the number of page faults per memory region: 35 | 36 | .. code:: bash 37 | 38 | cali-query -q "select alloc.label#pagefault.address,count() group by alloc.label#pagefault.address where pagefault.address format table" 39 | 40 | -------------------------------------------------------------------------------- /docs/sphinx/contribution_guide.rst: -------------------------------------------------------------------------------- 1 | .. _contribution_guide: 2 | 3 | ================== 4 | Contribution Guide 5 | ================== 6 | 7 | This document is intented for developers who want to add new features or 8 | bugfixes to umap. It assumes you have some familiarity with git and GitHub. 9 | It will discuss what a good pull request (PR) looks like, and the tests that 10 | your PR must pass before it can be merged into umap. 11 | 12 | -------------- 13 | Forking umap 14 | -------------- 15 | 16 | If you aren't an umap deveolper at LLNL, then you won't have permission to 17 | push new branches to the repository. First, you should create a `fork 18 | `_. This will create a copy of the umap 19 | repository that you own, and will ensure you can push your changes up to GitHub 20 | and create pull requests. 21 | 22 | ^^^^^^^^^^^^^^^^^^^^^^^^ 23 | Developing a New Feature 24 | ^^^^^^^^^^^^^^^^^^^^^^^^ 25 | 26 | New features should be based on the ``develop`` branch. When you want to create 27 | a new feature, first ensure you have an up-to-date copy of the ``develop`` 28 | branch: 29 | 30 | .. code-block:: bash 31 | 32 | $ git checkout develop 33 | $ git pull origin develop 34 | 35 | You can now create a new branch to develop your feature on: 36 | 37 | .. code-block:: bash 38 | 39 | $ git checkout -b feature/ 40 | 41 | Proceed to develop your feature on this branch, and add tests that will exercise 42 | your new code. If you are creating new methods or classes, please add Doxygen 43 | documentation. 44 | 45 | Once your feature is complete and your tests are passing, you can push your 46 | branch to GitHub and create a PR. 47 | 48 | ^^^^^^^^^^^^^^^^^^^^ 49 | Developing a Bug Fix 50 | ^^^^^^^^^^^^^^^^^^^^ 51 | 52 | First, check if the change you want to make has been fixed in ``develop``. If 53 | so, we suggest you either start using the ``develop`` branch, or temporarily 54 | apply the fix to whichever version of umap you are using. 55 | 56 | If the bug is still unfixed, first make sure you have an up-to-date copy 57 | of the develop branch: 58 | 59 | .. code-block:: bash 60 | 61 | $ git checkout develop 62 | $ git pull origin develop 63 | 64 | Then create a new branch for your bugfix: 65 | 66 | .. code-block:: bash 67 | 68 | $ git checkout -b bugfix/ 69 | 70 | First, add a test that reproduces the bug you have found. Then develop your 71 | bugfix as normal, and ensure to ``make test`` to check your changes actually 72 | fix the bug. 73 | 74 | Once you are finished, you can push your branch to GitHub, then create a PR. 75 | 76 | ^^^^^^^^^^^^^^^^^^^^^^^ 77 | Creating a Pull Request 78 | ^^^^^^^^^^^^^^^^^^^^^^^ 79 | 80 | You can create a new PR `here `_. 81 | Ensure that your PR base is the ``develop`` branch of umap. 82 | 83 | Add a descriptive title explaining the bug you fixed or the feature you have 84 | added, and put a longer description of the changes you have made in the comment 85 | box. 86 | 87 | Once your PR has been created, it will be run through our automated tests and 88 | also be reviewed by umap team members. Providing the branch passes both the 89 | tests and reviews, it will be merged into umap. 90 | 91 | ^^^^^ 92 | Tests 93 | ^^^^^ 94 | 95 | Umap uses Bamboo for continuous integration tests. Our tests are automatically 96 | run against every new pull request, and passing all tests is a requirement for 97 | merging your PR. If you are developing a bugfix or a new feature, please add a 98 | test that checks the correctness of your new code. 99 | 100 | Umap's tests are all in the ``tests`` directory. 101 | -------------------------------------------------------------------------------- /docs/sphinx/environment_variables.rst: -------------------------------------------------------------------------------- 1 | .. _environment_variables: 2 | 3 | ============================= 4 | Runtime Environment Variables 5 | ============================= 6 | 7 | The interface to the umap runtime library configuration is controlled by 8 | the following environment variables. 9 | 10 | .. code-block:: bash 11 | 12 | UMAP_PAGESIZE=$((2*4096)) your_program_that_uses_umap 13 | 14 | The following environment varialbles may be set: 15 | 16 | * ``UMAP_PAGE_FILLERS`` 17 | This is the number of worker threads that will perform read operations from 18 | the backing store (including read-ahead) for a specific umap region. 19 | 20 | Default: `std::thread::hardware_concurrency()` 21 | 22 | * ``UMAP_PAGE_EVICTORS`` 23 | This is the number of worker threads that will perform evictions of pages. 24 | Eviction includes writing to the backing store if the page is dirty and 25 | telling the operating system that the page is no longer needed. 26 | 27 | Default: `std::thread::hardware_concurrency()` 28 | 29 | * ``UMAP_EVICT_HIGH_WATER_THRESHOLD`` 30 | This is an integer percentage of present pages in the Umap Buffer that 31 | informs the Eviction workers that it is time to start evicting pages. 32 | 33 | Default: 90 34 | 35 | * ``UMAP_EVICT_LOW_WATER_THRESHOLD`` 36 | This is an integer percentage of present pages in the Umap Buffer that 37 | informs the Eviction workers when to stop evicting. 38 | 39 | Default: 70 40 | 41 | * ``UMAP_PAGESIZE`` 42 | This is the size of the umap pages. This must be a multiple of the system 43 | page size. 44 | 45 | Default: System Page Size 46 | 47 | * ``UMAP_BUFSIZE`` 48 | This is the total number of umap pages that may be present within the Umap 49 | Buffer. 50 | 51 | Default: (90% of free memory) 52 | 53 | * ``UMAP_MONITOR_FREQ`` 54 | This is the interval (in seconds) for the monitoring thread to print statistics, e.g., filled pages, 55 | free pages and processed events for debugging or tuning. 56 | 57 | Default: 0 58 | -------------------------------------------------------------------------------- /docs/sphinx/getting_started.rst: -------------------------------------------------------------------------------- 1 | .. _getting_started: 2 | 3 | =============== 4 | Getting Started 5 | =============== 6 | 7 | This page provides information on how to quickly get up and running with umap. 8 | 9 | ^^^^^^^^^^^^^ 10 | Dependencies 11 | ^^^^^^^^^^^^^ 12 | At a minimum, cmake 3.5.1 or greater is required for building umap. 13 | 14 | --------------------------- 15 | UMAP Build and Installation 16 | --------------------------- 17 | The following lines should get you up and running: 18 | 19 | .. code-block:: bash 20 | 21 | $ git clone https://github.com/LLNL/umap.git 22 | $ mkdir build && cd build 23 | $ cmake -DCMAKE_INSTALL_PREFIX="" ../umap 24 | $ make 25 | $ make install 26 | 27 | By default, umap will build a Release type build and will use the system 28 | defined directories for installation. To specify different build types or 29 | specify alternate installation paths, see the :doc:`advanced_configuration`. 30 | 31 | Umap install files to the ``lib``, ``include`` and ``bin`` directories of the 32 | ``CMAKE_INSTALL_PREFIX``. 33 | 34 | ----------- 35 | Basic Usage 36 | ----------- 37 | 38 | The interface to umap mirrors that of mmap(2) as shown: 39 | 40 | .. literalinclude:: ../../examples/bfs/utility/map_file.hpp 41 | :lines: 113 42 | 43 | The following code is a simple example of how one may use umap: 44 | 45 | .. literalinclude:: ../../examples/bfs/run_bfs.sh 46 | -------------------------------------------------------------------------------- /docs/sphinx/index.rst: -------------------------------------------------------------------------------- 1 | *********** 2 | UMAP v2.1.0 3 | *********** 4 | 5 | Umap is a library that provides an mmap()-like interface to a simple, user- 6 | space page fault handler based on the userfaultfd Linux feature (starting with 7 | 4.3 linux kernel). The use case is to have an application specific buffer of 8 | pages cached from a large file, i.e. out-of-core execution using memory map. 9 | 10 | - Take a look at our Getting Started guide for all you need to get up and 11 | running with umap. 12 | 13 | - If you are looking for developer documentation on a particular function, 14 | check out the code documentation. 15 | 16 | - Want to contribute? Take a look at our developer and contribution guides. 17 | 18 | Any questions? File an issue on GitHub. 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Basics 23 | 24 | getting_started 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | :caption: Reference 29 | 30 | advanced_configuration 31 | environment_variables 32 | sparse_store 33 | caliper 34 | 35 | .. toctree:: 36 | :maxdepth: 2 37 | :caption: Contributing 38 | 39 | contribution_guide 40 | -------------------------------------------------------------------------------- /docs/sphinx/requirements.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | 8 | breathe 9 | exhale 10 | -------------------------------------------------------------------------------- /docs/sphinx/sparse_store.rst: -------------------------------------------------------------------------------- 1 | .. _sparse_store 2 | 3 | ========================================== 4 | Sparse Multi-files Backing Store Interface 5 | ========================================== 6 | 7 | UMap provides a sparse and multi-files store object called "SparseStore", which partitions the backing file into multiple files that are created dynamically and only when needed. 8 | 9 | A SparseStore object is instantiated in either "create" or "open" mode. 10 | 11 | In "create" mode, the total region size, page size, backing directory path, and partitioning granularity need to be specified. 12 | 13 | In "open" mode, the backing directory path needs to be specified, along with a "read_only" boolean option. 14 | 15 | To instantiate and use a SparseStore object in "create" mode: 16 | 17 | .. code-block:: c 18 | 19 | 20 | Umap::SparseStore * sparse_store; 21 | sparse_store = new Umap::SparseStore(numbytes,page_size,root_path,file_size); 22 | 23 | // set umap flags 24 | int flags = UMAP_PRIVATE; 25 | 26 | if (start_addr != nullptr) 27 | flags |= MAP_FIXED; 28 | 29 | const int prot = PROT_READ|PROT_WRITE; 30 | 31 | /* Map region using UMap, Here, the file descriptor passed to umap is -1, as we do not start with mapping a file 32 | instead, file(s) will be created incrementally as needed using the "SparseStore" object. */ 33 | 34 | region = umap_ex(start_addr, numbytes, prot, flags, -1, 0, sparse_store); 35 | 36 | To instantiate and use a SparseStore object in "open" mode: 37 | 38 | .. code-block:: c 39 | 40 | Umap::SparseStore sparse_store; 41 | bool read_only = true; 42 | sparse_store = new Umap::SparseStore(root_path,read_only); 43 | 44 | // set umap flags 45 | int flags = UMAP_PRIVATE; 46 | 47 | if (start_addr != nullptr) 48 | flags |= MAP_FIXED; 49 | 50 | const int prot = PROT_READ|PROT_WRITE; 51 | 52 | region = umap_ex(start_addr, numbytes, prot, flags, -1, 0, sparse_store); 53 | 54 | 55 | To unmap a region created with SparseStore, the SparseStore object needs to explicitely close the open files and then be deleted: 56 | 57 | .. code-block:: c 58 | 59 | // Unmap region 60 | if (uunmap(region, numbytes) < 0) { 61 | // report failure and exit 62 | } 63 | 64 | int sparse_store_close_files = store->close_files(); 65 | if (sparse_store_close_files != 0 ){ 66 | // report failure and exit 67 | } 68 | delete store; 69 | } 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | add_subdirectory(stream) 8 | add_subdirectory(umapsort) 9 | add_subdirectory(bfs) 10 | if (UMAP_ENABLE_ZFP) 11 | add_subdirectory(zfp) 12 | endif(UMAP_ENABLE_ZFP) 13 | -------------------------------------------------------------------------------- /examples/bfs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(bfs) 2 | 3 | FIND_PACKAGE( OpenMP REQUIRED ) 4 | if(OPENMP_FOUND) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 8 | configure_file( 9 | "${CMAKE_CURRENT_SOURCE_DIR}/run_bfs.sh" 10 | "${CMAKE_CURRENT_BINARY_DIR}/run_bfs.sh" 11 | COPYONLY 12 | ) 13 | 14 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 15 | 16 | add_executable(bfs main.cpp) 17 | 18 | set(CMAKE_SKIP_RPATH TRUE) 19 | 20 | if(STATIC_UMAP_LINK) 21 | set(umap-lib "umap-static") 22 | else() 23 | set(umap-lib "umap") 24 | endif() 25 | 26 | add_dependencies(bfs ${umap-lib}) 27 | target_link_libraries(bfs ${umap-lib}) 28 | 29 | install(TARGETS bfs 30 | LIBRARY DESTINATION lib 31 | ARCHIVE DESTINATION lib/static 32 | RUNTIME DESTINATION bin ) 33 | 34 | else() 35 | message("Skipping bfs, OpenMP required") 36 | endif() 37 | 38 | add_subdirectory(rmat_graph_generator) 39 | -------------------------------------------------------------------------------- /examples/bfs/README.md: -------------------------------------------------------------------------------- 1 | 2 | # BFS 3 | 4 | ## Generate Edge List Using an R-MAT Generator 5 | 6 | ``` 7 | ./rmat_edge_generator/generate_edge_list 8 | 9 | -o [out edge list file name (required)] 10 | 11 | -s [seed for random number generator; default is 123] 12 | 13 | -v [SCALE; The logarithm base two of the number of vertices; default is 17] 14 | 15 | -e [#of edges; default is 2^{17} x 16] 16 | 17 | -a [initiator parameter A; default is 0.57] 18 | 19 | -b [initiator parameter B; default is 0.19] 20 | 21 | -c [initiator parameter C; default is 0.19] 22 | 23 | -r [if true, scrambles edge IDs; default is true] 24 | 25 | -u [if true, generates edges for both directions; default is true] 26 | ``` 27 | 28 | * As for the initiator parameters, see [Graph500, 3.2 Detailed Text Description](https://graph500.org/?page_id=12#sec-3_2) for more details. 29 | 30 | ### Generate Graph 500 Inputs 31 | 32 | ```bash 33 | ./rmat_edge_generator/generate_edge_list -o /mnt/ssd/edge_list -v 20 -e $((2**20*16)) 34 | ```` 35 | 36 | * This command generates a edge list file (/mnt/ssd/edge_list) which contains the edges of a SCALE 20 graph. 37 | * In Graph 500, the number of edges of a graph is \#vertices x 16 (16 is called 'edge factor') as an undirected graph. 38 | * Note that \#edges generated by this generator is \#vertices x 16 x 2 if -u option (generates edges for both directions) is true, which is default. 39 | * This is a multi-threads (OpenMP) program. You can control the number of threads using the environment variable OMP\_NUM\_THREADS. 40 | 41 | 42 | ## Ingest Edge List (construct CSR graph) 43 | 44 | ```bash 45 | ./ingest_edge_list -g /mnt/ssd/csr_graph_file /mnt/ssd/edge_list1 /mnt/ssd/edge_list2 46 | ``` 47 | 48 | * Load edge data from files /mnt/ssd/edge\_list1 and /mnt/ssd/edge\_list2 (you can specify an arbitrary number of files). A CSR graph is constructed in /mnt/ssd/csr\_graph\_file. 49 | * Each line of input files must be a pair of source and destination vertex IDs (unsigned 64bit number). 50 | * This program treats inputs as a directed graph, that is, it does not ingest edges for both directions. 51 | * This is a multi-threads (OpenMP) program. You can control the number of threads using the environment variable OMP\_NUM\_THREADS. 52 | * As for real-world datasets, [SNAP Datasets](http://snap.stanford.edu/data/index.html) is popular in the graph processing community. Please note that some datasets in SNAP are a little different. For example, the first line is a comment; you have to delete the line before running this program. 53 | 54 | 55 | ## Run BFS 56 | 57 | ```bash 58 | ./run_bfs -n [#of vertices] -m [#of edges] -g [/path/to/graph_file] -s 59 | ``` 60 | 61 | * You can get #of vertices and #of edges by running ingest\_edge\_list. 62 | * If '-s' is specified, the program uses system mmap instead of umap. 63 | * The interface to the umap runtime library configuration is controlled by environment variables, see [Umap Runtime Environment Variables](https://llnl-umap.readthedocs.io/en/develop/environment_variables.html). 64 | * This is a multi-threads (OpenMP) program. You can control the number of threads using the environment variable OMP\_NUM\_THREADS. It uses the static schedule. 65 | 66 | 67 | ## Tips for Running Benchmark (on large-scale) 68 | * The size of generated edge lists could be larger than the constructed CSR graph by a few times. As the rmat\_edge\_generator writes edges to files sequentially, you should be able to directly generate edge lists to a parallel file systems without an unreasonable execution time. 69 | * On the other hand, ingest\_edge\_list constructs a CSR graph causing a lot of random writes to a file mapped region (the location of the file is specified by -g option). We highly recommend that you should construct a graph on DRAM space, e.g., tmpfs, although you can still read input edge list files from a parallel file system. 70 | 71 | 72 | ### Example 73 | Run BFS on a SCALE 20 R-MAT graph using 4 threads and system mmap. 74 | ```bash 75 | env OMP_NUM_THREADS=4 ./rmat_edge_generator/generate_edge_list -o /mnt/ssd/edge_list -v 20 -e $((2**20*16)) 76 | env OMP_NUM_THREADS=4 ./ingest_edge_list -g /dev/shm/csr_graph_file /mnt/ssd/edge_list* 77 | mv /dev/shm/csr_graph_file /mnt/ssd/csr_graph_file 78 | sudo sync 79 | sudo echo 3 > /proc/sys/vm/drop_caches # drop page cache 80 | env OMP_NUM_THREADS=4 ./run_bfs -n $((2**20)) -m $((2**20*16*2)) -g /mnt/ssd/csr_graph_file -s 81 | ``` 82 | -------------------------------------------------------------------------------- /examples/bfs/bfs_kernel.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | #ifndef BFS_BFS_KERNEL_HPP 16 | #define BFS_BFS_KERNEL_HPP 17 | 18 | #include 19 | #include 20 | 21 | #ifdef _OPENMP 22 | #include 23 | #endif 24 | 25 | #include "utility/bitmap.hpp" 26 | #include "utility/open_mp.hpp" 27 | 28 | namespace bfs { 29 | 30 | static const uint16_t k_infinite_level = std::numeric_limits::max(); 31 | 32 | /// \brief initialize variables to run BFS 33 | /// \param num_vertices The number of vertices 34 | /// \param level A pointer of level array 35 | /// \param A pointer to an bitset for visited filter 36 | void init_bfs(const size_t num_vertices, uint16_t *const level, uint64_t *visited_filter) { 37 | for (size_t i = 0; i < num_vertices; ++i) 38 | level[i] = k_infinite_level; 39 | for (size_t i = 0; i < utility::bitmap_size(num_vertices); ++i) 40 | visited_filter[i] = 0; 41 | } 42 | 43 | /// \brief Print out the current omp configuration 44 | void print_omp_configuration() { 45 | #ifdef _OPENMP 46 | #pragma omp parallel 47 | { 48 | if (::omp_get_thread_num() == 0) 49 | std::cout << "Run with " << ::omp_get_num_threads() << " threads" << std::endl; 50 | } 51 | #else 52 | std::cout << "Run with a single thread" << std::endl; 53 | #endif 54 | } 55 | 56 | /// \brief BFS kernel. 57 | /// This kernel runs with OpenMP. 58 | /// In order to simplify the implementation of this kernel, 59 | /// some operations are not designed to avoid race conditions 60 | /// as long as they are consistent with the correct status. 61 | /// \param num_vertices The number of vertices 62 | /// \param index A pointer of an index array 63 | /// \param edges A pointer of an edges array 64 | /// \param level A pointer of level array 65 | /// \param visited_filter A pointer of an bitset for visited filter 66 | uint16_t run_bfs(const size_t num_vertices, 67 | const uint64_t *const index, 68 | const uint64_t *const edges, 69 | uint16_t *const level, 70 | uint64_t *visited_filter) { 71 | 72 | print_omp_configuration(); 73 | 74 | uint16_t current_level = 0; 75 | bool visited_new_vertex = false; 76 | 77 | while (true) { /// BFS main loop 78 | 79 | /// BFS loop for a single level 80 | /// We assume that the cost of generating threads at every level is negligible 81 | #ifdef _OPENMP 82 | #pragma omp parallel for schedule(static) 83 | #endif 84 | for (uint64_t src = 0; src < num_vertices; ++src) { /// BFS loop for each level 85 | if (level[src] != current_level) continue; 86 | for (size_t i = index[src]; i < index[src + 1]; ++i) { 87 | const uint64_t trg = edges[i]; 88 | if (!utility::get_bit(visited_filter, trg) && level[trg] == k_infinite_level) { 89 | level[trg] = current_level + 1; 90 | utility::set_bit(visited_filter, trg); 91 | visited_new_vertex = true; 92 | } 93 | } 94 | } 95 | 96 | if (!visited_new_vertex) break; 97 | 98 | ++current_level; 99 | printf("current_level = %d \n", current_level); 100 | visited_new_vertex = false; 101 | } /// End of BFS main loop 102 | 103 | return current_level; 104 | } 105 | 106 | } 107 | #endif //BFS_BFS_KERNEL_HPP 108 | -------------------------------------------------------------------------------- /examples/bfs/rmat_graph_generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") 2 | 3 | FIND_PACKAGE( OpenMP ) 4 | if(OPENMP_FOUND) 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 7 | else() 8 | message("Cannot find OpenMP for the rmat edge generator") 9 | endif() 10 | 11 | add_executable(generate_edge_list generate_edge_list.cpp) 12 | add_executable(ingest_edge_list ingest_edge_list.cpp) 13 | 14 | install(TARGETS generate_edge_list 15 | LIBRARY DESTINATION lib 16 | ARCHIVE DESTINATION lib/static 17 | RUNTIME DESTINATION bin ) 18 | 19 | install(TARGETS ingest_edge_list 20 | LIBRARY DESTINATION lib 21 | ARCHIVE DESTINATION lib/static 22 | RUNTIME DESTINATION bin ) -------------------------------------------------------------------------------- /examples/bfs/rmat_graph_generator/hash.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is coming from the following project 3 | * / 4 | / * 5 | * Copyright (c) 2013, Lawrence Livermore National Security, LLC. 6 | * Produced at the Lawrence Livermore National Laboratory. 7 | * Written by Roger Pearce . 8 | * LLNL-CODE-644630. 9 | * All rights reserved. 10 | * 11 | * This file is part of HavoqGT, Version 0.1. 12 | * For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html 13 | * 14 | * Please also read this link – Our Notice and GNU Lesser General Public License. 15 | * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 16 | * 17 | * This program is free software; you can redistribute it and/or modify it under 18 | * the terms of the GNU Lesser General Public License (as published by the Free 19 | * Software Foundation) version 2.1 dated February 1999. 20 | * 21 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 22 | * WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A 23 | * PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public 24 | * License for more details. 25 | * 26 | * You should have received a copy of the GNU Lesser General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 | * 30 | * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE 31 | * 32 | * Our Preamble Notice 33 | * 34 | * A. This notice is required to be provided under our contract with the 35 | * U.S. Department of Energy (DOE). This work was produced at the Lawrence 36 | * Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE. 37 | * 38 | * B. Neither the United States Government nor Lawrence Livermore National 39 | * Security, LLC nor any of their employees, makes any warranty, express or 40 | * implied, or assumes any liability or responsibility for the accuracy, 41 | * completeness, or usefulness of any information, apparatus, product, or process 42 | * disclosed, or represents that its use would not infringe privately-owned rights. 43 | * 44 | * C. Also, reference herein to any specific commercial products, process, or 45 | * services by trade name, trademark, manufacturer or otherwise does not 46 | * necessarily constitute or imply its endorsement, recommendation, or favoring by 47 | * the United States Government or Lawrence Livermore National Security, LLC. The 48 | * views and opinions of authors expressed herein do not necessarily state or 49 | * reflect those of the United States Government or Lawrence Livermore National 50 | * Security, LLC, and shall not be used for advertising or product endorsement 51 | * purposes. 52 | * 53 | */ 54 | 55 | #ifndef BFS_HASH_HPP 56 | #define BFS_HASH_HPP 57 | 58 | #include 59 | 60 | namespace rmat_edge_generator_detail { 61 | 62 | 63 | /// 64 | /// Hash functions 65 | /// 66 | /// \todo requires documentation! 67 | /// \todo requires testing! 68 | 69 | inline uint32_t hash32(uint32_t a) { 70 | a = (a + 0x7ed55d16) + (a << 12); 71 | a = (a ^ 0xc761c23c) ^ (a >> 19); 72 | a = (a + 0x165667b1) + (a << 5); 73 | a = (a + 0xd3a2646c) ^ (a << 9); 74 | a = (a + 0xfd7046c5) + (a << 3); 75 | a = (a ^ 0xb55a4f09) ^ (a >> 16); 76 | return a; 77 | } 78 | 79 | inline uint16_t hash16(uint16_t a) { 80 | a = (a + 0x5d16) + (a << 6); 81 | a = (a ^ 0xc23c) ^ (a >> 9); 82 | a = (a + 0x67b1) + (a << 5); 83 | a = (a + 0x646c) ^ (a << 7); 84 | a = (a + 0x46c5) + (a << 3); 85 | a = (a ^ 0x4f09) ^ (a >> 8); 86 | return a; 87 | } 88 | 89 | inline uint64_t shifted_n_hash32(uint64_t input, int n) { 90 | uint64_t to_hash = input >> n; 91 | uint64_t mask = 0xFFFFFFFF; 92 | to_hash &= mask; 93 | to_hash = hash32(to_hash); 94 | 95 | to_hash <<= n; 96 | mask <<= n; 97 | //clear bits 98 | input &= ~mask; 99 | input |= to_hash; 100 | return input; 101 | } 102 | 103 | inline uint64_t shifted_n_hash16(uint64_t input, int n) { 104 | uint64_t to_hash = input >> n; 105 | uint64_t mask = 0xFFFF; 106 | to_hash &= mask; 107 | to_hash = hash16(to_hash); 108 | 109 | to_hash <<= n; 110 | mask <<= n; 111 | //clear bits 112 | input &= ~mask; 113 | input |= to_hash; 114 | return input; 115 | } 116 | 117 | inline uint64_t hash_nbits(uint64_t input, int n) { 118 | //std::cout << "hash_nbits(" << input << ", " << n << ") = "; 119 | if (n == 32) { 120 | input = hash32(input); 121 | } else if (n > 32) { 122 | assert(n > 32); 123 | n -= 32; 124 | for (int i = 0; i <= n; ++i) { 125 | input = shifted_n_hash32(input, i); 126 | } 127 | for (int i = n; i >= 0; --i) { 128 | input = shifted_n_hash32(input, i); 129 | } 130 | } else if (n < 32) { 131 | assert(n < 32); 132 | assert(n > 16 && "Hashing less than 16bits is not supported"); 133 | n -= 16; 134 | for (int i = 0; i <= n; ++i) { 135 | input = shifted_n_hash16(input, i); 136 | } 137 | for (int i = n; i >= 0; --i) { 138 | input = shifted_n_hash16(input, i); 139 | } 140 | } 141 | //std::cout << input << std::endl; 142 | return input; 143 | } 144 | 145 | } // namespace rmat_edge_generator_detail 146 | #endif //BFS_HASH_HPP 147 | -------------------------------------------------------------------------------- /examples/bfs/run_bfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # This test script does not require sudo privilege 5 | # The tests run BFS, UMapsort, and Churn tests 6 | # with different parameters 7 | ################################################## 8 | 9 | if [ -z "$UMAP_ROOT" ]; 10 | then 11 | echo "UMAP_ROOT is not set." 12 | exit 13 | fi 14 | 15 | if [ -z "$UMAP_INSTALL_PATH" ]; 16 | then 17 | echo "UMAP_INSTALL_PATH is not set. use $UMAP_ROOT/build. " 18 | UMAP_INSTALL_PATH=$UMAP_ROOT/build 19 | fi 20 | 21 | INPUT_GRAPH="./test_graph" 22 | 23 | export LD_LIBRARY_PATH=$UMAP_INSTALL_PATH/lib:$LD_LIBRARY_PATH 24 | 25 | echo "##############################################" 26 | echo "# BFS " 27 | echo "##############################################" 28 | 29 | ./rmat_graph_generator/ingest_edge_list -g $INPUT_GRAPH $UMAP_ROOT/examples/bfs/data/edge_list_rmat_s10_?_of_4 30 | echo "" 31 | echo "" 32 | 33 | ./bfs -n 1017 -m 32768 -g $INPUT_GRAPH -l $UMAP_ROOT/examples/bfs/data//bfs_level_reference 34 | /bin/rm -f $INPUT_GRAPH 35 | echo "" 36 | echo "BFS finished" 37 | exit 38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/bfs/utility/bitmap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | #ifndef LIB_UTILITY_BITMAP_HPP 16 | #define LIB_UTILITY_BITMAP_HPP 17 | 18 | #include 19 | 20 | namespace utility 21 | { 22 | 23 | /// examples 24 | /// input 1 ~ 64 -> return 1; input 65 ~ 128 -> return 2 25 | inline constexpr size_t bitmap_size(const size_t size) 26 | { 27 | return (size == 0) ? 0 : 28 | (size - 1ULL) / (sizeof(uint64_t) * 8ULL) + 1ULL; 29 | } 30 | 31 | /// examples 32 | /// input 0 ~ 63 -> return 0; input 64 ~ 127 -> return 1; 33 | inline constexpr uint64_t bitmap_global_pos(const uint64_t pos) 34 | { 35 | return (pos >> 6ULL); 36 | } 37 | 38 | inline constexpr uint64_t bitmap_local_pos(const uint64_t pos) 39 | { 40 | return pos & 0x3FULL; 41 | } 42 | 43 | inline bool get_bit(const uint64_t* const bitmap, const uint64_t pos) 44 | { 45 | return static_cast(bitmap[bitmap_global_pos(pos)] & (0x1ULL << bitmap_local_pos(pos))); 46 | } 47 | 48 | inline void set_bit(uint64_t* const bitmap, const uint64_t pos) 49 | { 50 | bitmap[bitmap_global_pos(pos)] |= 0x1ULL << bitmap_local_pos(pos); 51 | } 52 | 53 | } // namespace utility 54 | 55 | #endif //LIB_UTILITY_BITMAP_HPP 56 | -------------------------------------------------------------------------------- /examples/bfs/utility/file.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | #ifndef LIB_UTILITY_FILE_HPP 16 | #define LIB_UTILITY_FILE_HPP 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace utility { 29 | inline void extend_file_size_manually(const int fd, const size_t file_size) { 30 | auto buffer = new unsigned char[4096]; 31 | for (off_t i = 0; i < file_size / 4096; ++i) { 32 | ::pwrite(fd, buffer, 4096, i * 4096); 33 | } 34 | const size_t remained_size = file_size % 4096; 35 | if (remained_size > 0) 36 | ::pwrite(fd, buffer, remained_size, static_cast(file_size - remained_size)); 37 | 38 | ::sync(); 39 | delete[] buffer; 40 | } 41 | 42 | inline bool extend_file_size(const int fd, const size_t file_size) { 43 | /// ----- extend the file if its size is smaller than that of mapped area ----- /// 44 | #ifdef __linux__ 45 | struct stat statbuf; 46 | if (::fstat(fd, &statbuf) == -1) { 47 | ::perror("fstat"); 48 | std::cerr << "errno: " << errno << std::endl; 49 | return false; 50 | } 51 | if (::llabs(statbuf.st_size) < static_cast(file_size)) { 52 | if (::ftruncate(fd, file_size) == -1) { 53 | ::perror("ftruncate"); 54 | std::cerr << "errno: " << errno << std::endl; 55 | return false; 56 | } 57 | } 58 | #else 59 | #warning "Manually extend file size instead of using ftruncate(2)" 60 | extend_file_size_manually(fd, file_size); 61 | #endif 62 | return true; 63 | } 64 | 65 | inline bool extend_file_size(const std::string &file_name, const size_t file_size) { 66 | const int fd = ::open(file_name.c_str(), O_RDWR); 67 | if (fd == -1) { 68 | ::perror("open"); 69 | std::cerr << "errno: " << errno << std::endl; 70 | return false; 71 | } 72 | 73 | if (!extend_file_size(fd, file_size)) return false; 74 | ::close(fd); 75 | 76 | return true; 77 | } 78 | 79 | inline bool create_file(const std::string &file_name) { 80 | const int fd = ::open(file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 81 | if (fd == -1) { 82 | ::perror("open"); 83 | std::cerr << "errno: " << errno << std::endl; 84 | return false; 85 | } 86 | ::close(fd); 87 | 88 | return true; 89 | } 90 | 91 | inline ssize_t get_file_size(const std::string &file_name) { 92 | std::ifstream ifs(file_name, std::ifstream::binary | std::ifstream::ate); 93 | ssize_t size = ifs.tellg(); 94 | if (size == -1) { 95 | std::cerr << "Failed to get file size: " << file_name << std::endl; 96 | } 97 | 98 | return size; 99 | } 100 | } // namespace utility 101 | 102 | #endif //LIB_UTILITY_FILE_HPP 103 | -------------------------------------------------------------------------------- /examples/bfs/utility/map_file.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of UMAP. For copyright information see the COPYRIGHT 2 | * file in the top level directory, or at 3 | * https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free 4 | * software; you can redistribute it and/or modify it under the terms of the 5 | * GNU Lesser General Public License (as published by the Free Software 6 | * Foundation) version 2.1 dated February 1999. This program is distributed in 7 | * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 8 | * IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | * See the terms and conditions of the GNU Lesser General Public License for 10 | * more details. You should have received a copy of the GNU Lesser General 11 | * Public License along with this program; if not, write to the Free Software 12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13 | */ 14 | #ifndef _MAP_FILE_HPP_ 15 | #define _MAP_FILE_HPP_ 16 | 17 | #ifndef _GNU_SOURCE 18 | #define _GNU_SOURCE 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "umap/umap.h" 27 | 28 | namespace utility { 29 | 30 | void* map_file( 31 | std::string filename, 32 | bool need_init, 33 | bool has_write, 34 | bool usemmap, 35 | uint64_t numbytes, 36 | void* start_addr=nullptr) 37 | { 38 | int o_opts = O_LARGEFILE | O_DIRECT; 39 | void* region = NULL; 40 | int fd; 41 | 42 | if ( need_init ) { 43 | o_opts |= O_CREAT; 44 | has_write = true; 45 | unlink(filename.c_str()); // Remove the file if it exists 46 | } 47 | 48 | if(has_write) 49 | o_opts |= O_RDWR; 50 | else 51 | o_opts |= O_RDONLY; 52 | 53 | if ( ( fd = open(filename.c_str(), o_opts, S_IRUSR | S_IWUSR) ) == -1 ) { 54 | std::string estr = "Failed to open/create " + filename + ": "; 55 | perror(estr.c_str()); 56 | return NULL; 57 | } 58 | 59 | if ( o_opts & O_CREAT ) { 60 | // If we are initializing, attempt to pre-allocate disk space for the file. 61 | try { 62 | int x; 63 | if ( ( x = posix_fallocate(fd, 0, numbytes) != 0 ) ) { 64 | std::ostringstream ss; 65 | ss << "Failed to pre-allocate " << numbytes << " bytes in " << filename << ": "; 66 | perror(ss.str().c_str()); 67 | return NULL; 68 | } 69 | } catch(const std::exception& e) { 70 | std::cerr << "posix_fallocate: " << e.what() << std::endl; 71 | return NULL; 72 | } catch(...) { 73 | std::cerr << "posix_fallocate failed to allocate backing store\n"; 74 | return NULL; 75 | } 76 | } 77 | 78 | struct stat sbuf; 79 | if (fstat(fd, &sbuf) == -1) { 80 | std::string estr = "Failed to get status (fstat) for " + filename + ": "; 81 | perror(estr.c_str()); 82 | return NULL; 83 | } 84 | 85 | if ( (off_t)sbuf.st_size != (numbytes) ) { 86 | std::cerr << filename << " size " << sbuf.st_size 87 | << " does not match specified data size of " << (numbytes) << std::endl; 88 | return NULL; 89 | } 90 | 91 | const int prot = (has_write) ?(PROT_READ|PROT_WRITE) : PROT_READ; 92 | 93 | if ( usemmap ) { 94 | int flags = MAP_SHARED | MAP_NORESERVE; 95 | 96 | if (start_addr != nullptr) 97 | flags |= MAP_FIXED; 98 | 99 | region = mmap(start_addr, numbytes, prot, flags, fd, 0); 100 | if (region == MAP_FAILED) { 101 | std::ostringstream ss; 102 | ss << "mmap of " << numbytes << " bytes failed for " << filename << ": "; 103 | perror(ss.str().c_str()); 104 | return NULL; 105 | } 106 | } 107 | else { 108 | int flags = UMAP_PRIVATE; 109 | 110 | if (start_addr != nullptr) 111 | flags |= MAP_FIXED; 112 | 113 | region = umap(start_addr, numbytes, prot, flags, fd, 0); 114 | if ( region == UMAP_FAILED ) { 115 | std::ostringstream ss; 116 | ss << "umap_mf of " << numbytes 117 | << " bytes failed for " << filename << ": "; 118 | perror(ss.str().c_str()); 119 | return NULL; 120 | } 121 | } 122 | 123 | return region; 124 | } 125 | 126 | void unmap_file(bool usemmap, uint64_t numbytes, void* region) 127 | { 128 | if ( usemmap ) { 129 | if ( munmap(region, numbytes) < 0 ) { 130 | std::ostringstream ss; 131 | ss << "munmap failure: "; 132 | perror(ss.str().c_str()); 133 | exit(-1); 134 | } 135 | } 136 | else { 137 | if (uunmap(region, numbytes) < 0) { 138 | std::ostringstream ss; 139 | ss << "uunmap of failure: "; 140 | perror(ss.str().c_str()); 141 | exit(-1); 142 | } 143 | } 144 | } 145 | 146 | } 147 | #endif 148 | -------------------------------------------------------------------------------- /examples/bfs/utility/open_mp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | #ifndef UMAP_APPS_UTILITY_OPEN_MP_HPP 16 | #define UMAP_APPS_UTILITY_OPEN_MP_HPP 17 | 18 | #include 19 | 20 | #ifdef _OPENMP 21 | #include 22 | #endif 23 | 24 | namespace utility { 25 | 26 | inline std::string omp_schedule_kind_name(const int kind_in_int) { 27 | #ifdef _OPENMP 28 | if (kind_in_int == omp_sched_static) { 29 | return std::string("omp_sched_static (" + std::to_string(kind_in_int) + ")"); 30 | } else if (kind_in_int == omp_sched_dynamic) { 31 | return std::string("omp_sched_dynamic (" + std::to_string(kind_in_int) + ")"); 32 | } else if (kind_in_int == omp_sched_guided) { 33 | return std::string("omp_sched_guided (" + std::to_string(kind_in_int) + ")"); 34 | } else if (kind_in_int == omp_sched_auto) { 35 | return std::string("omp_sched_auto (" + std::to_string(kind_in_int) + ")"); 36 | } 37 | return std::string("Unknown kind (" + std::to_string(kind_in_int) + ")"); 38 | #else 39 | return std::string("OpenMP is not supported"); 40 | #endif 41 | }; 42 | 43 | } // namespace utility 44 | #endif //UMAP_APPS_UTILITY_OPEN_MP_HPP 45 | -------------------------------------------------------------------------------- /examples/bfs/utility/time.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | 16 | #ifndef UMAP_TEST_LIB_UTILITY_TIME_HPP 17 | #define UMAP_TEST_LIB_UTILITY_TIME_HPP 18 | 19 | #include 20 | 21 | namespace utility { 22 | inline std::chrono::high_resolution_clock::time_point elapsed_time_sec() { 23 | return std::chrono::high_resolution_clock::now(); 24 | } 25 | 26 | inline double elapsed_time_sec(const std::chrono::high_resolution_clock::time_point &tic) { 27 | auto duration_time = std::chrono::high_resolution_clock::now() - tic; 28 | return static_cast(std::chrono::duration_cast(duration_time).count() / 1e6); 29 | } 30 | } 31 | #endif //UMAP_TEST_LIB_UTILITY_TIME_HPP 32 | -------------------------------------------------------------------------------- /examples/stream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | project(stream) 8 | 9 | FIND_PACKAGE( OpenMP REQUIRED ) 10 | if(OPENMP_FOUND) 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS} -D_GNU_SOURCE") #-DUSE_UMAP 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -D_GNU_SOURCE") 13 | set(CMAKE_EXE_LINKER_FLAGS 14 | "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 15 | 16 | configure_file( 17 | "${CMAKE_CURRENT_SOURCE_DIR}/run_stream.sh" 18 | "${CMAKE_CURRENT_BINARY_DIR}/run_stream.sh" 19 | COPYONLY 20 | ) 21 | add_executable(stream stream.c) 22 | 23 | set(CMAKE_SKIP_RPATH TRUE) 24 | 25 | if(STATIC_UMAP_LINK) 26 | set(umap-lib "umap-static") 27 | else() 28 | set(umap-lib "umap") 29 | endif() 30 | 31 | add_dependencies(stream ${umap-lib}) 32 | target_link_libraries(stream ${umap-lib}) 33 | 34 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 35 | 36 | install(TARGETS stream 37 | LIBRARY DESTINATION lib 38 | ARCHIVE DESTINATION lib/static 39 | RUNTIME DESTINATION bin ) 40 | else() 41 | message("Skipping stream, OpenMP required") 42 | endif() 43 | 44 | -------------------------------------------------------------------------------- /examples/stream/run_stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$UMAP_ROOT" ]; 4 | then 5 | echo "UMAP_ROOT is not set." 6 | exit 7 | fi 8 | 9 | if [ -z "$UMAP_INSTALL_PATH" ]; 10 | then 11 | echo "UMAP_INSTALL_PATH is not set. use $UMAP_ROOT/build. " 12 | UMAP_INSTALL_PATH=$UMAP_ROOT/build 13 | fi 14 | 15 | umap_psize=16384 16 | array_length=819200 17 | umap_bufsize=$(( array_length * 8 * 3 / umap_psize / 2 )) 18 | 19 | # init data array 20 | cmd="env LD_LIBRARY_PATH=${UMAP_INSTALL_PATH}/lib UMAP_PAGESIZE=$umap_psize ./stream $array_length 1" 21 | echo $cmd 22 | date 23 | eval $cmd 24 | 25 | # perform streaming tests 26 | cmd="env LD_LIBRARY_PATH=${UMAP_INSTALL_PATH}/lib UMAP_PAGESIZE=$umap_psize UMAP_BUFSIZE=$umap_bufsize ./stream $array_length 0" 27 | echo $cmd 28 | date 29 | eval $cmd 30 | 31 | echo "Done" 32 | exit 33 | -------------------------------------------------------------------------------- /examples/umapsort/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(umapsort) 2 | 3 | FIND_PACKAGE( OpenMP REQUIRED ) 4 | if(OPENMP_FOUND) 5 | configure_file( 6 | "${CMAKE_CURRENT_SOURCE_DIR}/run_umapsort.sh" 7 | "${CMAKE_CURRENT_BINARY_DIR}/run_umapsort.sh" 8 | COPYONLY 9 | ) 10 | 11 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 12 | 13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 15 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 16 | 17 | add_executable(umapsort main.cpp) 18 | 19 | set(CMAKE_SKIP_RPATH TRUE) 20 | 21 | if(STATIC_UMAP_LINK) 22 | set(umap-lib "umap-static") 23 | else() 24 | set(umap-lib "umap") 25 | endif() 26 | 27 | add_dependencies(umapsort ${umap-lib}) 28 | 29 | target_link_libraries(umapsort ${umap-lib}) 30 | 31 | install(TARGETS umapsort 32 | LIBRARY DESTINATION lib 33 | ARCHIVE DESTINATION lib/static 34 | RUNTIME DESTINATION bin ) 35 | else() 36 | message("Skipping umapsort, OpenMP required") 37 | endif() 38 | 39 | -------------------------------------------------------------------------------- /examples/umapsort/map_file.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of UMAP. For copyright information see the COPYRIGHT 2 | * file in the top level directory, or at 3 | * https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free 4 | * software; you can redistribute it and/or modify it under the terms of the 5 | * GNU Lesser General Public License (as published by the Free Software 6 | * Foundation) version 2.1 dated February 1999. This program is distributed in 7 | * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 8 | * IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | * See the terms and conditions of the GNU Lesser General Public License for 10 | * more details. You should have received a copy of the GNU Lesser General 11 | * Public License along with this program; if not, write to the Free Software 12 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13 | */ 14 | #ifndef _MAP_FILE_HPP_ 15 | #define _MAP_FILE_HPP_ 16 | 17 | #ifndef _GNU_SOURCE 18 | #define _GNU_SOURCE 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "umap/umap.h" 27 | 28 | namespace utility { 29 | 30 | void* map_file( 31 | std::string filename, 32 | bool need_init, 33 | bool has_write, 34 | bool usemmap, 35 | uint64_t numbytes, 36 | void* start_addr=nullptr) 37 | { 38 | int o_opts = O_LARGEFILE | O_DIRECT; 39 | void* region = NULL; 40 | int fd; 41 | 42 | if ( need_init ) { 43 | o_opts |= O_CREAT; 44 | has_write = true; 45 | unlink(filename.c_str()); // Remove the file if it exists 46 | } 47 | 48 | if(has_write) 49 | o_opts |= O_RDWR; 50 | else 51 | o_opts |= O_RDONLY; 52 | 53 | if ( ( fd = open(filename.c_str(), o_opts, S_IRUSR | S_IWUSR) ) == -1 ) { 54 | std::string estr = "Failed to open/create " + filename + ": "; 55 | perror(estr.c_str()); 56 | return NULL; 57 | } 58 | 59 | if ( o_opts & O_CREAT ) { 60 | // If we are initializing, attempt to pre-allocate disk space for the file. 61 | try { 62 | int x; 63 | if ( ( x = posix_fallocate(fd, 0, numbytes) != 0 ) ) { 64 | std::ostringstream ss; 65 | ss << "Failed to pre-allocate " << numbytes << " bytes in " << filename << ": "; 66 | perror(ss.str().c_str()); 67 | return NULL; 68 | } 69 | } catch(const std::exception& e) { 70 | std::cerr << "posix_fallocate: " << e.what() << std::endl; 71 | return NULL; 72 | } catch(...) { 73 | std::cerr << "posix_fallocate failed to allocate backing store\n"; 74 | return NULL; 75 | } 76 | } 77 | 78 | struct stat sbuf; 79 | if (fstat(fd, &sbuf) == -1) { 80 | std::string estr = "Failed to get status (fstat) for " + filename + ": "; 81 | perror(estr.c_str()); 82 | return NULL; 83 | } 84 | 85 | if ( (off_t)sbuf.st_size != (numbytes) ) { 86 | std::cerr << filename << " size " << sbuf.st_size 87 | << " does not match specified data size of " << (numbytes) << std::endl; 88 | return NULL; 89 | } 90 | 91 | const int prot = (has_write) ?(PROT_READ|PROT_WRITE) : PROT_READ; 92 | 93 | if ( usemmap ) { 94 | int flags = MAP_SHARED | MAP_NORESERVE; 95 | 96 | if (start_addr != nullptr) 97 | flags |= MAP_FIXED; 98 | 99 | region = mmap(start_addr, numbytes, prot, flags, fd, 0); 100 | if (region == MAP_FAILED) { 101 | std::ostringstream ss; 102 | ss << "mmap of " << numbytes << " bytes failed for " << filename << ": "; 103 | perror(ss.str().c_str()); 104 | return NULL; 105 | } 106 | } 107 | else { 108 | int flags = UMAP_PRIVATE; 109 | 110 | if (start_addr != nullptr) 111 | flags |= MAP_FIXED; 112 | 113 | region = umap(start_addr, numbytes, prot, flags, fd, 0); 114 | if ( region == UMAP_FAILED ) { 115 | std::ostringstream ss; 116 | ss << "umap_mf of " << numbytes 117 | << " bytes failed for " << filename << ": "; 118 | perror(ss.str().c_str()); 119 | return NULL; 120 | } 121 | } 122 | 123 | return region; 124 | } 125 | 126 | void unmap_file(bool usemmap, uint64_t numbytes, void* region) 127 | { 128 | if ( usemmap ) { 129 | if ( munmap(region, numbytes) < 0 ) { 130 | std::ostringstream ss; 131 | ss << "munmap failure: "; 132 | perror(ss.str().c_str()); 133 | exit(-1); 134 | } 135 | } 136 | else { 137 | if (uunmap(region, numbytes) < 0) { 138 | std::ostringstream ss; 139 | ss << "uunmap of failure: "; 140 | perror(ss.str().c_str()); 141 | exit(-1); 142 | } 143 | } 144 | } 145 | 146 | } 147 | #endif 148 | -------------------------------------------------------------------------------- /examples/umapsort/run_umapsort.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # This test script does not require sudo privilege 5 | # The tests run BFS, UMapsort, and Churn tests 6 | # with different parameters 7 | ################################################## 8 | 9 | 10 | if [ -z "$UMAP_ROOT" ]; 11 | then 12 | echo "UMAP_ROOT is not set." 13 | exit 14 | fi 15 | 16 | if [ -z "$UMAP_INSTALL_PATH" ]; 17 | then 18 | echo "UMAP_INSTALL_PATH is not set. use $UMAP_ROOT/build. " 19 | UMAP_INSTALL_PATH=$UMAP_ROOT/build 20 | fi 21 | 22 | export LD_LIBRARY_PATH=$UMAP_INSTALL_PATH/lib:$LD_LIBRARY_PATH 23 | 24 | echo "##############################################" 25 | echo "# UMapSort " 26 | echo "##############################################" 27 | DATA_SIZE=$(( 64*1024*1024 )) 28 | BUF_SIZE=$(( 32*1024*1024 )) 29 | UMAP_PSIZE=16384 30 | UMAP_BUFSIZE=$((BUF_SIZE/UMAP_PSIZE)) 31 | data_file=./sort_perf_data 32 | 33 | cmd="env UMAP_PAGESIZE=$UMAP_PSIZE UMAP_BUFSIZE=$UMAP_BUFSIZE ./umapsort -f $data_file -p $((DATA_SIZE/UMAP_PSIZE)) -N 1 -t 24" 34 | echo $cmd 35 | time sh -c "$cmd" 36 | echo "" 37 | exit 38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/umapsort/time.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of UMAP. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/umap/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | */ 15 | 16 | #ifndef UMAP_TEST_LIB_UTILITY_TIME_HPP 17 | #define UMAP_TEST_LIB_UTILITY_TIME_HPP 18 | 19 | #include 20 | 21 | namespace utility { 22 | inline std::chrono::high_resolution_clock::time_point elapsed_time_sec() { 23 | return std::chrono::high_resolution_clock::now(); 24 | } 25 | 26 | inline double elapsed_time_sec(const std::chrono::high_resolution_clock::time_point &tic) { 27 | auto duration_time = std::chrono::high_resolution_clock::now() - tic; 28 | return static_cast(std::chrono::duration_cast(duration_time).count() / 1e6); 29 | } 30 | } 31 | #endif //UMAP_TEST_LIB_UTILITY_TIME_HPP 32 | -------------------------------------------------------------------------------- /host-configs/toss_3_x86_64/gcc_4_8_5.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | set(CMAKE_CXX_COMPILER "g++" CACHE PATH "") 8 | set(CMAKE_C_COMPILER "gcc" CACHE PATH "") 9 | 10 | -------------------------------------------------------------------------------- /scripts/apply-license-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | setopt extended_glob 10 | 11 | RED="\033[1;31m" 12 | GREEN="\033[1;32m" 13 | NOCOLOR="\033[0m" 14 | 15 | LIC_CMD=$(which lic) 16 | if [ ! $LIC_CMD ]; then 17 | echo "${RED} [!] This script requires the lic command." 18 | exit 255 19 | fi 20 | 21 | echo "Applying licenses to files" 22 | 23 | files_no_license=$(grep -L 'This file is part of UMAP.' \ 24 | benchmarks/**/*(^/) \ 25 | cmake/**/*(^/) \ 26 | docs/**/*~*rst(^/)\ 27 | examples/**/*(^/) \ 28 | host-configs/**/*(^/) \ 29 | scripts/**/*(^/) \ 30 | src/**/*~*tpl*(^/) \ 31 | tests/**/*(^/) \ 32 | CMakeLists.txt) 33 | 34 | echo $files_no_license | xargs $LIC_CMD -f scripts/umap-license.txt 35 | 36 | echo "${GREEN} [Ok] License text applied. ${NOCOLOR}" 37 | -------------------------------------------------------------------------------- /scripts/bamboo/build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | # 10 | # This script is intended to be run by the bamboo continuous integration 11 | # project definition for UMAP. It is invoked with the following command 12 | # line arguments: 13 | # $1 - Optionally set to compiler configuration to run 14 | # $2 - Optionally set to -Release or -Debug build ($1 must be set) 15 | # 16 | function trycmd 17 | { 18 | echo $1 19 | $1 20 | 21 | if [ $? -ne 0 ]; then 22 | echo "Error" 23 | exit -1 24 | fi 25 | } 26 | 27 | cd `dirname $0` 28 | 29 | export UMAP_DIR=$(git rev-parse --show-toplevel) 30 | export BUILD_DIR=build-${SYS_TYPE} 31 | 32 | export COMPILER=${1:-gcc_4_8_5} 33 | export BUILD_TYPE=${2:-Release} 34 | export BUILD_OPTIONS="${BUILD_OPTIONS}" 35 | mkdir ${BUILD_DIR} 2> /dev/null 36 | cd ${BUILD_DIR} 37 | 38 | trycmd "cmake -C ${UMAP_DIR}/host-configs/${SYS_TYPE}/${COMPILER}.cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${BUILD_OPTIONS} ${UMAP_DIR}" 39 | 40 | trycmd "make -j" 41 | 42 | trycmd "./tests/churn/churn -f /tmp/regression_test_churn.dat -b 10000 -c 20000 -l 1000 -d 10" 43 | trycmd "./examples/psort /tmp/regression_test_sort.dat" 44 | /bin/rm -rf /tmp/regression_test_churn.dat /tmp/regression_test_sort.dat 45 | 46 | -------------------------------------------------------------------------------- /scripts/check-license-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | # This is used for the ~*tpl* line to ignore files in bundled tpls 10 | setopt extended_glob 11 | 12 | autoload colors 13 | 14 | RED="\033[1;31m" 15 | GREEN="\033[1;32m" 16 | NOCOLOR="\033[0m" 17 | 18 | files_no_license=$(grep -L 'Lawrence Livermore National Security' \ 19 | cmake/**/*(^/) \ 20 | docs/**/*~*rst(^/)\ 21 | config/config.h.in\ 22 | examples/*(^/) \ 23 | host-configs/**/*(^/) \ 24 | scripts/**/*(^/) \ 25 | src/**/*~*tpl*(^/) \ 26 | tests/**/*~*csv~*xlsx~*sysinfo(^/) \ 27 | tests/CMakeLists.txt \ 28 | CMakeLists.txt) 29 | 30 | if [ $files_no_license ]; then 31 | print "${RED} [!] Some files are missing license text: ${NOCOLOR}" 32 | echo "${files_no_license}" 33 | exit 255 34 | else 35 | print "${GREEN} [Ok] All files have required license info." 36 | exit 0 37 | fi 38 | -------------------------------------------------------------------------------- /scripts/make_release_tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | TAR_CMD=tar 10 | VERSION=1.0.0 11 | 12 | git archive --prefix=umap-${VERSION}/ -o umap-${VERSION}.tar HEAD 2> /dev/null 13 | 14 | gzip umap-${VERSION}.tar 15 | -------------------------------------------------------------------------------- /scripts/travis/build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | env 10 | function or_die () { 11 | "$@" 12 | local status=$? 13 | if [[ $status != 0 ]] ; then 14 | echo ERROR $status command: $@ 15 | exit $status 16 | fi 17 | } 18 | 19 | or_die mkdir travis-build 20 | cd travis-build 21 | if [[ "$DO_BUILD" == "yes" ]] ; then 22 | or_die cmake -DCMAKE_CXX_COMPILER="${COMPILER}" ${CMAKE_EXTRA_FLAGS} ../ 23 | if [[ ${CMAKE_EXTRA_FLAGS} == *COVERAGE* ]] ; then 24 | or_die make -j 3 25 | else 26 | or_die make -j 3 VERBOSE=1 27 | fi 28 | if [[ "${DO_TEST}" == "yes" ]] ; then 29 | or_die ctest -T test --output-on-failure -V 30 | fi 31 | if [[ "${DO_MEMCHECK}" == "yes" ]] ; then 32 | or_die ctest -T memcheck 33 | fi 34 | fi 35 | 36 | exit 0 37 | -------------------------------------------------------------------------------- /scripts/umap-license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 2 | UMAP Project Developers. See the top-level LICENSE file for details. 3 | 4 | SPDX-License-Identifier: LGPL-2.1-only 5 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | add_subdirectory(umap) 8 | -------------------------------------------------------------------------------- /src/umap/Buffer.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_Buffer_HPP 8 | #define _UMAP_Buffer_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "umap/RegionDescriptor.hpp" 16 | #include "umap/PageDescriptor.hpp" 17 | 18 | namespace Umap { 19 | class RegionManager; 20 | 21 | struct BufferStats { 22 | BufferStats() : lock_collision(0), lock(0), pages_inserted(0) 23 | , pages_deleted(0), not_avail(0), waits(0) 24 | , events_processed(0) 25 | {}; 26 | 27 | uint64_t lock_collision; 28 | uint64_t lock; 29 | uint64_t pages_inserted; 30 | uint64_t pages_deleted; 31 | uint64_t not_avail; 32 | uint64_t waits; 33 | uint64_t events_processed; 34 | }; 35 | 36 | class Buffer { 37 | friend std::ostream& operator<<(std::ostream& os, const Umap::Buffer* b); 38 | friend std::ostream& operator<<(std::ostream& os, const Umap::BufferStats& stats); 39 | public: 40 | void mark_page_as_present(PageDescriptor* pd); 41 | void mark_page_as_free( PageDescriptor* pd ); 42 | 43 | bool low_threshold_reached( void ); 44 | 45 | void fetch_and_pin(char* paddr, uint64_t size); 46 | 47 | PageDescriptor* evict_oldest_page( void ); 48 | std::vector evict_oldest_pages( void ); 49 | void process_page_event(char* paddr, bool iswrite, RegionDescriptor* rd); 50 | void evict_region(RegionDescriptor* rd); 51 | void flush_dirty_pages(); 52 | 53 | explicit Buffer( void ); 54 | ~Buffer( void ); 55 | 56 | private: 57 | RegionManager& m_rm; 58 | uint64_t m_size; // Maximum pages this buffer may have 59 | PageDescriptor* m_array; 60 | 61 | std::unordered_map m_present_pages; 62 | 63 | std::vector m_free_pages; 64 | std::deque m_busy_pages; 65 | 66 | uint64_t m_evict_low_water; // % to evict too 67 | uint64_t m_evict_high_water; // % to start evicting 68 | 69 | pthread_mutex_t m_mutex; 70 | 71 | int m_waits_for_avail_pd; 72 | pthread_cond_t m_avail_pd_cond; 73 | 74 | int m_waits_for_state_change; 75 | pthread_cond_t m_state_change_cond; 76 | 77 | BufferStats m_stats; 78 | bool is_monitor_on; 79 | pthread_t monitorThread; 80 | void monitor(void); 81 | static void* MonitorThreadEntryFunc(void * obj){ 82 | ((Buffer *) obj)->monitor(); 83 | return NULL; 84 | } 85 | 86 | void release_page_descriptor( PageDescriptor* pd ); 87 | 88 | PageDescriptor* page_already_present( char* page_addr ); 89 | PageDescriptor* get_page_descriptor( char* page_addr, RegionDescriptor* rd ); 90 | uint64_t apply_int_percentage( int percentage, uint64_t item ); 91 | 92 | void lock(); 93 | void unlock(); 94 | void wait_for_page_state( PageDescriptor* pd, PageDescriptor::State st); 95 | }; 96 | 97 | std::ostream& operator<<(std::ostream& os, const Umap::BufferStats& stats); 98 | std::ostream& operator<<(std::ostream& os, const Umap::Buffer* b); 99 | 100 | } // end of namespace Umap 101 | 102 | #endif // _UMAP_Buffer_HPP 103 | -------------------------------------------------------------------------------- /src/umap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | project(umap_libraries) 8 | 9 | set(umapheaders 10 | config.h 11 | Buffer.hpp 12 | EvictManager.hpp 13 | EvictWorkers.hpp 14 | FillWorkers.hpp 15 | PageDescriptor.hpp 16 | RegionManager.hpp 17 | RegionDescriptor.hpp 18 | Uffd.hpp 19 | umap.h 20 | WorkQueue.hpp 21 | WorkerPool.hpp 22 | store/StoreFile.h 23 | store/SparseStore.h 24 | store/Store.hpp 25 | util/Exception.hpp 26 | util/Logger.hpp 27 | util/Macros.hpp) 28 | 29 | set(umapsrc 30 | Buffer.cpp 31 | EvictManager.cpp 32 | EvictWorkers.cpp 33 | FillWorkers.cpp 34 | PageDescriptor.cpp 35 | RegionManager.cpp 36 | Uffd.cpp 37 | umap.cpp 38 | store/Store.cpp 39 | store/StoreFile.cpp 40 | store/SparseStore.cpp 41 | util/Exception.cpp 42 | util/Logger.cpp 43 | ${umapheaders}) 44 | 45 | find_package(Threads REQUIRED) 46 | 47 | add_library(umap SHARED ${umapsrc} ) 48 | add_library(umap-static STATIC ${umapsrc} ) 49 | set_target_properties(umap-static PROPERTIES OUTPUT_NAME umap) 50 | target_link_libraries (umap ${CMAKE_THREAD_LIBS_INIT}) 51 | 52 | if (caliper_DIR) 53 | find_package(caliper REQUIRED) 54 | message(STATUS "Found caliper_INCLUDE_DIR ${caliper_INCLUDE_DIR}" ) 55 | target_include_directories(umap PUBLIC ${caliper_INCLUDE_DIR}) 56 | target_include_directories(umap-static PUBLIC ${caliper_INCLUDE_DIR}) 57 | target_link_libraries(umap caliper) 58 | target_link_libraries(umap-static caliper) 59 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCALIPER") 60 | endif() 61 | 62 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 63 | 64 | install(TARGETS umap umap-static 65 | LIBRARY DESTINATION lib 66 | ARCHIVE DESTINATION lib 67 | RUNTIME DESTINATION bin ) 68 | 69 | install(FILES umap.h DESTINATION include/umap) 70 | 71 | install(FILES store/Store.hpp DESTINATION include/umap/store ) 72 | 73 | install(FILES store/SparseStore.h DESTINATION include/umap/store) 74 | -------------------------------------------------------------------------------- /src/umap/EvictManager.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include "umap/Buffer.hpp" 9 | #include "umap/EvictManager.hpp" 10 | #include "umap/EvictWorkers.hpp" 11 | #include "umap/RegionManager.hpp" 12 | #include "umap/Uffd.hpp" 13 | #include "umap/WorkerPool.hpp" 14 | #include "umap/util/Macros.hpp" 15 | #include "umap/store/Store.hpp" 16 | 17 | namespace Umap { 18 | 19 | void EvictManager::EvictMgr( void ) { 20 | while ( 1 ) { 21 | auto w = get_work(); 22 | 23 | if ( w.type == Umap::WorkItem::WorkType::EXIT ) 24 | break; // Time to leave 25 | 26 | while ( ! m_buffer->low_threshold_reached() ) { 27 | #if 0 28 | WorkItem work; 29 | work.type = Umap::WorkItem::WorkType::EVICT; 30 | work.page_desc = m_buffer->evict_oldest_page(); // Could block 31 | 32 | if ( work.page_desc == nullptr ) 33 | break; 34 | 35 | UMAP_LOG(Debug, m_buffer << ", " << work.page_desc); 36 | 37 | m_evict_workers->send_work(work); 38 | #else 39 | std::vector evicted_pages = m_buffer->evict_oldest_pages(); 40 | for(auto pd : evicted_pages){ 41 | WorkItem work; 42 | work.type = Umap::WorkItem::WorkType::EVICT; 43 | work.page_desc = pd; 44 | assert( work.page_desc != nullptr ); 45 | m_evict_workers->send_work(work); 46 | } 47 | #endif 48 | } 49 | } 50 | } 51 | void EvictManager::WaitAll( void ) 52 | { 53 | UMAP_LOG(Debug, "Entered"); 54 | m_evict_workers->wait_for_idle(); 55 | UMAP_LOG(Debug, "Done"); 56 | } 57 | 58 | void EvictManager::EvictAll( void ) 59 | { 60 | UMAP_LOG(Debug, "Entered"); 61 | 62 | for (auto pd = m_buffer->evict_oldest_page(); pd != nullptr; pd = m_buffer->evict_oldest_page()) { 63 | UMAP_LOG(Debug, "evicting: " << pd); 64 | if (pd->dirty) { 65 | WorkItem work = { .page_desc = pd, .type = Umap::WorkItem::WorkType::FAST_EVICT }; 66 | m_evict_workers->send_work(work); 67 | } 68 | else { 69 | m_buffer->mark_page_as_free(pd); 70 | } 71 | } 72 | 73 | m_evict_workers->wait_for_idle(); 74 | 75 | UMAP_LOG(Debug, "Done"); 76 | } 77 | 78 | void EvictManager::schedule_eviction(PageDescriptor* pd) 79 | { 80 | WorkItem work = { .page_desc = pd, .type = Umap::WorkItem::WorkType::EVICT }; 81 | 82 | m_evict_workers->send_work(work); 83 | } 84 | 85 | void EvictManager::schedule_flush(PageDescriptor* pd) 86 | { 87 | WorkItem work = { .page_desc = pd, .type = Umap::WorkItem::WorkType::FLUSH }; 88 | 89 | m_evict_workers->send_work(work); 90 | } 91 | 92 | EvictManager::EvictManager( void ) : 93 | WorkerPool("Evict Manager", 1) 94 | , m_buffer(RegionManager::getInstance().get_buffer_h()) 95 | { 96 | m_evict_workers = new EvictWorkers( RegionManager::getInstance().get_num_evictors() 97 | , m_buffer, RegionManager::getInstance().get_uffd_h()); 98 | start_thread_pool(); 99 | } 100 | 101 | EvictManager::~EvictManager( void ) { 102 | UMAP_LOG(Debug, "Calling EvictAll"); 103 | EvictAll(); 104 | UMAP_LOG(Debug, "Calling stop_thread_pool"); 105 | stop_thread_pool(); 106 | UMAP_LOG(Debug, "Deleting eviction workers"); 107 | delete m_evict_workers; 108 | UMAP_LOG(Debug, "Done"); 109 | } 110 | 111 | void EvictManager::ThreadEntry() { 112 | EvictMgr(); 113 | } 114 | 115 | } // end of namespace Umap 116 | -------------------------------------------------------------------------------- /src/umap/EvictManager.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_EvictManager_HPP 8 | #define _UMAP_EvictManager_HPP 9 | 10 | #include "umap/EvictWorkers.hpp" 11 | 12 | #include "umap/Buffer.hpp" 13 | #include "umap/PageDescriptor.hpp" 14 | #include "umap/RegionDescriptor.hpp" 15 | #include "umap/WorkerPool.hpp" 16 | 17 | namespace Umap { 18 | class EvictWorkers; 19 | 20 | class EvictManager : public WorkerPool { 21 | public: 22 | EvictManager( void ); 23 | ~EvictManager( void ); 24 | void schedule_eviction(PageDescriptor* pd); 25 | void schedule_flush(PageDescriptor* pd); 26 | void EvictAll( void ); 27 | void WaitAll( void ); 28 | 29 | private: 30 | Buffer* m_buffer; 31 | EvictWorkers* m_evict_workers; 32 | 33 | void EvictMgr(void); 34 | void ThreadEntry( void ); 35 | }; 36 | } // end of namespace Umap 37 | #endif // _UMAP_EvictManager_HPP 38 | -------------------------------------------------------------------------------- /src/umap/EvictWorkers.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include 8 | #include 9 | #include 10 | 11 | #include "umap/Buffer.hpp" 12 | #include "umap/EvictWorkers.hpp" 13 | #include "umap/RegionManager.hpp" 14 | #include "umap/Uffd.hpp" 15 | #include "umap/WorkerPool.hpp" 16 | #include "umap/util/Macros.hpp" 17 | 18 | namespace Umap { 19 | void EvictWorkers::EvictWorker( void ) 20 | { 21 | uint64_t page_size = RegionManager::getInstance().get_umap_page_size(); 22 | 23 | while ( 1 ) { 24 | auto w = get_work(); 25 | 26 | UMAP_LOG(Debug, " " << w << " " << m_buffer); 27 | 28 | if ( w.type == Umap::WorkItem::WorkType::EXIT ) 29 | break; // Time to leave 30 | 31 | auto pd = w.page_desc; 32 | 33 | if ( pd->dirty ) { 34 | auto store = pd->region->store(); 35 | auto offset = pd->region->store_offset(pd->page); 36 | 37 | m_uffd->enable_write_protect(pd->page); 38 | 39 | if (store->write_to_store(pd->page, page_size, offset) == -1) 40 | UMAP_ERROR("write_to_store failed: " 41 | << errno << " (" << strerror(errno) << ")"); 42 | 43 | pd->dirty = false; 44 | } 45 | 46 | if (w.type == Umap::WorkItem::WorkType::FLUSH) 47 | continue; 48 | 49 | if (w.type != Umap::WorkItem::WorkType::FAST_EVICT) { 50 | if (madvise(pd->page, page_size, MADV_DONTNEED) == -1) 51 | UMAP_ERROR("madvise failed: " << errno << " (" << strerror(errno) << ")"); 52 | } 53 | 54 | UMAP_LOG(Debug, "Removing page: " << w.page_desc); 55 | m_buffer->mark_page_as_free(w.page_desc); 56 | } 57 | } 58 | 59 | EvictWorkers::EvictWorkers(uint64_t num_evictors, Buffer* buffer, Uffd* uffd) 60 | : WorkerPool("Evict Workers", num_evictors), m_buffer(buffer) 61 | , m_uffd(uffd) 62 | { 63 | start_thread_pool(); 64 | } 65 | 66 | EvictWorkers::~EvictWorkers( void ) 67 | { 68 | stop_thread_pool(); 69 | } 70 | 71 | void EvictWorkers::ThreadEntry( void ) 72 | { 73 | EvictWorkers::EvictWorker(); 74 | } 75 | } // end of namespace Umap 76 | -------------------------------------------------------------------------------- /src/umap/EvictWorkers.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_EvictWorkers_HPP 8 | #define _UMAP_EvictWorkers_HPP 9 | 10 | #include "umap/config.h" 11 | 12 | #include "umap/Buffer.hpp" 13 | #include "umap/PageDescriptor.hpp" 14 | #include "umap/Uffd.hpp" 15 | #include "umap/WorkerPool.hpp" 16 | 17 | namespace Umap { 18 | class Uffd; 19 | class EvictWorkers : public WorkerPool { 20 | public: 21 | EvictWorkers(uint64_t num_evictors, Buffer* buffer, Uffd* uffd); 22 | ~EvictWorkers( void ); 23 | 24 | private: 25 | Buffer* m_buffer; 26 | Uffd* m_uffd; 27 | 28 | void EvictWorker( void ); 29 | void ThreadEntry( void ); 30 | }; 31 | } // end of namespace Umap 32 | #endif // _UMAP_EvictWorkers_HPP 33 | -------------------------------------------------------------------------------- /src/umap/FillWorkers.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "umap/config.h" 8 | 9 | #include // calloc 10 | #include 11 | #include // strerror() 12 | #include 13 | 14 | #include "umap/Buffer.hpp" 15 | #include "umap/FillWorkers.hpp" 16 | #include "umap/RegionManager.hpp" 17 | #include "umap/Uffd.hpp" 18 | #include "umap/WorkerPool.hpp" 19 | #include "umap/store/Store.hpp" 20 | #include "umap/util/Macros.hpp" 21 | 22 | namespace Umap { 23 | void FillWorkers::FillWorker( void ) { 24 | char* copyin_buf; 25 | uint64_t page_size = RegionManager::getInstance().get_umap_page_size(); 26 | std::size_t sz = page_size; 27 | 28 | if (posix_memalign((void**)©in_buf, page_size, sz)) { 29 | UMAP_ERROR("posix_memalign failed to allocated " 30 | << sz << " bytes of memory"); 31 | } 32 | 33 | if (copyin_buf == nullptr) { 34 | UMAP_ERROR("posix_memalign failed to allocated " 35 | << sz << " bytes of memory"); 36 | } 37 | 38 | while ( 1 ) { 39 | auto w = get_work(); 40 | 41 | UMAP_LOG(Debug, ": " << w << " " << m_buffer); 42 | 43 | if (w.type == Umap::WorkItem::WorkType::EXIT) 44 | break; // Time to leave 45 | 46 | if ( w.page_desc->dirty && w.page_desc->data_present ) { 47 | m_uffd->disable_write_protect(w.page_desc->page); 48 | } 49 | else { 50 | uint64_t offset = w.page_desc->region->store_offset(w.page_desc->page); 51 | 52 | if (w.page_desc->region->store()->read_from_store(copyin_buf, page_size, offset) == -1) 53 | UMAP_ERROR("read_from_store failed"); 54 | 55 | if ( ! w.page_desc->dirty ) { 56 | m_uffd->copy_in_page_and_write_protect(copyin_buf, w.page_desc->page); 57 | } 58 | else { 59 | m_uffd->copy_in_page(copyin_buf, w.page_desc->page); 60 | } 61 | w.page_desc->data_present = true; 62 | } 63 | 64 | m_buffer->mark_page_as_present(w.page_desc); 65 | } 66 | 67 | free(copyin_buf); 68 | } 69 | 70 | void FillWorkers::ThreadEntry( void ) { 71 | FillWorker(); 72 | } 73 | 74 | FillWorkers::FillWorkers( void ) 75 | : WorkerPool("Fill Workers", RegionManager::getInstance().get_num_fillers()) 76 | , m_uffd(RegionManager::getInstance().get_uffd_h()) 77 | , m_buffer(RegionManager::getInstance().get_buffer_h()) 78 | { 79 | start_thread_pool(); 80 | } 81 | 82 | FillWorkers::~FillWorkers( void ) { 83 | stop_thread_pool(); 84 | } 85 | } // end of namespace Umap 86 | -------------------------------------------------------------------------------- /src/umap/FillWorkers.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_FillWorkers_HPP 8 | #define _UMAP_FillWorkers_HPP 9 | 10 | #include "umap/Buffer.hpp" 11 | #include "umap/Uffd.hpp" 12 | #include "umap/WorkerPool.hpp" 13 | 14 | namespace Umap { 15 | class Buffer; 16 | class Uffd; 17 | 18 | class FillWorkers : public WorkerPool { 19 | public: 20 | FillWorkers( void ); 21 | ~FillWorkers( void ); 22 | 23 | private: 24 | Uffd* m_uffd; 25 | Buffer* m_buffer; 26 | 27 | void FillWorker( void ); 28 | void ThreadEntry( void ); 29 | }; 30 | } // end of namespace Umap 31 | #endif // _UMAP_FillWorker_HPP 32 | -------------------------------------------------------------------------------- /src/umap/PageDescriptor.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include 8 | 9 | #include "umap/PageDescriptor.hpp" 10 | #include "umap/RegionDescriptor.hpp" 11 | #include "umap/util/Macros.hpp" 12 | 13 | namespace Umap { 14 | std::string PageDescriptor::print_state( void ) const { 15 | switch (state) { 16 | default: return "???"; 17 | case Umap::PageDescriptor::State::FREE: return "FREE"; 18 | case Umap::PageDescriptor::State::FILLING: return "FILLING"; 19 | case Umap::PageDescriptor::State::PRESENT: return "PRESENT"; 20 | case Umap::PageDescriptor::State::UPDATING: return "UPDATING"; 21 | case Umap::PageDescriptor::State::LEAVING: return "LEAVING"; 22 | } 23 | } 24 | 25 | void PageDescriptor::set_state_free( void ) { 26 | if ( state != LEAVING ) 27 | UMAP_ERROR("Invalid state transition from: " << print_state()); 28 | state = FREE; 29 | } 30 | 31 | void PageDescriptor::set_state_filling( void ) { 32 | if ( state != FREE ) 33 | UMAP_ERROR("Invalid state transition from: " << print_state()); 34 | state = FILLING; 35 | } 36 | 37 | void PageDescriptor::set_state_present( void ) { 38 | if ( state != FILLING && state != UPDATING ) 39 | UMAP_ERROR("Invalid state transition from: " << print_state()); 40 | state = PRESENT; 41 | } 42 | 43 | void PageDescriptor::set_state_updating( void ) { 44 | if ( state != PRESENT ) 45 | UMAP_ERROR("Invalid state transition from: " << print_state()); 46 | state = UPDATING; 47 | } 48 | 49 | void PageDescriptor::set_state_leaving( void ) { 50 | if ( state != PRESENT ) 51 | UMAP_ERROR("Invalid state transition from: " << print_state()); 52 | state = LEAVING; 53 | } 54 | 55 | std::ostream& operator<<(std::ostream& os, const Umap::PageDescriptor* pd) 56 | { 57 | if (pd != nullptr) { 58 | os << "{ " 59 | << (void*)(pd->page) 60 | << ", " << pd->print_state(); 61 | 62 | if ( pd->dirty ) 63 | os << ", DIRTY"; 64 | if ( pd->deferred ) 65 | os << ", DEFERRED"; 66 | if ( pd->spurious_count ) 67 | os << ", spurious: " << pd->spurious_count; 68 | 69 | os << " }"; 70 | } 71 | else { 72 | os << "{ nullptr }"; 73 | } 74 | return os; 75 | } 76 | 77 | std::ostream& operator<<(std::ostream& os, const Umap::PageDescriptor::State st) 78 | { 79 | switch (st) { 80 | default: os << "???"; break; 81 | case Umap::PageDescriptor::State::FREE: os << "FREE"; break; 82 | case Umap::PageDescriptor::State::FILLING: os << "FILLING"; break; 83 | case Umap::PageDescriptor::State::PRESENT: os << "PRESENT"; break; 84 | case Umap::PageDescriptor::State::UPDATING: os << "UPDATING"; break; 85 | case Umap::PageDescriptor::State::LEAVING: os << "LEAVING"; break; 86 | } 87 | return os; 88 | } 89 | } // end of namespace Umap 90 | -------------------------------------------------------------------------------- /src/umap/PageDescriptor.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_PageDescriptor_HPP 8 | #define _UMAP_PageDescriptor_HPP 9 | 10 | #include 11 | #include 12 | 13 | namespace Umap { 14 | class RegionDescriptor; 15 | 16 | struct PageDescriptor { 17 | enum State { FREE = 0, FILLING, PRESENT, UPDATING, LEAVING }; 18 | char* page; 19 | RegionDescriptor* region; 20 | State state; 21 | bool dirty; 22 | bool deferred; 23 | bool data_present; 24 | int spurious_count; 25 | 26 | std::string print_state( void ) const; 27 | void set_state_free( void ); 28 | void set_state_filling( void ); 29 | void set_state_updating( void ); 30 | void set_state_present( void ); 31 | void set_state_leaving( void ); 32 | }; 33 | 34 | std::ostream& operator<<(std::ostream& os, const Umap::PageDescriptor::State st); 35 | std::ostream& operator<<(std::ostream& os, const Umap::PageDescriptor* pd); 36 | } // end of namespace Umap 37 | 38 | #endif // _UMAP_PageDescriptor_HPP 39 | -------------------------------------------------------------------------------- /src/umap/RegionDescriptor.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_RegionDescriptor_HPP 8 | #define _UMAP_RegionDescriptor_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "umap/PageDescriptor.hpp" 17 | #include "umap/store/Store.hpp" 18 | #include "umap/util/Macros.hpp" 19 | 20 | namespace Umap { 21 | class RegionDescriptor { 22 | public: 23 | RegionDescriptor( char* umap_region, uint64_t umap_size 24 | , char* mmap_region, uint64_t mmap_size 25 | , Store* store ) 26 | : m_umap_region(umap_region), m_umap_region_size(umap_size) 27 | , m_mmap_region(mmap_region), m_mmap_region_size(mmap_size) 28 | , m_store(store) {} 29 | 30 | ~RegionDescriptor( void ) {} 31 | 32 | inline uint64_t store_offset( char* addr ) { 33 | assert("Invalid address for calculating offset" && addr >= start() && addr < end()); 34 | return (uint64_t)(addr - start()); 35 | } 36 | 37 | inline uint64_t size( void ) { return m_umap_region_size; } 38 | inline Store* store( void ) { return m_store; } 39 | inline char* start( void ) { return m_umap_region; } 40 | inline char* end( void ) { return start() + size(); } 41 | inline uint64_t count( void ) { return m_active_pages.size(); } 42 | 43 | inline void insert_page_descriptor(PageDescriptor* pd) { 44 | m_active_pages.insert(pd); 45 | } 46 | 47 | inline void erase_page_descriptor(PageDescriptor* pd) { 48 | UMAP_LOG(Debug, "Erasing PD: " << pd); 49 | m_active_pages.erase(pd); 50 | } 51 | 52 | inline PageDescriptor* get_next_page_descriptor( void ) { 53 | if ( m_active_pages.size() == 0 ) 54 | return nullptr; 55 | 56 | auto it = m_active_pages.begin(); 57 | auto rval = *it; 58 | rval->deferred = false; 59 | erase_page_descriptor(rval); 60 | 61 | return rval; 62 | } 63 | 64 | private: 65 | char* m_umap_region; 66 | uint64_t m_umap_region_size; 67 | char* m_mmap_region; 68 | uint64_t m_mmap_region_size; 69 | Store* m_store; 70 | 71 | std::unordered_set m_active_pages; 72 | }; 73 | } // end of namespace Umap 74 | #endif // _UMAP_RegionDescripto_HPP 75 | -------------------------------------------------------------------------------- /src/umap/RegionManager.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_RegionManager_HPP 8 | #define _UMAP_RegionManager_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "umap/Buffer.hpp" 15 | #include "umap/EvictManager.hpp" 16 | #include "umap/FillWorkers.hpp" 17 | #include "umap/Uffd.hpp" 18 | #include "umap/umap.h" 19 | #include "umap/store/Store.hpp" 20 | #include "umap/RegionDescriptor.hpp" 21 | 22 | namespace Umap { 23 | class FillWorkers; 24 | class EvictManager; 25 | 26 | struct Version { 27 | int major; 28 | int minor; 29 | int patch; 30 | }; 31 | 32 | // 33 | // Implemented as a singleton for now. Things can get too weird attempting to 34 | // manage changes in configuration parameters when we have active monitors 35 | // working. So, we only allow changing configuration when there are no active 36 | // monitors 37 | // 38 | class RegionManager { 39 | public: 40 | static RegionManager& getInstance( void ); 41 | 42 | // delete copy, move, and assign operators 43 | RegionManager(RegionManager const&) = delete; // Copy construct 44 | RegionManager(RegionManager&&) = delete; // Move construct 45 | RegionManager& operator=(RegionManager const&) = delete; // Copy assign 46 | RegionManager& operator=(RegionManager &&) = delete; // Move assign 47 | 48 | void addRegion( 49 | Store* store 50 | , char* region 51 | , uint64_t region_size 52 | , char* mmap_region 53 | , uint64_t mmap_region_size 54 | ); 55 | 56 | int flush_buffer(); 57 | void prefetch(int npages, umap_prefetch_item* page_array); 58 | void fetch_and_pin( char* paddr, uint64_t size ); 59 | void removeRegion( char* mmap_region ); 60 | Version get_umap_version( void ) { return m_version; } 61 | long get_system_page_size( void ) { return m_system_page_size; } 62 | uint64_t get_max_pages_in_buffer( void ) { return m_max_pages_in_buffer; } 63 | int get_monitor_freq( void ) { return m_monitor_freq; } 64 | uint64_t get_umap_page_size( void ) { return m_umap_page_size; } 65 | uint64_t get_num_fillers( void ) { return m_num_fillers; } 66 | uint64_t get_num_evictors( void ) { return m_num_evictors; } 67 | int get_evict_low_water_threshold( void ) { return m_evict_low_water_threshold; } 68 | int get_evict_high_water_threshold( void ) { return m_evict_high_water_threshold; } 69 | uint64_t get_max_fault_events( void ) { return m_max_fault_events; } 70 | Buffer* get_buffer_h() { return m_buffer; } 71 | Uffd* get_uffd_h() { return m_uffd; } 72 | FillWorkers* get_fill_workers_h() { return m_fill_workers; } 73 | EvictManager* get_evict_manager() { return m_evict_manager; } 74 | RegionDescriptor* containing_region( char* vaddr ); 75 | uint64_t get_num_active_regions( void ) { return (uint64_t)m_active_regions.size(); } 76 | 77 | private: 78 | Version m_version; 79 | uint64_t m_max_pages_in_buffer; 80 | int m_monitor_freq; 81 | long m_umap_page_size; 82 | uint64_t m_system_page_size; 83 | uint64_t m_num_fillers; 84 | uint64_t m_num_evictors; 85 | int m_evict_low_water_threshold; 86 | int m_evict_high_water_threshold; 87 | uint64_t m_max_fault_events; 88 | Buffer* m_buffer; 89 | Uffd* m_uffd; 90 | FillWorkers* m_fill_workers; 91 | EvictManager* m_evict_manager; 92 | std::mutex m_mutex; 93 | 94 | std::map m_active_regions; 95 | std::map::iterator m_last_iter; 96 | 97 | RegionManager( void ); 98 | 99 | uint64_t* read_env_var( const char* env, uint64_t* val); 100 | uint64_t get_max_pages_in_memory( void ); 101 | void set_max_fault_events( uint64_t max_events ); 102 | void set_max_pages_in_buffer( uint64_t max_pages ); 103 | void set_umap_page_size( uint64_t page_size ); 104 | void set_num_fillers( uint64_t num_fillers ); 105 | void set_num_evictors( uint64_t num_evictors ); 106 | void set_evict_low_water_threshold( int percent ); 107 | void set_evict_high_water_threshold( int percent ); 108 | }; 109 | 110 | } // end of namespace Umap 111 | #endif // _UMAP_RegionManager_HPP 112 | -------------------------------------------------------------------------------- /src/umap/Uffd.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_Uffd_HPP 8 | #define _UMAP_Uffd_HPP 9 | 10 | #include // sort() 11 | #include // assert() 12 | #include // uint64_t 13 | #include 14 | #include 15 | #include // We all have lists to manage 16 | 17 | #include // strerror() 18 | #include // O_CLOEXEC 19 | #include // ioctl(UFFDIO_*) 20 | #include // poll() 21 | #include // strerror() 22 | #include // ioctl() 23 | #include // syscall() 24 | #include // syscall() 25 | 26 | #include "umap/config.h" 27 | // 28 | // The UFFDIO_COPY_MODE_WP is only defined in later versions of Linux (>5.0) 29 | // 30 | #ifndef UFFDIO_COPY_MODE_WP 31 | #define UMAP_RO_MODE 32 | #endif 33 | 34 | #include "umap/RegionDescriptor.hpp" 35 | #include "umap/RegionManager.hpp" 36 | #include "umap/WorkerPool.hpp" 37 | 38 | namespace Umap { 39 | class RegionManager; 40 | 41 | class PageEvent { 42 | public: 43 | PageEvent(void* paddr, bool iswrite); 44 | }; 45 | 46 | class Uffd : public WorkerPool { 47 | public: 48 | Uffd( void ); 49 | ~Uffd( void); 50 | 51 | void process_page(bool iswrite, char* addr ); 52 | void register_region( RegionDescriptor* region ); 53 | void unregister_region( RegionDescriptor* region ); 54 | 55 | void enable_write_protect( void* ); 56 | void disable_write_protect( void* ); 57 | void copy_in_page(char* data, void* page_address); 58 | void copy_in_page_and_write_protect(char* data, void* page_address); 59 | 60 | private: 61 | RegionManager& m_rm; 62 | uint64_t m_max_fault_events; 63 | uint64_t m_page_size; 64 | Buffer* m_buffer; 65 | int m_uffd_fd; 66 | int m_pipe[2]; 67 | std::vector m_events; 68 | 69 | void uffd_handler( void ); 70 | void ThreadEntry( void ); 71 | void check_uffd_compatibility( void ); 72 | }; 73 | } // end of namespace Umap 74 | #endif // _UMAP_Uffd_HPP 75 | -------------------------------------------------------------------------------- /src/umap/WorkQueue.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_WorkQueue_HPP 8 | #define _UMAP_WorkQueue_HPP 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "umap/Uffd.hpp" 17 | #include "umap/store/Store.hpp" 18 | #include "umap/util/Macros.hpp" 19 | 20 | namespace Umap { 21 | template 22 | class WorkQueue { 23 | public: 24 | WorkQueue(int max_workers) 25 | : m_max_waiting(max_workers) 26 | , m_waiting_workers(0) 27 | , m_idle_waiters(0) 28 | { 29 | pthread_mutex_init(&m_mutex, NULL); 30 | pthread_cond_init(&m_cond, NULL); 31 | pthread_cond_init(&m_idle_cond, NULL); 32 | } 33 | 34 | ~WorkQueue() { 35 | pthread_mutex_destroy(&m_mutex); 36 | pthread_cond_destroy(&m_cond); 37 | pthread_cond_destroy(&m_idle_cond); 38 | } 39 | 40 | void enqueue(T item) { 41 | pthread_mutex_lock(&m_mutex); 42 | m_queue.push_back(item); 43 | pthread_cond_signal(&m_cond); 44 | pthread_mutex_unlock(&m_mutex); 45 | } 46 | 47 | T dequeue() { 48 | pthread_mutex_lock(&m_mutex); 49 | 50 | ++m_waiting_workers; 51 | 52 | while ( m_queue.size() == 0 ) { 53 | if (m_waiting_workers == m_max_waiting && m_idle_waiters) 54 | pthread_cond_signal(&m_idle_cond); 55 | 56 | pthread_cond_wait(&m_cond, &m_mutex); 57 | } 58 | 59 | --m_waiting_workers; 60 | 61 | auto item = m_queue.front(); 62 | m_queue.pop_front(); 63 | 64 | pthread_mutex_unlock(&m_mutex); 65 | return item; 66 | } 67 | 68 | void wait_for_idle( void ) { 69 | pthread_mutex_lock(&m_mutex); 70 | ++m_idle_waiters; 71 | 72 | while ( ! ( m_queue.size() == 0 && m_waiting_workers == m_max_waiting ) ) 73 | pthread_cond_wait(&m_idle_cond, &m_mutex); 74 | 75 | --m_idle_waiters; 76 | pthread_mutex_unlock(&m_mutex); 77 | } 78 | 79 | bool is_empty() { 80 | pthread_mutex_lock(&m_mutex); 81 | bool empty = (m_queue.size() == 0); 82 | pthread_mutex_unlock(&m_mutex); 83 | return empty; 84 | } 85 | 86 | private: 87 | pthread_mutex_t m_mutex; 88 | pthread_cond_t m_cond; 89 | pthread_cond_t m_idle_cond; 90 | std::list m_queue; 91 | uint64_t m_max_waiting; 92 | uint64_t m_waiting_workers; 93 | int m_idle_waiters; 94 | }; 95 | 96 | } // end of namespace Umap 97 | 98 | #endif // _UMAP_WorkQueue_HPP 99 | -------------------------------------------------------------------------------- /src/umap/WorkerPool.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_Pthread_HPP 8 | #define _UMAP_Pthread_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "umap/PageDescriptor.hpp" 16 | #include "umap/WorkQueue.hpp" 17 | #include "umap/util/Macros.hpp" 18 | 19 | namespace Umap { 20 | struct WorkItem { 21 | enum WorkType { NONE, EXIT, THRESHOLD, EVICT, FAST_EVICT, FLUSH }; 22 | PageDescriptor* page_desc; 23 | WorkType type; 24 | }; 25 | 26 | static std::ostream& operator<<(std::ostream& os, const Umap::WorkItem& b) 27 | { 28 | os << "{ page_desc: " << b.page_desc; 29 | 30 | switch (b.type) { 31 | default: os << ", type: Unknown(" << b.type << ")"; break; 32 | case Umap::WorkItem::WorkType::NONE: os << ", type: " << "NONE"; break; 33 | case Umap::WorkItem::WorkType::EXIT: os << ", type: " << "EXIT"; break; 34 | case Umap::WorkItem::WorkType::THRESHOLD: os << ", type: " << "THRESHOLD"; break; 35 | case Umap::WorkItem::WorkType::EVICT: os << ", type: " << "EVICT"; break; 36 | case Umap::WorkItem::WorkType::FAST_EVICT: os << ", type: " << "FAST_EVICT"; break; 37 | case Umap::WorkItem::WorkType::FLUSH: os << ", type: " << "FLUSH"; break; 38 | } 39 | 40 | os << " }"; 41 | return os; 42 | } 43 | 44 | class WorkerPool { 45 | public: 46 | WorkerPool(const std::string& pool_name, uint64_t num_threads) 47 | : m_pool_name(pool_name) 48 | , m_num_threads(num_threads) 49 | , m_wq(new WorkQueue(num_threads)) 50 | { 51 | if (m_pool_name.length() > 15) 52 | m_pool_name.resize(15); 53 | } 54 | 55 | virtual ~WorkerPool() { 56 | stop_thread_pool(); 57 | delete m_wq; 58 | } 59 | 60 | void send_work(const WorkItem& work) { 61 | m_wq->enqueue(work); 62 | } 63 | 64 | WorkItem get_work() { 65 | return m_wq->dequeue(); 66 | } 67 | 68 | bool wq_is_empty( void ) { 69 | return m_wq->is_empty(); 70 | } 71 | 72 | void start_thread_pool() { 73 | UMAP_LOG(Debug, "Starting " << m_pool_name << " Pool of " 74 | << m_num_threads << " threads"); 75 | 76 | for ( uint64_t i = 0; i < m_num_threads; ++i) { 77 | pthread_t t; 78 | 79 | if (pthread_create(&t, NULL, ThreadEntryFunc, this) != 0) 80 | UMAP_ERROR("Failed to launch thread"); 81 | 82 | if (pthread_setname_np(t, m_pool_name.c_str()) != 0) 83 | UMAP_ERROR("Failed to set thread name"); 84 | 85 | m_threads.push_back(t); 86 | } 87 | } 88 | 89 | void stop_thread_pool() { 90 | UMAP_LOG(Debug, "Stopping " << m_pool_name << " Pool of " 91 | << m_num_threads << " threads"); 92 | 93 | WorkItem w = {.page_desc = nullptr, .type = Umap::WorkItem::WorkType::EXIT }; 94 | 95 | // 96 | // This will inform all of the threads it is time to go away 97 | // 98 | for ( uint64_t i = 0; i < m_num_threads; ++i) 99 | send_work(w); 100 | 101 | // 102 | // Wait for all of the threads to exit 103 | // 104 | for ( auto pt : m_threads ) 105 | (void) pthread_join(pt, NULL); 106 | 107 | m_threads.clear(); 108 | 109 | UMAP_LOG(Debug, m_pool_name << " stopped"); 110 | } 111 | 112 | void wait_for_idle( void ) { 113 | m_wq->wait_for_idle(); 114 | } 115 | 116 | protected: 117 | virtual void ThreadEntry() = 0; 118 | 119 | private: 120 | static void* ThreadEntryFunc(void * This) { 121 | ((WorkerPool *)This)->ThreadEntry(); 122 | return NULL; 123 | } 124 | 125 | std::string m_pool_name; 126 | uint64_t m_num_threads; 127 | WorkQueue* m_wq; 128 | std::vector m_threads; 129 | }; 130 | } // end of namespace Umap 131 | #endif // _UMAP_WorkerPool_HPP 132 | -------------------------------------------------------------------------------- /src/umap/store/SparseStore.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include 10 | #include "umap/store/Store.hpp" 11 | #include "umap/umap.h" 12 | 13 | namespace Umap { 14 | class SparseStore : public Store { 15 | public: 16 | SparseStore(size_t _rsize_, size_t _aligned_size_, std::string _root_path_, size_t _file_Size_); 17 | SparseStore(std::string _root_path, bool _read_only_); 18 | ~SparseStore(); 19 | ssize_t read_from_store(char* buf, size_t nb, off_t off); 20 | ssize_t write_to_store(char* buf, size_t nb, off_t off); 21 | size_t get_current_capacity(); 22 | static size_t get_capacity(std::string base_path); 23 | int close_files(); 24 | private: 25 | int fd; 26 | size_t file_size; 27 | size_t current_capacity; 28 | uint64_t num_files; 29 | size_t rsize; 30 | size_t aligned_size; 31 | bool read_only; 32 | std::string root_path; 33 | // reads and writes I/O counters 34 | std::atomic numreads; 35 | std::atomic numwrites; 36 | struct file_descriptor{ 37 | int id; 38 | off_t beginning; 39 | off_t end; 40 | }; 41 | file_descriptor* file_descriptors; 42 | std::mutex creation_mutex; 43 | int get_fd(off_t offset, off_t &file_offset); 44 | // ssize_t get_file_size(const std::string file_path); 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/umap/store/Store.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "umap/umap.h" 8 | #include "umap/store/Store.hpp" 9 | #include "umap/store/StoreFile.h" 10 | 11 | namespace Umap { 12 | Store* Store::make_store(void* _region_, size_t _rsize_, size_t _alignsize_, int _fd_) 13 | { 14 | return new StoreFile{_region_, _rsize_, _alignsize_, _fd_}; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/umap/store/Store.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_STORE_H_ 8 | #define _UMAP_STORE_H_ 9 | #include 10 | #include 11 | 12 | namespace Umap { 13 | class Store { 14 | public: 15 | static Store* make_store(void* _region_, std::size_t _rsize_, std::size_t _alignsize_, int _fd_); 16 | 17 | virtual ssize_t read_from_store(char* buf, std::size_t nb, off_t off) = 0; 18 | virtual ssize_t write_to_store(char* buf, std::size_t nb, off_t off) = 0; 19 | }; 20 | } // end of namespace Umap 21 | #endif 22 | -------------------------------------------------------------------------------- /src/umap/store/StoreFile.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include 8 | #include 9 | #include "StoreFile.h" 10 | #include 11 | #include 12 | #include 13 | 14 | #include "umap/store/Store.hpp" 15 | #include "umap/util/Macros.hpp" 16 | 17 | namespace Umap { 18 | StoreFile::StoreFile(void* _region_, size_t _rsize_, size_t _alignsize_, int _fd_) 19 | : region{_region_}, rsize{_rsize_}, alignsize{_alignsize_}, fd{_fd_} 20 | { 21 | UMAP_LOG(Debug, 22 | "region: " << region << " rsize: " << rsize 23 | << " alignsize: " << alignsize << " fd: " << fd); 24 | } 25 | 26 | ssize_t StoreFile::read_from_store(char* buf, size_t nb, off_t off) 27 | { 28 | size_t rval = 0; 29 | 30 | UMAP_LOG(Debug, "pread(fd=" << fd << ", buf=" << (void*)buf 31 | << ", nb=" << nb << ", off=" << off << ")";); 32 | 33 | rval = pread(fd, buf, nb, off); 34 | 35 | if (rval == -1) { 36 | int eno = errno; 37 | UMAP_ERROR("pread(fd=" << fd << ", buf=" << (void*)buf 38 | << ", nb=" << nb << ", off=" << off 39 | << "): Failed - " << strerror(eno)); 40 | } 41 | return rval; 42 | } 43 | 44 | ssize_t StoreFile::write_to_store(char* buf, size_t nb, off_t off) 45 | { 46 | size_t rval = 0; 47 | 48 | UMAP_LOG(Debug, "pwrite(fd=" << fd << ", buf=" << (void*)buf 49 | << ", nb=" << nb << ", off=" << off << ")";); 50 | 51 | rval = pwrite(fd, buf, nb, off); 52 | if (rval == -1) { 53 | int eno = errno; 54 | UMAP_ERROR("pwrite(fd=" << fd << ", buf=" << (void*)buf 55 | << ", nb=" << nb << ", off=" << off 56 | << "): Failed - " << strerror(eno)); 57 | } 58 | return rval; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/umap/store/StoreFile.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_STORE_FILE_H_ 8 | #define _UMAP_STORE_FILE_H_ 9 | #include 10 | #include "umap/store/Store.hpp" 11 | #include "umap/umap.h" 12 | 13 | namespace Umap { 14 | class StoreFile : public Store { 15 | public: 16 | StoreFile(void* _region_, size_t _rsize_, size_t _alignsize_, int _fd_); 17 | 18 | ssize_t read_from_store(char* buf, size_t nb, off_t off); 19 | ssize_t write_to_store(char* buf, size_t nb, off_t off); 20 | private: 21 | void* region; 22 | void* alignment_buffer; 23 | size_t rsize; 24 | size_t alignsize; 25 | int fd; 26 | }; 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /src/umap/umap.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include 9 | #include // strerror() 10 | #include // strerror() 11 | #include 12 | 13 | #include "umap/config.h" 14 | 15 | #include "umap/RegionManager.hpp" 16 | #include "umap/umap.h" 17 | #include "umap/store/Store.hpp" 18 | #include "umap/util/Macros.hpp" 19 | 20 | void* 21 | umap( 22 | void* region_addr 23 | , uint64_t region_size 24 | , int prot 25 | , int flags 26 | , int fd 27 | , off_t offset 28 | ) 29 | { 30 | UMAP_LOG(Debug, 31 | "region_addr: " << region_addr 32 | << ", region_size: " << region_size 33 | << ", prot: " << prot 34 | << ", flags: " << flags 35 | << ", offset: " << offset 36 | ); 37 | return Umap::umap_ex(region_addr, region_size, prot, flags, fd, 0, nullptr); 38 | } 39 | 40 | int 41 | uunmap(void* addr, uint64_t length) 42 | { 43 | UMAP_LOG(Debug, "addr: " << addr << ", length: " << length); 44 | auto& rm = Umap::RegionManager::getInstance(); 45 | rm.removeRegion((char*)addr); 46 | UMAP_LOG(Debug, "Done"); 47 | return 0; 48 | } 49 | 50 | 51 | int umap_flush(){ 52 | 53 | UMAP_LOG(Debug, "umap_flush " ); 54 | 55 | return Umap::RegionManager::getInstance().flush_buffer(); 56 | 57 | } 58 | 59 | int umap_has_write_support(){ 60 | #ifdef UMAP_RO_MODE 61 | return 0; 62 | #else 63 | return 1; 64 | #endif 65 | } 66 | 67 | void umap_prefetch( int npages, umap_prefetch_item* page_array ) 68 | { 69 | Umap::RegionManager::getInstance().prefetch(npages, page_array); 70 | } 71 | 72 | 73 | void umap_fetch_and_pin( char* paddr, uint64_t size ) 74 | { 75 | Umap::RegionManager::getInstance().fetch_and_pin(paddr, size); 76 | } 77 | 78 | 79 | long 80 | umapcfg_get_system_page_size( void ) 81 | { 82 | return Umap::RegionManager::getInstance().get_system_page_size(); 83 | } 84 | 85 | uint64_t 86 | umapcfg_get_max_pages_in_buffer( void ) 87 | { 88 | return Umap::RegionManager::getInstance().get_max_pages_in_buffer(); 89 | } 90 | 91 | uint64_t 92 | umapcfg_get_umap_page_size( void ) 93 | { 94 | return Umap::RegionManager::getInstance().get_umap_page_size(); 95 | } 96 | 97 | uint64_t 98 | umapcfg_get_num_fillers( void ) 99 | { 100 | return Umap::RegionManager::getInstance().get_num_fillers(); 101 | } 102 | 103 | uint64_t 104 | umapcfg_get_num_evictors( void ) 105 | { 106 | return Umap::RegionManager::getInstance().get_num_evictors(); 107 | } 108 | 109 | int 110 | umapcfg_get_evict_low_water_threshold( void ) 111 | { 112 | return Umap::RegionManager::getInstance().get_evict_low_water_threshold(); 113 | } 114 | 115 | int 116 | umapcfg_get_evict_high_water_threshold( void ) 117 | { 118 | return Umap::RegionManager::getInstance().get_evict_high_water_threshold(); 119 | } 120 | 121 | uint64_t 122 | umapcfg_get_max_fault_events( void ) 123 | { 124 | return Umap::RegionManager::getInstance().get_max_fault_events(); 125 | } 126 | 127 | namespace Umap { 128 | // A global variable to ensure thread-safety 129 | std::mutex g_mutex; 130 | 131 | void* 132 | umap_ex( 133 | void* region_addr 134 | , uint64_t region_size 135 | , int prot 136 | , int flags 137 | , int fd 138 | , off_t offset 139 | , Store* store 140 | ) 141 | { 142 | std::lock_guard lock(g_mutex); 143 | auto& rm = RegionManager::getInstance(); 144 | auto umap_psize = rm.get_umap_page_size(); 145 | 146 | if (region_size == 0){ 147 | errno = -EINVAL; 148 | return (void *)-1; 149 | } 150 | 151 | UMAP_LOG(Info, 152 | "region_addr: " << region_addr 153 | << ", region_size: " << region_size 154 | << ", prot: " << prot 155 | << ", flags: " << flags 156 | << ", offset: " << offset 157 | << ", store: " << store 158 | << ", umap_psize: " << umap_psize 159 | ); 160 | 161 | #ifdef UMAP_RO_MODE 162 | if( prot != PROT_READ ) 163 | UMAP_ERROR("only PROT_READ is supported in UMAP_RO_MODE compilation"); 164 | #else 165 | if( prot & ~(PROT_READ|PROT_WRITE) ) 166 | UMAP_ERROR("only PROT_READ or PROT_WRITE is supported in UMap"); 167 | #endif 168 | 169 | // 170 | // TODO: Allow for non-page-multiple size and zero-fill like mmap does 171 | // 172 | if ( ( region_size % umap_psize ) ) { 173 | UMAP_ERROR("Region size " << region_size 174 | << " is not a multple of umapPageSize (" 175 | << rm.get_umap_page_size() << ")"); 176 | } 177 | 178 | if ( ( (uint64_t)region_addr & (umap_psize - 1) ) ) { 179 | UMAP_ERROR("region_addr must be page aligned: " << region_addr 180 | << ", page size is: " << rm.get_umap_page_size()); 181 | } 182 | 183 | if (!(flags & UMAP_PRIVATE) || flags & ~(UMAP_PRIVATE|UMAP_FIXED)) { 184 | UMAP_ERROR("Invalid flags: " << std::hex << flags); 185 | } 186 | 187 | // 188 | // When dealing with umap-page-sizes that could be multiples of the actual 189 | // system-page-size, it is possible for mmap() to provide a region that is on 190 | // a system-page-boundary, but not necessarily on a umap-page-size boundary. 191 | // 192 | // We always allocate an additional umap-page-size set of bytes so that we can 193 | // make certain that the umap-region begins on a umap-page-size boundary. 194 | // 195 | uint64_t mmap_size = region_size + umap_psize; 196 | 197 | void* mmap_region = mmap(region_addr, mmap_size, 198 | prot, flags | (MAP_ANONYMOUS | MAP_NORESERVE), -1, 0); 199 | 200 | if (mmap_region == MAP_FAILED) { 201 | UMAP_ERROR("mmap failed: " << strerror(errno)); 202 | return UMAP_FAILED; 203 | } 204 | uint64_t umap_size = region_size; 205 | void* umap_region; 206 | umap_region = (void*)((uint64_t)mmap_region + umap_psize - 1); 207 | umap_region = (void*)((uint64_t)umap_region & ~(umap_psize - 1)); 208 | 209 | if ( store == nullptr ) 210 | store = Store::make_store(umap_region, umap_size, umap_psize, fd); 211 | 212 | rm.addRegion(store, (char*)umap_region, umap_size, (char*)mmap_region, mmap_size); 213 | 214 | return umap_region; 215 | } 216 | } // namespace Umap 217 | -------------------------------------------------------------------------------- /src/umap/umap.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_H_ 8 | #define _UMAP_H_ 9 | 10 | #ifdef __cplusplus 11 | #include 12 | #include 13 | #include "umap/store/Store.hpp" 14 | #else // __cplusplus 15 | #include 16 | #endif // __cplusplus 17 | 18 | #include 19 | #include 20 | 21 | #ifdef __cplusplus 22 | namespace Umap { 23 | /** Allow application to create region of memory to a persistent store 24 | * \param addr Same as input argument for mmap(2) 25 | * \param length Same as input argument of mmap(2) 26 | * \param prot Same as input argument of mmap(2) 27 | * \param flags Same as input argument of mmap(2) 28 | */ 29 | extern std::mutex m_mutex; 30 | extern int num_thread; 31 | void* umap_ex( 32 | void* addr 33 | , std::size_t length 34 | , int prot 35 | , int flags 36 | , int fd 37 | , off_t offset 38 | , Umap::Store* store 39 | ); 40 | } // namespace Umap 41 | #endif // __cplusplus 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | /** Allow application to create region of memory to a persistent store 47 | * \param addr Same as input argument for mmap(2) 48 | * \param length Same as input argument of mmap(2) 49 | * \param prot Same as input argument of mmap(2) 50 | * \param flags Same as input argument of mmap(2) 51 | */ 52 | void* umap( 53 | void* addr 54 | , size_t length 55 | , int prot 56 | , int flags 57 | , int fd 58 | , off_t offset 59 | ); 60 | 61 | int uunmap( 62 | void* addr 63 | , size_t length 64 | ); 65 | 66 | int umap_flush(); 67 | 68 | struct umap_prefetch_item { 69 | void* page_base_addr; 70 | }; 71 | 72 | int umap_has_write_support(); 73 | 74 | void umap_prefetch( int npages, struct umap_prefetch_item* page_array ); 75 | void umap_fetch_and_pin( char* paddr, uint64_t size ); 76 | uint64_t umapcfg_get_umap_page_size( void ); 77 | uint64_t umapcfg_get_max_fault_events( void ); 78 | uint64_t umapcfg_get_num_fillers( void ); 79 | uint64_t umapcfg_get_num_evictors( void ); 80 | uint64_t umapcfg_get_max_pages_in_buffer( void ); 81 | uint64_t umapcfg_get_read_ahead( void ); 82 | int umapcfg_get_evict_low_water_threshold( void ); 83 | int umapcfg_get_evict_high_water_threshold( void ); 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | /* 90 | * flags 91 | */ 92 | #define UMAP_PRIVATE MAP_PRIVATE // Note - UMAP_SHARED not currently supported 93 | #define UMAP_FIXED MAP_FIXED // See mmap(2) - This flag is currently then only flag supported. 94 | 95 | /* 96 | * Return codes 97 | */ 98 | #define UMAP_FAILED (void *)-1 99 | #endif // _UMAP_H 100 | -------------------------------------------------------------------------------- /src/umap/util/Exception.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "umap/util/Exception.hpp" 8 | 9 | #include 10 | 11 | namespace Umap { 12 | 13 | Exception::Exception( 14 | const std::string& message, 15 | const std::string &file, 16 | int line) : 17 | m_message(message), 18 | m_file(file), 19 | m_line(line) 20 | { 21 | m_what = this->message(); 22 | } 23 | 24 | std::string 25 | Exception::message() const 26 | { 27 | std::stringstream oss; 28 | oss << "! UMAP Exception [" << m_file << ":" << m_line << "]: "; 29 | oss << m_message; 30 | return oss.str(); 31 | } 32 | 33 | const char* 34 | Exception::what() const throw() 35 | { 36 | return m_what.c_str(); 37 | } 38 | 39 | } // end of namespace Umap 40 | -------------------------------------------------------------------------------- /src/umap/util/Exception.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef UMAP_Exception_HPP 8 | #define UMAP_Exception_HPP 9 | 10 | #include 11 | #include 12 | 13 | namespace Umap { 14 | 15 | class Exception : public std::exception { 16 | public: 17 | Exception(const std::string& msg, 18 | const std::string &file, 19 | int line); 20 | 21 | virtual ~Exception() = default; 22 | 23 | std::string message() const; 24 | virtual const char* what() const throw(); 25 | 26 | private: 27 | std::string m_message; 28 | std::string m_file; 29 | int m_line; 30 | 31 | std::string m_what; 32 | }; 33 | 34 | } // end of namespace Umap 35 | 36 | #endif // UMAP_Exception_HPP 37 | -------------------------------------------------------------------------------- /src/umap/util/Logger.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "umap/util/Logger.hpp" 8 | 9 | #include // for std::cout, std::cerr 10 | #include 11 | #include // for getenv() 12 | #include // for strcasecmp() 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace Umap { 20 | 21 | static const char* env_name = "UMAP_LOG_LEVEL"; 22 | static const char* env_name_no_timestamp = "UMAP_LOG_NO_TIMESTAMP_LEVEL"; 23 | static message::Level defaultLevel = message::Info; 24 | std::mutex g_logging_mutex; 25 | Logger* Logger::s_Logger = nullptr; 26 | 27 | static const std::string MessageLevelName[ message::Num_Levels ] = { 28 | "ERROR", 29 | "WARNING", 30 | "INFO", 31 | "DEBUG" 32 | }; 33 | 34 | Logger::Logger(bool log_with_timestamp) noexcept 35 | : m_log_timestamp(log_with_timestamp) 36 | { 37 | // by default, all message streams are disabled 38 | for ( int i=0 ; i < message::Num_Levels ; ++i ) 39 | m_isEnabled[ i ] = false; 40 | } 41 | 42 | Logger::~Logger() noexcept 43 | { 44 | } 45 | 46 | void Logger::setLoggingMsgLevel( message::Level level ) noexcept 47 | { 48 | for ( int i=0 ; i < message::Num_Levels ; ++i ) 49 | m_isEnabled[ i ] = (i<= level) ? true : false; 50 | } 51 | 52 | void Logger::logMessage( message::Level level, 53 | const std::string& message, 54 | const std::string& fileName, 55 | int line ) noexcept 56 | { 57 | if ( !logLevelEnabled( level ) ) 58 | return; /* short-circuit */ 59 | 60 | std::lock_guard guard(g_logging_mutex); 61 | if (m_log_timestamp) { 62 | std::ostringstream ss; 63 | ss << std::fixed << std::setprecision(3) << std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() / 1000.0; 64 | 65 | std::cout 66 | << ss.str() << ":" 67 | << getpid() << ":" 68 | << syscall(__NR_gettid) << " " 69 | << "[" << MessageLevelName[ level ] << "]" 70 | << "[" << fileName << ":" << line << "]:" 71 | << message 72 | << std::endl; 73 | } 74 | else { 75 | std::cout 76 | << message 77 | << std::endl; 78 | } 79 | } 80 | 81 | void Logger::initialize() 82 | { 83 | if ( s_Logger != nullptr ) 84 | return; 85 | 86 | message::Level level = defaultLevel; 87 | char* enval = getenv(env_name); 88 | char* enval_no_timestamp = getenv(env_name_no_timestamp); 89 | bool log_with_timestamp = true; 90 | 91 | if ( enval != NULL || enval_no_timestamp != NULL ) { 92 | 93 | if (enval_no_timestamp != NULL) { 94 | enval = enval_no_timestamp; 95 | log_with_timestamp = false; 96 | } 97 | 98 | bool level_found = false; 99 | for ( int i = 0; i < message::Num_Levels; ++i ) { 100 | if ( strcasecmp( enval, MessageLevelName[ i ].c_str() ) == 0 ) { 101 | level_found = true; 102 | level = (message::Level)i; 103 | break; 104 | } 105 | } 106 | if (! level_found ) { 107 | std::cerr << "No matching logging levels for: " << enval << "\n"; 108 | std::cerr << "Available levels are:\n"; 109 | for ( int i = 0; i < message::Num_Levels; ++i ) { 110 | std::cerr << "\t" << MessageLevelName[ i ] << "\n"; 111 | } 112 | } 113 | } 114 | 115 | s_Logger = new Logger(log_with_timestamp); 116 | s_Logger->setLoggingMsgLevel(level); 117 | } 118 | 119 | void Logger::finalize() 120 | { 121 | delete s_Logger; 122 | s_Logger = nullptr; 123 | } 124 | 125 | Logger* Logger::getActiveLogger() 126 | { 127 | if ( s_Logger == nullptr ) 128 | Logger::initialize(); 129 | 130 | return s_Logger; 131 | } 132 | 133 | } /* namespace umap */ 134 | -------------------------------------------------------------------------------- /src/umap/util/Logger.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef UMAP_Logger_HPP 8 | #define UMAP_Logger_HPP 9 | 10 | #include 11 | 12 | namespace Umap { 13 | 14 | namespace message { 15 | enum Level { 16 | Error, 17 | Warning, 18 | Info, 19 | Debug, 20 | 21 | Num_Levels 22 | }; 23 | 24 | static const std::string MessageLevelName[ Level::Num_Levels ] = { 25 | "ERROR", 26 | "WARNING", 27 | "INFO", 28 | "DEBUG" 29 | }; 30 | } /* namespace messge */ 31 | 32 | class Logger { 33 | public: 34 | 35 | void setLoggingMsgLevel( message::Level level ) noexcept; 36 | 37 | void logMessage( message::Level level, 38 | const std::string& message, 39 | const std::string& fileName, 40 | int line ) noexcept; 41 | 42 | static void initialize(); 43 | 44 | static void finalize(); 45 | 46 | static Logger* getActiveLogger(); 47 | 48 | static Logger* getRootLogger(); 49 | 50 | inline bool logLevelEnabled( message::Level level ) 51 | { 52 | if ( level < 0 || level >= message::Num_Levels || m_isEnabled[ level ] == false ) 53 | return false; 54 | else 55 | return true; 56 | }; 57 | 58 | private: 59 | Logger( bool log_with_timestamp ) noexcept; 60 | ~Logger() noexcept; 61 | 62 | bool m_log_timestamp; 63 | bool m_isEnabled[ message::Num_Levels ]; 64 | static Logger* s_Logger; 65 | }; 66 | 67 | } /* namespace Umap */ 68 | 69 | #endif /* UMAP_Logger_HPP */ 70 | -------------------------------------------------------------------------------- /src/umap/util/Macros.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef UMAP_Macros_HPP 8 | #define UMAP_Macros_HPP 9 | 10 | #include "umap/util/Exception.hpp" 11 | #include "umap/config.h" 12 | 13 | #include 14 | #include 15 | 16 | #ifdef UMAP_ENABLE_ASSERTS 17 | #include 18 | #define UMAP_ASSERT(condition) assert(condition) 19 | #else 20 | #define UMAP_ASSERT(condition) ((void)0) 21 | #endif // UMAP_ENABLE_ASSERTS 22 | 23 | #ifdef UMAP_DEBUG_LOGGING 24 | 25 | #include "umap/util/Logger.hpp" 26 | #define UMAP_LOG( lvl, msg ) \ 27 | { \ 28 | if (Umap::Logger::getActiveLogger()->logLevelEnabled(Umap::message::lvl)) { \ 29 | std::ostringstream local_msg; \ 30 | local_msg << " " << __func__ << " " << msg; \ 31 | Umap::Logger::getActiveLogger()->logMessage( \ 32 | Umap::message::lvl, local_msg.str(), \ 33 | std::string(__FILE__), __LINE__); \ 34 | } \ 35 | } 36 | 37 | #else 38 | 39 | #define UMAP_LOG( lvl, msg ) ((void)0) 40 | 41 | #endif // UMAP_DEBUG_LOGGING 42 | 43 | #define UMAP_UNUSED_ARG(x) 44 | 45 | #define UMAP_USE_VAR(x) static_cast(x) 46 | 47 | #define UMAP_ERROR( msg ) \ 48 | { \ 49 | UMAP_LOG(Error, msg); \ 50 | std::ostringstream umap_oss_error; \ 51 | umap_oss_error << " " << __func__ << " " << msg; \ 52 | throw Umap::Exception( umap_oss_error.str(), \ 53 | std::string(__FILE__), \ 54 | __LINE__); \ 55 | } 56 | 57 | #endif // UMAP_Macros_HPP 58 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | add_subdirectory(churn) 8 | add_subdirectory(flush_buffer) 9 | add_subdirectory(pfbenchmark) 10 | add_subdirectory(multi_thread) 11 | add_subdirectory(umap-sparsestore) 12 | if (caliper_DIR) 13 | add_subdirectory(caliper_trace) 14 | endif() 15 | -------------------------------------------------------------------------------- /tests/caliper_trace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2019 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | project(caliper_trace) 8 | 9 | find_package(caliper REQUIRED PATHS "${caliper_DIR}") 10 | if(caliper_FOUND) 11 | message(STATUS "Found caliper_INCLUDE_DIR ${caliper_INCLUDE_DIR}" ) 12 | 13 | FIND_PACKAGE( OpenMP REQUIRED ) 14 | if(OPENMP_FOUND) 15 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 17 | set(CMAKE_EXE_LINKER_FLAGS 18 | "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 19 | add_executable(caliper_trace caliper_trace.cpp) 20 | 21 | if(STATIC_UMAP_LINK) 22 | set(umap-lib "umap-static") 23 | else() 24 | set(umap-lib "umap") 25 | endif() 26 | 27 | add_dependencies(caliper_trace ${umap-lib}) 28 | target_link_libraries(caliper_trace ${umap-lib} caliper) 29 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ${caliper_INCLUDE_DIR}) 30 | 31 | install(TARGETS caliper_trace 32 | LIBRARY DESTINATION lib 33 | ARCHIVE DESTINATION lib/static 34 | RUNTIME DESTINATION bin ) 35 | 36 | else() 37 | message("Skipping caliper_trace, OpenMP required") 38 | endif() 39 | 40 | else() 41 | message("Skipping caliper_trace, Caliper package not found") 42 | endif() 43 | 44 | -------------------------------------------------------------------------------- /tests/caliper_trace/caliper_trace.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2019 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | * It is a simple example showing flush_cache ensures that 10 | * modified pages in buffer is persisted into back stores. 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "errno.h" 21 | #include "umap/umap.h" 22 | #include "caliper/cali_datatracker.h" 23 | #include "caliper/cali.h" 24 | 25 | using namespace std; 26 | 27 | int 28 | open_prealloc_file( const char* fname, uint64_t totalbytes) 29 | { 30 | 31 | int fd = open(fname, O_RDWR | O_LARGEFILE | O_DIRECT | O_CREAT, S_IRUSR | S_IWUSR); 32 | if ( fd == -1 ) { 33 | int eno = errno; 34 | std::cerr << "Failed to create " << fname << ": " << strerror(eno) << std::endl; 35 | exit(1); 36 | } 37 | 38 | // Pre-allocate disk space for the file. 39 | try { 40 | int x; 41 | if ( ( x = posix_fallocate(fd, 0, totalbytes) != 0 ) ) { 42 | int eno = errno; 43 | std::cerr << "Failed to pre-allocate " << fname << ": " << strerror(eno) << std::endl; 44 | exit(1); 45 | } 46 | } catch(const std::exception& e) { 47 | std::cerr << "posix_fallocate: " << e.what() << std::endl; 48 | exit(1); 49 | } catch(...) { 50 | int eno = errno; 51 | std::cerr << "Failed to pre-allocate " << fname << ": " << strerror(eno) << std::endl; 52 | exit(1); 53 | } 54 | 55 | void* temp = malloc(totalbytes); 56 | memset(temp, 'c', totalbytes); 57 | ssize_t res = write(fd, temp, totalbytes); 58 | assert(res == totalbytes); 59 | close(fd); 60 | free(temp); 61 | 62 | /* re-open and return file descriptor for read-only */ 63 | fd = open(fname, O_RDONLY, S_IRUSR | S_IWUSR); 64 | if ( fd == -1 ) { 65 | int eno = errno; 66 | std::cerr << "Failed to create " << fname << ": " << strerror(eno) << std::endl; 67 | exit(1); 68 | } 69 | 70 | return fd; 71 | } 72 | 73 | 74 | int 75 | main(int argc, char **argv) 76 | { 77 | const char* filename = "caliper_trace_test_file.txt"; 78 | 79 | uint64_t umap_pagesize = umapcfg_get_umap_page_size(); 80 | const uint64_t umap_region_length = 128 * umap_pagesize; 81 | int fd = open_prealloc_file(filename, umap_region_length); 82 | 83 | std::cout << "umap_pagesize " << umap_pagesize << "\n"; 84 | std::cout << "umap_region_length " << umap_region_length << "\n"; 85 | std::cout << "open_prealloc_file "<< filename << "\n"; 86 | 87 | 88 | /* Ensure Caliper tracing is enabled*/ 89 | cali_config_set("CALI_SERVICES_ENABLE", "alloc,event,trace,recorder"); 90 | cali_config_set("CALI_ALLOC_TRACK_ALLOCATIONS", "true"); 91 | cali_config_set("CALI_ALLOC_RESOLVE_ADDRESSES", "true"); 92 | 93 | 94 | void* base_addr = umap(NULL, umap_region_length, PROT_READ, UMAP_PRIVATE, fd, 0); 95 | if ( base_addr == UMAP_FAILED ) { 96 | int eno = errno; 97 | std::cerr << "Failed to umap " << filename << ": " << strerror(eno) << std::endl; 98 | return -1; 99 | } 100 | std::cout << "umap base_addr at "<< base_addr <<"\n"; 101 | cali_datatracker_track(base_addr, "umap", umap_region_length); 102 | 103 | 104 | /* Read From the File to trigger page faults */ 105 | char *arr = (char *) base_addr; 106 | size_t array_size = umap_region_length/umap_pagesize; 107 | 108 | #pragma omp parallel for 109 | for(size_t i=0; i < umap_region_length; i=i+umap_pagesize){ 110 | char c = arr[i]; 111 | if( c != 'c' ) 112 | std::cout << "ERROR: arr[" << i << "] = " << c <<"\n"; 113 | } 114 | 115 | /* Unmap the file */ 116 | if (uunmap(base_addr, umap_region_length) < 0) { 117 | int eno = errno; 118 | std::cerr << "Failed to uumap " << filename << ": " << strerror(eno) << std::endl; 119 | return -1; 120 | } 121 | 122 | /* Clean up*/ 123 | close(fd); 124 | cali_datatracker_untrack(base_addr); 125 | 126 | std::cout <<"Completed: " << array_size <<" page faults are supposed to be captured \n"; 127 | std::cout <<"Query the caliper trace file: \n"; 128 | std::cout <<"\tcali-query -q \"select alloc.label#pagefault.address,count() group by alloc.label#pagefault.address where pagefault.address format table\" \n\n"; 129 | 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /tests/churn/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | project(churn) 8 | 9 | FIND_PACKAGE( OpenMP REQUIRED ) 10 | if(OPENMP_FOUND) 11 | configure_file( 12 | "${CMAKE_CURRENT_SOURCE_DIR}/churntest_umap.sh" 13 | "${CMAKE_CURRENT_BINARY_DIR}/churntest_umap.sh" 14 | COPYONLY 15 | ) 16 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 17 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 18 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 19 | add_executable(churn churn.cpp options.cpp) 20 | 21 | if(STATIC_UMAP_LINK) 22 | set(umap-lib "umap-static") 23 | else() 24 | set(umap-lib "umap") 25 | endif() 26 | 27 | add_dependencies(churn ${umap-lib}) 28 | target_link_libraries(churn ${umap-lib}) 29 | 30 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 31 | 32 | install(TARGETS churn 33 | LIBRARY DESTINATION lib 34 | ARCHIVE DESTINATION lib/static 35 | RUNTIME DESTINATION bin ) 36 | else() 37 | message("Skipping churn, OpenMP required") 38 | endif() 39 | 40 | -------------------------------------------------------------------------------- /tests/churn/churntest_umap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | function free_mem { 9 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 10 | fm=$(((${m}/1024)/1024)) 11 | echo $fm GB Free 12 | } 13 | 14 | function drop_page_cache { 15 | echo "Dropping page cache" 16 | echo 3 > /proc/sys/vm/drop_caches 17 | } 18 | 19 | function disable_swap { 20 | echo "Disabling swap" 21 | swapoff -av 22 | } 23 | 24 | function set_readahead { 25 | fs=`mount | grep intel | cut -d " " -f 1` 26 | blockdev --setra $readahead $fs 27 | ra=`blockdev --getra $fs` 28 | echo "Read ahead set to $ra for $fs" 29 | } 30 | 31 | function amounttowaste { 32 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 33 | echo $m 34 | fm=$(((${m}/1024)/1024)) 35 | waste=$((${fm}-${memtoleave})) 36 | echo $fm GB Available, Wasting $waste GB 37 | } 38 | 39 | function setuptmpfs { 40 | if [ ! -d /mnt/tmpfs ]; then 41 | mkdir -p /mnt/tmpfs 42 | fi 43 | 44 | # Unmount / Reset of already mounted 45 | fs=`stat -f -c '%T' /mnt/tmpfs` 46 | 47 | if [ "$fs" = "tmpfs" ]; then 48 | echo "Resetting tmpfs" 49 | umount /mnt/tmpfs 50 | fi 51 | 52 | fs=`stat -f -c '%T' /mnt/tmpfs` 53 | if [ "$fs" != "tmpfs" ]; then 54 | if [ ! -d /mnt/tmpfs ]; then 55 | mkdir -p /mnt/tmpfs 56 | fi 57 | chmod go+rwx /mnt/tmpfs 58 | mount -t tmpfs -o size=600g tmpfs /mnt/tmpfs 59 | fs=`stat -f -c '%T' /mnt/tmpfs` 60 | echo "/mnt/tmpfs mounted as: $fs" 61 | else 62 | echo "Unable to reset /mnt/tmpfs, exiting" 63 | exit 1 64 | fi 65 | } 66 | 67 | function waste_memory { 68 | echo "Wasting $waste GB of memory" 69 | echo dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 70 | dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 71 | } 72 | 73 | memtoleave=$((64+6)) 74 | readahead=256 75 | 76 | disable_swap 77 | # setuptmpfs 78 | drop_page_cache 79 | # amounttowaste 80 | # waste_memory 81 | 82 | rm -f /mnt/intel/churn.data 83 | cmd="./churn --usemmap --initonly --directio -d 60 -f /mnt/intel/churn.data -b $(((4*1024*1024*1024)/4096)) -l $(((512*1024*1024)/4096)) -c $(((1*1024*1024*1024)/4096)) -t 40 -r 40 -w 40" 84 | echo $cmd 85 | time sh -c "$cmd" 86 | 87 | set_readahead 88 | 89 | for t in 1 2 3 4 5 6 90 | do 91 | drop_page_cache 92 | free_mem 93 | cmd="./churn --usemmap --noinit --directio -d 60 -f /mnt/intel/churn.data -b $(((1*1024*1024*1024)/4096)) -l $(((512*1024*1024)/4096)) -c $(((1*1024*1024*1024)/4096)) -t 40 -r 40 -w 40" 94 | date 95 | echo $cmd 96 | time sh -c "$cmd" 97 | done 98 | 99 | readahead=0 100 | set_readahead 101 | 102 | rm -f /mnt/intel/churn.data 103 | cmd="./churn --initonly --directio -d 60 -f /mnt/intel/churn.data -b $(((4*1024*1024*1024)/4096)) -l $(((512*1024*1024)/4096)) -c $(((1*1024*1024*1024)/4096)) -t 40 -r 40 -w 40" 104 | echo $cmd 105 | time sh -c "$cmd" 106 | 107 | 108 | for t in 1 2 3 4 5 6 109 | do 110 | drop_page_cache 111 | free_mem 112 | cmd="./churn --noinit --directio -d 60 -f /mnt/intel/churn.data -b $(((1*1024*1024*1024)/4096)) -l $(((512*1024*1024)/4096)) -c $(((1*1024*1024*1024)/4096)) -t 40 -r 40 -w 40" 113 | date 114 | echo $cmd 115 | time sh -c "$cmd" 116 | done 117 | -------------------------------------------------------------------------------- /tests/churn/options.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include // cout/cerr 9 | #include // getopt() 10 | #include // duh... 11 | #include "options.h" 12 | #include "umap/umap.h" 13 | 14 | static char const* FILENAME = "/tmp/abc"; 15 | static const uint64_t NUMCHURNPAGES = 99; 16 | static const uint64_t NUMLOADPAGES = 1; 17 | static const uint64_t NUMCHURNTHREADS = 48; 18 | static const uint64_t NUMLOADREADERS = 48; 19 | static const uint64_t NUMLOADWRITERS = 48; 20 | static const uint64_t TESTDURATION = 60; 21 | 22 | using namespace std; 23 | 24 | static void usage(char* pname) 25 | { 26 | cerr 27 | << "Usage: " << pname << " [Options...]\n\n" 28 | << " --help - This message\n" 29 | << " --initonly - Initialize only\n" 30 | << " --noinit - No Initialization\n" 31 | << " --directio - Use O_DIRECT for file IO\n" 32 | << " --usemmap - Use mmap instead of umap\n" 33 | << " -b # of pages in page buffer - default: " << umapcfg_get_max_pages_in_buffer() << " Pages\n" 34 | << " -c # of churn pages - default: " << NUMCHURNPAGES << " Pages\n" 35 | << " -l # of load pages - default: " << NUMLOADPAGES << " Pages\n" 36 | << " -t # of churn threads - default: " << NUMCHURNTHREADS << endl 37 | << " -r # of load reader threads - default: " << NUMLOADREADERS << endl 38 | << " -w # of load writer threads - default: " << NUMLOADWRITERS << endl 39 | << " -f [backing file name] - default: " << FILENAME << endl 40 | << " -d # seconds to run test - default: " << TESTDURATION << " seconds\n" 41 | << " \n" 42 | << " Environment Variable Configuration:\n" 43 | << " UMAP_PAGE_FILLERS(env) - currently: " << umapcfg_get_num_fillers() << " fillers\n" 44 | << " UMAP_PAGE_EVICTORS(env)- currently: " << umapcfg_get_num_evictors() << " evictors\n" 45 | << " UMAP_BUFSIZE(env) - currently: " << umapcfg_get_max_pages_in_buffer() << " pages\n" 46 | << " UMAP_PAGESIZE(env) - currently: " << umapcfg_get_umap_page_size() << " bytes\n" 47 | ; 48 | exit(1); 49 | } 50 | 51 | void getoptions(options_t& testops, int& argc, char **argv) 52 | { 53 | int c; 54 | char *pname = argv[0]; 55 | 56 | testops.iodirect=0; 57 | testops.usemmap=0; 58 | testops.noinit=0; 59 | testops.initonly=0; 60 | testops.num_churn_pages=NUMCHURNPAGES; 61 | testops.num_churn_threads=NUMCHURNTHREADS; 62 | testops.num_load_pages=NUMLOADPAGES; 63 | testops.num_load_reader_threads=NUMLOADREADERS; 64 | testops.num_load_writer_threads=NUMLOADWRITERS; 65 | testops.fn=FILENAME; 66 | testops.testduration=TESTDURATION; 67 | testops.page_buffer_size = umapcfg_get_max_pages_in_buffer(); 68 | 69 | while (1) { 70 | int option_index = 0; 71 | static struct option long_options[] = { 72 | {"directio", no_argument, &testops.iodirect, 1 }, 73 | {"usemmap", no_argument, &testops.usemmap, 1 }, 74 | {"initonly", no_argument, &testops.initonly, 1 }, 75 | {"noinit", no_argument, &testops.noinit, 1 }, 76 | {"help", no_argument, NULL, 0 }, 77 | {0, 0, 0, 0 } 78 | }; 79 | 80 | c = getopt_long(argc, argv, "b:c:l:t:r:w:f:d:", long_options, &option_index); 81 | if (c == -1) 82 | break; 83 | 84 | switch(c) { 85 | case 0: 86 | if (long_options[option_index].flag != 0) 87 | break; 88 | 89 | usage(pname); 90 | break; 91 | 92 | case 'b': 93 | if ((testops.page_buffer_size = strtoull(optarg, nullptr, 0)) > 0) 94 | break; 95 | goto R0; 96 | case 'c': 97 | if ((testops.num_churn_pages = strtoull(optarg, nullptr, 0)) > 0) 98 | break; 99 | goto R0; 100 | case 'l': 101 | if ((testops.num_load_pages = strtoull(optarg, nullptr, 0)) > 0) 102 | break; 103 | goto R0; 104 | 105 | case 'd': 106 | if ((testops.testduration = strtoull(optarg, nullptr, 0)) > 0) 107 | break; 108 | goto R0; 109 | case 'f': 110 | testops.fn = optarg; 111 | break; 112 | case 'w': 113 | testops.num_load_writer_threads = strtoull(optarg, nullptr, 0); 114 | break; 115 | case 'r': 116 | testops.num_load_reader_threads = strtoull(optarg, nullptr, 0); 117 | break; 118 | goto R0; 119 | case 't': 120 | testops.num_churn_threads = strtoull(optarg, nullptr, 0); 121 | break; 122 | default: 123 | R0: 124 | usage(pname); 125 | } 126 | } 127 | 128 | if (optind < argc) { 129 | cerr << "Unknown Arguments: "; 130 | while (optind < argc) 131 | cerr << "\"" << argv[optind++] << "\" "; 132 | cerr << endl; 133 | usage(pname); 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /tests/churn/options.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _OPTIONS_H 8 | #define _OPTIONS_H 9 | #include 10 | #include "options.h" 11 | 12 | typedef struct { 13 | int iodirect; 14 | int usemmap; 15 | int initonly; 16 | int noinit; 17 | 18 | uint64_t page_buffer_size; // # of pages that page buffer can hold 19 | 20 | uint64_t num_churn_pages; 21 | uint64_t num_load_pages; 22 | 23 | uint64_t num_churn_threads; 24 | 25 | uint64_t num_load_reader_threads; 26 | uint64_t num_load_writer_threads; 27 | 28 | char const* fn; // Backing file name 29 | 30 | uint64_t testduration; // Duration (in seconds) to run test 31 | } options_t; 32 | 33 | void getoptions(options_t&, int&, char **argv); 34 | #endif // _OPTIONS_H 35 | -------------------------------------------------------------------------------- /tests/flush_buffer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | # UMAP Project Developers. See the top-level LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: LGPL-2.1-only 6 | ############################################################################# 7 | project(flush_buffer) 8 | 9 | FIND_PACKAGE( OpenMP REQUIRED ) 10 | if(OPENMP_FOUND) 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 13 | set(CMAKE_EXE_LINKER_FLAGS 14 | "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 15 | add_executable(flush_buffer flush_buffer.cpp) 16 | 17 | if(STATIC_UMAP_LINK) 18 | set(umap-lib "umap-static") 19 | else() 20 | set(umap-lib "umap") 21 | endif() 22 | 23 | add_dependencies(flush_buffer ${umap-lib}) 24 | target_link_libraries(flush_buffer ${umap-lib}) 25 | 26 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 27 | 28 | install(TARGETS flush_buffer 29 | LIBRARY DESTINATION lib 30 | ARCHIVE DESTINATION lib/static 31 | RUNTIME DESTINATION bin ) 32 | else() 33 | message("Skipping flush_buffer, OpenMP required") 34 | endif() 35 | 36 | -------------------------------------------------------------------------------- /tests/flush_buffer/flush_buffer.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | * It is a simple example showing flush_cache ensures that 10 | * modified pages in buffer is persisted into back stores. 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "errno.h" 21 | #include "umap/umap.h" 22 | 23 | #define FLUSH_BUF 1 24 | 25 | using namespace std; 26 | 27 | int 28 | open_prealloc_file( const char* fname, uint64_t totalbytes) 29 | { 30 | /* 31 | int status = unlink(fname); 32 | int eno = errno; 33 | if ( status!=0 && eno != ENOENT ) { 34 | std::cerr << "Failed to unlink " << fname << ": "<< strerror(eno) << " Errno=" << eno < 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "errno.h" 22 | #include "umap/umap.h" 23 | 24 | #define FLUSH_BUF 1 25 | 26 | using namespace std; 27 | 28 | int 29 | open_prealloc_file( const char* fname, uint64_t totalbytes) 30 | { 31 | /* 32 | int status = unlink(fname); 33 | int eno = errno; 34 | if ( status!=0 && eno != ENOENT ) { 35 | std::cerr << "Failed to unlink " << fname << ": "<< strerror(eno) << " Errno=" << eno < 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "umap/umap.h" 35 | #include "../utility/commandline.hpp" 36 | 37 | using namespace std; 38 | using namespace chrono; 39 | static uint64_t pagesize; 40 | static uint64_t pages_to_access; 41 | static char** tmppagebuf; // One per thread 42 | static int fd; 43 | static utility::umt_optstruct_t options; 44 | vector shuffled_indexes; 45 | 46 | void do_write_pages(uint64_t pages) 47 | { 48 | #pragma omp parallel for 49 | for (uint64_t i = 0; i < pages; ++i) { 50 | uint64_t myidx = shuffled_indexes[i]; 51 | uint64_t* ptr = (uint64_t*)tmppagebuf[omp_get_thread_num()]; 52 | *ptr = myidx * pagesize/sizeof(uint64_t); 53 | if (pwrite(fd, ptr, pagesize, myidx*pagesize) < 0) { 54 | perror("pwrite"); 55 | exit(1); 56 | } 57 | } 58 | } 59 | 60 | void do_read_pages(uint64_t pages) 61 | { 62 | #pragma omp parallel for 63 | for (uint64_t i = 0; i < pages; ++i) { 64 | uint64_t myidx = shuffled_indexes[i]; 65 | uint64_t* ptr = (uint64_t*)tmppagebuf[omp_get_thread_num()]; 66 | if (pread(fd, ptr, pagesize, myidx*pagesize) < 0) { 67 | perror("pread"); 68 | exit(1); 69 | } 70 | if ( *ptr != myidx * pagesize/sizeof(uint64_t) ) { 71 | cout << i << " " << myidx << " " << *ptr << " != " << (myidx * pagesize/sizeof(uint64_t)) << "\n"; 72 | exit(1); 73 | } 74 | } 75 | } 76 | 77 | int read_pages(int argc, char **argv) 78 | { 79 | fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT); 80 | 81 | if (fd == -1) { 82 | perror("open failed\n"); 83 | exit(1); 84 | } 85 | 86 | auto start_time = chrono::high_resolution_clock::now(); 87 | do_read_pages(pages_to_access); 88 | auto end_time = chrono::high_resolution_clock::now(); 89 | 90 | cout << "nvme," 91 | << "+IO," 92 | << (( options.shuffle == 1) ? "shuffle" : "seq") << "," 93 | << "read," 94 | << options.numthreads << "," 95 | << 0 << "," 96 | << chrono::duration_cast(end_time - start_time).count() / pages_to_access << "\n"; 97 | 98 | close(fd); 99 | return 0; 100 | } 101 | 102 | int write_pages(int argc, char **argv) 103 | { 104 | if ( !options.noinit ) { 105 | cout << "Removing " << options.filename << "\n"; 106 | unlink(options.filename); 107 | cout << "Creating " << options.filename << "\n"; 108 | fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT | O_CREAT, S_IRUSR | S_IWUSR); 109 | } 110 | else { 111 | fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT); 112 | } 113 | 114 | if (fd == -1) { 115 | perror("open failed\n"); 116 | exit(1); 117 | } 118 | 119 | auto start_time = chrono::high_resolution_clock::now(); 120 | do_write_pages(pages_to_access); 121 | auto end_time = chrono::high_resolution_clock::now(); 122 | 123 | cout << "nvme," 124 | << "+IO," 125 | << (( options.shuffle == 1) ? "shuffle" : "seq") << "," 126 | << "write," 127 | << options.numthreads << "," 128 | << 0 << "," 129 | << chrono::duration_cast(end_time - start_time).count() / pages_to_access << "\n"; 130 | 131 | close(fd); 132 | return 0; 133 | } 134 | 135 | int main(int argc, char **argv) 136 | { 137 | int rval = 0; 138 | std::random_device rd; 139 | std::mt19937 g(rd()); 140 | 141 | umt_getoptions(&options, argc, argv); 142 | 143 | for (uint64_t i = 0; i < options.numpages; ++i) 144 | shuffled_indexes.push_back(i); 145 | 146 | pages_to_access = options.pages_to_access ? options.pages_to_access : options.numpages; 147 | 148 | if ( options.shuffle ) 149 | std::shuffle(shuffled_indexes.begin(), shuffled_indexes.end(), g); 150 | 151 | omp_set_num_threads(options.numthreads); 152 | pagesize = (uint64_t)utility::umt_getpagesize(); 153 | 154 | tmppagebuf = (char**)calloc(options.numthreads, sizeof(char*)); 155 | 156 | for (int i = 0; i < options.numthreads; ++i) { 157 | if (posix_memalign((void**)&tmppagebuf[i], (uint64_t)512, pagesize)) { 158 | cerr << "ERROR: posix_memalign: failed\n"; 159 | exit(1); 160 | } 161 | 162 | if (tmppagebuf[i] == nullptr) { 163 | cerr << "Unable to allocate " << pagesize << " bytes for temporary buffer\n"; 164 | exit(1); 165 | } 166 | } 167 | 168 | if (strcmp(argv[0], "nvmebenchmark-write") == 0) 169 | rval = write_pages(argc, argv); 170 | else if (strcmp(argv[0], "nvmebenchmark-read") == 0) 171 | rval = read_pages(argc, argv); 172 | 173 | return rval; 174 | } 175 | -------------------------------------------------------------------------------- /tests/pfbenchmark/test_results/data.csv: -------------------------------------------------------------------------------- 1 | nvme,+IO,shuffle,write,16,0,2994 2 | nvme,+IO,shuffle,write,32,0,3084 3 | nvme,+IO,shuffle,write,64,0,2776 4 | nvme,+IO,shuffle,write,128,0,2695 5 | nvme,+IO,shuffle,write,256,0,3090 6 | umap,+IO,shuffle,write,16,32,21359 7 | umap,+IO,shuffle,write,32,32,16338 8 | umap,+IO,shuffle,write,64,32,13858 9 | umap,+IO,shuffle,write,128,32,12569 10 | umap,+IO,shuffle,write,256,32,11276 11 | umap,+IO,shuffle,write,16,64,19384 12 | umap,+IO,shuffle,write,32,64,14115 13 | umap,+IO,shuffle,write,64,64,11726 14 | umap,+IO,shuffle,write,128,64,10581 15 | umap,+IO,shuffle,write,256,64,9630 16 | umap,+IO,shuffle,write,16,128,18269 17 | umap,+IO,shuffle,write,32,128,13857 18 | umap,+IO,shuffle,write,64,128,12053 19 | umap,+IO,shuffle,write,128,128,9849 20 | umap,+IO,shuffle,write,256,128,9796 21 | umap,-IO,shuffle,write,16,32,4215 22 | umap,-IO,shuffle,write,32,32,3945 23 | umap,-IO,shuffle,write,64,32,3638 24 | umap,-IO,shuffle,write,128,32,3271 25 | umap,-IO,shuffle,write,256,32,3374 26 | umap,-IO,shuffle,write,16,64,4285 27 | umap,-IO,shuffle,write,32,64,3972 28 | umap,-IO,shuffle,write,64,64,3580 29 | umap,-IO,shuffle,write,128,64,3141 30 | umap,-IO,shuffle,write,256,64,3079 31 | umap,-IO,shuffle,write,16,128,4253 32 | umap,-IO,shuffle,write,32,128,3940 33 | umap,-IO,shuffle,write,64,128,3557 34 | umap,-IO,shuffle,write,128,128,3107 35 | umap,-IO,shuffle,write,256,128,3122 36 | nvme,+IO,shuffle,read,16,0,5807 37 | nvme,+IO,shuffle,read,32,0,3265 38 | nvme,+IO,shuffle,read,64,0,2044 39 | nvme,+IO,shuffle,read,128,0,1541 40 | nvme,+IO,shuffle,read,256,0,1362 41 | umap,+IO,shuffle,read,16,32,9332 42 | umap,+IO,shuffle,read,32,32,6349 43 | umap,+IO,shuffle,read,64,32,5056 44 | umap,+IO,shuffle,read,128,32,4515 45 | umap,+IO,shuffle,read,256,32,4280 46 | umap,+IO,shuffle,read,16,64,8367 47 | umap,+IO,shuffle,read,32,64,5267 48 | umap,+IO,shuffle,read,64,64,3772 49 | umap,+IO,shuffle,read,128,64,3190 50 | umap,+IO,shuffle,read,256,64,2882 51 | umap,+IO,shuffle,read,16,128,8029 52 | umap,+IO,shuffle,read,32,128,4791 53 | umap,+IO,shuffle,read,64,128,3346 54 | umap,+IO,shuffle,read,128,128,2691 55 | umap,+IO,shuffle,read,256,128,2450 56 | umap,-IO,shuffle,read,16,32,2546 57 | umap,-IO,shuffle,read,32,32,2098 58 | umap,-IO,shuffle,read,64,32,1922 59 | umap,-IO,shuffle,read,128,32,1850 60 | umap,-IO,shuffle,read,256,32,2136 61 | umap,-IO,shuffle,read,16,64,2577 62 | umap,-IO,shuffle,read,32,64,2109 63 | umap,-IO,shuffle,read,64,64,1892 64 | umap,-IO,shuffle,read,128,64,1789 65 | umap,-IO,shuffle,read,256,64,1761 66 | umap,-IO,shuffle,read,16,128,2640 67 | umap,-IO,shuffle,read,32,128,2168 68 | umap,-IO,shuffle,read,64,128,1893 69 | umap,-IO,shuffle,read,128,128,1789 70 | umap,-IO,shuffle,read,256,128,1789 71 | -------------------------------------------------------------------------------- /tests/pfbenchmark/test_results/data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/umap/0e7297b35c8a1ba888ce7c568de751fbda8f3769/tests/pfbenchmark/test_results/data.xlsx -------------------------------------------------------------------------------- /tests/pfbenchmark/test_results/runbenchmarks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | function drop_page_cache { 10 | # sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches' 11 | echo 3 > /proc/sys/vm/drop_caches 12 | } 13 | 14 | export PATH=/home/martymcf/.sessions/dst-intel/install/linux-rhel7-x86_64/install/bin:$PATH 15 | buffersize=$((((128*256)))) 16 | # numpages=$(((16*1024*1024*1024)/4096)) 17 | numpages=$(((1*1024*1024*1024*1024)/4096)) 18 | 19 | # numaccesspages=0 20 | numaccesspages=$(((32*1024*1024*1024)/4096)) 21 | 22 | file=/mnt/xfs/pfbench 23 | 24 | # drop_page_cache 25 | # nvmebenchmark-write -b $buffersize -p $numpages -t 1 -f $file --directio -u 1 26 | 27 | for test in "write" "read" 28 | do 29 | for i in 16 32 64 128 256 30 | do 31 | drop_page_cache 32 | nvmebenchmark-$test -b $buffersize -p $numpages -t $i -f $file --directio --noinit --shuffle -a $numaccesspages 33 | done 34 | 35 | for noio in " " "--noio" 36 | do 37 | for j in 32 64 128 38 | do 39 | for i in 16 32 64 128 256 40 | do 41 | drop_page_cache 42 | pfbenchmark-$test -b $buffersize -p $numpages $noio -t $i -f $file -u $j --directio --noinit --shuffle -a $numaccesspages 43 | done 44 | done 45 | done 46 | done 47 | -------------------------------------------------------------------------------- /tests/pfbenchmark/test_results/sysinfo: -------------------------------------------------------------------------------- 1 | $ uname -a 2 | Linux dst-intel 4.13.0uffdio-ge561891-dirty #1 SMP Fri Oct 13 13:51:34 PDT 2017 x86_64 x86_64 x86_64 GNU/Linux 3 | 4 | $ lscpu 5 | Architecture: x86_64 6 | CPU op-mode(s): 32-bit, 64-bit 7 | Byte Order: Little Endian 8 | CPU(s): 48 9 | On-line CPU(s) list: 0-47 10 | Thread(s) per core: 2 11 | Core(s) per socket: 12 12 | Socket(s): 2 13 | NUMA node(s): 2 14 | Vendor ID: GenuineIntel 15 | CPU family: 6 16 | Model: 63 17 | Model name: Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz 18 | Stepping: 2 19 | CPU MHz: 2294.734 20 | BogoMIPS: 4589.03 21 | Virtualization: VT-x 22 | L1d cache: 32K 23 | L1i cache: 32K 24 | L2 cache: 256K 25 | L3 cache: 30720K 26 | NUMA node0 CPU(s): 0-11,24-35 27 | NUMA node1 CPU(s): 12-23,36-47 28 | 29 | $ lspci | grep -i nvme 30 | 83:00.0 Non-Volatile memory controller: HGST, Inc. Ultrastar SN100 Series NVMe SSD (rev 05) 31 | 32 | $ sudo lspci -s 83:00.0 -v 33 | 83:00.0 Non-Volatile memory controller: HGST, Inc. Ultrastar SN100 Series NVMe SSD (rev 05) (prog-if 02 [NVM Express]) 34 | Subsystem: HGST, Inc. Ultrastar SN100 Series NVMe SSD 35 | Physical Slot: 803 36 | Flags: bus master, fast devsel, latency 0, IRQ 36, NUMA node 1 37 | Memory at c8010000 (64-bit, non-prefetchable) [size=16K] 38 | Memory at c8000000 (64-bit, non-prefetchable) [size=64K] 39 | Expansion ROM at c8020000 [disabled] [size=128K] 40 | Capabilities: [c0] Power Management version 3 41 | Capabilities: [70] Express Endpoint, MSI 00 42 | Capabilities: [c8] MSI: Enable- Count=1/32 Maskable+ 64bit+ 43 | Capabilities: [e0] MSI-X: Enable+ Count=129 Masked- 44 | Capabilities: [100] Advanced Error Reporting 45 | Capabilities: [180] #19 46 | Kernel driver in use: nvme 47 | Kernel modules: nvme 48 | 49 | -------------------------------------------------------------------------------- /tests/tools/adjust_free_mem: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | function usage { 9 | echo "Usage:" 10 | echo "$0 Size - Size is the number of GB to adjust free memory to." 11 | exit 1 12 | } 13 | 14 | function amounttowaste { 15 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 16 | echo $m 17 | fm=$(((${m}/1024)/1024)) 18 | waste=$((${fm}-${memtoleave})) 19 | echo $fm GB Available, Wasting $waste GB 20 | } 21 | 22 | function setuptmpfs { 23 | if [ ! -d /mnt/tmpfs ]; then 24 | sudo mkdir -p /mnt/tmpfs 25 | fi 26 | 27 | # Unmount / Reset of already mounted 28 | fs=`stat -f -c '%T' /mnt/tmpfs` 29 | 30 | if [ "$fs" = "tmpfs" ]; then 31 | echo "Resetting tmpfs" 32 | sudo umount /mnt/tmpfs 33 | fi 34 | 35 | fs=`stat -f -c '%T' /mnt/tmpfs` 36 | if [ "$fs" != "tmpfs" ]; then 37 | if [ ! -d /mnt/tmpfs ]; then 38 | sudo mkdir -p /mnt/tmpfs 39 | fi 40 | sudo chmod go+rwx /mnt/tmpfs 41 | sudo mount -t tmpfs -o size=600g tmpfs /mnt/tmpfs 42 | fs=`stat -f -c '%T' /mnt/tmpfs` 43 | echo "/mnt/tmpfs mounted as: $fs" 44 | else 45 | echo "Unable to reset /mnt/tmpfs, exiting" 46 | exit 1 47 | fi 48 | } 49 | 50 | function drop_page_cache { 51 | echo "Dropping page cache" 52 | sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches' 53 | } 54 | 55 | function disable_swap { 56 | echo "Disabling swap" 57 | sudo swapoff -a 58 | } 59 | 60 | function turn_off_readahead { 61 | fs=`mount | grep intel | cut -d " " -f 1` 62 | sudo blockdev --setra 0 $fs 63 | ra=`sudo blockdev --getra $fs` 64 | echo "Read ahead set to $ra for $fs" 65 | } 66 | 67 | function waste_memory { 68 | echo "Wasting $waste GB of memory" 69 | 70 | #echo numactl -i 1 dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 71 | #numactl -i 1 dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 72 | echo dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 73 | dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 74 | } 75 | 76 | if [ $# -ne 1 ]; then 77 | echo "Bad argument count: $#" 78 | usage 79 | fi 80 | 81 | memtoleave=$1 82 | 83 | turn_off_readahead 84 | disable_swap 85 | setuptmpfs 86 | drop_page_cache 87 | amounttowaste 88 | waste_memory 89 | -------------------------------------------------------------------------------- /tests/tools/flush_cache: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | function free_mem { 10 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 11 | fm=$(((${m}/1024)/1024)) 12 | echo $fm GB Free 13 | } 14 | 15 | function drop_page_cache { 16 | echo "Dropping page cache" 17 | sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches' 18 | } 19 | 20 | function disable_swap { 21 | echo "Disabling swap" 22 | sudo swapoff -a 23 | } 24 | 25 | function turn_off_readahead { 26 | fs=`mount | grep intel | cut -d " " -f 1` 27 | sudo blockdev --setra 0 $fs 28 | ra=`sudo blockdev --getra $fs` 29 | echo "Read ahead set to $ra for $fs" 30 | } 31 | 32 | free_mem 33 | disable_swap 34 | turn_off_readahead 35 | drop_page_cache 36 | free_mem 37 | -------------------------------------------------------------------------------- /tests/tools/freemem: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 9 | fm=$(((${m}/1024)/1024)) 10 | echo $fm GB Free 11 | -------------------------------------------------------------------------------- /tests/tools/waste_memory: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################# 3 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | 9 | function usage { 10 | echo "Usage:" 11 | echo "$0 Size - Size is the number of GB to waste." 12 | exit 1 13 | } 14 | 15 | function free_mem { 16 | m=`grep MemFree /proc/meminfo | awk -v N=2 '{print $N}'` 17 | echo $m 18 | fm=$(((${m}/1024)/1024)) 19 | wm=$((${fm}-20)) 20 | echo $fm GB Available, Wasting $wm GB 21 | } 22 | 23 | function setuptmpfs { 24 | if [ ! -d /mnt/tmpfs ]; then 25 | sudo mkdir -p /mnt/tmpfs 26 | fi 27 | 28 | # Unmount / Reset of already mounted 29 | fs=`stat -f -c '%T' /mnt/tmpfs` 30 | 31 | if [ "$fs" = "tmpfs" ]; then 32 | echo "Resetting tmpfs" 33 | sudo umount /mnt/tmpfs 34 | fi 35 | 36 | fs=`stat -f -c '%T' /mnt/tmpfs` 37 | if [ "$fs" != "tmpfs" ]; then 38 | if [ ! -d /mnt/tmpfs ]; then 39 | sudo mkdir -p /mnt/tmpfs 40 | fi 41 | sudo chmod go+rwx /mnt/tmpfs 42 | sudo mount -t tmpfs -o size=600g tmpfs /mnt/tmpfs 43 | fs=`stat -f -c '%T' /mnt/tmpfs` 44 | echo "/mnt/tmpfs mounted as: $fs" 45 | else 46 | echo "Unable to reset /mnt/tmpfs, exiting" 47 | exit 1 48 | fi 49 | } 50 | 51 | function drop_page_cache { 52 | echo "Dropping page cache" 53 | sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches' 54 | } 55 | 56 | function disable_swap { 57 | echo "Disabling swap" 58 | sudo swapoff -a 59 | } 60 | 61 | function turn_off_readahead { 62 | fs=`mount | grep intel | cut -d " " -f 1` 63 | sudo blockdev --setra 0 $fs 64 | ra=`sudo blockdev --getra $fs` 65 | echo "Read ahead set to $ra for $fs" 66 | } 67 | 68 | function waste_memory { 69 | echo "Wasting $waste GB of memory" 70 | 71 | #echo numactl -i 1 dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 72 | #numactl -i 1 dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 73 | echo dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 74 | dd if=/dev/zero of=/mnt/tmpfs/${waste}GB bs=4096 count=$((${waste}*256*1024)) 75 | } 76 | 77 | if [ $# -ne 1 ]; then 78 | echo "Bad argument count: $#" 79 | usage 80 | fi 81 | 82 | waste=$1 83 | 84 | setuptmpfs 85 | drop_page_cache 86 | disable_swap 87 | turn_off_readahead 88 | drop_page_cache 89 | waste_memory 90 | -------------------------------------------------------------------------------- /tests/umap-sparsestore/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | ############################################################################# 3 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 4 | # UMAP Project Developers. See the top-level LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: LGPL-2.1-only 7 | ############################################################################# 8 | project(umap-server) 9 | 10 | FIND_PACKAGE( OpenMP REQUIRED ) 11 | if(OPENMP_FOUND) 12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 14 | set(CMAKE_EXE_LINKER_FLAGS 15 | "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 16 | add_executable(umap-sparsestore umap-sparsestore.cpp) 17 | 18 | if(STATIC_UMAP_LINK) 19 | set(umap-lib "umap-static") 20 | else() 21 | set(umap-lib "umap") 22 | endif() 23 | 24 | add_dependencies(umap-sparsestore ${umap-lib}) 25 | target_link_libraries(umap-sparsestore ${umap-lib}) 26 | 27 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${UMAPINCLUDEDIRS} ) 28 | 29 | install(TARGETS umap-sparsestore 30 | LIBRARY DESTINATION lib 31 | ARCHIVE DESTINATION lib/static 32 | RUNTIME DESTINATION bin ) 33 | else() 34 | message("Skipping flush_buffer, OpenMP required") 35 | endif() 36 | -------------------------------------------------------------------------------- /tests/umap-sparsestore/umap-sparsestore.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | void populate_region(uint64_t* region, uint64_t region_length){ 14 | #pragma omp parallel for 15 | for(uint64_t i=0; i < region_length; ++i) 16 | region[i] = (uint64_t) (region_length - i); 17 | } 18 | 19 | int remove_directory(std::string root_path){ 20 | DIR *directory; 21 | struct dirent *ent; 22 | if ((directory = opendir(root_path.c_str())) != NULL){ 23 | while ((ent = readdir(directory)) != NULL){ 24 | std::string filename_str(ent->d_name); 25 | std::string file_path = root_path + "/" + filename_str; 26 | unlink(file_path.c_str()); 27 | } 28 | closedir(directory); 29 | if( remove(root_path.c_str()) != 0 ){ 30 | perror("Error deleting directory from new function"); 31 | return -1; 32 | } 33 | else{ 34 | std::cout << "Successfully deleted directory" << std::endl; 35 | return 0; 36 | } 37 | } else { 38 | perror("Error deleting directory"); 39 | return -1; 40 | } 41 | } 42 | 43 | int main(int argc, char *argv[]){ 44 | void *region; 45 | unsigned long page_size = 16384; 46 | uint64_t region_size_bytes = 1073741824; 47 | size_t sparsestore_file_granularity = 134217728; 48 | unsigned long long map_len; 49 | struct stat st; 50 | int fd; 51 | void* start_addr = (void *)0x600000000000;// NULL; 52 | unsigned long i=0; 53 | if(argc < 2){ 54 | std::cout<<"Please provide a base directory name"; 55 | exit(-1); 56 | } 57 | 58 | std::string root_path = argv[1]; 59 | struct stat info; 60 | 61 | if(stat( root_path.c_str(), &info ) == 0){ 62 | remove_directory(root_path.c_str()); 63 | } 64 | { //start "create" scope 65 | Umap::SparseStore* store; 66 | 67 | store = new Umap::SparseStore(region_size_bytes,page_size,root_path,sparsestore_file_granularity); 68 | 69 | 70 | // call umap 71 | int flags = UMAP_PRIVATE; 72 | 73 | // if (start_addr != nullptr) 74 | flags |= MAP_FIXED; 75 | 76 | const int prot = PROT_READ|PROT_WRITE; 77 | region = umap_ex(start_addr, region_size_bytes, prot, flags, -1, 0, store); 78 | 79 | if ( region == UMAP_FAILED ) { 80 | perror("UMap failed..."); 81 | delete store; 82 | exit(-1); 83 | } 84 | 85 | // Start: populate region as array of ints 86 | uint64_t *arr = (uint64_t *) region; 87 | uint64_t arraysize = region_size_bytes/sizeof(uint64_t); 88 | 89 | populate_region(arr,arraysize); 90 | // End: populate region as array of ints 91 | 92 | // unmap 93 | if (uunmap(region, region_size_bytes) < 0) { 94 | perror("uunmap failed.."); 95 | exit(-1); 96 | } 97 | int sparse_store_close_files = store->close_files(); 98 | if (sparse_store_close_files != 0 ){ 99 | std::cerr << "Error closing SparseStore files" << std::endl; 100 | delete store; 101 | exit(-1); 102 | } 103 | delete store; 104 | 105 | } 106 | { 107 | // open 108 | Umap::SparseStore* store; 109 | store = new Umap::SparseStore(root_path,false); 110 | 111 | 112 | 113 | int flags = UMAP_PRIVATE; 114 | 115 | // if (start_addr != nullptr) 116 | flags |= MAP_FIXED; 117 | 118 | const int prot = PROT_READ;//|PROT_WRITE; 119 | 120 | 121 | // call umap 122 | region = umap_ex(start_addr, region_size_bytes, prot, flags, -1, 0, store); 123 | 124 | if ( region == UMAP_FAILED ) { 125 | perror("UMap failed..."); 126 | delete store; 127 | exit(-1); 128 | } 129 | 130 | // Start: unmap 131 | if (uunmap(region, region_size_bytes) < 0) { 132 | perror("uunmap failed.."); 133 | exit(-1); 134 | } 135 | int sparse_store_close_files = store->close_files(); 136 | if (sparse_store_close_files != 0 ){ 137 | std::cerr << "Error closing SparseStore files" << std::endl; 138 | delete store; 139 | exit(-1); 140 | } 141 | delete store; 142 | // End: unmap 143 | 144 | // End: repeat 145 | } 146 | return 0; 147 | } 148 | -------------------------------------------------------------------------------- /tests/utility/commandline.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _COMMANDLING_HPP 8 | #define _COMMANDLING_HPP 9 | 10 | #include 11 | #include // cout/cerr 12 | #include // getopt() 13 | #include // duh... 14 | #include "umap/umap.h" 15 | 16 | namespace utility { 17 | typedef struct { 18 | int initonly; // Just perform initialization, then quit 19 | int noinit; // Init already done, so skip it 20 | int usemmap; 21 | int shuffle; 22 | 23 | long pagesize; 24 | uint64_t numpages; 25 | uint64_t numthreads; 26 | uint64_t bufsize; 27 | uint64_t uffdthreads; 28 | uint64_t pages_to_access; // 0 (default) - access all pages 29 | char const* filename; // file name or basename 30 | char const* dirname; // dir name or basename 31 | } umt_optstruct_t; 32 | 33 | static char const* DIRNAME = "/mnt/intel/"; 34 | static char const* FILENAME = "abc"; 35 | const uint64_t NUMPAGES = 10000000; 36 | const uint64_t NUMTHREADS = 2; 37 | const uint64_t BUFFERSIZE = 16; 38 | 39 | using namespace std; 40 | 41 | static void usage(char* pname) 42 | { 43 | cerr 44 | << "Usage: " << pname << " [--initonly] [--noinit] [--directio]" 45 | << " [--usemmap] [-p #] [-t #] [-b #] [-f name]\n\n" 46 | << " --help - This message\n" 47 | << " --initonly - Initialize file, then stop\n" 48 | << " --noinit - Use previously initialized file\n" 49 | << " --usemmap - Use mmap instead of umap\n" 50 | << " --shuffle - Shuffle memory accesses (instead of sequential access)\n" 51 | << " -p # of pages - default: " << NUMPAGES << " test pages\n" 52 | << " -t # of threads - default: " << NUMTHREADS << " application threads\n" 53 | << " -a # pages to access - default: 0 - access all pages\n" 54 | << " -f [file name] - backing file name. Or file basename if multiple files\n" 55 | << " -d [directory name] - backing directory name. Or dir basename if multiple dirs\n" 56 | << " \n" 57 | << " Environment Variable Configuration:\n" 58 | << " UMAP_PAGE_FILLERS(env) - currently: " << umapcfg_get_num_fillers() << " fillers\n" 59 | << " UMAP_PAGE_EVICTORS(env)- currently: " << umapcfg_get_num_evictors() << " evictors\n" 60 | << " UMAP_BUFSIZE(env) - currently: " << umapcfg_get_max_pages_in_buffer() << " pages\n" 61 | << " UMAP_PAGESIZE(env) - currently: " << umapcfg_get_umap_page_size() << " bytes\n" 62 | ; 63 | exit(1); 64 | } 65 | 66 | void umt_getoptions(utility::umt_optstruct_t* testops, int argc, char *argv[]) 67 | { 68 | int c; 69 | char *pname = argv[0]; 70 | 71 | testops->initonly = 0; 72 | testops->noinit = 0; 73 | testops->usemmap = 0; 74 | testops->shuffle = 0; 75 | testops->pages_to_access = 0; 76 | testops->numpages = NUMPAGES; 77 | testops->numthreads = NUMTHREADS; 78 | testops->bufsize = umapcfg_get_max_pages_in_buffer(); 79 | testops->uffdthreads = umapcfg_get_num_fillers(); 80 | testops->filename = FILENAME; 81 | testops->dirname = DIRNAME; 82 | testops->pagesize = umapcfg_get_umap_page_size(); 83 | 84 | while (1) { 85 | int option_index = 0; 86 | static struct option long_options[] = { 87 | {"initonly", no_argument, &testops->initonly, 1 }, 88 | {"noinit", no_argument, &testops->noinit, 1 }, 89 | {"usemmap", no_argument, &testops->usemmap, 1 }, 90 | {"shuffle", no_argument, &testops->shuffle, 1 }, 91 | {"help", no_argument, NULL, 0 }, 92 | {0, 0, 0, 0 } 93 | }; 94 | 95 | c = getopt_long(argc, argv, "p:t:f:d:a:", long_options, &option_index); 96 | if (c == -1) 97 | break; 98 | 99 | switch(c) { 100 | case 0: 101 | if (long_options[option_index].flag != 0) 102 | break; 103 | 104 | usage(pname); 105 | break; 106 | case 'p': 107 | if ((testops->numpages = strtoull(optarg, nullptr, 0)) > 0) 108 | break; 109 | goto R0; 110 | case 't': 111 | if ((testops->numthreads = strtoull(optarg, nullptr, 0)) > 0) 112 | break; 113 | else goto R0; 114 | case 'a': 115 | testops->pages_to_access = strtoull(optarg, nullptr, 0); 116 | break; 117 | case 'd': 118 | testops->dirname = optarg; 119 | break; 120 | case 'f': 121 | testops->filename = optarg; 122 | break; 123 | default: 124 | R0: 125 | usage(pname); 126 | } 127 | } 128 | 129 | if (testops->numpages < testops->pages_to_access) { 130 | cerr << "Invalid -a argument " << testops->pages_to_access << "\n"; 131 | usage(pname); 132 | } 133 | 134 | if (optind < argc) { 135 | cerr << "Unknown Arguments: "; 136 | while (optind < argc) 137 | cerr << "\"" << argv[optind++] << "\" "; 138 | cerr << endl; 139 | usage(pname); 140 | } 141 | } 142 | 143 | long umt_getpagesize(void) 144 | { 145 | return umapcfg_get_umap_page_size(); 146 | } 147 | } 148 | #endif // _COMMANDLING_HPP 149 | -------------------------------------------------------------------------------- /tests/utility/file.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef LIB_UTILITY_FILE_HPP 8 | #define LIB_UTILITY_FILE_HPP 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | namespace utility { 20 | void extend_file_size_manually(const int fd, const ssize_t file_size) { 21 | auto buffer = new unsigned char[4096]; 22 | for (off_t i = 0; i < file_size / 4096; ++i) { 23 | ::pwrite(fd, buffer, 4096, i * 4096); 24 | } 25 | const size_t remained_size = file_size % 4096; 26 | if (remained_size > 0) 27 | ::pwrite(fd, buffer, remained_size, file_size - remained_size); 28 | 29 | ::sync(); 30 | delete[] buffer; 31 | } 32 | 33 | bool extend_file_size(const int fd, const size_t file_size) { 34 | /// ----- extend the file if its size is smaller than that of mapped area ----- /// 35 | #ifdef __linux__ 36 | struct stat statbuf; 37 | if (::fstat(fd, &statbuf) == -1) { 38 | ::perror("fstat"); 39 | std::cerr << "errno: " << errno << std::endl; 40 | return false; 41 | } 42 | if (::llabs(statbuf.st_size) < static_cast(file_size)) { 43 | if (::ftruncate(fd, file_size) == -1) { 44 | ::perror("ftruncate"); 45 | std::cerr << "errno: " << errno << std::endl; 46 | return false; 47 | } 48 | } 49 | #else 50 | #warning "Manually extend file size" 51 | extend_file_size_manually(fd, file_size); 52 | #endif 53 | return true; 54 | } 55 | 56 | bool extend_file_size(const std::string &file_name, const size_t file_size) { 57 | const int fd = ::open(file_name.c_str(), O_RDWR); 58 | if (fd == -1) { 59 | ::perror("open"); 60 | std::cerr << "errno: " << errno << std::endl; 61 | return false; 62 | } 63 | 64 | if (!extend_file_size(fd, file_size)) return false; 65 | ::close(fd); 66 | 67 | return true; 68 | } 69 | 70 | bool create_file(const std::string &file_name) { 71 | const int fd = ::open(file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 72 | if (fd == -1) { 73 | ::perror("open"); 74 | std::cerr << "errno: " << errno << std::endl; 75 | return false; 76 | } 77 | ::close(fd); 78 | 79 | return true; 80 | } 81 | } // namespace utility 82 | 83 | #endif //LIB_UTILITY_FILE_HPP 84 | -------------------------------------------------------------------------------- /tests/utility/umap_file.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 3 | // UMAP Project Developers. See the top-level LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: LGPL-2.1-only 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef _UMAP_FILE_HPP_ 8 | #define _UMAP_FILE_HPP_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "umap/umap.h" 16 | 17 | namespace utility { 18 | 19 | void* map_in_file( 20 | std::string filename, 21 | bool initonly, 22 | bool noinit, 23 | bool usemmap, 24 | uint64_t numbytes) 25 | { 26 | int o_opts = O_RDWR | O_LARGEFILE | O_DIRECT; 27 | void* region = NULL; 28 | int fd; 29 | 30 | if ( initonly || !noinit ) { 31 | o_opts |= O_CREAT; 32 | unlink(filename.c_str()); // Remove the file if it exists 33 | } 34 | 35 | if ( ( fd = open(filename.c_str(), o_opts, S_IRUSR | S_IWUSR) ) == -1 ) { 36 | std::string estr = "Failed to open/create " + filename + ": "; 37 | perror(estr.c_str()); 38 | return NULL; 39 | } 40 | 41 | if ( o_opts & O_CREAT ) { 42 | // If we are initializing, attempt to pre-allocate disk space for the file. 43 | try { 44 | int x; 45 | if ( ( x = posix_fallocate(fd, 0, numbytes) != 0 ) ) { 46 | std::ostringstream ss; 47 | ss << "Failed to pre-allocate " << 48 | numbytes << " bytes in " << filename << ": "; 49 | perror(ss.str().c_str()); 50 | return NULL; 51 | } 52 | } catch(const std::exception& e) { 53 | std::cerr << "posix_fallocate: " << e.what() << std::endl; 54 | return NULL; 55 | } catch(...) { 56 | std::cerr << "posix_fallocate failed to allocate backing store\n"; 57 | return NULL; 58 | } 59 | } 60 | 61 | struct stat sbuf; 62 | if (fstat(fd, &sbuf) == -1) { 63 | std::string estr = "Failed to get status (fstat) for " + filename + ": "; 64 | perror(estr.c_str()); 65 | return NULL; 66 | } 67 | 68 | if ( (off_t)sbuf.st_size != (numbytes) ) { 69 | std::cerr << filename << " size " << sbuf.st_size 70 | << " does not match specified data size of " << (numbytes) << std::endl; 71 | return NULL; 72 | } 73 | 74 | const int prot = PROT_READ|PROT_WRITE; 75 | 76 | if ( usemmap ) { 77 | region = mmap(NULL, numbytes, prot, MAP_SHARED | MAP_NORESERVE, fd, 0); 78 | if (region == MAP_FAILED) { 79 | std::ostringstream ss; 80 | ss << "mmap of " << numbytes << " bytes failed for " << filename << ": "; 81 | perror(ss.str().c_str()); 82 | return NULL; 83 | } 84 | } 85 | else { 86 | int flags = UMAP_PRIVATE; 87 | 88 | region = umap(NULL, numbytes, prot, flags, fd, 0); 89 | if ( region == UMAP_FAILED ) { 90 | std::ostringstream ss; 91 | ss << "umap_mf of " << numbytes 92 | << " bytes failed for " << filename << ": "; 93 | perror(ss.str().c_str()); 94 | return NULL; 95 | } 96 | } 97 | 98 | return region; 99 | } 100 | 101 | void unmap_file(bool usemmap, uint64_t numbytes, void* region) 102 | { 103 | if ( usemmap ) { 104 | if ( munmap(region, numbytes) < 0 ) { 105 | std::ostringstream ss; 106 | ss << "munmap failure: "; 107 | perror(ss.str().c_str()); 108 | exit(-1); 109 | } 110 | } 111 | else { 112 | if (uunmap(region, numbytes) < 0) { 113 | std::ostringstream ss; 114 | ss << "uunmap of failure: "; 115 | perror(ss.str().c_str()); 116 | exit(-1); 117 | } 118 | } 119 | } 120 | 121 | } 122 | #endif 123 | -------------------------------------------------------------------------------- /thirdparty_licenses.md: -------------------------------------------------------------------------------- 1 | # Third Party Licenses 2 | ==================== 3 | 4 | --------------------------------------------------------------------------------