[
  {
    "path": ".bazelrc",
    "content": "build --cxxopt=-std=c++1z\nbuild --incompatible_remove_native_http_archive=false \nbuild --incompatible_package_name_is_a_function=false\n"
  },
  {
    "path": ".clang-format",
    "content": "#BasedOnStyle: Google\n\nLanguage:        Cpp\n# BasedOnStyle:  LLVM\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlinesLeft: true\nAlignOperands:   true\nAlignTrailingComments: false\nAllowAllParametersOfDeclarationOnNextLine: true\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortIfStatementsOnASingleLine: true\nAllowShortFunctionsOnASingleLine: true\nAllowShortLoopsOnASingleLine: true\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: false\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: true\nBinPackParameters: true\nBraceWrapping:\n  AfterClass:      true\n  AfterControlStatement: true\n  AfterEnum:       true\n  AfterFunction:   true\n  AfterNamespace:  false\n  AfterObjCDeclaration: false\n  AfterStruct:     true\n  AfterUnion:      true\n  BeforeCatch:     true\n  BeforeElse:      true\n  IndentBraces:    false\nBreakBeforeBinaryOperators: None\nBreakBeforeBraces: Custom\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: false\nBreakAfterJavaFieldAnnotations: false\nBreakStringLiterals: true\nColumnLimit:     100\nCommentPragmas:  '^ IWYU pragma:'\nConstructorInitializerAllOnOneLineOrOnePerLine: false\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nDisableFormat:   false\nForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]\nIncludeCategories:\n  - Regex:           '^\"(llvm|llvm-c|clang|clang-c)/'\n    Priority:        2\n  - Regex:           '^(<|\"(gtest|isl|json)/)'\n    Priority:        3\n  - Regex:           '.*'\n    Priority:        1\nIncludeIsMainRegex: '$'\nIndentCaseLabels: true\nIndentWidth:     4\nIndentWrappedFunctionNames: true\nJavaScriptQuotes: Leave\nKeepEmptyLinesAtTheStartOfBlocks: false\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 100\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 60\nPointerAlignment: Left\nReflowComments:  true\nSortIncludes:    true\nSpaceAfterCStyleCast: false\nSpaceAfterTemplateKeyword: false\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeParens: Never\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 1\nSpacesInAngles:  false\nSpacesInContainerLiterals: false\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard:        Cpp11\nTabWidth:        4\nUseTab:          Never\n"
  },
  {
    "path": ".dockerignore",
    "content": "build\n*.engine\nmodels\n@eaDir\n__pycache__\nbazel-*\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"third_party/cpuaff\"]\n\tpath = third_party/cpuaff\n\turl = https://github.com/dcdillon/cpuaff\n[submodule \"third_party/gflags\"]\n\tpath = third_party/gflags\n\turl = https://github.com/gflags/gflags.git\n[submodule \"third_party/glog\"]\n\tpath = third_party/glog\n\turl = https://github.com/google/glog.git\n[submodule \"third_party/grpc\"]\n\tpath = third_party/grpc\n\turl = https://github.com/grpc/grpc\n[submodule \"third_party/wait-for-it\"]\n\tpath = third_party/wait-for-it\n\turl = https://github.com/vishnubob/wait-for-it\n[submodule \"third_party/benchmark\"]\n\tpath = third_party/benchmark\n\turl = https://github.com/google/benchmark.git\n[submodule \"third_party/googletest\"]\n\tpath = third_party/googletest\n\turl = https://github.com/google/googletest.git\n[submodule \"third_party/pybind11\"]\n\tpath = third_party/pybind11\n\turl = https://github.com/pybind/pybind11.git\n[submodule \"third_party/flatbuffers\"]\n\tpath = third_party/flatbuffers\n\turl = https://github.com/google/flatbuffers.git\n"
  },
  {
    "path": "BUILD.bazel",
    "content": "package(default_visibility = [\"//visibility:public\"])\n"
  },
  {
    "path": "CLA",
    "content": "                       The NVIDIA TensorRT Laboratory\n   Software Grant and Corporate Contributor License Agreement (\"Agreement\")\n\n   Thank you for your interest in the NVIDIA TensorRT Laboratory Project \n   (the \"Project\"). In order to clarify the intellectual property license\n   granted with Contributions from any person or entity, NVIDIA\n   Corporation (the “Copyright Holders\") must have a Contributor License\n   Agreement (CLA) on file that has been signed by each Contributor,\n   indicating agreement to the license terms below. This license is\n   for your protection as a Contributor as well as the protection of the\n   Project and its users; it does not change your rights to use your own\n   Contributions for any other purpose.\n\n   This version of the Agreement allows an entity (the \"Corporation\") to\n   submit Contributions to the Project, to authorize Contributions\n   submitted by its designated employees to the Project, and to grant\n   copyright and patent licenses thereto to the Copyright Holders.\n\n   If you have not already done so, please complete and sign, then scan and\n   email a pdf file of this Agreement to rolson@nvidia.com.\n   Please read this document carefully before signing and keep a copy for\n   your records.\n\n   Corporation name:    ________________________________________________\n\n   Corporation address: ________________________________________________\n\n                        ________________________________________________\n\n                        ________________________________________________\n\n   Point of Contact:    ________________________________________________\n\n          E-Mail:       ________________________________________________\n\n          Telephone:    _____________________ Fax: _____________________\n\n\n   You accept and agree to the following terms and conditions for Your\n   present and future Contributions submitted to the Project. In\n   return, the Copyright Holders shall not use Your Contributions in a way\n   that is contrary to the public benefit or inconsistent with its nonprofit\n   status and bylaws in effect at the time of the Contribution. Except\n   for the license granted herein to the Copyright Holders and recipients of\n   software distributed by the Copyright Holders, You reserve all right, title,\n   and interest in and to Your Contributions.\n\n   1. Definitions.\n\n      \"You\" (or \"Your\") shall mean the copyright owner or legal entity\n      authorized by the copyright owner that is making this Agreement\n      with the Copyright Holders. For legal entities, the entity making a\n      Contribution and all other entities that control, are controlled by,\n      or are under common control with that entity are considered to be a\n      single Contributor. For the purposes of this definition, \"control\"\n      means (i) the power, direct or indirect, to cause the direction or\n      management of such entity, whether by contract or otherwise, or\n      (ii) ownership of fifty percent (50%) or more of the outstanding\n      shares, or (iii) beneficial ownership of such entity.\n\n      \"Contribution\" shall mean the code, documentation or other original\n      works of authorship expressly identified in Schedule B, as well as\n      any original work of authorship, including\n      any modifications or additions to an existing work, that is intentionally\n      submitted by You to the Copyright Holders for inclusion in, or\n      documentation of, any of the products owned or managed by the\n      Copyright Holders (the \"Work\"). For the purposes of this definition,\n      \"submitted\" means any form of electronic, verbal, or written\n      communication sent to the Copyright Holders or its representatives,\n      including but not limited to communication on electronic mailing\n      lists, source code control systems, and issue tracking systems\n      that are managed by, or on behalf of, the Copyright Holders for the\n      purpose of discussing and improving the Work, but excluding\n      communication that is conspicuously marked or otherwise designated\n      in writing by You as \"Not a Contribution.\"\n\n   2. Grant of Copyright License. Subject to the terms and conditions\n      of this Agreement, You hereby grant to the Copyright Holders and to\n      recipients of software distributed by the Copyright Holders a\n      perpetual, worldwide, non-exclusive, no-charge, royalty-free,\n      irrevocable copyright license to reproduce, prepare derivative works\n      of, publicly display, publicly perform, sublicense, and distribute\n      Your Contributions and such derivative works.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this Agreement, You hereby grant to the Copyright Holders and to\n      recipients of software distributed by the Copyright Holders\n      a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\n      irrevocable (except as stated in this section) patent license\n      to make, have made, use, offer to sell, sell, import, and otherwise\n      transfer the Work, where such license applies only to those\n      patent claims licensable by You that are necessarily infringed\n      by Your Contribution(s) alone or by combination of Your Contribution(s)\n      with the Work to which such Contribution(s) were submitted.\n      If any entity institutes patent litigation against You or any\n      other entity (including a cross-claim or counterclaim in a lawsuit)\n      alleging that your Contribution, or the Work to which you have\n      contributed, constitutes direct or contributory patent infringement,\n      then any patent licenses granted to that entity under this Agreement\n      for that Contribution or Work shall terminate as of the date such\n      litigation is filed.\n\n   4. You represent that You are legally entitled to grant the above\n      license. You represent further that each employee of the\n      Corporation designated on Schedule A below (or in a subsequent\n      written modification to that Schedule) is authorized to submit\n      Contributions on behalf of the Corporation.\n\n   5. You represent that each of Your Contributions is Your original\n      creation (see section 7 for submissions on behalf of others).\n\n   6. You are not expected to provide support for Your Contributions,\n      except to the extent You desire to provide support. You may provide\n      support for free, for a fee, or not at all. Unless required by\n      applicable law or agreed to in writing, You provide Your\n      Contributions on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS\n      OF ANY KIND, either express or implied, including, without\n      limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,\n      MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.\n\n   7. Should You wish to submit work that is not Your original creation,\n      You may submit it to the Copyright Holders separately from any\n      Contribution, identifying the complete details of its source and\n      of any license or other restriction (including, but not limited\n      to, related patents, trademarks, and license agreements) of which\n      you are personally aware, and conspicuously marking the work as\n      \"Submitted on behalf of a third-party: [named here]\".\n\n   8. It is your responsibility to notify the Copyright Holders when any change\n      is required to the list of designated employees authorized to submit\n      Contributions on behalf of the Corporation, or to the Corporation's\n      Point of Contact with the Copyright Holders.\n\n\n\n   Please sign: __________________________________ Date: _______________\n\n   Title:       __________________________________\n\n   Corporation: __________________________________\n\n\n\n\nSchedule A\n\n   [Initial list of designated employees.  NB: authorization is not\n    tied to particular Contributions.]\n\n\n\n\n\n\nSchedule B\n\n   [Identification of optional concurrent software grant.  Would be\n    left blank or omitted if there is no concurrent software grant.]\n\n\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ncmake_minimum_required(VERSION 3.13 FATAL_ERROR)\n\noption (BUILD_DEPENDENCIES \"Whether or not a superbuild should be invoked\" ON)\noption (BUILD_MEMORY \"Whether or not build trtlab/memory\" ON)\noption (BUILD_CORE \"Whether or not build trtlab/core\" ON)\noption (BUILD_CUDA \"Whether or not build trtlab/cuda\" ON)\noption (BUILD_NVRPC \"Whether or not build trtlab/nvrpc\" ON)\noption (BUILD_TENSORRT \"Whether or not build trtlab/tensorrt\" ON)\noption (BUILD_PYTHON \"Whether or not build trtlab/pybind\" OFF)\noption (BUILD_EXAMPLES \"Whether or not to build trtlab examples\" OFF)\n\nif (BUILD_DEPENDENCIES)\n  project (trtlab_dependencies NONE)\n  include (cmake/dependencies.cmake)\n  return() # stop processing this file further\nelse()\n  project (trtlab)\nendif()\n\n# CMake path\nlist(APPEND CMAKE_MODULE_PATH \"${PROJECT_SOURCE_DIR}/cmake\")\nlist(APPEND CMAKE_PREFIX_PATH \"${PROJECT_SOURCE_DIR}/cmake\")\n\n# trtlab \nadd_subdirectory(trtlab)\n\nif (BUILD_EXAMPLES)\n  add_subdirectory(examples)\nendif()\n"
  },
  {
    "path": "CREDITS.md",
    "content": "`ThreadPool` class was derived from https://github.com/progschj/ThreadPool\n\n> Copyright (c) 2012 Jakob Progsch, Václav Zeman\n> \n> This software is provided 'as-is', without any express or implied\n> warranty. In no event will the authors be held liable for any damages\n> arising from the use of this software.\n> \n> Permission is granted to anyone to use this software for any purpose,\n> including commercial applications, and to alter it and redistribute it\n> freely, subject to the following restrictions:\n> \n>   1. The origin of this software must not be misrepresented; you must not\n>   claim that you wrote the original software. If you use this software\n>   in a product, an acknowledgment in the product documentation would be\n>   appreciated but is not required.\n> \n>   2. Altered source versions must be plainly marked as such, and must not be\n>   misrepresented as being the original software.\n> \n>   3. This notice may not be removed or altered from any source\n>   distribution.\n> \n> Modifications to the original work include:\n>   * Header-only file was split into .h/.cc files\n>   * Added an extra safety check (lines 30-31) in the construction (.cc file).\n>   * Added CPU affinity options to the constructor\n\n-----\n\n`cpuaff` is distributed unmodified from the original in [`third-party/cpuaff`]\n(https://github.com/dcdillon/cpuaff)\n\n> Copyright (c) 2015, Daniel C. Dillon\n> All rights reserved.\n> \n> Redistribution and use in source and binary forms, with or without\n> modification, are permitted provided that the following conditions are met:\n> \n> * Redistributions of source code must retain the above copyright notice, this\n>   list of conditions and the following disclaimer.\n> \n> * Redistributions in binary form must reproduce the above copyright notice,\n>   this list of conditions and the following disclaimer in the documentation\n>   and/or other materials provided with the distribution.\n> \n> * Neither the name of cpuaff nor the names of its\n>   contributors may be used to endorse or promote products derived from\n>   this software without specific prior written permission.\n> \n> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----\n\n`wait-for-it.sh` is distributed unmodified from the original in [`third-pary/wait-for-it`]\n(https://github.com/vishnubob/wait-for-it).\n\n> The MIT License (MIT)\n> Copyright (c) 2016 Giles Hall\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n> of the Software, and to permit persons to whom the Software is furnished to do\n> so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\n---\n\nExample gRPC client code was used with modification from the [gRPC project]\n(https://github.com/grpc/grpc), specifically the [synchronous c++ client]\n(https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_client.cc)\n\n> Copyright 2015 gRPC authors.\n> \n> Licensed under the Apache License, Version 2.0 (the \"License\");\n> you may not use this file except in compliance with the License.\n> You may obtain a copy of the License at\n> \n>     http://www.apache.org/licenses/LICENSE-2.0\n> \n> Unless required by applicable law or agreed to in writing, software\n> distributed under the License is distributed on an \"AS IS\" BASIS,\n> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n> See the License for the specific language governing permissions and\n> limitations under the License.\n\n---\n\n[moodycamel::ConcurrentQueue](https://github.com/cameron314/concurrentqueue) is\nadded unmodified to the Docker images and loaded into the `playground` namespace.\n\n> Simplified BSD License:\n> \n> Copyright (c) 2013-2016, Cameron Desrochers. All rights reserved.\n> \n> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n> \n> Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n> Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---\n\n`transwarp` is used unmodified from the original [bloomen/transwarp](https://github.com/bloomen/transwarp)\n\n> MIT License\n> \n> Copyright (c) 2018-2019 Christian Blume, Guan Wang\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---\n\nCaffe ResNet-50 and ResNet-152 models from [KaimingHe/deep-residual-networks]\n(https://github.com/KaimingHe/deep-residual-networks) are included without modification.\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2016 Shaoqing Ren\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---\n"
  },
  {
    "path": "Dockerfile",
    "content": "# stage 1 - development container\n# holds the core nvidia libraries but does not container the project source code\n# use this container for development by mapping our source into the image which\n# persists your source code outside of the container lifecycle\n\nFROM nvcr.io/nvidia/tensorrt:20.06-py3 AS base\n\nRUN apt update\nRUN apt install -y clang-format libssl-dev openssl libz-dev software-properties-common\n\n# remove base cmake\nRUN apt remove --purge -y cmake\nRUN apt autoremove -y\nRUN apt autoclean -y\n\n# install cmake ppa from kitware - https://apt.kitware.com/\nRUN apt install -y apt-transport-https ca-certificates gnupg software-properties-common wget\nRUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add -\nRUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main'\nRUN apt update && apt install -y cmake\n\n# then remove FindGTest.cmake installed by cmake\nRUN find / -name \"FindGTest.cmake\" -exec rm -f {} \\;\n\n# add cufft and nvml to the container image\nRUN apt install -y libcufft-dev-11-0 cuda-nvml-dev-11-0\n\n# override some envs\nENV LD_LIBRARY_PATH=/externals/myelin/x86_64/cuda-11.0/lib:/externals/cudnn/x86_64/8.0/cuda-11.0/lib64:/usr/local/cuda-11.0/targets/x86_64-linux/lib\nENV CCACHE_DIR=/tmp/.ccache\nRUN cd /usr/lib/x86_64-linux-gnu && ln -s libnvidia-ml.so.1 libnvidia-ml.so\n\n\n# stage 2: build the project inside the dev container\n\nFROM base AS trtlab\n\nWORKDIR /work\n\nCOPY . .\n\nRUN mkdir build && cd build && cmake .. && make -j\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2018-2019, NVIDIA Corporation\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# TensorRT Laboratory\n\nThe TensorRT Laboratory (trtlab) is a general purpose set of tools to build customer inference applications\nand services.\n\n[Triton](https://github.com/nvidia/triton) is a professional grade production inference server.\n\nThis project is broken into 4 primary components:\n\n  * `memory` is based on [foonathan/memory](https://github.com/foonathan/memory) the `memory` module \n     was designed to write custom allocators for both host and gpu memory.  Several custom allocators are\n     included.  \n\n  * `core` contains host/cpu-side tools for common components such as thread pools, resource pool, \n    and userspace threading based on boost fibers.\n\n  * `cuda` extends `memory` with a new memory_type for CUDA device memory.  All custom allocators\n    in `memory` can be used with `device_memory`, `device_managed_memory` or `host_pinned_memory`.\n\n  * `nvrpc` is an abstraction layer for building asynchronous microservices.  The current implementation\n    is based on grpc.\n\n  * `tensorrt` provides an opinionated runtime built on the TensorRT API.\n\n## Quickstart\n\nThe easiest way to manage the external NVIDIA dependencies is to leverage the containers hosted on\n[NGC](https://ngc.nvidia.com).  For bare metal installs, use the `Dockerfile` as a template for\nwhich NVIDIA libraries to install.\n\n```\ndocker build -t trtlab . \n```\n\nFor development purposes, the following set of commands first builds the base image, then\nmaps the source code on the host into a running container.\n\n\n```\ndocker build -t trtlab:dev --target base .\ndocker run --rm -ti --gpus=all -v $PWD:/work --workdir=/work --net=host trtlab:dev bash\n```\n\n\n## Copyright and License\n\nThis project is released under the [BSD 3-clause license](LICENSE).\n\n## Issues and Contributing\n\n* Please let us know by [filing a new issue](https://github.com/NVIDIA/tensorrt-laboratory/issues/new)\n* You can contribute by opening a [pull request](https://help.github.com/articles/using-pull-requests/)\n\nPull requests with changes of 10 lines or more will require a [Contributor License Agreement](CLA).\n"
  },
  {
    "path": "WORKSPACE",
    "content": "workspace(name = \"com_github_nvidia_trtlab\")\n\nload(\":bazel/repositories.bzl\", \"repositories\")\nrepositories()\n\nload (\"//bazel:cuda_configure.bzl\", \"cuda_configure\")\ncuda_configure(name = \"local_config_cuda\")\n\nload (\"//bazel:tensorrt_configure.bzl\", \"tensorrt_configure\")\ntensorrt_configure(name = \"local_config_tensorrt\")\n\nload(\"@com_github_grpc_grpc//bazel:grpc_deps.bzl\", \"grpc_deps\")\ngrpc_deps()\n"
  },
  {
    "path": "bazel/BUILD.bazel",
    "content": "exports_files(\n    glob([\"*.bzl\"]),\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "bazel/cuda_configure.bzl",
    "content": "\"\"\"Build rule generator for locally installed CUDA toolkit and cuDNN SDK.\"\"\"\n\n# src: https://github.com/google/nvidia_libs_test\n\ndef _get_env_var(repository_ctx, name, default):\n    if name in repository_ctx.os.environ:\n        return repository_ctx.os.environ[name]\n    return default\n\ndef _impl(repository_ctx):\n    cuda_path = _get_env_var(repository_ctx, \"CUDA_PATH\", \"/usr/local/cuda\")\n    cudnn_path = _get_env_var(repository_ctx, \"CUDNN_PATH\", cuda_path)\n\n    print(\"Using CUDA from %s\\n\" % cuda_path)\n    print(\"Using cuDNN from %s\\n\" % cudnn_path)\n\n    repository_ctx.symlink(cuda_path, \"cuda\")\n    repository_ctx.symlink(cudnn_path, \"cudnn\")\n\n    repository_ctx.file(\"nvcc.sh\", \"\"\"\n#! /bin/bash\nrepo_path=%s\ncompiler=${CC:+\"--compiler-bindir=$CC\"}\n$repo_path/cuda/bin/nvcc $compiler --compiler-options=-fPIC --include-path=$repo_path $*\n\"\"\" % repository_ctx.path(\".\"))\n\n    repository_ctx.file(\"BUILD\", \"\"\"\npackage(default_visibility = [\"//visibility:public\"])\n\nsh_binary(\n    name = \"nvcc\",\n    srcs = [\"nvcc.sh\"],\n)\n\n# The *_headers cc_library rules below aren't cc_inc_library rules because\n# dependent targets would only see the first one.\n\ncc_library(\n    name = \"cuda_headers\",\n    hdrs = glob(\n        include = [\"cuda/include/**/*.h*\"],\n        exclude = [\"cuda/include/cudnn.h\"]\n    ),\n    # Allows including CUDA headers with angle brackets.\n    includes = [\"cuda/include\"],\n)\n\ncc_library(\n    name = \"cuda\",\n    srcs = [\"cuda/lib64/stubs/libcuda.so\"],\n    linkopts = [\"-ldl\"],\n)\n\ncc_library(\n    name = \"cuda_runtime\",\n    srcs = [\"cuda/lib64/libcudart_static.a\"],\n    deps = [\":cuda\"],\n    linkopts = [\"-lrt\"],\n)\n\ncc_library(\n    name = \"curand_static\",\n    srcs = [\n        \"cuda/lib64/libcurand_static.a\",\n        \"cuda/lib64/libculibos.a\",\n    ],\n)\n\ncc_library(\n    name = \"cupti_headers\",\n    hdrs = glob([\"cuda/extras/CUPTI/include/**/*.h\"]),\n    # Allows including CUPTI headers with angle brackets.\n    includes = [\"cuda/extras/CUPTI/include\"],\n)\n\ncc_library(\n    name = \"cupti\",\n    srcs = glob([\"cuda/extras/CUPTI/lib64/libcupti.so*\"]),\n)\n\ncc_library(\n    name = \"cudnn\",\n    srcs = [\n        \"cudnn/lib64/libcudnn_static.a\",\n        \"cuda/lib64/libcublas_static.a\",\n        \"cuda/lib64/libculibos.a\",\n    ],\n    hdrs = [\"cudnn/include/cudnn.h\"],\n    deps = [\n        \":cuda\",\n        \":cuda_headers\"\n    ],\n)\n\ncc_library(\n    name = \"cuda_util\",\n    deps = [\":cuda_util_compile\"],\n)\n\"\"\")\n\ncuda_configure = repository_rule(\n    implementation = _impl,\n    environ = [\"CUDA_PATH\", \"CUDNN_PATH\"],\n)\n"
  },
  {
    "path": "bazel/repositories.bzl",
    "content": "load(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\n\ndef repositories():\n    _maybe(\n        http_archive,\n        name = \"com_github_antonovvk_bazel_rules\",\n        sha256 = \"ba75b07d3fd297375a6688e9a16583eb616e7a74b3d5e8791e7a222cf36ab26e\",\n        strip_prefix = \"bazel_rules-98ddd7e4f7c63ea0868f08bcc228463dac2f9f12\",\n        urls = [\n            \"https://mirror.bazel.build/github.com/antonovvk/bazel_rules/archive/98ddd7e4f7c63ea0868f08bcc228463dac2f9f12.tar.gz\",\n            \"https://github.com/antonovvk/bazel_rules/archive/98ddd7e4f7c63ea0868f08bcc228463dac2f9f12.tar.gz\",\n        ],\n    )\n\n    _maybe(\n        http_archive,\n        name = \"com_github_gflags_gflags\",\n        sha256 = \"6e16c8bc91b1310a44f3965e616383dbda48f83e8c1eaa2370a215057b00cabe\",\n        strip_prefix = \"gflags-77592648e3f3be87d6c7123eb81cbad75f9aef5a\",\n        urls = [\n            \"https://mirror.bazel.build/github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz\",\n            \"https://github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz\",\n        ],\n    )\n\n    _maybe(\n        http_archive,\n        name = \"com_google_glog\",\n        sha256 = \"1ee310e5d0a19b9d584a855000434bb724aa744745d5b8ab1855c85bff8a8e21\",\n        strip_prefix = \"glog-028d37889a1e80e8a07da1b8945ac706259e5fd8\",\n        urls = [\n            \"https://mirror.bazel.build/github.com/google/glog/archive/028d37889a1e80e8a07da1b8945ac706259e5fd8.tar.gz\",\n            \"https://github.com/google/glog/archive/028d37889a1e80e8a07da1b8945ac706259e5fd8.tar.gz\",\n        ],\n    )\n\n    _maybe(\n        http_archive,\n        name = \"com_google_googletest\",\n        sha256 = \"c18f281fd6621bb264570b99860a0241939b4a251c9b1af709b811d33bc63af8\",\n        strip_prefix = \"googletest-e3bd4cbeaeef3cee65a68a8bd3c535cb779e9b6d\",\n        urls = [\n            \"https://mirror.bazel.build/github.com/google/googletest/archive/e3bd4cbeaeef3cee65a68a8bd3c535cb779e9b6d.tar.gz\",\n            \"https://github.com/google/googletest/archive/e3bd4cbeaeef3cee65a68a8bd3c535cb779e9b6d.tar.gz\",\n        ],\n    )\n\n    _maybe(\n        http_archive,\n        name = \"com_github_grpc_grpc\",\n        strip_prefix = \"grpc-1.16.1\",\n        urls = [\n            \"https://github.com/grpc/grpc/archive/v1.16.1.tar.gz\",\n        ],\n    )\n\ndef load_trtis():\n    http_archive(\n        name = \"com_github_nvidia_trtis\",\n        strip_prefix = \"tensorrt-inference-server-0.9.0\",\n        urls = [\n            \"https://github.com/NVIDIA/tensorrt-inference-server/archive/v0.9.0.tar.gz\",\n        ],\n    )\n\ndef load_benchmark():\n    http_archive(\n        name = \"com_github_google_benchmark\",\n        sha256 = \"f8e525db3c42efc9c7f3bc5176a8fa893a9a9920bbd08cef30fb56a51854d60d\",\n        strip_prefix = \"benchmark-1.4.1\",\n        urls = [\n            \"https://github.com/google/benchmark/archive/v1.4.1.tar.gz\",\n        ],\n    )\n\ndef _maybe(repo_rule, name, **kwargs):\n    if name not in native.existing_rules():\n        repo_rule(name = name, **kwargs)\n"
  },
  {
    "path": "bazel/tensorrt_configure.bzl",
    "content": "\"\"\"Build rule generator for locally installed TensorRT.\"\"\"\n\n# inspired from: https://github.com/google/nvidia_libs_test\n\ndef _get_env_var(repository_ctx, name, default):\n    if name in repository_ctx.os.environ:\n        return repository_ctx.os.environ[name]\n    return default\n\ndef _impl(repository_ctx):\n    hdrs_path = _get_env_var(repository_ctx, \"TENSORRT_HDRS_PATH\", \"/usr/include/x86_64-linux-gnu\")\n    libs_path = _get_env_var(repository_ctx, \"TENSORRT_LIBS_PATH\", \"/usr/lib/x86_64-linux-gnu\")\n\n    print(\"Using TensorRT Headers from %s\\n\" % hdrs_path)\n    print(\"Using TensorRT Libs from %s\\n\" % libs_path)\n\n    repository_ctx.symlink(hdrs_path, \"include\")\n    repository_ctx.symlink(libs_path, \"libs\")\n\n    repository_ctx.file(\"BUILD\", \"\"\"\npackage(default_visibility = [\"//visibility:public\"])\n\n# The *_headers cc_library rules below aren't cc_inc_library rules because\n# dependent targets would only see the first one.\n\ncc_library(\n    name = \"tensorrt_headers\",\n    hdrs = glob(\n        include = [\"include/Nv*.h\"],\n    ),\n    strip_include_prefix = \"include\",\n    # Allows including CUDA headers with angle brackets.\n    # includes = [\"cuda/include\"],\n)\n\ncc_library(\n    name = \"tensorrt_infer\",\n    srcs = [\"libs/libnvinfer.so\"],\n    linkopts = [\"-ldl\"],\n)\n\n\"\"\")\n\ntensorrt_configure = repository_rule(\n    implementation = _impl,\n    environ = [\"TENSORRT_HDRS_PATH\", \"TENSORRT_LIBS_PATH\"],\n)\n"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/bash\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nmkdir -p build\ncd build\ncmake -DCMAKE_BUILD_TYPE=Release ..\ncmake -DCMAKE_BUILD_TYPE=Release ..\nmake -j\ncd /work/notebooks\nln -f -s /work/build/tensorrt-laboratory/python/trtlab/trtlab.cpython-35m-x86_64-linux-gnu.so\n#make install\n"
  },
  {
    "path": "cmake/FindTensorRT.cmake",
    "content": "# This module defines the following variables:\n#\n# ::\n#\n#   TensorRT_INCLUDE_DIRS\n#   TensorRT_LIBRARIES\n#   TensorRT_FOUND\n#\n# ::\n#\n#   TensorRT_VERSION_STRING - version (x.y.z)\n#   TensorRT_VERSION_MAJOR  - major version (x)\n#   TensorRT_VERSION_MINOR  - minor version (y)\n#   TensorRT_VERSION_PATCH  - patch version (z)\n#\n# Hints\n# ^^^^^\n# A user may set ``TensorRT_ROOT`` to an installation root to tell this module where to look.\n#\nset(_TensorRT_SEARCHES)\n\nif(TensorRT_ROOT)\n  set(_TensorRT_SEARCH_ROOT PATHS ${TensorRT_ROOT} NO_DEFAULT_PATH)\n  list(APPEND _TensorRT_SEARCHES _TensorRT_SEARCH_ROOT)\nendif()\n\n# appends some common paths\nset(_TensorRT_SEARCH_NORMAL\n  PATHS \"/usr\"\n)\nlist(APPEND _TensorRT_SEARCHES _TensorRT_SEARCH_NORMAL)\n\n# Include dir\nforeach(search ${_TensorRT_SEARCHES})\n  find_path(TensorRT_INCLUDE_DIR NAMES NvInfer.h ${${search}} PATH_SUFFIXES include)\nendforeach()\n\nif(NOT TensorRT_LIBRARY)\n  foreach(search ${_TensorRT_SEARCHES})\n    find_library(TensorRT_LIBRARY NAMES nvinfer ${${search}} PATH_SUFFIXES lib)\n  endforeach()\nendif()\n\nmark_as_advanced(TensorRT_INCLUDE_DIR)\n\nif(TensorRT_INCLUDE_DIR AND EXISTS \"${TensorRT_INCLUDE_DIR}/NvInfer.h\")\n    file(STRINGS \"${TensorRT_INCLUDE_DIR}/NvInfer.h\" TensorRT_MAJOR REGEX \"^#define NV_TENSORRT_MAJOR [0-9]+.*$\")\n    file(STRINGS \"${TensorRT_INCLUDE_DIR}/NvInfer.h\" TensorRT_MINOR REGEX \"^#define NV_TENSORRT_MINOR [0-9]+.*$\")\n    file(STRINGS \"${TensorRT_INCLUDE_DIR}/NvInfer.h\" TensorRT_PATCH REGEX \"^#define NV_TENSORRT_PATCH [0-9]+.*$\")\n\n    string(REGEX REPLACE \"^#define NV_TENSORRT_MAJOR ([0-9]+).*$\" \"\\\\1\" TensorRT_VERSION_MAJOR \"${TensorRT_MAJOR}\")\n    string(REGEX REPLACE \"^#define NV_TENSORRT_MINOR ([0-9]+).*$\" \"\\\\1\" TensorRT_VERSION_MINOR \"${TensorRT_MINOR}\")\n    string(REGEX REPLACE \"^#define NV_TENSORRT_PATCH ([0-9]+).*$\" \"\\\\1\" TensorRT_VERSION_PATCH \"${TensorRT_PATCH}\")\n    set(TensorRT_VERSION_STRING \"${TensorRT_VERSION_MAJOR}.${TensorRT_VERSION_MINOR}.${TensorRT_VERSION_PATCH}\")\nendif()\n\ninclude(FindPackageHandleStandardArgs)\nFIND_PACKAGE_HANDLE_STANDARD_ARGS(TensorRT REQUIRED_VARS TensorRT_LIBRARY TensorRT_INCLUDE_DIR VERSION_VAR TensorRT_VERSION_STRING)\n\nif(TensorRT_FOUND)\n  set(TensorRT_INCLUDE_DIRS ${TensorRT_INCLUDE_DIR})\n\n  if(NOT TensorRT_LIBRARIES)\n    set(TensorRT_LIBRARIES ${TensorRT_LIBRARY})\n  endif()\n\n  if(NOT TARGET TensorRT::TensorRT)\n    add_library(TensorRT::TensorRT UNKNOWN IMPORTED)\n    set_target_properties(TensorRT::TensorRT PROPERTIES INTERFACE_INCLUDE_DIRECTORIES \"${TensorRT_INCLUDE_DIRS}\")\n    set_property(TARGET TensorRT::TensorRT APPEND PROPERTY IMPORTED_LOCATION \"${TensorRT_LIBRARY}\")\n  endif()\nendif()\n"
  },
  {
    "path": "cmake/Findcpuaff.cmake",
    "content": "# This module defines the following variables:\n#\n# ::\n#\n#   CPUAFF_INCLUDE_DIRS\n#   CPUAFF_FOUND\n#\n# ::\n#\n# Hints\n# ^^^^^\n# A user may set ``CPUAFF_ROOT`` to an installation root to tell this module where to look.\n#\nset(CPUAFF_FOUND FALSE)\nset(_CPUAFF_SEARCHES)\n\nif(CPUAFF_ROOT)\n  set(_CPUAFF_SEARCH_ROOT PATHS ${CPUAFF_ROOT} NO_DEFAULT_PATH)\n  list(APPEND _CPUAFF_SEARCHES _CPUAFF_SEARCH_ROOT)\nelse()\n  list(APPEND _CPUAFF_SEARCHES \"/usr\")\n  list(APPEND _CPUAFF_SEARCHES \"/usr/local\")\nendif()\n\n# Include dir\nforeach(search ${_CPUAFF_SEARCHES})\n  find_path(\n    CPUAFF_INCLUDE_DIR \n    NAMES cpuaff/cpuaff.hpp\n    PATHS ${CPUAFF_ROOT}\n    PATH_SUFFIXES include)\n  message(STATUS \"cpuaff: ${CPUAFF_INCLUDE_DIR}\")\nendforeach()\n\nmark_as_advanced(CPUAFF_INCLUDE_DIR)\n\nif(CPUAFF_INCLUDE_DIR AND EXISTS \"${CPUAFF_INCLUDE_DIR}/cpuaff/cpuaff.hpp\")\n    set(CPUAFF_FOUND True)\n\n    add_library(cpuaff INTERFACE)\n    target_include_directories(cpuaff INTERFACE ${CPUAFF_INCLUDE_DIR})\nendif()\n"
  },
  {
    "path": "cmake/GRPCGenerateCPP.cmake",
    "content": "\nfind_package(gRPC REQUIRED COMPONENTS grpc_cpp_plugin)\nset(_gRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)\n\nfunction(PROTOBUF_GENERATE_GRPC_CPP SRCS HDRS)\n  cmake_parse_arguments(protobuf \"\" \"EXPORT_MACRO;DESCRIPTORS\" \"\" ${ARGN})\n\n  set(PROTO_FILES \"${protobuf_UNPARSED_ARGUMENTS}\")\n  if(NOT PROTO_FILES)\n    message(SEND_ERROR \"Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files\")\n    return()\n  endif()\n\n  if(PROTOBUF_GENERATE_CPP_APPEND_PATH) # This variable is common for all types of output.\n    # Create an include path for each file specified\n    foreach(FIL ${PROTO_FILES})\n      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n      get_filename_component(ABS_PATH ${ABS_FIL} PATH)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  else()\n    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})\n  endif()\n\n  if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)\n    set(Protobuf_IMPORT_DIR \"${PROTOBUF_IMPORT_DIRS\")\n  endif()\n\n  if(DEFINED Protobuf_IMPORT_DIRS)\n    foreach(DIR ${Protobuf_IMPORT_DIRS})\n      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  endif()\n\n  set(${SRCS})\n  set(${HDRS})\n  foreach(FIL ${PROTO_FILES})\n    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n    get_filename_component(FIL_WE ${FIL} NAME_WE)\n\n    if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)\n      get_filename_component(FIL_DIR ${FIL} DIRECTORY)\n      if(FIL_DIR)\n        set(FIL_WE \"${FIL_DIR}/${FIL_WE}\")\n      endif()\n    endif()\n\n    set(_protobuf_grpc_src \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc\")\n    set(_protobuf_grpc_hdr \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h\")\n    list(APPEND ${SRCS} \"${_protobuf_grpc_src}\")\n    list(APPEND ${HDRS} \"${_protobuf_grpc_hdr}\")\n\n    add_custom_command(\n      OUTPUT \"${_protobuf_grpc_src}\"\n             \"${_protobuf_grpc_hdr}\"\n      COMMAND ${Protobuf_PROTOC_EXECUTABLE}\n              --grpc_out=${CMAKE_CURRENT_BINARY_DIR}\n              --plugin=protoc-gen-grpc=${_gRPC_CPP_PLUGIN_EXECUTABLE}\n              ${_protobuf_include_path} ${ABS_FIL}\n      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}\n      COMMENT \"Running gRPC C++ protocol buffer compiler on ${FIL}\"\n      VERBATIM)\n  endforeach()\n\n  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)\n  set(${SRCS} ${${SRCS}} PARENT_SCOPE)\n  set(${HDRS} ${${HDRS}} PARENT_SCOPE)\nendfunction()"
  },
  {
    "path": "cmake/GRPCGenerateCPPLikeBazel.cmake",
    "content": "find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) # Get full path to plugin\n\nfunction(PROTOBUF_GENERATE_GRPC_CPP_LIKE_BAZEL SRCS HDRS)\n  cmake_parse_arguments(protobuf \"\" \"EXPORT_MACRO;DESCRIPTORS\" \"\" ${ARGN})\n\n  set(PROTO_FILES \"${protobuf_UNPARSED_ARGUMENTS}\")\n  if(NOT PROTO_FILES)\n    message(SEND_ERROR \"Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files\")\n    return()\n  endif()\n\n  if(protobuf_EXPORT_MACRO)\n    set(DLL_EXPORT_DECL \"dllexport_decl=${protobuf_EXPORT_MACRO}:\")\n  endif()\n\n  get_filename_component(ABS_PROTO_PATH ${CMAKE_SOURCE_DIR} ABSOLUTE)\n  set(EXTRA_ARGS \"--proto_path=${ABS_PROTO_PATH}\")\n  file(RELATIVE_PATH Protobuf_PRE_IMPORT_DIRS ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})\n\n  if(PROTOBUF_GENERATE_CPP_APPEND_PATH) # This variable is common for all types of output.\n    # Create an include path for each file specified\n    foreach(FIL ${PROTO_FILES})\n      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n      get_filename_component(ABS_PATH ${ABS_FIL} PATH)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  else()\n    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})\n  endif()\n\n  if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)\n    set(Protobuf_IMPORT_DIR \"${PROTOBUF_IMPORT_DIRS\")\n  endif()\n\n  if(DEFINED Protobuf_IMPORT_DIRS)\n    foreach(DIR ${Protobuf_IMPORT_DIRS})\n      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  endif()\n\n  set(${SRCS})\n  set(${HDRS})\n  foreach(FIL ${PROTO_FILES})\n    message(STATUS \"grpc_cpp_proto: ${FIL}\")\n    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n    get_filename_component(FIL_WE ${FIL} NAME_WE)\n    message(STATUS \"grpc_cpp_proto_abs: ${ABS_FIL}\")\n\n    if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)\n      get_filename_component(FIL_DIR ${FIL} DIRECTORY)\n      if(FIL_DIR)\n        set(FIL_WE \"${FIL_DIR}/${FIL_WE}\")\n      endif()\n    endif()\n\n    if(Protobuf_PRE_IMPORT_DIRS)\n    set(_protobuf_protoc_src \"${CMAKE_CURRENT_BINARY_DIR}/${Protobuf_PRE_IMPORT_DIRS}/${FIL_WE}.grpc.pb.cc\")\n    set(_protobuf_protoc_hdr \"${CMAKE_CURRENT_BINARY_DIR}/${Protobuf_PRE_IMPORT_DIRS}/${FIL_WE}.grpc.pb.h\")\n  else()\n    set(_protobuf_protoc_src \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc\")\n    set(_protobuf_protoc_hdr \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h\")\n  endif()\n    message(STATUS \"grpc_cpp_src: ${_protobuf_protoc_src}\")\n    list(APPEND ${SRCS} \"${_protobuf_protoc_src}\")\n    list(APPEND ${HDRS} \"${_protobuf_protoc_hdr}\")\n\n    add_custom_command(\n      OUTPUT \"${_protobuf_protoc_src}\"\n             \"${_protobuf_protoc_hdr}\"\n      COMMAND ${Protobuf_PROTOC_EXECUTABLE}\n              ${EXTRA_ARGS}\n              \"--grpc_out=${CMAKE_CURRENT_BINARY_DIR}\"\n              \"--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}\"\n              ${_protobuf_protoc_flags}\n              ${_protobuf_include_path} ${ABS_FIL}\n      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}\n      COMMENT \"Running gRPC C++ protocol buffer compiler on ${FIL}\"\n      VERBATIM)\n  endforeach()\n\n  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)\n  set(${SRCS} ${${SRCS}} PARENT_SCOPE)\n  set(${HDRS} ${${HDRS}} PARENT_SCOPE)\nendfunction()"
  },
  {
    "path": "cmake/LibFindMacros.cmake",
    "content": "# Version 2.2\n# Public Domain, originally written by Lasse Kärkkäinen <tronic>\n# Maintained at https://github.com/Tronic/cmake-modules\n# Please send your improvements as pull requests on Github.\n\n# Find another package and make it a dependency of the current package.\n# This also automatically forwards the \"REQUIRED\" argument.\n# Usage: libfind_package(<prefix> <another package> [extra args to find_package])\nmacro (libfind_package PREFIX PKG)\n  set(${PREFIX}_args ${PKG} ${ARGN})\n  if (${PREFIX}_FIND_REQUIRED)\n    set(${PREFIX}_args ${${PREFIX}_args} REQUIRED)\n  endif()\n  find_package(${${PREFIX}_args})\n  set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG})\n  unset(${PREFIX}_args)\nendmacro()\n\n# A simple wrapper to make pkg-config searches a bit easier.\n# Works the same as CMake's internal pkg_check_modules but is always quiet.\nmacro (libfind_pkg_check_modules)\n  find_package(PkgConfig QUIET)\n  if (PKG_CONFIG_FOUND)\n    pkg_check_modules(${ARGN} QUIET)\n  endif()\nendmacro()\n\n# Avoid useless copy&pasta by doing what most simple libraries do anyway:\n# pkg-config, find headers, find library.\n# Usage: libfind_pkg_detect(<prefix> <pkg-config args> FIND_PATH <name> [other args] FIND_LIBRARY <name> [other args])\n# E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2)\nfunction (libfind_pkg_detect PREFIX)\n  # Parse arguments\n  set(argname pkgargs)\n  foreach (i ${ARGN})\n    if (\"${i}\" STREQUAL \"FIND_PATH\")\n      set(argname pathargs)\n    elseif (\"${i}\" STREQUAL \"FIND_LIBRARY\")\n      set(argname libraryargs)\n    else()\n      set(${argname} ${${argname}} ${i})\n    endif()\n  endforeach()\n  if (NOT pkgargs)\n    message(FATAL_ERROR \"libfind_pkg_detect requires at least a pkg_config package name to be passed.\")\n  endif()\n  # Find library\n  libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs})\n  if (pathargs)\n    find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS})\n  endif()\n  if (libraryargs)\n    find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS})\n  endif()\nendfunction()\n\n# Extracts a version #define from a version.h file, output stored to <PREFIX>_VERSION.\n# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR)\n# Fourth argument \"QUIET\" may be used for silently testing different define names.\n# This function does nothing if the version variable is already defined.\nfunction (libfind_version_header PREFIX VERSION_H DEFINE_NAME)\n  # Skip processing if we already have a version or if the include dir was not found\n  if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR)\n    return()\n  endif()\n  set(quiet ${${PREFIX}_FIND_QUIETLY})\n  # Process optional arguments\n  foreach(arg ${ARGN})\n    if (arg STREQUAL \"QUIET\")\n      set(quiet TRUE)\n    else()\n      message(AUTHOR_WARNING \"Unknown argument ${arg} to libfind_version_header ignored.\")\n    endif()\n  endforeach()\n  # Read the header and parse for version number\n  set(filename \"${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\n  if (NOT EXISTS ${filename})\n    if (NOT quiet)\n      message(AUTHOR_WARNING \"Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\n    endif()\n    return()\n  endif()\n  file(READ \"${filename}\" header)\n  string(REGEX REPLACE \".*#[ \\t]*define[ \\t]*${DEFINE_NAME}[ \\t]*\\\"([^\\n]*)\\\".*\" \"\\\\1\" match \"${header}\")\n  # No regex match?\n  if (match STREQUAL header)\n    if (NOT quiet)\n      message(AUTHOR_WARNING \"Unable to find \\#define ${DEFINE_NAME} \\\"<version>\\\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}\")\n    endif()\n    return()\n  endif()\n  # Export the version string\n  set(${PREFIX}_VERSION \"${match}\" PARENT_SCOPE)\nendfunction()\n\n# Do the final processing once the paths have been detected.\n# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain\n# all the variables, each of which contain one include directory.\n# Ditto for ${PREFIX}_PROCESS_LIBS and library files.\n# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.\n# Also handles errors in case library detection was required, etc.\nfunction (libfind_process PREFIX)\n  # Skip processing if already processed during this configuration run\n  if (${PREFIX}_FOUND)\n    return()\n  endif()\n\n  set(found TRUE)  # Start with the assumption that the package was found\n\n  # Did we find any files? Did we miss includes? These are for formatting better error messages.\n  set(some_files FALSE)\n  set(missing_headers FALSE)\n\n  # Shorthands for some variables that we need often\n  set(quiet ${${PREFIX}_FIND_QUIETLY})\n  set(required ${${PREFIX}_FIND_REQUIRED})\n  set(exactver ${${PREFIX}_FIND_VERSION_EXACT})\n  set(findver \"${${PREFIX}_FIND_VERSION}\")\n  set(version \"${${PREFIX}_VERSION}\")\n\n  # Lists of config option names (all, includes, libs)\n  unset(configopts)\n  set(includeopts ${${PREFIX}_PROCESS_INCLUDES})\n  set(libraryopts ${${PREFIX}_PROCESS_LIBS})\n\n  # Process deps to add to \n  foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES})\n    if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS)\n      # The package seems to export option lists that we can use, woohoo!\n      list(APPEND includeopts ${${i}_INCLUDE_OPTS})\n      list(APPEND libraryopts ${${i}_LIBRARY_OPTS})\n    else()\n      # If plural forms don't exist or they equal singular forms\n      if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR\n          ({i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES))\n        # Singular forms can be used\n        if (DEFINED ${i}_INCLUDE_DIR)\n          list(APPEND includeopts ${i}_INCLUDE_DIR)\n        endif()\n        if (DEFINED ${i}_LIBRARY)\n          list(APPEND libraryopts ${i}_LIBRARY)\n        endif()\n      else()\n        # Oh no, we don't know the option names\n        message(FATAL_ERROR \"We couldn't determine config variable names for ${i} includes and libs. Aieeh!\")\n      endif()\n    endif()\n  endforeach()\n  \n  if (includeopts)\n    list(REMOVE_DUPLICATES includeopts)\n  endif()\n  \n  if (libraryopts)\n    list(REMOVE_DUPLICATES libraryopts)\n  endif()\n\n  string(REGEX REPLACE \".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))\" \"\\\\1\" tmp \"${includeopts} ${libraryopts}\")\n  if (NOT tmp STREQUAL \"${includeopts} ${libraryopts}\")\n    message(AUTHOR_WARNING \"Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).\")\n  endif()\n\n  # Include/library names separated by spaces (notice: not CMake lists)\n  unset(includes)\n  unset(libs)\n\n  # Process all includes and set found false if any are missing\n  foreach (i ${includeopts})\n    list(APPEND configopts ${i})\n    if (NOT \"${${i}}\" STREQUAL \"${i}-NOTFOUND\")\n      list(APPEND includes \"${${i}}\")\n    else()\n      set(found FALSE)\n      set(missing_headers TRUE)\n    endif()\n  endforeach()\n\n  # Process all libraries and set found false if any are missing\n  foreach (i ${libraryopts})\n    list(APPEND configopts ${i})\n    if (NOT \"${${i}}\" STREQUAL \"${i}-NOTFOUND\")\n      list(APPEND libs \"${${i}}\")\n    else()\n      set (found FALSE)\n    endif()\n  endforeach()\n\n  # Version checks\n  if (found AND findver)\n    if (NOT version)\n      message(WARNING \"The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.\")\n    elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver))\n      set(found FALSE)\n      set(version_unsuitable TRUE)\n    endif()\n  endif()\n\n  # If all-OK, hide all config options, export variables, print status and exit\n  if (found)\n    foreach (i ${configopts})\n      mark_as_advanced(${i})\n    endforeach()\n    if (NOT quiet)\n      message(STATUS \"Found ${PREFIX} ${${PREFIX}_VERSION}\")\n      if (LIBFIND_DEBUG)\n        message(STATUS \"  ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}\")\n        message(STATUS \"  ${PREFIX}_INCLUDE_OPTS=${includeopts}\")\n        message(STATUS \"  ${PREFIX}_INCLUDE_DIRS=${includes}\")\n        message(STATUS \"  ${PREFIX}_LIBRARY_OPTS=${libraryopts}\")\n        message(STATUS \"  ${PREFIX}_LIBRARIES=${libs}\")\n      endif()\n      set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE)\n      set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE)\n      set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE)\n      set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE)\n      set (${PREFIX}_FOUND TRUE PARENT_SCOPE)\n    endif()\n    return()    \n  endif()\n\n  # Format messages for debug info and the type of error\n  set(vars \"Relevant CMake configuration variables:\\n\")\n  foreach (i ${configopts})\n    mark_as_advanced(CLEAR ${i})\n    set(val ${${i}})\n    if (\"${val}\" STREQUAL \"${i}-NOTFOUND\")\n      set (val \"<not found>\")\n    elseif (val AND NOT EXISTS ${val})\n      set (val \"${val}  (does not exist)\")\n    else()\n      set(some_files TRUE)\n    endif()\n    set(vars \"${vars}  ${i}=${val}\\n\")\n  endforeach()\n  set(vars \"${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\\n\")\n  if (version_unsuitable)\n    set(msg \"${PREFIX} ${${PREFIX}_VERSION} was found but\")\n    if (exactver)\n      set(msg \"${msg} only version ${findver} is acceptable.\")\n    else()\n      set(msg \"${msg} version ${findver} is the minimum requirement.\")\n    endif()\n  else()\n    if (missing_headers)\n      set(msg \"We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?\")\n    elseif (some_files)\n      set(msg \"We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?\")\n      if(findver)\n        set(msg \"${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).\")\n      endif()\n    else()\n      set(msg \"We were unable to find package ${PREFIX}.\")\n    endif()\n  endif()\n\n  # Fatal error out if REQUIRED\n  if (required)\n    set(msg \"REQUIRED PACKAGE NOT FOUND\\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.\")\n    message(FATAL_ERROR \"${msg}\\n${vars}\")\n  endif()\n  # Otherwise just print a nasty warning\n  if (NOT quiet)\n    message(WARNING \"WARNING: MISSING PACKAGE\\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \\n${vars}\")\n  endif()\nendfunction()\n\n"
  },
  {
    "path": "cmake/ProtobufGenerateCPPLikeBazel.cmake",
    "content": "function(PROTOBUF_GENERATE_CPP_LIKE_BAZEL SRCS HDRS)\n  cmake_parse_arguments(protobuf \"\" \"EXPORT_MACRO;DESCRIPTORS\" \"\" ${ARGN})\n\n  set(PROTO_FILES \"${protobuf_UNPARSED_ARGUMENTS}\")\n  if(NOT PROTO_FILES)\n    message(SEND_ERROR \"Error: PROTOBUF_GENERATE_CPP() called without any proto files\")\n    return()\n  endif()\n\n  if(protobuf_EXPORT_MACRO)\n    set(DLL_EXPORT_DECL \"dllexport_decl=${protobuf_EXPORT_MACRO}:\")\n  endif()\n\n  get_filename_component(ABS_PROTO_PATH ${CMAKE_SOURCE_DIR} ABSOLUTE)\n  set(EXTRA_ARGS \"--proto_path=${ABS_PROTO_PATH}\")\n  file(RELATIVE_PATH Protobuf_PRE_IMPORT_DIRS ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})\n\n  if(PROTOBUF_GENERATE_CPP_APPEND_PATH)\n    # Create an include path for each file specified\n    foreach(FIL ${PROTO_FILES})\n      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n      get_filename_component(ABS_PATH ${ABS_FIL} PATH)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  else()\n    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})\n  endif()\n\n  if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)\n    set(Protobuf_IMPORT_DIRS \"${PROTOBUF_IMPORT_DIRS}\")\n  endif()\n\n  if(DEFINED Protobuf_IMPORT_DIRS)\n    foreach(DIR ${Protobuf_IMPORT_DIRS})\n      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)\n      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)\n      if(${_contains_already} EQUAL -1)\n          list(APPEND _protobuf_include_path -I ${ABS_PATH})\n      endif()\n    endforeach()\n  endif()\n\n  set(${SRCS})\n  set(${HDRS})\n  if (protobuf_DESCRIPTORS)\n    set(${protobuf_DESCRIPTORS})\n  endif()\n\n  foreach(FIL ${PROTO_FILES})\n    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)\n    get_filename_component(FIL_WE ${FIL} NAME_WE)\n    if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)\n      get_filename_component(FIL_DIR ${FIL} DIRECTORY)\n      if(FIL_DIR)\n        set(FIL_WE \"${FIL_DIR}/${FIL_WE}\")\n      endif()\n    endif()\n\n    if(Protobuf_PRE_IMPORT_DIRS)\n      set(_protobuf_protoc_src \"${CMAKE_CURRENT_BINARY_DIR}/${Protobuf_PRE_IMPORT_DIRS}/${FIL_WE}.pb.cc\")\n      set(_protobuf_protoc_hdr \"${CMAKE_CURRENT_BINARY_DIR}/${Protobuf_PRE_IMPORT_DIRS}/${FIL_WE}.pb.h\")\n    else()\n      set(_protobuf_protoc_src \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc\")\n      set(_protobuf_protoc_hdr \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h\")\n    endif()\n    list(APPEND ${SRCS} \"${_protobuf_protoc_src}\")\n    list(APPEND ${HDRS} \"${_protobuf_protoc_hdr}\")\n\n    if(protobuf_DESCRIPTORS)\n      set(_protobuf_protoc_desc \"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.desc\")\n      set(_protobuf_protoc_flags \"--descriptor_set_out=${_protobuf_protoc_desc}\")\n      list(APPEND ${protobuf_DESCRIPTORS} \"${_protobuf_protoc_desc}\")\n    else()\n      set(_protobuf_protoc_desc \"\")\n      set(_protobuf_protoc_flags \"\")\n    endif()\n\n    add_custom_command(\n      OUTPUT \"${_protobuf_protoc_src}\"\n             \"${_protobuf_protoc_hdr}\"\n             ${_protobuf_protoc_desc}\n      COMMAND  protobuf::protoc\n               ${EXTRA_ARGS}\n               \"--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_BINARY_DIR}\"\n               ${_protobuf_protoc_flags}\n               ${_protobuf_include_path} ${ABS_FIL}\n      DEPENDS ${ABS_FIL} protobuf::protoc\n      COMMENT \"Running C++ protocol buffer compiler on ${FIL}\"\n      VERBATIM )\n  endforeach()\n\n  set(${SRCS} \"${${SRCS}}\" PARENT_SCOPE)\n  set(${HDRS} \"${${HDRS}}\" PARENT_SCOPE)\n  if(protobuf_DESCRIPTORS)\n    set(${protobuf_DESCRIPTORS} \"${${protobuf_DESCRIPTORS}}\" PARENT_SCOPE)\n  endif()\nendfunction()\n"
  },
  {
    "path": "cmake/dependencies.cmake",
    "content": "include (ExternalProject)\n\nset (DEPENDENCIES)\nset (EXTRA_CMAKE_ARGS)\n\n# trtlab external dependencies\nlist (APPEND DEPENDENCIES boost dlpack gflags glog benchmark googletest cpuaff jemalloc)\nlist (APPEND DEPENDENCIES grpc-repo protobuf c-ares grpc cub cnpy)\n\n# note on ubuntu 18.04, you need\n# apt install libz-dev libssl-dev\n\n# customize the folder for external projects\n# download, source and builds for dependencies \n# will be in <build-dir>/Dependencies\nset_property (DIRECTORY PROPERTY EP_BASE Dependencies)\n\n# all dependencies will be installed here\n# typical directories: bin, include and lib\nset (BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build)\nset (SOURCE_ROOT ${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Source)\nset (INSTALL_ROOT ${CMAKE_CURRENT_BINARY_DIR}/local)\n\n# set cmake search paths to pick up installed .cmake files\nlist(INSERT CMAKE_MODULE_PATH 0 \"${INSTALL_ROOT}/lib/cmake\")\nlist(INSERT CMAKE_PREFIX_PATH 0 \"${INSTALL_ROOT}/lib/cmake\")\n\n# cmake config args forwarded to trtlab\nlist(APPEND EXTRA_CMAKE_ARGS\n  -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\n  -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}\n# -DBoost_VERBOSE=ON\n  -DBoost_USE_STATIC_LIBS=ON\n  -DCPUAFF_ROOT=${INSTALL_ROOT}\n  -DJEMALLOC_STATIC_LIBRARIES=${INSTALL_ROOT}/lib/libjemalloc_pic.a\n  -DCUB_INCLUDE_DIR=${SOURCE_ROOT}/cub\n  -DINSTALL_ROOT=${INSTALL_ROOT}\n)\n\n# short-cut to dependencies build path\nset (BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build)\n\n# Boost\n# =====\n# - Use static linking to avoid issues with system-wide installations of Boost.\n# - Use numa=on to ensure the numa component of fiber gets built\nset(BOOST_COMPONENTS \"context,fiber,filesystem\")\nExternalProject_Add (boost\n  URL https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.tar.gz\n  URL_HASH SHA256=c66e88d5786f2ca4dbebb14e06b566fb642a1a6947ad8cc9091f9f445134143f\n  CONFIGURE_COMMAND ./bootstrap.sh --prefix=${INSTALL_ROOT} --with-libraries=${BOOST_COMPONENTS} numa=on\n  BUILD_COMMAND ./b2 link=static cxxflags=-fPIC cflags=-fPIC cxxflags=\"-std=c++14\" numa=on \n                     --build-dir=${BUILD_ROOT}/boost --stagedir=${BUILD_ROOT}/boost\n  BUILD_IN_SOURCE 1\n  INSTALL_COMMAND ./b2 install numa=on\n)\n\n# DLPack\n# ======\nExternalProject_Add(dlpack\n  GIT_REPOSITORY \"https://github.com/dmlc/dlpack.git\"\n  GIT_TAG \"master\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n)\n\n\n# gflags\n# ======\n# config, build and install to INSTALL_ROOT\nExternalProject_Add(gflags\n  GIT_REPOSITORY \"https://github.com/gflags/gflags.git\"\n  GIT_TAG \"v2.2.2\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DBUILD_SHARED_LIBS=ON\n             -DBUILD_STATIC_LIBS=ON\n             -DBUILD_PACKAGING=OFF\n             -DBUILD_TESTING=OFF\n             -DBUILD_CONFIG_TESTS=OFF\n             -DINSTALL_HEADERS=ON\n             -DBUILD_gflags_LIB=OFF\n             -DBUILD_gflags_nothreads_LIB=ON\n             -DGFLAGS_NAMESPACE=google\n)\n\n# glog\n# ====\n# - link against shared \n# - todo: compile with -DWITH_GFLAGS=OFF and remove gflags dependency\nExternalProject_Add(glog\n  DEPENDS gflags\n  GIT_REPOSITORY \"https://github.com/google/glog\"\n  GIT_TAG \"v0.4.0\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DCMAKE_BUILD_TYPE=Release\n             -DBUILD_TESTING=OFF\n)\n\n# google benchmark\n# ================\nExternalProject_Add(benchmark\n  DEPENDS \n  GIT_REPOSITORY    https://github.com/google/benchmark.git\n  GIT_TAG           \"v1.5.0\"\n  BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build/benchmark\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DCMAKE_BUILD_TYPE=Release\n             -DBENCHMARK_ENABLE_TESTING=OFF\n)\n\n# google test\n# ===========\nExternalProject_Add(googletest\n  DEPENDS glog gflags\n  GIT_REPOSITORY    https://github.com/google/googletest.git\n  GIT_TAG           \"release-1.10.0\"\n  BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build/googletest\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DCMAKE_BUILD_TYPE=Release\n)\n\n# cpuaff\n# ======\nExternalProject_Add(cpuaff\n  URL http://dcdillon.github.io/cpuaff/releases/cpuaff-1.0.6.tar.gz\n  CONFIGURE_COMMAND ./configure --prefix=${INSTALL_ROOT}\n  BUILD_COMMAND     make include\n  INSTALL_COMMAND   make install include\n  BUILD_IN_SOURCE 1\n)\n\n# nvidia cub\n# ==========\nExternalProject_Add(cub\n  GIT_REPOSITORY    https://github.com/NVlabs/cub.git \n  GIT_TAG           \"1.8.0\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND \"\"\n  INSTALL_COMMAND \"\"\n  TEST_COMMAND \"\"\n)\n\n# jemalloc\n# ========\nExternalProject_Add(jemalloc\n  URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2\n  CONFIGURE_COMMAND ./configure --prefix=${INSTALL_ROOT}\n  BUILD_COMMAND     make include\n  INSTALL_COMMAND   make install include\n  BUILD_IN_SOURCE 1\n)\n\n# cnpy - c++ library for reading and writing .npy/.npz files\n# ==========================================================\nExternalProject_Add(cnpy\n  GIT_REPOSITORY \"https://github.com/rogersce/cnpy.git\"\n  GIT_TAG \"master\"\n  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DCMAKE_BUILD_TYPE=Release\n             -DBUILD_TESTING=OFF\n             -DCMAKE_POSITION_INDEPENDENT_CODEL=ON\n)\n\n# grpc-repo\n# =========\nExternalProject_Add(grpc-repo\n  GIT_REPOSITORY \"https://github.com/grpc/grpc.git\"\n  GIT_TAG \"v1.32.0\"\n  GIT_SUBMODULES \"third_party/cares/cares\" \"third_party/protobuf\" \"third_party/abseil-cpp\" \"third_party/re2\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND \"\"\n  INSTALL_COMMAND \"\"\n  TEST_COMMAND \"\"\n)\n\n#\n# Build protobuf project from grpc-repo\n#\nExternalProject_Add(absl\n  SOURCE_DIR \"${SOURCE_ROOT}/grpc-repo/third_party/abseil-cpp\"\n  DOWNLOAD_COMMAND \"\"\n  CMAKE_CACHE_ARGS\n        -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=TRUE\n        -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_ROOT}\n  DEPENDS grpc-repo\n)\n\nExternalProject_Add(re2\n  SOURCE_DIR \"${SOURCE_ROOT}/grpc-repo/third_party/re2\"\n  DOWNLOAD_COMMAND \"\"\n  CMAKE_CACHE_ARGS\n        -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=TRUE\n        -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_ROOT}\n  DEPENDS grpc-repo\n)\n\nExternalProject_Add(protobuf\n  SOURCE_DIR \"${SOURCE_ROOT}/grpc-repo/third_party/protobuf/cmake\"\n  DOWNLOAD_COMMAND \"\"\n  CMAKE_ARGS\n    -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON\n    -Dprotobuf_BUILD_TESTS:BOOL=OFF\n    -Dprotobuf_WITH_ZLIB:BOOL=OFF\n    -Dprotobuf_MSVC_STATIC_RUNTIME:BOOL=OFF\n    -DCMAKE_BUILD_TYPE=Release\n    -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_ROOT}\n  DEPENDS grpc-repo\n)\n\n# Location where protobuf-config.cmake will be installed varies by\n# platform\nif (WIN32)\n  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR \"${CMAKE_CURRENT_BINARY_DIR}/protobuf/cmake\")\nelse()\n  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR \"${INSTALL_ROOT}/lib/cmake\")\nendif()\n\n#\n# Build c-area project from grpc-repo\n#\nExternalProject_Add(c-ares\n  SOURCE_DIR \"${SOURCE_ROOT}/grpc-repo/third_party/cares/cares\"\n  DOWNLOAD_COMMAND \"\"\n  CMAKE_ARGS\n    -DCARES_SHARED:BOOL=OFF\n    -DCARES_STATIC:BOOL=ON\n    -DCARES_STATIC_PIC:BOOL=ON\n    -DCMAKE_BUILD_TYPE=Release\n    -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_ROOT}\n  DEPENDS grpc-repo\n)\n\n\n#\n# Build GRPC\n#\nExternalProject_Add(grpc\n  SOURCE_DIR \"${SOURCE_ROOT}/grpc-repo\"\n  DOWNLOAD_COMMAND \"\"\n  CMAKE_ARGS\n    -DgRPC_INSTALL:BOOL=ON\n    -DgRPC_BUILD_TESTS:BOOL=OFF\n    -DgRPC_PROTOBUF_PROVIDER:STRING=package\n    -DgRPC_PROTOBUF_PACKAGE_TYPE:STRING=CONFIG\n    -DProtobuf_DIR:PATH=${INSTALL_ROOT}/lib/cmake\n    -DgRPC_ZLIB_PROVIDER:STRING=package\n    -DgRPC_CARES_PROVIDER:STRING=package\n    -Dc-ares_DIR:PATH=${INSTALL_ROOT}/lib/cmake\n    -DgRPC_SSL_PROVIDER:STRING=package\n    -DgRPC_GFLAGS_PROVIDER=package\n    -DgRPC_BENCHMARK_PROVIDER=package\n    -DgRPC_RE2_PROVIDER:STRING=package\n    -Dre2_DIR:STRING=${INSTALL_ROOT}/lib/cmake\n    -DgRPC_ABSL_PROVIDER:STRING=package\n    -Dabsl_DIR:STRING=${INSTALL_ROOT}/lib/cmake\n    ${_CMAKE_ARGS_OPENSSL_ROOT_DIR}\n    -DCMAKE_BUILD_TYPE=Release\n    -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_ROOT}\n  DEPENDS grpc-repo c-ares protobuf re2 absl gflags benchmark\n)\n\n\n\n# trtlab\n# ======\nExternalProject_Add (trtlab\n  DEPENDS ${DEPENDENCIES}\n  SOURCE_DIR ${PROJECT_SOURCE_DIR}\n  CMAKE_ARGS -DBUILD_DEPENDENCIES=OFF ${EXTRA_CMAKE_ARGS}\n  INSTALL_COMMAND \"\"\n  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})"
  },
  {
    "path": "devel.sh",
    "content": "#!/bin/bash\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nmodels_path=${TRT_MODELS_PATH:-\"/path/to/my/models\"}\nmodels_cli=\"\"\nif [ -d \"$models_path\" ]; then\n  models_cli=\" -v $(realpath $models_path):/work/models \"\nfi\n\ncrt=\"\"\nif [ -x \"$(which luda)\" ] ; then\n    echo \"Using luda\"\n    crt=\"$(which luda) --no-home\"\nelif [ -x \"$(which nvidia-docker)\" ]; then\n    echo \"Using nvidia-docker\"\n    crt=\"nvidia-docker run --rm -ti\"\nelse\n    echo \"No GPU container runtime found\"\n    exit 911\nfi\nNV_GPU=0 $crt -v $PWD:/work $models_cli --workdir /work --name trtlab --net host trtlab\n"
  },
  {
    "path": "examples/00_TensorRT/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ninclude_directories(${CUDA_INCLUDE_DIRS})\ninclude_directories(${TensorRT_INCLUDE_DIRS})\n\n\n\nadd_executable(inference.x\n    inference.cc\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS})\n\ntarget_link_libraries(inference.x\n    trtlab::nvrpc\n    trtlab::tensorrt\n    gflags\n)\n\nadd_executable(infer.x\n    infer.cc\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS})\n\ntarget_link_libraries(infer.x\n    trtlab::nvrpc\n    trtlab::tensorrt\n    gflags\n)\n\nif(YAIS_ENABLE_MPI)\nfind_package(MPI)\ninclude_directories(SYSTEM ${MPI_INCLUDE_PATH})\ntarget_link_libraries(inference.x\n    ${MPI_C_LIBRARIES}\n    ${MPI_CXX_LIBRARIES}\n)\ntarget_compile_definitions(inference.x PUBLIC PLAYGROUND_USE_MPI)\nendif()\n"
  },
  {
    "path": "examples/00_TensorRT/README.md",
    "content": "# Inference Example\n\nBasic CLI tool for executing TensorRT engines.\n\nProvide an engine and `inference.x` will run a simplifed inference pipeline using synthetic data.\n\nThe program will run a pipelined H2D -> TensorRT -> D2H calculation for `--seconds` (default: 5) with a\n0.1 second warmup run. By default, only 1 TensorRT Execution Context is used to perform the evaulation.\nYou can modify the number of contexts using the `--contexts`. Unless provided, the number of Input/Output\nBuffers is set to `(2 * contexts)`.  See below for the list of [options](#options).\n\nThe `inference.x` program is fully pipelined and asynchronous.  It performs uses three threads (default)\nto: 1) async copy input H2D, 2) launch the async inference evaluation and return output tensor to the host,\nand 3) to wait on the resouces used during execution and release them when finished.  This final thread is\nwhere one might build a return message or do something else with the results.\n\nWhile running `inference.x`, you may find it useful to monitor GPU metrics using:\n```\nnvidia-smi dmon -i 0 -s put\n```\n\nNote: If you see numbers that differ from the output of `giexec`, you may have an IO bottleneck in that \nthe transfers are more expensive than the compute.\n\n * TODO: Update the program to output avg xfer time.\n * TODO: Build .engine files as part of the build\n\n## Quickstart\n\n```\nroot@dgx:/work/build/examples/00_TensorRT# ./inference.x --engine=/work/models/ResNet-50-b1-int8.engine\nI0702 22:16:51.868419 10857 TensorRT.cc:561] -- Initialzing TensorRT Resource Manager --\nI0702 22:16:51.868676 10857 TensorRT.cc:562] Maximum Execution Concurrency: 1\nI0702 22:16:51.868686 10857 TensorRT.cc:563] Maximum Copy Concurrency: 2\nI0702 22:16:53.430330 10857 TensorRT.cc:628] -- Registering Model: 0 --\nI0702 22:16:53.430399 10857 TensorRT.cc:629] Input/Output Tensors require 591.9 KiB\nI0702 22:16:53.430415 10857 TensorRT.cc:630] Execution Activations require 2.5 MiB\nI0702 22:16:53.430428 10857 TensorRT.cc:633] Weights require 30.7 MiB\nI0702 22:16:53.437571 10857 TensorRT.cc:652] -- Allocating TensorRT Resources --\nI0702 22:16:53.437587 10857 TensorRT.cc:653] Creating 1 TensorRT execution tokens.\nI0702 22:16:53.437595 10857 TensorRT.cc:654] Creating a Pool of 2 Host/Device Memory Stacks\nI0702 22:16:53.437607 10857 TensorRT.cc:655] Each Host Stack contains 608.0 KiB\nI0702 22:16:53.437614 10857 TensorRT.cc:656] Each Device Stack contains 3.2 MiB\nI0702 22:16:53.437623 10857 TensorRT.cc:657] Total GPU Memory: 6.5 MiB\nI0702 22:16:53.540400 10857 inference.cc:93] -- Inference: Running for ~5 seconds with batch_size 1 --\nI0702 22:16:58.543475 10857 inference.cc:131] Inference Results: 4770 batches in 5.00307 seconds; sec/batch: 0.00104886; inf/sec: 953.414\n```\n\n## Options\n```\n    -buffers (Number of Buffers (default: 2x contexts)) type: int32 default: 0\n    -contexts (Number of Execution Contexts) type: int32 default: 1\n    -cudathreads (Number Cuda Launcher Threads) type: int32 default: 1\n    -engine (TensorRT serialized engine) type: string\n      default: \"/work/models/trt4.engine\"\n    -respthreads (Number Response Sync Threads) type: int32 default: 1\n    -seconds (Number of Execution Contexts) type: int32 default: 5\n```\n\n\n"
  },
  {
    "path": "examples/00_TensorRT/infer.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n#include \"tensorrt/laboratory/infer_bench.h\"\n#include \"tensorrt/laboratory/inference_manager.h\"\n#include \"tensorrt/laboratory/model.h\"\n#include \"tensorrt/laboratory/runtime.h\"\n\n#ifdef PLAYGROUND_USE_MPI\n#include \"mpi.h\"\n#define MPI_CHECK(mpicall) mpicall\n#else\n#define MPI_CHECK(mpicall)\n#endif\n\nusing trtlab::ThreadPool;\nusing trtlab::TensorRT::InferBench;\nusing trtlab::TensorRT::InferBenchKey;\nusing trtlab::TensorRT::InferenceManager;\nusing trtlab::TensorRT::ManagedRuntime;\nusing trtlab::TensorRT::Model;\nusing trtlab::TensorRT::Runtime;\nusing trtlab::TensorRT::StandardRuntime;\n\nstatic std::string ModelName(int model_id)\n{\n    std::ostringstream stream;\n    stream << model_id;\n    return stream.str();\n}\n\nstatic bool ValidateEngine(const char* flagname, const std::string& value)\n{\n    struct stat buffer;\n    return (stat(value.c_str(), &buffer) == 0);\n}\n\nDEFINE_string(engine, \"/path/to/tensorrt.engine\", \"TensorRT serialized engine\");\nDEFINE_validator(engine, &ValidateEngine);\nDEFINE_string(runtime, \"default\", \"TensorRT Runtime\");\nDEFINE_int32(seconds, 5, \"Approximate number of seconds for the timing loop\");\nDEFINE_int32(contexts, 1, \"Number of Execution Contexts\");\nDEFINE_int32(buffers, 0, \"Number of Buffers (default: 2x contexts)\");\nDEFINE_int32(cudathreads, 1, \"Number Cuda Launcher Threads\");\nDEFINE_int32(respthreads, 1, \"Number Response Sync Threads\");\nDEFINE_int32(replicas, 1, \"Number of Replicas of the Model to load\");\nDEFINE_int32(batch_size, 0, \"Overrides the max batch_size of the provided engine\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"TensorRT Inference\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    MPI_CHECK(MPI_Init(&argc, &argv));\n\n    auto contexts = FLAGS_contexts;\n    auto buffers = FLAGS_buffers ? FLAGS_buffers : 2 * FLAGS_contexts;\n\n    auto resources = std::make_shared<InferenceManager>(contexts, buffers);\n    resources->RegisterThreadPool(\"pre\", std::make_unique<ThreadPool>(1));\n    resources->RegisterThreadPool(\"cuda\", std::make_unique<ThreadPool>(1));\n    resources->RegisterThreadPool(\"post\", std::make_unique<ThreadPool>(3));\n\n    //, FLAGS_cudathreads, FLAGS_respthreads);\n    std::shared_ptr<Runtime> runtime;\n    if(FLAGS_runtime == \"default\")\n    {\n        runtime = std::make_shared<StandardRuntime>();\n    }\n    else if(FLAGS_runtime == \"unified\")\n    {\n        runtime = std::make_shared<ManagedRuntime>();\n    }\n    else\n    {\n        LOG(FATAL) << \"Invalid TensorRT Runtime\";\n    }\n\n    std::vector<std::shared_ptr<Model>> models;\n\n    models.push_back(runtime->DeserializeEngine(FLAGS_engine));\n    resources->RegisterModel(\"0\", models.back());\n    resources->AllocateResources();\n\n    auto batch_size = FLAGS_batch_size ? FLAGS_batch_size : models.back()->GetMaxBatchSize();\n\n    for(int i = 1; i < FLAGS_replicas; i++)\n    {\n        models.push_back(runtime->DeserializeEngine(FLAGS_engine));\n        resources->RegisterModel(ModelName(i), models.back());\n    }\n\n    {\n        InferBench benchmark(resources);\n        benchmark.Run(models, batch_size, 0.1);\n\n        // if testing mps - sync all processes before executing timed loop\n        MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD));\n        auto results = benchmark.Run(models, batch_size, FLAGS_seconds);\n        MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD));\n        // todo: perform an mpi_allreduce to collect the per process timings\n        //       for a simplified report\n        MPI_CHECK(MPI_Finalize());\n\n        using namespace trtlab::TensorRT;\n        LOG(INFO) << \"Inference Results: \" << (*results)[kBatchesComputed]\n                  << \" batches computed in \" << (*results)[kWalltime] << \" seconds on \"\n                  << (*results)[kMaxExecConcurrency]\n                  << \" compute streams using batch_size: \" << (*results)[kBatchSize]\n                  << \"; inf/sec: \" << (*results)[kInferencesPerSecond]\n                  << \"; batches/sec: \" << (*results)[kBatchesPerSecond]\n                  << \"; execution time per batch: \" << (*results)[kExecutionTimePerBatch];\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/00_TensorRT/inference.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n#include \"tensorrt/laboratory/inference_manager.h\"\n#include \"tensorrt/laboratory/runtime.h\"\n\n#ifdef PLAYGROUND_USE_MPI\n#include \"mpi.h\"\n#define MPI_CHECK(mpicall) mpicall\n#else\n#define MPI_CHECK(mpicall)\n#endif\n\nusing trtlab::ThreadPool;\nusing trtlab::TensorRT::CustomRuntime;\nusing trtlab::TensorRT::InferenceManager;\nusing trtlab::TensorRT::ManagedAllocator;\nusing trtlab::TensorRT::Runtime;\nusing trtlab::TensorRT::StandardAllocator;\n\nstatic int g_Concurrency = 0;\n\nstatic std::string ModelName(int model_id)\n{\n    std::ostringstream stream;\n    stream << model_id;\n    return stream.str();\n}\n\nclass InferenceResources : public InferenceManager\n{\n  public:\n    InferenceResources(int max_executions, int max_buffers, size_t nCuda, size_t nResp)\n        : InferenceManager(max_executions, max_buffers),\n          m_CudaThreadPool(std::make_unique<ThreadPool>(nCuda)),\n          m_ResponseThreadPool(std::make_unique<ThreadPool>(nResp))\n    {\n    }\n\n    ~InferenceResources() override {}\n\n    std::unique_ptr<ThreadPool>& GetCudaThreadPool() { return m_CudaThreadPool; }\n    std::unique_ptr<ThreadPool>& GetResponseThreadPool() { return m_ResponseThreadPool; }\n\n  private:\n    std::unique_ptr<ThreadPool> m_CudaThreadPool;\n    std::unique_ptr<ThreadPool> m_ResponseThreadPool;\n};\n\nclass Inference final\n{\n  public:\n    Inference(std::shared_ptr<InferenceResources> resources) : m_Resources(resources) {}\n\n    void Run(float seconds, bool warmup, int replicas, uint32_t requested_batch_size)\n    {\n        int replica = 0;\n        uint64_t inf_count = 0;\n\n        auto start = std::chrono::steady_clock::now();\n        auto elapsed = [start]() -> float {\n            return std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n        };\n\n        auto model = GetResources()->GetModel(ModelName(replica++));\n        auto batch_size = requested_batch_size ? requested_batch_size : model->GetMaxBatchSize();\n        if(batch_size > model->GetMaxBatchSize())\n        {\n            LOG(FATAL)\n                << \"Requested batch_size greater than allowed by the compiled TensorRT Engine\";\n        }\n\n        // Inference Loop - Main thread copies, cuda thread launches, response thread completes\n        if(!warmup)\n        {\n            LOG(INFO) << \"-- Inference: Running for ~\" << (int)seconds\n                      << \" seconds with batch_size \" << batch_size << \" --\";\n        }\n\n        std::vector<std::future<void>> futures;\n\n        while(elapsed() < seconds && ++inf_count)\n        {\n            if(replica >= replicas) replica = 0;\n\n            // This thread only async copies buffers H2D\n            auto model = GetResources()->GetModel(ModelName(replica++));\n            auto buffers = GetResources()->GetBuffers(); // <=== Limited Resource; May Block !!!\n            auto bindings = buffers->CreateBindings(model);\n            auto promise = std::make_shared<std::promise<void>>();\n            futures.push_back(promise->get_future());\n\n            bindings->SetBatchSize(batch_size);\n            bindings->CopyToDevice(bindings->InputBindings());\n\n            GetResources()->GetCudaThreadPool()->enqueue([this, bindings, promise]() mutable {\n                // This thread enqueues two async kernels:\n                //  1) TensorRT execution\n                //  2) D2H of output tensors\n                auto trt = GetResources()->GetExecutionContext(\n                    bindings->GetModel()); // <=== Limited Resource; May Block !!!\n                trt->Infer(bindings);\n                bindings->CopyFromDevice(bindings->OutputBindings());\n\n                GetResources()->GetResponseThreadPool()->enqueue(\n                    [bindings, trt, promise]() mutable {\n                        // This thread waits on the completion of the async compute and the async\n                        // copy\n                        trt->Synchronize();\n                        trt.reset(); // Finished with the Execution Context - Release it to\n                                     // competing threads\n                        bindings->Synchronize();\n                        bindings.reset(); // Finished with Buffers - Release it to competing threads\n                        promise->set_value();\n                    });\n            });\n        }\n\n        for(const auto& f : futures)\n        {\n            f.wait();\n        }\n\n        /*\n                // Join worker threads\n                if (!warmup)\n                    GetResources()->GetCudaThreadPool().reset();\n                if (!warmup)\n                    GetResources()->GetResponseThreadPool().reset();\n        */\n        // End timing and report\n        auto total_time = std::chrono::duration<float>(elapsed()).count();\n        auto inferences = inf_count * batch_size;\n        if(!warmup)\n            LOG(INFO) << \"Inference Results: \" << inf_count << \"; batches in \" << total_time\n                      << \" seconds\"\n                      << \"; sec/batch/stream: \" << total_time / (inf_count / g_Concurrency)\n                      << \"; batches/sec: \" << inf_count / total_time\n                      << \"; inf/sec: \" << inferences / total_time;\n    }\n\n  protected:\n    inline std::shared_ptr<InferenceResources> GetResources() { return m_Resources; }\n\n  private:\n    std::shared_ptr<InferenceResources> m_Resources;\n};\n\nstatic bool ValidateEngine(const char* flagname, const std::string& value)\n{\n    struct stat buffer;\n    return (stat(value.c_str(), &buffer) == 0);\n}\n\nDEFINE_string(engine, \"/path/to/tensorrt.engine\", \"TensorRT serialized engine\");\nDEFINE_validator(engine, &ValidateEngine);\nDEFINE_string(runtime, \"default\", \"TensorRT Runtime\");\nDEFINE_int32(seconds, 5, \"Approximate number of seconds for the timing loop\");\nDEFINE_int32(contexts, 1, \"Number of Execution Contexts\");\nDEFINE_int32(buffers, 0, \"Number of Buffers (default: 2x contexts)\");\nDEFINE_int32(cudathreads, 1, \"Number Cuda Launcher Threads\");\nDEFINE_int32(respthreads, 1, \"Number Response Sync Threads\");\nDEFINE_int32(replicas, 1, \"Number of Replicas of the Model to load\");\nDEFINE_int32(batch_size, 0, \"Overrides the max batch_size of the provided engine\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"TensorRT Inference\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    MPI_CHECK(MPI_Init(&argc, &argv));\n\n    auto contexts = g_Concurrency = FLAGS_contexts;\n    auto buffers = FLAGS_buffers ? FLAGS_buffers : 2 * FLAGS_contexts;\n\n    auto resources = std::make_shared<InferenceResources>(contexts, buffers, FLAGS_cudathreads,\n                                                          FLAGS_respthreads);\n\n    std::shared_ptr<Runtime> runtime;\n    if(FLAGS_runtime == \"default\")\n    {\n        runtime = std::make_shared<CustomRuntime<StandardAllocator>>();\n    }\n    else if(FLAGS_runtime == \"unified\")\n    {\n        runtime = std::make_shared<CustomRuntime<ManagedAllocator>>();\n    }\n    else\n    {\n        LOG(FATAL) << \"Invalid TensorRT Runtime\";\n    }\n\n    resources->RegisterModel(\"0\", runtime->DeserializeEngine(FLAGS_engine));\n    resources->AllocateResources();\n\n    for(int i = 1; i < FLAGS_replicas; i++)\n    {\n        resources->RegisterModel(ModelName(i), runtime->DeserializeEngine(FLAGS_engine));\n    }\n\n    Inference inference(resources);\n    inference.Run(0.1, true, 1, 0); // warmup\n\n    // if testing mps - sync all processes before executing timed loop\n    MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD));\n    inference.Run(FLAGS_seconds, false, FLAGS_replicas, FLAGS_batch_size);\n    MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD));\n\n    // todo: perform an mpi_allreduce to collect the per process timings\n    //       for a simplified report\n    MPI_CHECK(MPI_Finalize());\n    return 0;\n}\n"
  },
  {
    "path": "examples/01_Basic_GRPC/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(echo-grpc.x\n    src/server.cpp)\n\ntarget_link_libraries(echo-grpc.x\n    nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(echo-client.x\n    src/client.cpp)\n\ntarget_link_libraries(echo-client.x\n    nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(async-echo-client.x\n    src/async_client.cc)\n\ntarget_link_libraries(async-echo-client.x\n    nvrpc\n    nvrpc-client\n    echo-protos\n    gflags\n)"
  },
  {
    "path": "examples/01_Basic_GRPC/README.md",
    "content": "Simple service to test and stress the core service and request logic.\n\nThe [`server.cc`](examples/01_Basic_GRPC/server.cc) is very well documented and\nshould be used a reference for the gRPC interface provided by the library.\n\n\n"
  },
  {
    "path": "examples/01_Basic_GRPC/src/async_client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"nvrpc/client/client_unary.h\"\n#include \"nvrpc/client/executor.h\"\n\n#include \"echo.grpc.pb.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\nusing simple::Inference;\nusing simple::Input;\nusing simple::Output;\n\nusing nvrpc::client::ClientUnary;\nusing nvrpc::client::Executor;\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    auto executor = std::make_shared<Executor>(FLAGS_thread_count);\n\n    auto channel = grpc::CreateChannel(\"localhost:50051\", grpc::InsecureChannelCredentials());\n    auto stub = Inference::NewStub(channel);\n\n    auto infer_prepare_fn = [&stub](::grpc::ClientContext * context, const ::simple::Input& request,\n                                    ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncCompute(context, request, cq));\n    };\n\n    auto runner = std::make_unique<ClientUnary<Input, Output>>(infer_prepare_fn, executor);\n\n    auto start = std::chrono::steady_clock::now();\n    auto elapsed = [start]() -> float {\n        return std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n    };\n\n    for(int i = 0; i < FLAGS_count; i++)\n    {\n        Input input;\n        input.set_batch_id(i);\n        runner->Enqueue(std::move(input),\n                        [i](Input& input, Output& output, ::grpc::Status& status) -> bool {\n                            CHECK(output.batch_id() == i);\n                            LOG_FIRST_N(INFO, 20) << \"Check: \" << i;\n                            return (bool)(output.batch_id() == i);\n                        });\n    }\n    std::cout << FLAGS_count << \" queued in \" << elapsed() << \"seconds\" << std::endl;\n    executor->ShutdownAndJoin();\n    std::cout << FLAGS_count << \" completed in \" << elapsed() << \"seconds\" << std::endl;\n    return 0;\n}"
  },
  {
    "path": "examples/01_Basic_GRPC/src/client.cpp",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <iostream>\n#include <memory>\n#include <string>\n#include <chrono>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"echo.grpc.pb.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\nusing simple::Input;\nusing simple::Output;\nusing simple::Inference;\n\nclass SimpleClient {\n public:\n  SimpleClient(std::shared_ptr<Channel> channel)\n      : stub_(Inference::NewStub(channel)) {}\n\n  // Assembles the client's payload, sends it and presents the response back\n  // from the server.\n  int Compute(const int batch_id) {\n    // Data we are sending to the server.\n    Input request;\n    request.set_batch_id(batch_id);\n\n    // Container for the data we expect from the server.\n    Output reply;\n\n    // Context for the client. It could be used to convey extra information to\n    // the server and/or tweak certain RPC behaviors.\n    ClientContext context;\n\n    // The actual RPC.\n    Status status = stub_->Compute(&context, request, &reply);\n\n    // Act upon its status.\n    if (status.ok()) {\n      return reply.batch_id();\n    } else {\n      std::cout << status.error_code() << \": \" << status.error_message()\n                << std::endl;\n      return -1;\n    }\n  }\n\n private:\n  std::unique_ptr<Inference::Stub> stub_;\n};\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\n\nint main(int argc, char** argv) {\n  // Instantiate the client. It requires a channel, out of which the actual RPCs\n  // are created. This channel models a connection to an endpoint (in this case,\n  // localhost at port 50051). We indicate that the channel isn't authenticated\n  // (use of InsecureChannelCredentials()).\n  FLAGS_alsologtostderr = 1; // It will dump to console\n   ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n  SimpleClient client(grpc::CreateChannel(\n      \"localhost:50051\", grpc::InsecureChannelCredentials()));\n  auto start = std::chrono::steady_clock::now();\n  for(int i=0; i<FLAGS_count; i++) {\n      auto reply = client.Compute(i);\n      if(reply == -1 || reply != i) std::cout << \"BatchId received: \" << reply << std::endl;\n  }\n  auto end = std::chrono::steady_clock::now();\n  float elapsed = std::chrono::duration<float>(end - start).count();\n  std::cout << FLAGS_count << \" requests in \" << elapsed << \"seconds\" << std::endl;\n  return 0;\n}\n"
  },
  {
    "path": "examples/01_Basic_GRPC/src/server.cpp",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <chrono>\n#include <thread>\n\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n#include \"nvrpc/executor.h\"\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\n#include \"echo.pb.h\"\n#include \"echo.grpc.pb.h\"\n\nusing nvrpc::AsyncService;\nusing nvrpc::AsyncRPC;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\n/**\n * Embedding a copy of the Protobuf specification for the gRPC service.\n *\n * Package Name: simple\n * Service Name: Inference\n *     RPC Name: Compute\n * \n * Incoming Message: Input\n * Outgoing Message: Ouput\n **\n\nsyntax = \"proto3\";\n\npackage simple;\n\nservice Inference {\n   rpc Compute (Input) returns (Output) {}\n}\n\nmessage Input {\n    uint64 batch_id = 1;\n}\n\nmessage Output {\n    uint64 batch_id = 1;\n}\n*/\n\n// Define the resources your RPC will need to execute\n// ==================================================\n// In this case, all simple::Inference::Compute RPCs share a threadpool in which they will\n// queue up some work on.  This essentially means, after the message as been received and\n// processed, the actual work for the RPC is pushed to a worker pool outside the scope of\n// the transaction processing system (TPS).  This is essentially async computing, we have \n// decoupled the transaction from the workers executing the implementation.  The TPS can\n// continue to queue work, while the workers process the load.\nstruct SimpleResources : public Resources\n{\n    SimpleResources(int numThreadsInPool=3) : m_ThreadPool(numThreadsInPool) {\n        LOG(INFO) << \"Server ThreadCount: \" << numThreadsInPool;\n    }\n\n    ThreadPool& AcquireThreadPool()\n    {\n        return m_ThreadPool;\n    }\n\n  private:\n    ThreadPool m_ThreadPool;\n};\n\n// Contexts hold the state and provide the definition of the work to be performed by the RPC.\n// This is where you define what gets executed for a given RPC.\n// Incoming Message = simple::Input (RequestType)\n// Outgoing Message = simple::Output (ResponseType)\nclass SimpleContext final : public Context<simple::Input, simple::Output, SimpleResources>\n{\n    void ExecuteRPC(RequestType &input, ResponseType &output) final override\n    {\n        // We could do work here, but we'd block the TPS, i.e. the threads pulling messages \n        // off the incoming recieve queue.  Very quick responses are best done here; however,\n        // longer running workload should be offloaded so the TPS can avoid being blocked.\n        GetResources()->AcquireThreadPool().enqueue([this, &input, &output]{\n            // Now running on a worker thread of the ThreadPool defined in SimpleResources.\n            // Here we are just echoing back the incoming // batch_id; however, in later \n            // examples, we'll show how to run an async cuda pipline.\n            LOG_FIRST_N(INFO, 20) << \"Tag = \" << Tag() << \" Thread = \" << std::this_thread::get_id();\n            output.set_batch_id(input.batch_id());\n            this->FinishResponse();\n        });\n        // The TPS thread is now free to continue processing message - async ftw!\n    }\n};\n\n\nint main(int argc, char *argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // A server will bind an IP:PORT to listen on\n    Server server(\"0.0.0.0:50051\");\n\n    // A server can host multiple services\n    LOG(INFO) << \"Register Service (simple::Inference) with Server\"; \n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n\n    // An RPC has two components that need to be specified when registering with the service:\n    //  1) Type of Execution Context (SimpleContext).  The execution context defines the behavor\n    //     of the RPC, i.e. it contains the control logic for the execution of the RPC.\n    //  2) The Request function (RequestCompute) which was generated by gRPC when compiling the\n    //     protobuf which defined the service.  This function is responsible for queuing the\n    //     RPC's execution context to the \n    LOG(INFO) << \"Register RPC (simple::Inference::Compute) with Service (simple::Inference)\";\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestCompute\n    );\n\n    LOG(INFO) << \"Initializing Resources for RPC (simple::Inference::Compute)\";\n    auto rpcResources = std::make_shared<SimpleResources>(FLAGS_thread_count);\n\n    // Create Executors - Executors provide the messaging processing resources for the RPCs\n    // Multiple Executors can be registered with a Server.  The executor is responsible\n    // for pulling incoming message off the receive queue and executing the associated\n    // context.  By default, an executor only uses a single thread.  A typical usecase is\n    // an Executor executes a context, which immediate pushes the work to a thread pool.\n    // However, for very low-latency messaging, you might want to use a multi-threaded \n    // Executor and a Blocking Context - meaning the Context performs the entire RPC function\n    // on the Executor's thread.\n    LOG(INFO) << \"Creating Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    // You can register RPC execution contexts from any registered RPC on any executor.\n    // The power of that will become clear in later examples. For now, we will register\n    // 10 instances of the simple::Inference::Compute RPC's SimpleContext execution context\n    // with the Executor.\n    LOG(INFO) << \"Creating Execution Contexts for RPC (simple::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), []{\n        // This is a timeout loop executed every 2seconds\n        // Run() with no arguments will run an empty timeout loop every 5 seconds.\n        // RunAsync() will return immediately, its your responsibility to ensure the\n        // server doesn't go out of scope or a Shutdown will be triggered on your services.\n    });\n}\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(prometheus-cpp CONFIG REQUIRED)\nif(prometheus-cpp_FOUND)\n  message(STATUS \"Prometheus Metics Enabled\")\nendif(prometheus-cpp_FOUND)\n\n\nadd_executable(inference-grpc.x\n    src/metrics.cc\n    src/server.cc\n)\ntarget_include_directories(inference-grpc.x\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n)\ntarget_link_libraries(inference-grpc.x\n    trtlab::nvrpc\n    trtlab::tensorrt\n    prometheus-cpp::prometheus-cpp\n    demo-protos\n    gflags\n)\n\nadd_executable(client-sync.x\n    src/sync-client.cc\n)\ntarget_link_libraries(client-sync.x\n    nvrpc\n    demo-protos\n    gflags\n)\n\nadd_executable(client-async.x\n    src/async-client.cc\n)\ntarget_link_libraries(client-async.x\n    nvrpc\n    demo-protos\n    gflags\n)\n\nadd_executable(siege.x\n    src/siege.cc\n)\ntarget_link_libraries(siege.x\n    nvrpc\n    demo-protos\n    gflags\n)\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/README.md",
    "content": "# TensorRT GRPC Example\n\nThis examples extends the [TensorRT](examples/00_TensorRT) compute loop into an\nasync gRPC service similar to [example 01_gRPC](examples/01_GRPC).\n\nThere are three take-aways from this example:\n\n1. TensorRT compute pipeline is implemented as the `ExecuteRPC` virtual function\n   of the `Context`.\n2. An external datasource is used to override the input bindings\n3. Custom [Prometheus](https://prometheus.io) metrics for inference compute and\n     request durations, load ratio, and GPU power gauge.\n     are recorded/observed.\n\n## Quickstart\n\n```\ncd /work/build/examples/02_TensorRT_GRPC\n./inference-grpc.x --contexts=8 --engine=/work/models/ResNet-50-b1-int8.engine --port 50051 &\n./siege.x --port=50051 --rate=2500\n# ctrl+c to cancel client\ntelegraf -test -config /work/examples/91_Prometheus/scrape.conf\n```\n\n## Explore\n\nFun things to try:\n\n  * Evaluate the performance of the model using `inference.x` in \n    [examples/00_TensorRT](examples/00_TensorRT)\n  * Try running `siege.x` below, at, and above the benchmarked rate and watch the metrics\n    via `telegraf`.\n  * Deploy on Kubernetes, collect metrics via Prometheus and visualize using Grafana;\n    [examples/90_Kubernetes](examples/90_Kubernetes).\n\n## Server/Service\n\n`inference-grpc.x` CLI options:\n\n  * `--engine` - the compiled TensorRT plan/engine\n  * `--contexts` - the maximium number of concurrent evaluations of the engine.\n  * `--port` - the port on which requests are received (default: 50051)\n  * `--metrics` - the port on which to expose metrics to be scraped (default: 50078)\n\n\n## Clients\n\nThree clients are available:\n  * `client-sync.x` - sends a blocking inference request to the service and waits for the\n     response.  Only 1 request is ever in-flight at a given time.\n  * `client-async.x` - the async client is capable of issuing multiple in-flight requests.\n     Note: the load-balancer is limited to 1000 outstanding requests per client before circuit-\n     breaking.  Running more than 1000 requests will trigger 503 if targeting the envoy load-\n     balancer.  The client has no backoff and will try to send the full compliment of requested\n     inference requests.  `siege.x` is the better async client.\n  * `siege.x` - constant rate (`--rate`) async engine that is hard-coded to have no more than\n     950 outstanding in-flight requests.  A warning will be given client-side if the outstanding\n     requests tops meaning the rate is limited by the server-side compute.\n\nTODO:\n  * Add more varied test clients akin to [Netflix's Chaos Monkeys](https://github.com/Netflix/chaosmonkey),\n    but for gRPC client behavior.\n    * Random rate, random pulses, canceled messsages, messages wiht unreasonable timeouts, etc.\n\n## Metrics\n\nYAIS metrics are gathered and exposed via the [prometheus-cpp](https://github.com/jupp0r/prometheus-cpp) \nclient library.  In this example, we expose four custom \n[metrics](https://prometheus.io/docs/concepts/metric_types/): 2 Summaries, 1 Histogram and 1 Gauge.\n\n  * `compute_duration` and `request_duration` are summaries recored with the model\n     name as a component of the metric.  This is useful for evaluating how a given\n     model is performing, but this is not a good metric to aggregate across multiple\n     service.\n  * `load_ratio` is a histogram of `request_duraton / compute_duration`.  Ideally, this\n     unitless value is just over 1.0.  Values higher than 1.0 are indictive of some\n     delays in the compute of a given request. Sources of delays include, overloaded\n     queues and/or starvation of resources. Histograms can be aggregated across services,\n     which makes this metric a good candidate for triggering auto-scaling.\n  * `gpu_power` is a simple gauge that periodicly reports the instaneous power being\n    consumed by the device.  As the load increases on the service, the power should \n    increase proprotionally, until the power is capped either by device limits or compute \n    resources. When power capped, the `load_ratio` will begin to increase under futher \n    increases in traffic.\n\n\n### Acquiring Metrics\n\nPrometheus metrics are generally scraped by a Prometheus service.  When using Kubernetes\nto deploy services, the [prometheus-operator](https://github.com/coreos/prometheus-operator)\nprovides a [`ServiceMonitor`](https://github.com/coreos/prometheus-operator#customresourcedefinitions)\nwhich allows you to define custom scraping configuration per service. See the \n[Kubernetes example](examples/90_Kubernetes) for more details.\n\nWhile testing, you can use the [`telegraf`](https://github.com/influxdata/telegraf) application\nto scrape local services.\n\n```\n# start service\ntelegraf -test -config /work/examples/91_Prometheus/scrape.conf\n```\n\nHere is some sample output (line breaks added for readability):\n```\n> yais_inference_compute_duration_ms,host=dgx,model=flowers,url=http://localhost:50078/metrics count=1000,sum=2554.070996 1530985302000000000\n\n> yais_inference_compute_duration_ms_quantile,host=dgx,model=flowers,quantile=0.500000,url=http://localhost:50078/metrics value=2.526903 1530985302000000000\n> yais_inference_compute_duration_ms_quantile,host=dgx,model=flowers,quantile=0.900000,url=http://localhost:50078/metrics value=2.625447 1530985302000000000\n> yais_inference_compute_duration_ms_quantile,host=dgx,model=flowers,quantile=0.990000,url=http://localhost:50078/metrics value=2.855728 1530985302000000000\n\n> yais_inference_request_duration_ms,host=dgx,model=flowers,url=http://localhost:50078/metrics count=1000,sum=243547.558097 1530985302000000000\n> yais_inference_request_duration_ms_quantile,host=dgx,model=flowers,quantile=0.500000,url=http://localhost:50078/metrics value=253.216653 1530985302000000000\n> yais_inference_request_duration_ms_quantile,host=dgx,model=flowers,quantile=0.900000,url=http://localhost:50078/metrics value=256.715759 1530985302000000000\n> yais_inference_request_duration_ms_quantile,host=dgx,model=flowers,quantile=0.990000,url=http://localhost:50078/metrics value=275.407232 1530985302000000000\n\n> yais_inference_load_ratio,host=dgx,url=http://localhost:50078/metrics +Inf=1000,1.25=1,1.5=1,10=9,100=253,2=1,count=1000,sum=95879.013208 1530985302000000000\n\n> yais_gpus_power_usage,gpu=0,host=dgx,url=http://localhost:50078/metrics gauge=52.821 1530985302000000000\n\n> yais_executor_queue_depth,host=dgx,url=http://localhost:50078/metrics gauge=0 1530985302000000000\n```\n### Best Practices\n\nFor a good description of using histograms vs. summaries to collect meaningful metrics\nsee: https://prometheus.io/docs/practices/histograms/\n\nTwo rules of thumb:\n - If you need to aggregate, choose histograms.\n - Otherwise, choose a histogram if you have an idea of the range and distribution of \n   values that will be observed. Choose a summary if you need an accurate quantile, no\n   matter what the range and distribution of the values is.\n\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/async-client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Original Copyright proivded below.\n * This work extends the original gRPC client examples to work with the\n * implemented server.\n *\n * Copyright 2015 gRPC authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include <grpc/support/log.h>\n#include <grpcpp/grpcpp.h>\n#include <thread>\n\n#include \"inference.grpc.pb.h\"\n\nusing grpc::Channel;\nusing grpc::ClientAsyncResponseReader;\nusing grpc::ClientContext;\nusing grpc::CompletionQueue;\nusing grpc::Status;\nusing ssd::BatchInput;\nusing ssd::BatchPredictions;\nusing ssd::Inference;\n\nclass GreeterClient\n{\n  public:\n    explicit GreeterClient(std::shared_ptr<Channel> channel) : stub_(Inference::NewStub(channel)) {}\n\n    // Assembles the client's payload and sends it to the server.\n    void SayHello(const size_t batch_id, const int batch_size)\n    {\n        // Data we are sending to the server.\n        BatchInput request;\n        request.set_batch_id(batch_id);\n        request.set_batch_size(batch_size);\n\n        // Call object to store rpc data\n        AsyncClientCall* call = new AsyncClientCall;\n\n        // stub_->PrepareAsyncSayHello() creates an RPC object, returning\n        // an instance to store in \"call\" but does not actually start the RPC\n        // Because we are using the asynchronous API, we need to hold on to\n        // the \"call\" instance in order to get updates on the ongoing RPC.\n        call->response_reader = stub_->PrepareAsyncCompute(&call->context, request, &cq_);\n\n        // StartCall initiates the RPC call\n        call->response_reader->StartCall();\n\n        // Request that, upon completion of the RPC, \"reply\" be updated with the\n        // server's response; \"status\" with the indication of whether the operation\n        // was successful. Tag the request with the memory address of the call object.\n        call->response_reader->Finish(&call->reply, &call->status, (void*)call);\n    }\n\n    // Loop while listening for completed responses.\n    // Prints out the response from the server.\n    void AsyncCompleteRpc()\n    {\n        void* got_tag;\n        bool ok = false;\n\n        // Block until the next result is available in the completion queue \"cq\".\n        while(cq_.Next(&got_tag, &ok))\n        {\n            // The tag in this example is the memory location of the call object\n            AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag);\n\n            // Verify that the request was completed successfully. Note that \"ok\"\n            // corresponds solely to the request for updates introduced by Finish().\n            GPR_ASSERT(ok);\n\n            if(call->status.ok())\n            {\n                // std::cout << \"Greeter received: \" << call->reply.batch_id() << std::endl;\n            }\n            else\n            {\n                std::cout << \"RPC failed\" << std::endl;\n            }\n            // Once we're complete, deallocate the call object.\n            delete call;\n        }\n    }\n\n    void Shutdown() { cq_.Shutdown(); }\n\n  private:\n    // struct for keeping state and data information\n    struct AsyncClientCall\n    {\n        // Container for the data we expect from the server.\n        BatchPredictions reply;\n\n        // Context for the client. It could be used to convey extra information to\n        // the server and/or tweak certain RPC behaviors.\n        ClientContext context;\n\n        // Storage for the status of the RPC upon completion.\n        Status status;\n\n        std::unique_ptr<ClientAsyncResponseReader<BatchPredictions>> response_reader;\n    };\n\n    // Out of the passed in Channel comes the stub, stored here, our view of the\n    // server's exposed services.\n    std::unique_ptr<Inference::Stub> stub_;\n\n    // The producer-consumer queue we use to communicate asynchronously with the\n    // gRPC runtime.\n    CompletionQueue cq_;\n};\n\nDEFINE_int32(count, 500, \"number of grpc messages to send\");\nDEFINE_int32(batch_size, 1, \"batch_size\");\nDEFINE_int32(port, 50051, \"server_port\");\n\nint main(int argc, char** argv)\n{\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    std::ostringstream ip_port;\n    ip_port << \"localhost:\" << FLAGS_port;\n    GreeterClient greeter(grpc::CreateChannel(ip_port.str(), grpc::InsecureChannelCredentials()));\n\n    // Spawn reader thread that loops indefinitely\n    std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter);\n\n    auto start = std::chrono::steady_clock::now();\n    for(size_t i = 0; i < FLAGS_count; i++)\n    {\n        greeter.SayHello(i, FLAGS_batch_size); // The actual RPC call!\n    }\n\n    greeter.Shutdown();\n    thread_.join(); // blocks forever\n    auto end = std::chrono::steady_clock::now();\n    float elapsed = std::chrono::duration<float>(end - start).count();\n    std::cout << FLAGS_count << \" requests in \" << elapsed\n              << \"seconds; inf/sec: \" << FLAGS_count * FLAGS_batch_size / elapsed << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/metrics.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"metrics.h\"\n\n#include <glog/logging.h>\n#include <ostream>\n\nnamespace trtlab {\n\nvoid Metrics::Initialize(uint32_t port)\n{\n    auto singleton = GetSingleton();\n    if(singleton->m_Exposer)\n    {\n        LOG(WARNING) << \"Metrics already initialized.  This call is ignored\";\n        return;\n    }\n    std::ostringstream stream;\n    stream << \"0.0.0.0:\" << port;\n    singleton->m_Exposer = std::make_unique<Exposer>(stream.str());\n    singleton->m_Exposer->RegisterCollectable(singleton->m_Registry);\n}\n\nauto Metrics::GetRegistry() -> Registry&\n{\n    auto singleton = Metrics::GetSingleton();\n    return *(singleton->m_Registry);\n}\n\nMetrics* Metrics::GetSingleton()\n{\n    static Metrics singleton;\n    return &singleton;\n}\n\nMetrics::Metrics() : m_Registry(std::make_shared<Registry>()) {}\n\nMetrics::~Metrics() {}\n\n} // namespace trtlab"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/metrics.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <prometheus/exposer.h>\n#include <prometheus/registry.h>\n\nusing prometheus::Exposer;\nusing prometheus::Registry;\n\nnamespace trtlab {\n\nclass Metrics\n{\n  public:\n    static void Initialize(uint32_t port);\n    static auto GetRegistry() -> Registry&;\n\n  protected:\n    Metrics();\n    virtual ~Metrics();\n    static Metrics* GetSingleton();\n\n  private:\n    std::unique_ptr<Exposer> m_Exposer;\n    std::shared_ptr<Registry> m_Registry;\n};\n\n} // namespace trtlab\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"nvml.h\"\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <sys/stat.h>\n#include <thread>\n#include <unistd.h>\n\n#include \"tensorrt/laboratory/core/affinity.h\"\n#include \"tensorrt/laboratory/core/memory/allocator.h\"\n#include \"tensorrt/laboratory/cuda/device_info.h\"\n#include \"tensorrt/laboratory/cuda/memory/cuda_pinned_host.h\"\n#include \"tensorrt/laboratory/inference_manager.h\"\n#include \"tensorrt/laboratory/runtime.h\"\n\n#include \"nvrpc/context.h\"\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\n#include \"metrics.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::Affinity;\nusing trtlab::Allocator;\nusing trtlab::CudaPinnedHostMemory;\nusing trtlab::DeviceInfo;\nusing trtlab::Metrics;\nusing trtlab::ThreadPool;\nusing trtlab::TensorRT::InferenceManager;\nusing trtlab::TensorRT::ManagedRuntime;\nusing trtlab::TensorRT::Model;\nusing trtlab::TensorRT::Runtime;\nusing trtlab::TensorRT::StandardRuntime;\n\n// Flowers Protos\n#include \"inference.grpc.pb.h\"\n#include \"inference.pb.h\"\n\nusing ssd::BatchInput;\nusing ssd::BatchPredictions;\nusing ssd::Inference;\n\n/*\n * Prometheus Metrics\n *\n * It is important to make collect measurements to find bottlenecks, performance issues,\n * and to trigger auto-scaling.\n */\nstatic auto& registry = Metrics::GetRegistry();\n\n// Summaries - Request and Compute duration on a per service basis\nstatic auto& inf_compute =\n    prometheus::BuildSummary().Name(\"yais_inference_compute_duration_ms\").Register(registry);\nstatic auto& inf_request =\n    prometheus::BuildSummary().Name(\"yais_inference_request_duration_ms\").Register(registry);\nstatic const auto& quantiles =\n    prometheus::Summary::Quantiles{{0.5, 0.05}, {0.90, 0.01}, {0.99, 0.001}};\n\n// Histogram - Load Ratio = Request/Compute duration - should just above one for a service\n//             that can keep up with its current load.  This metrics provides more\n//             detailed information on the impact of the queue depth because it accounts\n//             for request time.\nstatic const std::vector<double> buckets = {1.25, 1.50, 2.0, 10.0, 100.0}; // unitless\nstatic auto& inf_load_ratio_fam =\n    prometheus::BuildHistogram().Name(\"yais_inference_load_ratio\").Register(registry);\nstatic auto& inf_load_ratio = inf_load_ratio_fam.Add({}, buckets);\n\n// Gauge - Periodically measure and report GPU power utilization.  As the load increases\n//         on the service, the power should increase proprotionally, until the power is capped\n//         either by device limits or compute resources.  At this level, the inf_load_ratio\n//         will begin to increase under futher increases in traffic\nstatic auto& power_gauge_fam =\n    prometheus::BuildGauge().Name(\"yais_gpus_power_usage\").Register(registry);\nstatic auto& power_gauge = power_gauge_fam.Add({{\"gpu\", \"0\"}});\n\n/*\n * External Data Source\n *\n * Attaches to a System V shared memory segment owned by an external resources.\n * Example: the results of an image decode service could use this mechanism to transfer\n *          large tensors to an inference service by simply passing an offset.\n */\nfloat* GetSharedMemory(const std::string& address);\n\n/*\n * YAIS Resources - TensorRT InferenceManager + ThreadPools + External Datasource\n */\nclass FlowersResources : public InferenceManager\n{\n  public:\n    explicit FlowersResources(int max_executions, int max_buffers, int nCuda, int nResp,\n                              float* sysv_data)\n        : InferenceManager(max_executions, max_buffers), m_CudaThreadPool(nCuda),\n          m_ResponseThreadPool(nResp), m_SharedMemory(sysv_data)\n    {\n    }\n\n    ThreadPool& GetCudaThreadPool() { return m_CudaThreadPool; }\n    ThreadPool& GetResponseThreadPool() { return m_ResponseThreadPool; }\n\n    float* GetSysvOffset(size_t offset_in_bytes)\n    {\n        return &m_SharedMemory[offset_in_bytes / sizeof(float)];\n    }\n\n  private:\n    ThreadPool m_CudaThreadPool;\n    ThreadPool m_ResponseThreadPool;\n    float* m_SharedMemory;\n};\n\n/*\n * nvRPC Context - Defines the logic of the RPC.\n */\nclass FlowersContext final : public Context<BatchInput, BatchPredictions, FlowersResources>\n{\n    void ExecuteRPC(RequestType& input, ResponseType& output) final override\n    {\n        // Executing on a Executor threads - we don't want to block message handling, so we offload\n        GetResources()->GetCudaThreadPool().enqueue([this, &input, &output]() {\n            // Executed on a thread from CudaThreadPool\n            auto model = GetResources()->GetModel(\"flowers\");\n            auto buffers = GetResources()->GetBuffers(); // <=== Limited Resource; May Block !!!\n            auto bindings = buffers->CreateBindings(model);\n            bindings->SetBatchSize(input.batch_size());\n            bindings->SetHostAddress(0, GetResources()->GetSysvOffset(input.sysv_offset()));\n            bindings->CopyToDevice(bindings->InputBindings());\n            auto ctx =\n                GetResources()->GetExecutionContext(model); // <=== Limited Resource; May Block !!!\n            ctx->Infer(bindings);\n            bindings->CopyFromDevice(bindings->OutputBindings());\n            // All Async CUDA work has been queued - this thread's work is done.\n            GetResources()->GetResponseThreadPool().enqueue([this, &input, &output, model, bindings,\n                                                             ctx]() mutable {\n                // Executed on a thread from ResponseThreadPool\n                auto compute_time = ctx->Synchronize();\n                ctx.reset(); // Finished with the Execution Context - Release it to competing\n                             // threads\n                bindings->Synchronize(); // Blocks on H2D, Compute, D2H Pipeline\n                WriteBatchPredictions(input, output, (float*)bindings->HostAddress(1));\n                bindings.reset(); // Finished with Buffers - Release it to competing threads\n                auto request_time = Walltime();\n                output.set_compute_time(static_cast<float>(compute_time));\n                output.set_total_time(static_cast<float>(request_time));\n                this->FinishResponse();\n                // The Response is now sending; Record some metrics and be done\n                inf_compute.Add({{\"model\", model->Name()}}, quantiles).Observe(compute_time * 1000);\n                inf_request.Add({{\"model\", model->Name()}}, quantiles).Observe(request_time * 1000);\n                inf_load_ratio.Observe(request_time / compute_time);\n            });\n        });\n    }\n\n    void WriteBatchPredictions(RequestType& input, ResponseType& output, float* scores)\n    {\n        int N = input.batch_size();\n        auto nClasses = GetResources()->GetModel(\"flowers\")->GetBinding(1).elementsPerBatchItem;\n        size_t cntr = 0;\n        for(int p = 0; p < N; p++)\n        {\n            auto element = output.add_elements();\n            /* Customize the post-processing of the output tensor *\\\n            float max_val = -1.0;\n            int max_idx = -1;\n            for (int i = 0; i < nClasses; i++)\n            {\n                if (max_val < scores[cntr])\n                {\n                    max_val = scores[cntr];\n                    max_idx = i;\n                }\n                cntr++;\n            }\n            auto top1 = element->add_predictions();\n            top1->set_class_id(max_idx);\n            top1->set_score(max_val);\n            \\* Customize the post-processing of the output tensor */\n        }\n        output.set_batch_id(input.batch_id());\n    }\n};\n\nstatic bool ValidateEngine(const char* flagname, const std::string& value)\n{\n    struct stat buffer;\n    return (stat(value.c_str(), &buffer) == 0);\n}\n\nstatic bool ValidateBytes(const char* flagname, const std::string& value)\n{\n    trtlab::StringToBytes(value);\n    return true;\n}\n\nDEFINE_string(engine, \"/path/to/tensorrt.engine\", \"TensorRT serialized engine\");\nDEFINE_validator(engine, &ValidateEngine);\nDEFINE_string(dataset, \"127.0.0.1:4444\", \"GRPC Dataset/SharedMemory Service Address\");\nDEFINE_int32(contexts, 1, \"Number of Execution Contexts\");\nDEFINE_int32(buffers, 0, \"Number of Input/Output Buffers\");\nDEFINE_string(runtime, \"default\", \"TensorRT Runtime\");\nDEFINE_int32(execution_threads, 1, \"Number of RPC execution threads\");\nDEFINE_int32(preprocessing_threads, 0, \"Number of preprocessing threads\");\nDEFINE_int32(kernel_launching_threads, 1, \"Number of threads to launch CUDA kernels\");\nDEFINE_int32(postprocessing_threads, 2, \"Number of postprocessing threads\");\nDEFINE_string(max_recv_bytes, \"10MiB\", \"Maximum number of bytes for incoming messages\");\nDEFINE_validator(max_recv_bytes, &ValidateBytes);\nDEFINE_int32(port, 50051, \"Port to listen for gRPC requests\");\nDEFINE_int32(metrics, 50078, \"Port to expose metrics for scraping\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"flowers\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Set CPU Affinity to be near the GPU\n    auto cpus = DeviceInfo::Affinity(0);\n    Affinity::SetAffinity(cpus);\n\n    // Enable metrics on port\n    Metrics::Initialize(FLAGS_metrics);\n\n    // Create a gRPC server bound to IP:PORT\n    std::ostringstream ip_port;\n    ip_port << \"0.0.0.0:\" << FLAGS_port;\n    Server server(ip_port.str());\n\n    // Modify MaxReceiveMessageSize\n    auto bytes = trtlab::StringToBytes(FLAGS_max_recv_bytes);\n    server.Builder().SetMaxReceiveMessageSize(bytes);\n    LOG(INFO) << \"gRPC MaxReceiveMessageSize = \" << trtlab::BytesToString(bytes);\n\n    // A server can host multiple services\n    LOG(INFO) << \"Register Service (flowers::Inference) with Server\";\n    auto inferenceService = server.RegisterAsyncService<Inference>();\n\n    // An RPC has two components that need to be specified when registering with the service:\n    //  1) Type of Execution Context (FlowersContext).  The execution context defines the behavor\n    //     of the RPC, i.e. it contains the control logic for the execution of the RPC.\n    //  2) The Request function (RequestCompute) which was generated by gRPC when compiling the\n    //     protobuf which defined the service.  This function is responsible for queuing the\n    //     RPC's execution context to the\n    LOG(INFO) << \"Register RPC (flowers::Inference::Compute) with Service (flowers::Inference)\";\n    auto rpcCompute =\n        inferenceService->RegisterRPC<FlowersContext>(&Inference::AsyncService::RequestCompute);\n\n    // Buffers default to execution contexts + 2\n    // Allows for 1 H2D, N TensorRT Executions, 1 D2H to be inflight\n    auto buffers = FLAGS_buffers;\n    if(buffers == 0) buffers = FLAGS_contexts + 2;\n\n    // Initialize Resources\n    LOG(INFO) << \"Initializing Resources for RPC (flowers::Inference::Compute)\";\n    auto rpcResources = std::make_shared<FlowersResources>(\n        FLAGS_contexts, // number of IExecutionContexts - scratch space for DNN activations\n        buffers, // number of host/device buffers for input/output tensors\n        FLAGS_kernel_launching_threads, // number of threads used to execute cuda kernel launches\n        FLAGS_postprocessing_threads, // number of threads used to write and complete responses\n        GetSharedMemory(FLAGS_dataset) // pointer to data in shared memory\n    );\n\n    std::shared_ptr<Runtime> runtime;\n    if(FLAGS_runtime == \"default\")\n    {\n        runtime = std::make_shared<StandardRuntime>();\n    }\n    else if(FLAGS_runtime == \"unified\")\n    {\n        runtime = std::make_shared<ManagedRuntime>();\n    }\n    else\n    {\n        LOG(FATAL) << \"Invalid TensorRT Runtime\";\n    }\n\n    rpcResources->RegisterModel(\"flowers\", runtime->DeserializeEngine(FLAGS_engine));\n    rpcResources->AllocateResources();\n\n    // Create Executors - Executors provide the messaging processing resources for the RPCs\n    LOG(INFO) << \"Initializing Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    // You can register RPC execution contexts from any registered RPC on any executor.\n    LOG(INFO)\n        << \"Registering Execution Contexts for RPC (flowers::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 100);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {\n        // Query GPU Power\n        nvmlDevice_t gpu;\n        unsigned int power;\n        CHECK_EQ(nvmlDeviceGetHandleByIndex(0, &gpu), NVML_SUCCESS)\n            << \"Failed to get Device for index=\" << 0;\n        CHECK_EQ(nvmlDeviceGetPowerUsage(gpu, &power), NVML_SUCCESS)\n            << \"Failed to get Power Usage for GPU=\" << 0;\n        power_gauge.Set((double)power * 0.001);\n    });\n}\n\nstatic auto pinned_memory = std::make_unique<Allocator<CudaPinnedHostMemory>>(1024 * 1024 * 1024);\n\nfloat* GetSharedMemory(const std::string& address)\n{\n    /* data in shared memory should go here - for the sake of quick examples just use and emptry\n     * array */\n    pinned_memory->Fill((char)0);\n    return (float*)pinned_memory->Data();\n    // the following code connects to a shared memory service to allow for non-serialized transfers\n    // between microservices\n    /*\n    InfoRequest request;\n    Info reply;\n    grpc::ClientContext context;\n    auto channel = grpc::CreateChannel(address, grpc::InsecureChannelCredentials());\n    auto stub = SharedMemoryDataSet::NewStub(channel);\n    auto status = stub->GetInfo(&context, request, &reply);\n    CHECK(status.ok()) << \"Dataset shared memory request failed\";\n    DLOG(INFO) << \"SysV ShmKey: \" << reply.sysv_key();\n    int shmid = shmget(reply.sysv_key(), 0, 0);\n    DLOG(INFO) << \"SysV ShmID: \" << shmid;\n    float* data = (float*) shmat(shmid, 0, 0);\n    CHECK(data) << \"SysV Attached failed\";\n    return data;\n    */\n}\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/siege.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Original Copyright proivded below.\n * This work extends the original gRPC client examples to work with the\n * implemented server.\n *\n * Copyright 2015 gRPC authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include <grpc/support/log.h>\n#include <grpcpp/grpcpp.h>\n#include <thread>\n\n#include \"inference.grpc.pb.h\"\n\n#include \"tensorrt/laboratory/core/utils.h\"\n\nusing grpc::Channel;\nusing grpc::ClientAsyncResponseReader;\nusing grpc::ClientContext;\nusing grpc::CompletionQueue;\nusing grpc::Status;\nusing ssd::BatchInput;\nusing ssd::BatchPredictions;\nusing ssd::Inference;\n\nstatic int g_BatchSize = 1;\n\nclass GreeterClient\n{\n  public:\n    explicit GreeterClient(std::shared_ptr<Channel> channel, int max_outstanding)\n        : stub_(Inference::NewStub(channel)), m_OutstandingMessageCount(0),\n          m_MaxOutstandingMessageCount(max_outstanding)\n    {\n    }\n\n    // Assembles the client's payload and sends it to the server.\n    void SayHello(const size_t batch_id, const int batch_size, char* bytes, uint64_t total)\n    {\n        // Data we are sending to the server.\n        {\n            std::unique_lock<std::mutex> lock(m_Mutex);\n            m_OutstandingMessageCount++;\n            while(m_OutstandingMessageCount >= m_MaxOutstandingMessageCount)\n            {\n                LOG_FIRST_N(WARNING, 10) << \"Initiated Backoff - (Siege Rate > Server Compute \"\n                                            \"Rate) - Server Queues are full.\";\n                m_Condition.wait(lock);\n            }\n        }\n\n        auto start = std::chrono::high_resolution_clock::now();\n\n        BatchInput request;\n        request.set_batch_id(batch_id);\n        request.set_batch_size(batch_size);\n        if(total)\n        {\n            request.set_data(bytes, total);\n        }\n\n        // Call object to store rpc data\n        AsyncClientCall* call = new AsyncClientCall;\n\n        // stub_->PrepareAsyncSayHello() creates an RPC object, returning\n        // an instance to store in \"call\" but does not actually start the RPC\n        // Because we are using the asynchronous API, we need to hold on to\n        // the \"call\" instance in order to get updates on the ongoing RPC.\n        call->response_reader = stub_->PrepareAsyncCompute(&call->context, request, &cq_);\n\n        // StartCall initiates the RPC call\n        call->response_reader->StartCall();\n\n        // Request that, upon completion of the RPC, \"reply\" be updated with the\n        // server's response; \"status\" with the indication of whether the operation\n        // was successful. Tag the request with the memory address of the call object.\n        call->response_reader->Finish(&call->reply, &call->status, (void*)call);\n\n        float elapsed =\n            std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - start).count();\n        m_RequestCalls++;\n        m_TotalRequestTime += elapsed;\n        // LOG_EVERY_N(INFO, 200) << \"Request overhead: \" << m_TotalRequestTime/m_RequestCalls;\n    }\n\n    // Loop while listening for completed responses.\n    // Prints out the response from the server.\n    void AsyncCompleteRpc()\n    {\n        void* got_tag;\n        bool ok = false;\n        size_t cntr = 0;\n        auto start = std::chrono::steady_clock::now();\n        float last = 0.0;\n\n        // Block until the next result is available in the completion queue \"cq\".\n        while(cq_.Next(&got_tag, &ok))\n        {\n            // The tag in this example is the memory location of the call object\n            AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag);\n\n            // Verify that the request was completed successfully. Note that \"ok\"\n            // corresponds solely to the request for updates introduced by Finish().\n            GPR_ASSERT(ok);\n\n            if(call->status.ok())\n            {\n                // std::cout << \"Greeter received: \" << call->reply.batch_id() << std::endl;\n            }\n            else\n            {\n                std::cout << \"RPC failed\" << std::endl;\n            }\n            // Once we're complete, deallocate the call object.\n            delete call;\n\n            cntr++;\n            float elapsed =\n                std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n            if(elapsed - last > 0.5)\n            {\n                LOG(INFO) << \"avg. rate: \" << (float)cntr / (elapsed - last) << \"( \"\n                          << (float)(cntr * g_BatchSize) / (elapsed - last) << \" inf/sec)\";\n                last = elapsed;\n                cntr = 0;\n            }\n\n            {\n                std::unique_lock<std::mutex> lock(m_Mutex);\n                m_OutstandingMessageCount--;\n            }\n            m_Condition.notify_one();\n        }\n    }\n\n    void Shutdown() { cq_.Shutdown(); }\n\n  private:\n    // struct for keeping state and data information\n    struct AsyncClientCall\n    {\n        // Container for the data we expect from the server.\n        BatchPredictions reply;\n\n        // Context for the client. It could be used to convey extra information to\n        // the server and/or tweak certain RPC behaviors.\n        ClientContext context;\n\n        // Storage for the status of the RPC upon completion.\n        Status status;\n\n        std::unique_ptr<ClientAsyncResponseReader<BatchPredictions>> response_reader;\n    };\n\n    // Out of the passed in Channel comes the stub, stored here, our view of the\n    // server's exposed services.\n    std::unique_ptr<Inference::Stub> stub_;\n\n    // The producer-consumer queue we use to communicate asynchronously with the\n    // gRPC runtime.\n    CompletionQueue cq_;\n\n    // mutex to help control rate\n    std::mutex m_Mutex;\n    std::condition_variable m_Condition;\n    int m_OutstandingMessageCount;\n    int m_MaxOutstandingMessageCount;\n    float m_TotalRequestTime;\n    size_t m_RequestCalls;\n};\n\nstatic bool ValidateBytes(const char* flagname, const std::string& value)\n{\n    trtlab::StringToBytes(value);\n    return true;\n}\n\nDEFINE_int32(count, 1000000, \"number of grpc messages to send\");\nDEFINE_int32(batch_size, 1, \"batch_size\");\nDEFINE_int32(max_outstanding, 950, \"maximum outstanding requests\");\nDEFINE_int32(port, 50051, \"server_port\");\nDEFINE_double(rate, 1.0, \"messages per second\");\nDEFINE_double(max_rate, 100000, \"maximum number of messages per second when func is applied\");\nDEFINE_double(alpha, 0, \"alpha\");\nDEFINE_double(beta, 1, \"beta\");\nDEFINE_string(func, \"constant\", \"constant, linear or cyclic\");\nDEFINE_string(bytes, \"0B\", \"add extra bytes to the request payload\");\nDEFINE_validator(bytes, &ValidateBytes);\n\nint main(int argc, char** argv)\n{\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    g_BatchSize = FLAGS_batch_size;\n\n    auto bytes = trtlab::StringToBytes(FLAGS_bytes);\n    char extra_bytes[bytes];\n    if(bytes)\n        LOG(INFO) << \"Sending an addition \" << trtlab::BytesToString(bytes)\n                  << \" bytes in request payload\";\n\n    // using a fixed rate of 15us per rpc call.  i could adjust dynamically as i'm tracking\n    // the call overhead, but it's close enough.\n    auto start = std::chrono::system_clock::now();\n    auto walltime = [start]() -> double {\n        return std::chrono::duration<double>(std::chrono::system_clock::now() - start).count();\n    };\n    std::map<std::string, std::function<double()>> rates_by_name;\n    rates_by_name[\"constant\"] = []() -> double { return std::min(FLAGS_rate, FLAGS_max_rate); };\n    rates_by_name[\"linear\"] = [start, walltime]() -> double {\n        return std::min(FLAGS_rate + (FLAGS_alpha / 60.0) * walltime(), FLAGS_max_rate);\n    };\n    rates_by_name[\"cyclic\"] = [start, walltime]() -> double {\n        return std::min(FLAGS_rate + FLAGS_alpha *\n                                         std::sin(2.0 * 3.14159 * (FLAGS_beta / 60.0) * walltime()),\n                        FLAGS_max_rate);\n    };\n    auto search = rates_by_name.find(FLAGS_func);\n    if(search == rates_by_name.end())\n    {\n        LOG(FATAL) << \"--func must be constant, linear or cyclic; your value = \" << FLAGS_func;\n    }\n    auto sleepy = [search]() -> double {\n        auto sleep_time = ((std::chrono::seconds(1) / std::max((search->second)(), 2.0))) -\n                          std::chrono::microseconds(15);\n        return std::chrono::duration<double>(sleep_time).count();\n    };\n\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    std::ostringstream ip_port;\n    ip_port << \"localhost:\" << FLAGS_port;\n\n    grpc::ChannelArguments ch_args;\n    ch_args.SetMaxReceiveMessageSize(-1);\n    GreeterClient greeter(\n        grpc::CreateCustomChannel(ip_port.str(), grpc::InsecureChannelCredentials(), ch_args),\n        FLAGS_max_outstanding);\n\n    // Spawn reader thread that loops indefinitely\n    std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter);\n\n    for(size_t i = 0; i < FLAGS_count; i++)\n    {\n        greeter.SayHello(i, FLAGS_batch_size, extra_bytes, bytes); // The actual RPC call!\n        auto start = std::chrono::high_resolution_clock::now();\n        while(std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - start)\n                  .count() < sleepy())\n        {\n            std::this_thread::yield();\n        }\n    }\n\n    greeter.Shutdown();\n    thread_.join(); // blocks forever\n    auto elapsed = walltime();\n    std::cout << FLAGS_count << \" requests in \" << elapsed\n              << \"seconds; inf/sec: \" << FLAGS_count * FLAGS_batch_size / elapsed << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/02_TensorRT_GRPC/src/sync-client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Original Copyright proivded below.\n * This work extends the original gRPC client examples to work with the\n * implemented server.\n *\n * Copyright 2015 gRPC authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"inference.grpc.pb.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\nusing ssd::BatchInput;\nusing ssd::BatchPredictions;\nusing ssd::Inference;\n\nclass SimpleClient\n{\n  public:\n    SimpleClient(std::shared_ptr<Channel> channel) : stub_(Inference::NewStub(channel)) {}\n\n    // Assembles the client's payload, sends it and presents the response back\n    // from the server.\n    int Compute(const int batch_id, const int batch_size)\n    {\n        // Data we are sending to the server.\n        BatchInput request;\n        request.set_batch_id(batch_id);\n        request.set_batch_size(batch_size);\n\n        // Container for the data we expect from the server.\n        BatchPredictions reply;\n\n        // Context for the client. It could be used to convey extra information to\n        // the server and/or tweak certain RPC behaviors.\n        ClientContext context;\n\n        // The actual RPC.\n        Status status = stub_->Compute(&context, request, &reply);\n\n        // Act upon its status.\n        if(status.ok())\n        {\n            return reply.batch_id();\n        }\n        else\n        {\n            std::cout << status.error_code() << \": \" << status.error_message() << std::endl;\n            return -1;\n        }\n    }\n\n  private:\n    std::unique_ptr<Inference::Stub> stub_;\n};\n\nDEFINE_int32(count, 1000, \"number of grpc messages to send\");\nDEFINE_int32(port, 50051, \"server_port\");\nDEFINE_int32(batch, 1, \"batch size\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    std::ostringstream ip_port;\n    ip_port << \"localhost:\" << FLAGS_port;\n    SimpleClient client(grpc::CreateChannel(ip_port.str(), grpc::InsecureChannelCredentials()));\n    auto start = std::chrono::steady_clock::now();\n    for(int i = 0; i < FLAGS_count; i++)\n    {\n        auto reply = client.Compute(i, FLAGS_batch);\n        if(reply == -1 || reply != i) std::cout << \"BatchId received: \" << reply << std::endl;\n    }\n    auto end = std::chrono::steady_clock::now();\n    float elapsed = std::chrono::duration<float>(end - start).count();\n    std::cout << FLAGS_count << \" requests in \" << elapsed\n              << \" seconds; inf/sec: \" << FLAGS_count * FLAGS_batch / elapsed << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "examples/03_Batching/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(streaming-service-echo.x\n    streaming-service.cc\n)\ntarget_link_libraries(streaming-service-echo.x\n    trtlab::nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(batching-service-echo.x\n    inference-batcher.cc\n)\n\ntarget_link_libraries(batching-service-echo.x\n    trtlab::nvrpc\n    echo-protos\n    gflags\n)\n\n"
  },
  {
    "path": "examples/03_Batching/README.md",
    "content": "# Batching Service\n\nA batching service is a service that trying to collect sets of similar requests into a\ncollective batch which can be executed in a single-shot.\n\n#### Why do we want to batch?\n\nIn the case of Deep Neural Networks, batching can improve the computational efficiency\nof executing on a GPU by increases the operational intensity, i.e. improving the ratio of \nthe number of math operations per memory transaction.  This translates to improved\nthroughput, better hardware utilization and cost reductions.\n\n#### Sounds great, but what's the catch?\n\nIn many cases, batching can add latency to an individual request.  Because a batch of more\nthan 1 item, BatchN, computed as a single unit, the time to compute BatchN is greater than\nBatch1.  However, in many cases, the time to compute delta between Batch1 and Batch2/4/8 is \nfairly small due to the improved operational efficiency.\n\nSecondly, because batching requires requests to be collected, there is a timed collection\nwindow prior to the compute.  The first request in a batch sees the longest latency. \n\nThe worst-case increased latency is bounded by the following formula:\n```\nworst_additional_latency = batch_window_timeout + batchN_compute - batch1_compute\n```\n\n#### When to Batch?\n\nYou want to batch requests when your service has very high-load and you can tolerate\nminor increases in latency.\n\nThroughput improvements can be 2-5x which translates into direct cost savings.\n\n#### What does this Batching Service do for me?\n\nThe basis YAIS service examples [01_GRPC](../01_GRPC) and [02_GRPC_TensorRT](../02_GRPC_TensorRT)\nhave implemented high-performance send/recv unary services.  That is, the client\nsends a request which is computed and a response is returned.  The client could in theory\ncreate a single message is itself a batch, i.e. multiple images files or sentences to be \ntranslated.  However, in most common realworld usecases, the clients of a service send\na single item at a time.  This keeps the logic simple and lifecycle of the request simple.\n\nIf this is your RPC definition,\n```\nservice Inference {\n   rpc Compute (Input) returns (Output) {}\n}\n```\n\nThen, instead of implementing `rpc Compute` to perform the inference computation, instead, we\nhyjack that RPC and turn it into a batcher.  In the [`inference-batcher.cc`](inference-batcher.cc)\nfile, you will see that we are indeed we implement our batching service as the `Compute` method.\n\nThe batching service collecting incoming `Input` requests and forwards them via a gRPC stream\nto a service that accepts a \"batching stream\".\n\nA “batching stream” is a stream where the endpoint service reads and collects the elements of the stream until the client signifies it is done writing.  That is the signal at which YAIS performs a single batched inference call on the concatenated set of requests that came in over the stream.  After the inference calculation is complete, the server writes the results for each request item to the stream.  That is, for each request that came in on the stream, the server is expected to return a response.  \n\nWe still need to compute inference on the batching stream.  This is performed by [streaming-service.cc](streaming-service.cc).\n\nThe `streaming-service` implements the `BatchedCompute` RPC method using a `BatchingContext`.\n```\nservice Inference {\n   rpc Compute (Input) returns (Output) {}\n   rpc BatchedCompute (stream Input) returns (stream Output) {}\n}\n```\n\nBecause the stream consists of an array of individual messages, you simply need to make\nminor modifications to your existing Batch1 service to preprocess and concat the incoming requests\ntogether to form a single batch compute.  For each `Input` item in the stream, it is expected that\nthe service writes an `Output` response in the same order as the inputs (FIFO).\n\nThe batching service doesn’t need to know anything about the format of the `Input`/`Output` messages.  It simply accepts and forwards them.  The result is that this batching service example should be able to work with any unary gRPC service with any request/response message.  You simply need to implement a streaming service capable of handling the forwarding stream.\n\n## Running Example\n\n```\n./launch_batching.sh\n```\n\n```\n... # streaming service startup\n... # batching service startup\n\nStarting a shell keeping the services and load-balancer running...\nTry python unary_client.py - exit shell to kill services\nBatching Subshell: python unary_client.py\nI0822 14:48:18.900671    50 inference-batcher.cc:344] incoming unary request\nI0822 14:48:18.902642    41 inference-batcher.cc:109] Client using CQ: 0x14470f0\nI0822 14:48:18.902680    41 inference-batcher.cc:140] Starting Batch Forwarding of Size 1 for Tag 0x1458450\nI0822 14:48:18.903472    35 streaming-service.cc:61] Recieved request with batch_id=78\nI0822 14:48:18.903504    35 streaming-service.cc:54] Response with batch_id=78\nI0822 14:48:18.903656    47 inference-batcher.cc:243] Batch Forwarding Completed for Tag 0x1458450\nReceived msg  with batch_id=78\n```\n"
  },
  {
    "path": "examples/03_Batching/inference-batcher.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"nvrpc/context.h\"\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::ThreadPool;\n\n#include \"moodycamel/blockingconcurrentqueue.h\"\n\nusing moodycamel::BlockingConcurrentQueue;\nusing moodycamel::ConsumerToken;\nusing moodycamel::ProducerToken;\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n\n/**\n * @brief Batching Service for Unary Requests\n *\n * Exposes a Unary (send/recv) interface for a given RPC, but rather than\n * computing the RPC, the service simply batches the incoming requests and\n * forwards them via a gRPC stream to a service that implements the actual\n * compute portion of the RPC.\n *\n * The backend compute service is not a Unary service.  Rather it must\n * implemented the LifeCycleBatching service Context, i.e. BatchingContext.\n * The other application in this folder implements the backend service.\n *\n * Streams are used as a forwarding mechanism because of how they interact\n * with a load-balancer.  Unlike unary requests which get balanced on each\n * request, a stream only get balanced when it is opened.  All items of a stream\n * go to the same endpoint service.\n *\n * @tparam ServiceType\n * @tparam Request\n * @tparam Response\n */\ntemplate<class ServiceType, class Request, class Response>\nstruct BatchingService\n{\n    using Callback = std::function<void(bool)>;\n\n    struct MessageType\n    {\n        Request* request;\n        Response* response;\n        Callback callback;\n    };\n\n    /**\n     * @brief Forwards incoming Unary requests via a gRPC Stream to\n     * a Batched Steaming Service that implements the actual RPC\n     */\n    class Client\n    {\n      public:\n        using PrepareFunc =\n            std::function<std::unique_ptr<::grpc::ClientAsyncReaderWriter<Request, Response>>(\n                ::grpc::ClientContext*, ::grpc::CompletionQueue*)>;\n\n        Client(PrepareFunc prepare_func, std::shared_ptr<ThreadPool> thread_pool)\n            : m_PrepareFunc(prepare_func), m_ThreadPool(thread_pool), m_CurrentCQ(0)\n        {\n            for(decltype(m_ThreadPool->Size()) i = 0; i < m_ThreadPool->Size(); i++)\n            {\n                LOG(INFO) << \"Starting Client Progress Engine #\" << i;\n                m_CQs.emplace_back(new ::grpc::CompletionQueue);\n                auto cq = m_CQs.back().get();\n                m_ThreadPool->enqueue([this, cq] { ProgressEngine(*cq); });\n            }\n        }\n\n        void WriteAndCloseStream(uint32_t messages_count, MessageType* messages)\n        {\n            auto cq = m_CQs[++m_CurrentCQ % m_CQs.size()].get();\n            LOG(INFO) << \"Client using CQ: \" << (void*)cq;\n\n            auto ctx = new Call;\n            for(uint32_t i = 0; i < messages_count; i++)\n            {\n                ctx->Push(messages[i]);\n            }\n\n            ctx->m_Stream = m_PrepareFunc(&ctx->m_Context, cq);\n            ctx->Start();\n        }\n\n      private:\n        class Call\n        {\n          public:\n            Call() : m_Started(false), m_NextState(&Call::StateInvalid) {}\n            virtual ~Call() {}\n\n            void Push(MessageType& message)\n            {\n                if(m_Started) LOG(FATAL) << \"Stream started; No pushing allowed.\";\n                m_Requests.push(message.request);\n                m_Responses.push(message.response);\n                m_CallbackByResponse[message.response] = message.callback;\n            }\n\n            void Start()\n            {\n                LOG(INFO) << \"Starting Batch Forwarding of Size \" << m_Requests.size()\n                          << \" for Tag \" << Tag();\n                m_NextState = &Call::StateWriteDone;\n                m_Stream->StartCall(Tag());\n            }\n\n          private:\n            bool RunNextState(bool ok)\n            {\n                bool ret = (this->*m_NextState)(ok);\n                if(!ret) DLOG(INFO) << \"RunNextState returning false\";\n                return ret;\n            }\n\n            void* Tag() { return static_cast<void*>(this); }\n\n            bool Fail()\n            {\n                LOG(FATAL) << \"Fail\";\n                return false;\n            }\n\n            void WriteNext()\n            {\n                if(m_Requests.size())\n                {\n                    auto request = m_Requests.front();\n                    m_Requests.pop();\n                    DLOG(INFO) << \"forwarding request\";\n                    m_NextState = &Call::StateWriteDone;\n                    m_Stream->Write(*request, Tag());\n                }\n                else\n                {\n                    DLOG(INFO) << \"closing client stream for writing\";\n                    m_NextState = &Call::StateCloseStreamDone;\n                    m_Stream->WritesDone(Tag());\n                }\n            }\n\n            void ReadNext()\n            {\n                if(m_Responses.size())\n                {\n                    DLOG(INFO) << \"waiting on response\";\n                    auto response = m_Responses.front();\n                    m_NextState = &Call::StateReadDone;\n                    m_Stream->Read(response, Tag());\n                }\n                else\n                {\n                    DLOG(INFO) << \"waiting on finished message from server\";\n                    m_NextState = &Call::StateFinishedDone;\n                    m_Stream->Finish(&m_Status, Tag());\n                }\n            }\n\n            bool StateWriteDone(bool ok)\n            {\n                if(!ok) return Fail();\n                DLOG(INFO) << \"request forwarded!\";\n                WriteNext();\n                return true;\n            }\n\n            bool StateReadDone(bool ok)\n            {\n                if(!ok) return Fail();\n                DLOG(INFO) << \"response received\";\n                auto response = m_Responses.front();\n                m_Responses.pop();\n                auto search = m_CallbackByResponse.find(response);\n                if(search == m_CallbackByResponse.end())\n                    LOG(FATAL) << \"Callback for response not found\";\n                ReadNext();\n                // Execute callback which will complete the unary request for this stream item\n                DLOG(INFO) << \"triggering callback on held receive context\";\n                search->second(true);\n                DLOG(INFO) << \"callback completed\";\n                return true;\n            }\n\n            bool StateCloseStreamDone(bool ok)\n            {\n                if(!ok) return Fail();\n                DLOG(INFO) << \"closed client stream for writing\";\n                ReadNext();\n                return true;\n            }\n\n            bool StateFinishedDone(bool ok)\n            {\n                if(m_Status.ok())\n                    DLOG(INFO) << \"ClientContext: \" << Tag() << \" finished with OK\";\n                else\n                    DLOG(INFO) << \"ClientContext: \" << Tag() << \" finished with CANCELLED\";\n                m_NextState = &Call::StateInvalid;\n                LOG(INFO) << \"Batch Forwarding Completed for Tag \" << Tag();\n                return false;\n            }\n\n            bool StateInvalid(bool ok) { LOG(FATAL) << \"This should never be called\"; }\n\n          private:\n            std::queue<Request*> m_Requests;\n            std::queue<Response*> m_Responses;\n            std::map<const Response*, Callback> m_CallbackByResponse;\n\n            bool (Call::*m_NextState)(bool);\n\n            ::grpc::Status m_Status;\n            ::grpc::ClientContext m_Context;\n            std::unique_ptr<::grpc::ClientAsyncReaderWriter<Request, Response>> m_Stream;\n            bool m_Started;\n\n            friend class Client;\n        };\n\n        void ProgressEngine(::grpc::CompletionQueue& cq)\n        {\n            void* tag;\n            bool ok = false;\n\n            while(cq.Next(&tag, &ok))\n            {\n                CHECK(ok) << \"not ok\";\n                Call* call = static_cast<Call*>(tag);\n                if(!call->RunNextState(ok))\n                {\n                    DLOG(INFO) << \"Deleting Stream: \" << tag;\n                    delete call;\n                }\n            }\n        }\n\n        int m_CurrentCQ;\n        PrepareFunc m_PrepareFunc;\n        std::shared_ptr<ThreadPool> m_ThreadPool;\n        std::vector<std::unique_ptr<::grpc::CompletionQueue>> m_CQs;\n    };\n\n    class Resources : public ::trtlab::Resources\n    {\n      public:\n        Resources(uint32_t max_batch_size, uint64_t timeout, std::shared_ptr<Client> client)\n            : m_MaxBatchsize(max_batch_size), m_Timeout(timeout), m_Client(client)\n        {\n        }\n\n        virtual void PreprocessRequest(Request* req) {}\n\n        void Push(Request* req, Response* resp, Callback callback)\n        {\n            // thread_local ProducerToken token(m_MessageQueue);\n            // m_MessageQueue.enqueue(token, MessageType(req, resp, callback));\n            PreprocessRequest(req);\n            m_MessageQueue.enqueue(MessageType{req, resp, callback});\n        }\n\n        void ProgressEngine()\n        {\n            constexpr uint64_t quanta = 100;\n            const double timeout = static_cast<double>(m_Timeout - quanta) / 1000000.0;\n            size_t total_count;\n            size_t max_batch;\n            std::vector<MessageType> messages;\n            messages.resize(m_MaxBatch)\n\n                thread_local ConsumerToken token(m_MessageQueue);\n            for(;;)\n            {\n                max_batch = m_MaxBatchsize;\n                total_count = 0;\n                auto start = std::chrono::steady_clock::now();\n                auto elapsed = [start]() -> double {\n                    return std::chrono::duration<double>(std::chrono::steady_clock::now() - start)\n                        .count();\n                };\n\n                // initial pull - if not successful, restart loop\n\n                // if successful, then open a stream, push message to stream and continue to collect\n                // requests until the max_batch_size is reach for the timeout is triggered\n\n                // finish sending\n\n                // r\n                do\n                {\n                    auto count = m_MessageQueue.wait_dequeue_bulk_timed(\n                        token, &messages[total_count], max_batch, quanta);\n                    total_count += count;\n                    max_batch -= count;\n                } while(total_count && total_count < m_MaxBatchsize && elapsed() < timeout);\n                if(total_count)\n                {\n                    m_Client->WriteAndCloseStream(total_count, messages);\n                }\n            }\n        }\n\n      private:\n        size_t m_MaxBatchsize;\n        uint64_t m_Timeout;\n        std::shared_ptr<Client> m_Client;\n        BlockingConcurrentQueue<MessageType> m_MessageQueue;\n    };\n\n    class ReceiveContext final : public ::nvrpc::Context<Request, Response, Resources>\n    {\n        void ExecuteRPC(Request& request, Response& response) final override\n        {\n            LOG(INFO) << \"incoming unary request\";\n            this->GetResources()->Push(&request, &response, [this](bool ok) {\n                if(ok)\n                    this->FinishResponse();\n                else\n                {\n                    LOG(INFO) << \"shoot\";\n                    this->CancelResponse();\n                }\n            });\n        }\n    };\n};\n\nDEFINE_uint32(max_batch_size, 8, \"Maximum batch size to collect and foward\");\nDEFINE_uint64(timeout_usecs, 2000, \"Batching window timeout in microseconds\");\nDEFINE_uint32(max_batches_in_flight, 1, \"Maximum number of forwarded batches\");\nDEFINE_uint32(receiving_threads, 1, \"Number of Forwarding threads\");\nDEFINE_uint32(forwarding_threads, 1, \"Number of Forwarding threads\");\nDEFINE_string(forwarding_target, \"localhost:50051\", \"Batched Compute Service / Load-Balancer\");\n\nusing InferenceBatchingService = BatchingService<simple::Inference, simple::Input, simple::Output>;\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"simpleBatchingService\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n    auto forwarding_threads = std::make_shared<ThreadPool>(FLAGS_forwarding_threads);\n    auto channel = grpc::CreateChannel(FLAGS_forwarding_target, grpc::InsecureChannelCredentials());\n    auto stub = ::simple::Inference::NewStub(channel);\n    auto forwarding_prepare_func = [&stub](::grpc::ClientContext * context,\n                                           ::grpc::CompletionQueue * cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncBatchedCompute(context, cq));\n    };\n\n    auto client = std::make_shared<InferenceBatchingService::Client>(forwarding_prepare_func,\n                                                                     forwarding_threads);\n\n    auto rpcResources = std::make_shared<InferenceBatchingService::Resources>(\n        FLAGS_max_batch_size, FLAGS_timeout_usecs, client);\n\n    Server server(\"0.0.0.0:50049\");\n    auto recvService = server.RegisterAsyncService<::simple::Inference>();\n    auto rpcCompute = recvService->RegisterRPC<InferenceBatchingService::ReceiveContext>(\n        &::simple::Inference::AsyncService::RequestCompute);\n\n    uint64_t context_count = FLAGS_max_batch_size * FLAGS_max_batches_in_flight;\n    uint64_t contexts_per_executor_thread = std::max(context_count / FLAGS_receiving_threads, 1UL);\n\n    auto executor = server.RegisterExecutor(new Executor(FLAGS_receiving_threads));\n    executor->RegisterContexts(rpcCompute, rpcResources, contexts_per_executor_thread);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(1), [rpcResources] { rpcResources->ProgressEngine(); });\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/03_Batching/launch_batching.sh",
    "content": "#!/bin/bash -e\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\ncleanup() {\n  kill $(jobs -p) ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\nsleep 1\n\necho \"starting streaming services\"\n/work/build/examples/03_Batching/streaming-service-echo.x &\nwait-for-it.sh localhost:50051 --timeout=0 -- echo \"Streaming service is ready.\"\n\necho \"starting batching service\"\n/work/build/examples/03_Batching/batching-service-echo.x &\nwait-for-it.sh localhost:50049 --timeout=0 -- echo \"Batching service is ready.\"\n\necho\necho \"Starting a shell keeping the services and load-balancer running...\"\necho \"Try python unary_client.py - exit shell to kill services\"\nbash --rcfile <(echo \"PS1='Batching Subshell: '\")\n"
  },
  {
    "path": "examples/03_Batching/simple_batching_client.py",
    "content": "import grpc\n\nimport simple_pb2\nimport simple_pb2_grpc\n\n\ndef run():\n    with grpc.insecure_channel('localhost:50051') as channel:\n        stub = simple_pb2_grpc.InferenceStub(channel)\n        def requests():\n            messages = [simple_pb2.Input(batch_id=i) for i in range(10)]\n            for msg in messages:\n                print(\"Sending Stream batch_id={}\".format(msg.batch_id))\n                yield msg\n\n        responses = stub.BatchedCompute(requests())\n        for resp in responses:\n            print(\"Received msg on stream with batch_id={}\".format(resp.batch_id))\n\nif __name__ == \"__main__\":\n    run() \n"
  },
  {
    "path": "examples/03_Batching/simple_pb2.py",
    "content": "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n# source: simple.proto\n\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))\nfrom google.protobuf import descriptor as _descriptor\nfrom google.protobuf import message as _message\nfrom google.protobuf import reflection as _reflection\nfrom google.protobuf import symbol_database as _symbol_database\nfrom google.protobuf import descriptor_pb2\n# @@protoc_insertion_point(imports)\n\n_sym_db = _symbol_database.Default()\n\n\n\n\nDESCRIPTOR = _descriptor.FileDescriptor(\n  name='simple.proto',\n  package='simple',\n  syntax='proto3',\n  serialized_pb=_b('\\n\\x0csimple.proto\\x12\\x06simple\\\"\\x19\\n\\x05Input\\x12\\x10\\n\\x08\\x62\\x61tch_id\\x18\\x01 \\x01(\\x04\\\"\\x1a\\n\\x06Output\\x12\\x10\\n\\x08\\x62\\x61tch_id\\x18\\x01 \\x01(\\x04\\x32n\\n\\tInference\\x12*\\n\\x07\\x43ompute\\x12\\r.simple.Input\\x1a\\x0e.simple.Output\\\"\\x00\\x12\\x35\\n\\x0e\\x42\\x61tchedCompute\\x12\\r.simple.Input\\x1a\\x0e.simple.Output\\\"\\x00(\\x01\\x30\\x01\\x62\\x06proto3')\n)\n\n\n\n\n_INPUT = _descriptor.Descriptor(\n  name='Input',\n  full_name='simple.Input',\n  filename=None,\n  file=DESCRIPTOR,\n  containing_type=None,\n  fields=[\n    _descriptor.FieldDescriptor(\n      name='batch_id', full_name='simple.Input.batch_id', index=0,\n      number=1, type=4, cpp_type=4, label=1,\n      has_default_value=False, default_value=0,\n      message_type=None, enum_type=None, containing_type=None,\n      is_extension=False, extension_scope=None,\n      options=None, file=DESCRIPTOR),\n  ],\n  extensions=[\n  ],\n  nested_types=[],\n  enum_types=[\n  ],\n  options=None,\n  is_extendable=False,\n  syntax='proto3',\n  extension_ranges=[],\n  oneofs=[\n  ],\n  serialized_start=24,\n  serialized_end=49,\n)\n\n\n_OUTPUT = _descriptor.Descriptor(\n  name='Output',\n  full_name='simple.Output',\n  filename=None,\n  file=DESCRIPTOR,\n  containing_type=None,\n  fields=[\n    _descriptor.FieldDescriptor(\n      name='batch_id', full_name='simple.Output.batch_id', index=0,\n      number=1, type=4, cpp_type=4, label=1,\n      has_default_value=False, default_value=0,\n      message_type=None, enum_type=None, containing_type=None,\n      is_extension=False, extension_scope=None,\n      options=None, file=DESCRIPTOR),\n  ],\n  extensions=[\n  ],\n  nested_types=[],\n  enum_types=[\n  ],\n  options=None,\n  is_extendable=False,\n  syntax='proto3',\n  extension_ranges=[],\n  oneofs=[\n  ],\n  serialized_start=51,\n  serialized_end=77,\n)\n\nDESCRIPTOR.message_types_by_name['Input'] = _INPUT\nDESCRIPTOR.message_types_by_name['Output'] = _OUTPUT\n_sym_db.RegisterFileDescriptor(DESCRIPTOR)\n\nInput = _reflection.GeneratedProtocolMessageType('Input', (_message.Message,), dict(\n  DESCRIPTOR = _INPUT,\n  __module__ = 'simple_pb2'\n  # @@protoc_insertion_point(class_scope:simple.Input)\n  ))\n_sym_db.RegisterMessage(Input)\n\nOutput = _reflection.GeneratedProtocolMessageType('Output', (_message.Message,), dict(\n  DESCRIPTOR = _OUTPUT,\n  __module__ = 'simple_pb2'\n  # @@protoc_insertion_point(class_scope:simple.Output)\n  ))\n_sym_db.RegisterMessage(Output)\n\n\n\n_INFERENCE = _descriptor.ServiceDescriptor(\n  name='Inference',\n  full_name='simple.Inference',\n  file=DESCRIPTOR,\n  index=0,\n  options=None,\n  serialized_start=79,\n  serialized_end=189,\n  methods=[\n  _descriptor.MethodDescriptor(\n    name='Compute',\n    full_name='simple.Inference.Compute',\n    index=0,\n    containing_service=None,\n    input_type=_INPUT,\n    output_type=_OUTPUT,\n    options=None,\n  ),\n  _descriptor.MethodDescriptor(\n    name='BatchedCompute',\n    full_name='simple.Inference.BatchedCompute',\n    index=1,\n    containing_service=None,\n    input_type=_INPUT,\n    output_type=_OUTPUT,\n    options=None,\n  ),\n])\n_sym_db.RegisterServiceDescriptor(_INFERENCE)\n\nDESCRIPTOR.services_by_name['Inference'] = _INFERENCE\n\n# @@protoc_insertion_point(module_scope)\n"
  },
  {
    "path": "examples/03_Batching/simple_pb2_grpc.py",
    "content": "# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!\nimport grpc\n\nimport simple_pb2 as simple__pb2\n\n\nclass InferenceStub(object):\n  # missing associated documentation comment in .proto file\n  pass\n\n  def __init__(self, channel):\n    \"\"\"Constructor.\n\n    Args:\n      channel: A grpc.Channel.\n    \"\"\"\n    self.Compute = channel.unary_unary(\n        '/simple.Inference/Compute',\n        request_serializer=simple__pb2.Input.SerializeToString,\n        response_deserializer=simple__pb2.Output.FromString,\n        )\n    self.BatchedCompute = channel.stream_stream(\n        '/simple.Inference/BatchedCompute',\n        request_serializer=simple__pb2.Input.SerializeToString,\n        response_deserializer=simple__pb2.Output.FromString,\n        )\n\n\nclass InferenceServicer(object):\n  # missing associated documentation comment in .proto file\n  pass\n\n  def Compute(self, request, context):\n    # missing associated documentation comment in .proto file\n    pass\n    context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n    context.set_details('Method not implemented!')\n    raise NotImplementedError('Method not implemented!')\n\n  def BatchedCompute(self, request_iterator, context):\n    # missing associated documentation comment in .proto file\n    pass\n    context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n    context.set_details('Method not implemented!')\n    raise NotImplementedError('Method not implemented!')\n\n\ndef add_InferenceServicer_to_server(servicer, server):\n  rpc_method_handlers = {\n      'Compute': grpc.unary_unary_rpc_method_handler(\n          servicer.Compute,\n          request_deserializer=simple__pb2.Input.FromString,\n          response_serializer=simple__pb2.Output.SerializeToString,\n      ),\n      'BatchedCompute': grpc.stream_stream_rpc_method_handler(\n          servicer.BatchedCompute,\n          request_deserializer=simple__pb2.Input.FromString,\n          response_serializer=simple__pb2.Output.SerializeToString,\n      ),\n  }\n  generic_handler = grpc.method_handlers_generic_handler(\n      'simple.Inference', rpc_method_handlers)\n  server.add_generic_rpc_handlers((generic_handler,))\n"
  },
  {
    "path": "examples/03_Batching/streaming-service.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"nvrpc/context.h\"\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/rpc.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::BatchingContext;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n\nclass SimpleContext final : public BatchingContext<simple::Input, simple::Output, Resources>\n{\n    void ExecuteRPC(std::vector<RequestType>& inputs,\n                    std::vector<ResponseType>& outputs) final override\n    {\n        for(auto input = inputs.cbegin(); input != inputs.cend(); input++)\n        {\n            auto output = outputs.emplace(outputs.end());\n            output->set_batch_id(input->batch_id());\n            LOG(INFO) << \"Response with batch_id=\" << output->batch_id();\n        }\n        this->FinishResponse();\n    }\n\n    void OnRequestReceived(const RequestType& request) final override\n    {\n        LOG(INFO) << \"Recieved request with batch_id=\" << request.batch_id();\n    }\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    Server server(\"0.0.0.0:50051\");\n\n    LOG(INFO) << \"Register Service (simple::Inference)\";\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n\n    LOG(INFO)\n        << \"Register RPC (simple::Inference::BatchedCompute) with Service (simple::Inference)\";\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestBatchedCompute);\n\n    LOG(INFO) << \"Initializing Resources for RPC (simple::Inference::BatchedCompute)\";\n    auto rpcResources = std::make_shared<Resources>();\n\n    LOG(INFO) << \"Creating Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    LOG(INFO) << \"Creating Execution Contexts for RPC (simple::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {\n        // This is a timeout loop executed every 2seconds\n        // Run() with no arguments will run an empty timeout loop every 5 seconds.\n        // RunAsync() will return immediately, its your responsibility to ensure the\n        // server doesn't go out of scope or a Shutdown will be triggered on your services.\n    });\n}\n"
  },
  {
    "path": "examples/03_Batching/unary_client.py",
    "content": "import grpc\n\nimport simple_pb2\nimport simple_pb2_grpc\n\n\ndef run():\n    with grpc.insecure_channel('localhost:50049') as channel:\n        stub = simple_pb2_grpc.InferenceStub(channel)\n        \n        response  = stub.Compute(simple_pb2.Input(batch_id=78))\n        print(\"Received msg  with batch_id={}\".format(response.batch_id))\n\nif __name__ == \"__main__\":\n    run() \n"
  },
  {
    "path": "examples/04_Middleman/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(middleman-client.x\n    middleman-client.cc\n)\n\ntarget_link_libraries(middleman-client.x\n    trtlab::nvrpc\n    nv-inference-protos\n    gflags\n)\n"
  },
  {
    "path": "examples/04_Middleman/middleman-client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"tensorrt/laboratory/core/memory/allocator.h\"\n#include \"tensorrt/laboratory/core/memory/malloc.h\"\n\nusing trtlab::Allocator;\nusing trtlab::Malloc;\n\n#include \"nvrpc/context.h\"\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::ThreadPool;\n\n#include \"moodycamel/blockingconcurrentqueue.h\"\n\nusing moodycamel::BlockingConcurrentQueue;\nusing moodycamel::ConsumerToken;\nusing moodycamel::ProducerToken;\n\n// NVIDIA Inference Server Protos\n#include \"nvidia_inference.grpc.pb.h\"\n#include \"nvidia_inference.pb.h\"\n\nnamespace easter = ::nvidia::inferenceserver;\n/*\nusing nvidia::inferenceserver::GRPCService;\nusing nvidia::inferenceserver::InferRequest;\nusing nvidia::inferenceserver::InferResponse;\n*/\n\n/**\n * @brief Batching Service for Unary Requests\n *\n * Exposes a Unary (send/recv) interface for a given RPC, but rather than\n * computing the RPC, the service simply batches the incoming requests and\n * forwards them via a gRPC stream to a service that implements the actual\n * compute portion of the RPC.\n *\n * The backend compute service is not a Unary service.  Rather it must\n * implemented the LifeCycleBatching service Context, i.e. BatchingContext.\n * The other application in this folder implements the backend service.\n *\n * Streams are used as a forwarding mechanism because of how they interact\n * with a load-balancer.  Unlike unary requests which get balanced on each\n * request, a stream only get balanced when it is opened.  All items of a stream\n * go to the same endpoint service.\n *\n * @tparam ServiceType\n * @tparam Request\n * @tparam Response\n */\ntemplate<class ServiceType, class Request, class Response>\nstruct MiddlemanService\n{\n    using Callback = std::function<void(bool)>;\n\n    struct MessageType\n    {\n        Request* request;\n        Response* response;\n        Callback callback;\n    };\n\n    /**\n     * @brief Forwards incoming Unary requests via a gRPC Stream to\n     * a Batched Steaming Service that implements the actual RPC\n     */\n    class Client\n    {\n      public:\n        using PrepareFunc =\n            std::function<std::unique_ptr<::grpc::ClientAsyncResponseReader<Response>>(\n                ::grpc::ClientContext*, const Request&, ::grpc::CompletionQueue*)>;\n\n        Client(PrepareFunc prepare_func, std::shared_ptr<ThreadPool> thread_pool)\n            : m_PrepareFunc(prepare_func), m_ThreadPool(thread_pool), m_CurrentCQ(0)\n        {\n            for(decltype(m_ThreadPool->Size()) i = 0; i < m_ThreadPool->Size(); i++)\n            {\n                LOG(INFO) << \"Starting Client Progress Engine #\" << i;\n                m_CQs.emplace_back(new ::grpc::CompletionQueue);\n                auto cq = m_CQs.back().get();\n                m_ThreadPool->enqueue([this, cq] { ProgressEngine(*cq); });\n            }\n        }\n\n        void WriteAndCloseStream(uint32_t messages_count, MessageType* messages)\n        {\n            auto cq = m_CQs[++m_CurrentCQ % m_CQs.size()].get();\n            DLOG(INFO) << \"Client using CQ: \" << (void*)cq;\n            CHECK_EQ(1U, messages_count) << \"forwarder; not batcher\";\n\n            auto ctx = new Call;\n            for(uint32_t i = 0; i < messages_count; i++)\n            {\n                ctx->Push(messages[i]);\n            }\n\n            ctx->m_Reader = m_PrepareFunc(&ctx->m_Context, *ctx->m_Request, cq);\n            ctx->m_Reader->StartCall();\n            ctx->m_Reader->Finish(ctx->m_Response, &ctx->m_Status, ctx->Tag());\n        }\n\n      private:\n        class Call\n        {\n          public:\n            Call() : m_NextState(&Call::StateFinishedDone) {}\n            virtual ~Call() {}\n\n            void Push(MessageType& message)\n            {\n                m_Request = message.request;\n                m_Response = message.response;\n                m_Callback = message.callback;\n            }\n\n          private:\n            bool RunNextState(bool ok)\n            {\n                bool ret = (this->*m_NextState)(ok);\n                if(!ret) DLOG(INFO) << \"RunNextState returning false\";\n                return ret;\n            }\n\n            void* Tag() { return static_cast<void*>(this); }\n\n            bool Fail()\n            {\n                LOG(FATAL) << \"Fail\";\n                return false;\n            }\n\n            bool StateFinishedDone(bool ok)\n            {\n                if(m_Status.ok())\n                    DLOG(INFO) << \"ClientContext: \" << Tag() << \" finished with OK\";\n                else\n                    DLOG(INFO) << \"ClientContext: \" << Tag() << \" finished with CANCELLED\";\n                m_Callback(m_Status.ok());\n                DLOG(INFO) << \"Forwarding Completed for Tag \" << Tag();\n                return false;\n            }\n\n          private:\n            Request* m_Request;\n            Response* m_Response;\n            Callback m_Callback;\n\n            bool (Call::*m_NextState)(bool);\n\n            ::grpc::Status m_Status;\n            ::grpc::ClientContext m_Context;\n            std::unique_ptr<::grpc::ClientAsyncResponseReader<Response>> m_Reader;\n\n            friend class Client;\n        };\n\n        void ProgressEngine(::grpc::CompletionQueue& cq)\n        {\n            void* tag;\n            bool ok = false;\n\n            while(cq.Next(&tag, &ok))\n            {\n                CHECK(ok) << \"not ok\";\n                Call* call = static_cast<Call*>(tag);\n                if(!call->RunNextState(ok))\n                {\n                    DLOG(INFO) << \"Deleting Stream: \" << tag;\n                    delete call;\n                }\n            }\n        }\n\n        int m_CurrentCQ;\n        PrepareFunc m_PrepareFunc;\n        std::shared_ptr<ThreadPool> m_ThreadPool;\n        std::vector<std::unique_ptr<::grpc::CompletionQueue>> m_CQs;\n    };\n\n  public:\n    class Resources : public ::trtlab::Resources\n    {\n      public:\n        Resources(uint32_t max_batch_size, uint64_t timeout, std::shared_ptr<Client> client)\n            : m_MaxBatchsize(max_batch_size), m_Timeout(timeout), m_Client(client)\n        {\n        }\n\n        virtual void PreprocessRequest(Request* req) {}\n\n        void Push(Request* req, Response* resp, Callback callback)\n        {\n            // thread_local ProducerToken token(m_MessageQueue);\n            // m_MessageQueue.enqueue(token, MessageType(req, resp, callback));\n            PreprocessRequest(req);\n            m_MessageQueue.enqueue(MessageType{req, resp, callback});\n        }\n\n        void ProgressEngine()\n        {\n            constexpr uint64_t quanta = 100;\n            const double timeout = static_cast<double>(m_Timeout - quanta) / 1000000.0;\n            size_t total_count;\n            size_t max_batch;\n\n            thread_local ConsumerToken token(m_MessageQueue);\n            for(;;)\n            {\n                MessageType messages[m_MaxBatchsize];\n                max_batch = m_MaxBatchsize;\n                total_count = 0;\n                auto start = std::chrono::steady_clock::now();\n                auto elapsed = [start]() -> double {\n                    return std::chrono::duration<double>(std::chrono::steady_clock::now() - start)\n                        .count();\n                };\n                do\n                {\n                    auto count = m_MessageQueue.wait_dequeue_bulk_timed(\n                        token, &messages[total_count], max_batch, quanta);\n                    CHECK_LE(count, max_batch);\n                    total_count += count;\n                    max_batch -= count;\n                } while(total_count && total_count < m_MaxBatchsize && elapsed() < timeout);\n                if(total_count)\n                {\n                    m_Client->WriteAndCloseStream(total_count, messages);\n                }\n            }\n        }\n\n      private:\n        size_t m_MaxBatchsize;\n        uint64_t m_Timeout;\n        std::shared_ptr<Client> m_Client;\n        BlockingConcurrentQueue<MessageType> m_MessageQueue;\n    };\n\n    class ReceiveContext final : public ::nvrpc::Context<Request, Response, Resources>\n    {\n        void ExecuteRPC(Request& request, Response& response) final override\n        {\n            DLOG(INFO) << \"incoming unary request\";\n            this->GetResources()->Push(&request, &response, [this](bool ok) {\n                if(ok)\n                    this->FinishResponse();\n                else\n                {\n                    LOG(INFO) << \"shoot\";\n                    this->CancelResponse();\n                }\n            });\n        }\n    };\n};\n\nDEFINE_uint32(max_batch_size, 1, \"Maximum batch size to collect and foward\");\nDEFINE_uint64(timeout_usecs, 200, \"Batching window timeout in microseconds\");\nDEFINE_uint32(max_batches_in_flight, 300, \"Maximum number of forwarded batches\");\nDEFINE_uint32(receiving_threads, 2, \"Number of Forwarding threads\");\nDEFINE_uint32(forwarding_threads, 2, \"Number of Forwarding threads\");\nDEFINE_string(forwarding_target, \"localhost:8001\", \"Batched Compute Service / Load-Balancer\");\n\nusing InferMiddlemanService =\n    MiddlemanService<easter::GRPCService, easter::InferRequest, easter::InferResponse>;\nusing StatusMiddlemanService =\n    MiddlemanService<easter::GRPCService, easter::StatusRequest, easter::StatusResponse>;\n\nclass DemoMiddlemanService : public InferMiddlemanService\n{\n  public:\n    class Resources : public InferMiddlemanService::Resources\n    {\n      public:\n        using InferMiddlemanService::Resources::Resources;\n        void PreprocessRequest(easter::InferRequest* req) override\n        {\n            static auto local_data = std::make_unique<Allocator<Malloc>>(10 * 1024 * 1024);\n            DLOG(INFO) << \"Boom - preprocess request here!\";\n            auto bytes = req->meta_data().batch_size() * req->meta_data().input(0).byte_size();\n            CHECK_EQ(0, req->raw_input_size());\n            req->add_raw_input(local_data->Data(), bytes);\n        }\n    };\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"easterForwardingService\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    grpc::ChannelArguments ch_args;\n    ch_args.SetMaxReceiveMessageSize(-1);\n    auto channel = grpc::CreateCustomChannel(FLAGS_forwarding_target,\n                                             grpc::InsecureChannelCredentials(), ch_args);\n\n    // GRPCService::Infer async forwarder\n    auto forwarding_threads = std::make_shared<ThreadPool>(FLAGS_forwarding_threads);\n    auto stub = ::easter::GRPCService::NewStub(channel);\n    auto forwarding_prepare_func = [&stub](::grpc::ClientContext * context,\n                                           const ::easter::InferRequest& request,\n                                           ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncInfer(context, request, cq));\n    };\n    auto client =\n        std::make_shared<DemoMiddlemanService::Client>(forwarding_prepare_func, forwarding_threads);\n\n    // GRPCService::Status async forwarder\n    auto status_forwarding_threads = std::make_shared<ThreadPool>(1);\n    auto status_stub = ::easter::GRPCService::NewStub(channel);\n    auto status_forwarding_prepare_func = [&stub](::grpc::ClientContext * context,\n                                                  const ::easter::StatusRequest& request,\n                                                  ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncStatus(context, request, cq));\n    };\n    auto status_client = std::make_shared<StatusMiddlemanService::Client>(\n        status_forwarding_prepare_func, status_forwarding_threads);\n\n    auto rpcResources = std::make_shared<DemoMiddlemanService::Resources>(\n        FLAGS_max_batch_size, FLAGS_timeout_usecs, client);\n\n    auto statusResources = std::make_shared<StatusMiddlemanService::Resources>(\n        FLAGS_max_batch_size, FLAGS_timeout_usecs, status_client);\n\n    Server server(\"0.0.0.0:50049\");\n    auto bytes = trtlab::StringToBytes(\"100MiB\");\n    server.Builder().SetMaxReceiveMessageSize(bytes);\n    LOG(INFO) << \"gRPC MaxReceiveMessageSize = \" << trtlab::BytesToString(bytes);\n\n    auto recvService = server.RegisterAsyncService<::easter::GRPCService>();\n    auto rpcCompute = recvService->RegisterRPC<DemoMiddlemanService::ReceiveContext>(\n        &::easter::GRPCService::AsyncService::RequestInfer);\n    auto rpcStatus = recvService->RegisterRPC<StatusMiddlemanService::ReceiveContext>(\n        &::easter::GRPCService::AsyncService::RequestStatus);\n\n    uint64_t context_count = FLAGS_max_batch_size * FLAGS_max_batches_in_flight;\n    uint64_t contexts_per_executor_thread = std::max(context_count / FLAGS_receiving_threads, 1UL);\n\n    auto executor = server.RegisterExecutor(new Executor(FLAGS_receiving_threads));\n    executor->RegisterContexts(rpcCompute, rpcResources, contexts_per_executor_thread);\n\n    auto status_executor = server.RegisterExecutor(new Executor(1));\n    status_executor->RegisterContexts(rpcStatus, statusResources, 1);\n\n    auto executor_threads = std::make_shared<ThreadPool>(2);\n    executor_threads->enqueue([rpcResources] { rpcResources->ProgressEngine(); });\n    executor_threads->enqueue([statusResources] { statusResources->ProgressEngine(); });\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(1), [] {});\n}\n"
  },
  {
    "path": "examples/10_Internals/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(internals.x\n    internals.cc\n)\ntarget_link_libraries(internals.x\n    trtlab::core\n    trtlab::cuda\n    gflags\n)"
  },
  {
    "path": "examples/10_Internals/README.md",
    "content": "# YAIS Internals\n\nThe `internals.x` program is designed to be run on a DGX-Station or DGX-1.  This is mostly to highlight\nthe use of the Affinity API.  If you want to run on a different CPU architecture, you simply need to\nchange the following lines to a range that works with your CPU.\n\n```\n    // Socket 1 - non-hyperthreads on a DGX-1, or\n    // Socket 0 - hyperthreads on a DGX-Station\n    auto socket_1 = Affinity::GetAffinity().Intersection(\n        Affinity::GetCpusFromString(\"20-39\") // <== Change Me!\n    );\n```\n\n## Primative Classes\n\n  * `Affinity` \n    * Get and Set CPU affinities for current thread\n  * `ThreadPool` \n    * Create generic worker thread pool that accept arbiturary lambda functions.\n    * Pinned threads from `ThreadPools` are used to allocate memory to ensure that the CPU allocation\n      are allocated and first-touched on the threads on the NUMA node for which it will be used.\n      This is important for keeping threads and memory pool separate on NUMA systems.\n  * `Memory`\n    * `Memory` and the derived classes (`MallocMemory`, `CudaPinnedHostMemory`, `CudaDeviceMemory`) are not\n      used directly; however they provided the implmentation details used by the generic `Allocator`.\n  * `Allocator<MemoryType>`\n    * Generic Templated Class used to create `std::shared_ptr` and `std::unique_ptr` to instances of\n      `Allocator<MemoryType>`.\n  * `MemoryStack<AllocatorType>`\n    * Generic Templated Class to create a memory stack from a given `AllocatorType`.\n    * You can only advance the stack pointer, or reset the entire stack.\n    * TODO: Create sub-stacks from a given stack.\n  * `Pool<ResourceType>`\n    * Generic Templated Class that holds objects of `ResourceType`.\n    * Resources can be checked-out of the Pool (Pop) as a *special-type* of `std::shared_ptr<ResourceType>`,\n      which automatically returned the Resource object the pool when the reference count of the\n      `shared_ptr` goes to zero.  This Resources are not lost on exceptions, but also that the Pool can not\n      be deleted until all object have been returned to the Pool.\n\n## TensorRT Classes\n\n  * `Model` \n    * Wrapper around `nvinfer1::ICudaEngine`\n  * `Buffers` \n    * `MemoryStackWithTracking<CudaPinnedHostMemory>` and `MemoryStackWithTracking<CudaDeviceMemory>` used\n      to manage Input/Output Tensor Bindings.\n    * Owns a `cudaStream_t` to be used with Async Copies and Kernel Executions on the data held by the Buffers.\n    * Convenience H2D and D2H copy functions\n  * `ExecutionContext` - Wrapper around `nvinfer1::IExecutionContext`\n    * `Enqueue` launches the inference calculuation and adds a `cudaEvent_t` to the stream to be triggered\n      when the inference calcuation is finished and the `ExecutionContext` can be released.\n  * `Resources`\n    * Combines the above set of resources into a single `trtlab::Resources` class capable of being associated\n      with a `nvrpc::Context`.\n\n\n## Examples\n\n### Affinity\n\n  * [Definition: tensorrt/laboratory/core/affinity.h](../../yais/include/tensorrt/laboratory/core/affinity.h)\n  * [Implementation: YAIS/Affinity.cc](../../yais/src/Affinity.cc)\n\nIn this, we request the all logical CPUs from Socket 0 that are not hyperthreads, then we get either all \nthe non-hyperthreads from socket_1 on a DGX-1, or the hyperthreads on socket0 on a DGX-Station using \n`GetCpusFromString`.\n\n```\n    // Socket 0 - non-hyperthreads on a DGX-1 or Station\n    auto socket_0 = Affinity::GetAffinity().Intersection(\n        Affinity::GetCpusBySocket(0).Intersection(\n            Affinity::GetCpusByProcessingUnit(0)\n    ));\n\n    // Socket 1 - non-hyperthreads on a DGX-1, or\n    // Socket 0 - hyperthreads on a DGX-Station\n    auto socket_1 = Affinity::GetAffinity().Intersection(\n        Affinity::GetCpusFromString(\"20-39\")\n    );\n\n    LOG(INFO) << socket_0;\n```\n\nSingle line output reformatted to per-line-indented output for readability.\n```\n0515 07:14:48.007148 10919 test_affinity.cc:61] \n    [id: 0, numa: 0, socket: 0, core: 0, processing_unit: 0], \n    [id: 1, numa: 0, socket: 0, core: 1, processing_unit: 0], \n    [id: 2, numa: 0, socket: 0, core: 2, processing_unit: 0],\n    ... omitted for brevity ...\n    [id: 18, numa: 0, socket: 0, core: 18, processing_unit: 0], \n    [id: 19, numa: 0, socket: 0, core: 19, processing_unit: 0]\n```\n\n### ThreadPool\n\n  * [Definition: tensorrt/laboratory/core/thread_pool.h](../../yais/include/tensorrt/laboratory/core/thread_pool.h)\n  * [Implementation: YAIS/ThreadPool.cc](../../yais/src/ThreadPool.cc)\n\nThe ThreadPool class creates a pool of worker threads that pull work from a queue.  The work queue can\nbe any set of captured lambda functions or function pointers passed to the `enqueue` function.\n\n```\n    // Create a ThreadPool where each thread is pinned to one logical CPU in the CpuSet\n    auto workers_0 = std::make_shared<ThreadPool>(socket_0);\n    auto workers_1 = std::make_shared<ThreadPool>(socket_1);\n\n    // Create a massive set of threads that can run anywhere our current process is allowed to run\n    auto bftp = std::make_unique<ThreadPool>(128, Affinity::GetAffinity());\n\n    // Shutdown the BFTP\n    bftp.reset();\n\n    // Enqueue some basic logging\n    for(int i=0; i<10; i++) {\n        auto result = workers->enqueue([i]{\n            LOG(INFO) << i << \" \" << Affinity::GetAffinity();\n            std::this_thread::sleep_for(std::chrono::milliseconds(10));\n        });\n    }\n```\n\nAs these ThreadPools are generic, we can enqueue any type of work to them.  Many thanks to the original\nauthors Jakob Progsch and Václav Zeman for this incredible useful class.  For details on the original\nwork and the modificiations made in this project, see [CREDITS.md](../../CREDITS.md) and the source code.\n\n\n### Memory\n\nOne of the reasons why `Affinity` and `ThreadPool` were introduced prior to `Memory` is that memory on\nNUMA system can be difficult to do correctly.  For memory segments that will be primarly used by sets\nof threads, it is very important to first set the affinity of the threads, then allocate and touch each\npage in the memory allocation (first-touch) on the thread that will primarly use the segment.  NERSC \nhas a nice [write-up on memory affinity and first touch policies](http://www.nersc.gov/users/computational-systems/cori/application-porting-and-performance/improving-openmp-scaling/).\nIn this section, we'll show how to properly use the `Memory` and `Allocator` classes in a NUMA friendly\nway using `ThreadPool`s.\n\n  * [Definition: tensorrt/laboratory/core/memory.h](../../yais/include/tensorrt/laboratory/core/memory.h)\n\nThe `Memory` class and its derived classes, see below, are the core memory classes in YAIS; however,\nthese classes are not direclty used.  Instead, they provide the implmentation details on how memory of\ntheir respective classes is to be allocated, freed, and page-aligned.  For details, see the comments\nin the source code.\n\nDerived `Memory` Classes:\n  * `Malloc`\n  * `CudaPinnedHostMemory`\n  * `CudaDeviceMemory`\n  * `CudaManagedMemory`\n\n### Allocator<MemoryType>\n\n  * [Definition: tensorrt/laboratory/core/memory.h](../../yais/include/tensorrt/laboratory/core/memory.h)\n\nThe templated `Allocator<MemoryType>` class performs memory allocations and freeing operations.  This\nclass does not have a public constructor, instead, you are required to use either the `make_shared`\nor `make_unique` static methods.  In doing so, the method to free the allocation is captured by the\ndeconstructor which is triggered by the default deleter of `shared_ptr` and `unique_ptr`.\n\nAn allocated memory segments is of type `Allocator<MemoryType>` which inherits from `MemoryType`.\nThe base `Memory` class provides three functions, `GetPointer()`, `GetSize()`, and `WriteZeros()`.\n\n```\n    std::shared_ptr<CudaPinnedHostMemory> pinned_0, pinned_1;\n\n    auto future_0 = workers_0->enqueue([&pinned_0]{\n        pinned_0 = Allocator<CudaPinnedHostMemory>::make_shared(1024*1024*1024);\n        pinned_0->WriteZeros();\n    });\n\n    auto future_1 = workers_1->enqueue([&pinned_1]{\n        pinned_1 = Allocator<CudaPinnedHostMemory>::make_shared(1024*1024*1024);\n        pinned_1->WriteZeros();\n    });\n\n    future_0.get();\n    CHECK(pinned_0) << \"pinned_0 got deallocated - fail\";\n    LOG(INFO) << \"pinned_0 (ptr, size): (\" \n              << pinned_0->GetPointer() << \", \"\n              << pinned_0->GetSize() << \")\";\n```\n\n```\nI0515 08:36:56.619297 13260 test_affinity.cc:59] pinned_0 (ptr, size): (0x1005e000000, 1073741824)\n```\n\n### MemoryStack<AllocatorType>\n\n  * [Definition: tensorrt/laboratory/core/memory_stack.h](../../yais/include/tensorrt/laboratory/core/memory_stack.h)\n\nGeneric `MemoryStack` that takes an `AllocatorType`.  The memory stack advances the stack pointer\nvia `Allocate` and resets the stack pointer via `ResetAllocations`.  `MemoryStackWithTracking`\nis a specialized derivation that records the pointer and size of each call to `Allocate`.\n`MemoryStackWithTracking` is used in the provided TensorRT classes as a means to push the\ninput/output tensor bindings onto the stack.\n\n```\n    std::shared_ptr<MemoryStackWithTracking<CudaDeviceMemory>> gpu_stack_on_socket0;\n\n    future_0 = workers_0->enqueue([&gpu_stack_on_socket0]{\n        CHECK_EQ(cudaSetDevice(0), CUDA_SUCCESS) << \"Set Device 0 failed\";\n        gpu_stack_on_socket0 = std::make_shared<\n            MemoryStackWithTracking<CudaDeviceMemory>>(1024*1024*1024);\n    });\n\n    future_0.get(); // thread allocating gpu_stack_on_socket0 finished with task\n    \n    LOG(INFO) << \"Push Binding 0 - 10MB - stack_ptr = \" \n        << gpu_stack_on_socket0->Allocate(10*1024*1024);\n    LOG(INFO) << \"Push Binding 1 - 128MB - stack_ptr = \" \n        << gpu_stack_on_socket0->Allocate(128*1024*1024);\n    gpu_stack_on_socket0->ResetAllocations();\n```\n\n```\nI0515 09:46:55.159700 14176 test_affinity.cc:78] Push Binding 0 - 10MB - stack_ptr = 0x1009e000000\nI0515 09:46:55.159710 14176 test_affinity.cc:80] Push Binding 1 - 128MB - stack_ptr = 0x1009ea00000\n```\n\n### Pool<ResourceType>\n\n  * [Definition: tensorrt/laboratory/core/pool.h](../../yais/include/tensorrt/laboratory/core/pool.h)\n\nA `Pool<ResourceType>` is a generic of `Queue<std::shared_ptr<ResourceType>>` with a special `Pop`\nmethod.  The class inherits from `std::enabled_shared_from_this` meaning it must be constructed using\nthe factory method, which ensures the object is owned by a `std::shared_ptr`.\n\nThe `Pop` method of `Pool<ResourceType>` is probably the coolest and most contensious component of this\nlibrary.  `Pop` pulls an resource off the queue (`from_queue`); however, it does not return this resource.\nInstead, a *new type* of `std::shared_ptr<ResourceType>` is created using the raw pointer from `from_pool`.\nThe reason they this is a *new type* of `shared_ptr` is because we provide a custom `Deleter` method that\ncaptures by value (increments reference count) of both `from_pool` and a `shared_ptr` to the pool itself.\n\nThe custom `Deleter` does not free the resource when its reference count goes to zero; rather, it returns\nthe original `from_pool` `shared_ptr` to the pool.\n\nBy capturing a `shared_ptr` to the pool in the `Deleter`, we ensure the the pool can not be freed while\nresources are checkedout.  This also ensures that the `shared_ptr` returned from `Pop` is exception\nsafe; meaning, the resource will be returned to the pool if an exception is thrown and caught - it won't\nleak resources.\n\nAlternatively, `Pop` can be called with an `onReturn` lambda function, which will be executed just prior\nto the original object being returned to the Pool. If the `ResourceType` is stateful, this is a good \nchance to clear the state and prepare it for the next use.\n\n```\n    struct Buffer\n    {\n        Buffer(\n            std::shared_ptr<CudaPinnedHostMemory> pinned_,\n            std::shared_ptr<MemoryStackWithTracking<CudaDeviceMemory>> gpu_stack_,\n            std::shared_ptr<ThreadPool> workers_\n        ) : pinned(pinned_), gpu_stack(gpu_stack_), workers(workers_) {}\n\n        // a real example probably includes a deviceID and a stream as part of the buffer\n\n        std::shared_ptr<CudaPinnedHostMemory> pinned;\n        std::shared_ptr<MemoryStackWithTracking<CudaDeviceMemory>> gpu_stack;\n        std::shared_ptr<ThreadPool> workers;\n    };\n\n    auto buffers = Pool<Buffer>::Create();\n\n    buffers->EmplacePush(new Buffer(pinned_0, gpu_stack_on_socket0, workers_0));\n    buffers->EmplacePush(new Buffer(pinned_1, gpu_stack_on_socket1, workers_1));\n\n    for(int i=0; i<6; i++)\n    {\n        auto buffer = buffers->Pop();\n        buffer->workers->enqueue([buffer]{\n            // perform some work - regardless of which buffer you got, you are working\n            // on a thread properly assocated with the resources\n            // note: buffer is captures by value, incrementing its reference count,\n            // meaning you have access to it here and when it goes out of scope, it will\n            // be returned to the Pool.\n            LOG(INFO) << Affinity::GetAffinity();\n        });\n    }\n```\n\n## TensorRT Examples\n\n  * [Definition: YAIS/YAIS/TensorRT/TensorRT.h](../../yais/include/YAIS/TensorRT/TensorRT.h)\n  * [Implemenation: YAIS/TensorRT.cc](../../yais/src/TensorRT.cc)\n\nTensoRT classes build on the primatives above.  For now, see the comments in the header file, as\nthe header file is pretty well documented.\n"
  },
  {
    "path": "examples/10_Internals/internals.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"tensorrt/laboratory/core/affinity.h\"\n#include \"tensorrt/laboratory/core/memory/allocator.h\"\n#include \"tensorrt/laboratory/core/memory/memory_stack.h\"\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n#include \"tensorrt/laboratory/cuda/device_info.h\"\n#include \"tensorrt/laboratory/cuda/memory/cuda_device.h\"\n#include \"tensorrt/laboratory/cuda/memory/cuda_managed.h\"\n#include \"tensorrt/laboratory/cuda/memory/cuda_pinned_host.h\"\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <glog/logging.h>\n\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing trtlab::Affinity;\nusing trtlab::Allocator;\nusing trtlab::CpuSet;\nusing trtlab::CudaDeviceMemory;\nusing trtlab::CudaPinnedHostMemory;\nusing trtlab::DeviceInfo;\nusing trtlab::MemoryStack;\nusing trtlab::Pool;\nusing trtlab::ThreadPool;\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"example10/internals.x\");\n\n    auto one_gib = 1024 * 1024 * 1024;\n    auto zeroMemory = true;\n\n    const auto& gpu_0 = DeviceInfo::Affinity(0);\n\n    // Socket 0 - non-hyperthreads on a DGX-1 or Station\n    const auto& socket_0 = Affinity::GetAffinity().Intersection(\n        Affinity::GetCpusBySocket(0).Intersection(Affinity::GetCpusByProcessingUnit(0)));\n\n    // Socket 1 - non-hyperthreads on a DGX-1, or\n    // Socket 0 - hyperthreads on a DGX-Station\n    const auto& socket_1 =\n        Affinity::GetAffinity().Intersection(Affinity::GetCpusFromString(\"20-39\"));\n\n    auto workers_0 = std::make_shared<ThreadPool>(socket_0);\n    auto workers_1 = std::make_shared<ThreadPool>(socket_1);\n\n    std::shared_ptr<CudaPinnedHostMemory> pinned_0, pinned_1;\n\n    auto future_0 = workers_0->enqueue([=, &pinned_0] {\n        pinned_0 = std::make_shared<Allocator<CudaPinnedHostMemory>>(one_gib);\n        pinned_0->Fill(0);\n    });\n\n    auto future_1 = workers_1->enqueue([=, &pinned_1] {\n        pinned_1 = std::make_shared<Allocator<CudaPinnedHostMemory>>(one_gib);\n        pinned_1->Fill(0);\n    });\n\n    LOG(INFO) << socket_0;\n\n    future_0.get();\n    CHECK(pinned_0) << \"pinned_0 got deAllocator - fail\";\n    LOG(INFO) << \"pinned_0 (ptr, size): (\" << pinned_0->Data() << \", \" << pinned_0->Size() << \")\";\n    future_1.get();\n\n    std::shared_ptr<MemoryStack<CudaDeviceMemory>> gpu_stack_on_socket0;\n    std::shared_ptr<MemoryStack<CudaDeviceMemory>> gpu_stack_on_socket1;\n\n    // It's not strictly necessary to alloaction GPU memory from threads near the GPU\n    // this just drives home the point that we want to align CPU worker thread to GPU affinity.\n    future_0 = workers_0->enqueue([=, &gpu_stack_on_socket0] {\n        CHECK_EQ(cudaSetDevice(0), CUDA_SUCCESS) << \"Set Device 0 failed\";\n        gpu_stack_on_socket0 = std::make_shared<MemoryStack<CudaDeviceMemory>>(one_gib);\n        gpu_stack_on_socket0->Reset(zeroMemory);\n    });\n\n    // On a dual-socket system, we could use workers_1 to allocation device memory.\n    // Leaving this as an exercise to the reader.\n\n    future_0.get(); // thread allocating gpu_stack_on_socket0 finished with task\n    LOG(INFO) << \"Push Binding 0 - 10MB - stack_ptr = \"\n              << gpu_stack_on_socket0->Allocate(10 * 1024 * 1024);\n    LOG(INFO) << \"Push Binding 1 - 128MB - stack_ptr = \"\n              << gpu_stack_on_socket0->Allocate(128 * 1024 * 1024);\n    // Try allocating 1 byte. Notice how the memory is aligned. Default alignment\n    // is defined by the MemoryType in Memory.h\n    gpu_stack_on_socket0->Reset();\n\n    /**\n     * Create a Buffer object associates a worker threads, host memory and device memory\n     * that are properly aligned to the hardware topology.\n     */\n    struct Buffer\n    {\n        Buffer(std::shared_ptr<CudaPinnedHostMemory> pinned_,\n               std::shared_ptr<MemoryStack<CudaDeviceMemory>> gpu_stack_,\n               std::shared_ptr<ThreadPool> workers_)\n            : pinned(pinned_), gpu_stack(gpu_stack_), workers(workers_)\n        {\n        }\n\n        std::shared_ptr<CudaPinnedHostMemory> pinned;\n        std::shared_ptr<MemoryStack<CudaDeviceMemory>> gpu_stack;\n        std::shared_ptr<ThreadPool> workers;\n\n        // Normally, we'd associate some GPU index value to the buffer.\n    };\n\n    // Now create a Pool of Buffers\n    auto buffers = Pool<Buffer>::Create();\n\n    // Here we push two buffers, one for each socket.\n    buffers->EmplacePush(new Buffer(pinned_0, gpu_stack_on_socket0, workers_0));\n    buffers->EmplacePush(new Buffer(pinned_1, gpu_stack_on_socket1, workers_1));\n\n    // Exercise: add more buffer objects.  Which of the three objects per Buffer\n    // will you reuse, which will you make new instances of?\n\n    // If you have arbituray work which is not necesasry topology aligned, say an incoming\n    // inference request, you can pull a buffer object from the pool and queue work to the\n    // proper set of threads best associated with that device\n    for(int i = 0; i < 6; i++)\n    {\n        auto buffer = buffers->Pop();\n        buffer->workers->enqueue([buffer] {\n            // perform some work - regardless of which buffer you got, you are working\n            // on a thread properly assocated with the resources\n            LOG(INFO) << Affinity::GetAffinity();\n            std::this_thread::sleep_for(std::chrono::milliseconds(1));\n        });\n    }\n\n    workers_0.reset();\n    workers_1.reset();\n\n    return 0;\n}\n"
  },
  {
    "path": "examples/11_Protos/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\nset(protobuf_MODULE_COMPATIBLE TRUE)\nfind_package(Protobuf CONFIG REQUIRED)\nmessage(STATUS \"Using protobuf ${protobuf_VERSION}\")\nset(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)\nset(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)\n\nadd_subdirectory(echo)\nadd_subdirectory(demo)\nadd_subdirectory(inference)\n"
  },
  {
    "path": "examples/11_Protos/demo/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nINCLUDE(GRPCGenerateCPP)\n\nPROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS \n    dataset.proto\n    inference.proto\n)\n\nPROTOBUF_GENERATE_GRPC_CPP(PROTO_GRPC_SRCS PROTO_GRPC_HDRS \n    dataset.proto\n    inference.proto\n)\n\nadd_library(demo-protos\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS}\n)\n\ntarget_link_libraries(demo-protos\n  PUBLIC\n  ${_PROTOBUF_LIBPROTOBUF}\n)\n\ntarget_include_directories(demo-protos PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\n"
  },
  {
    "path": "examples/11_Protos/demo/dataset.proto",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nsyntax = \"proto3\";\n\nservice SharedMemoryDataSet {\n    rpc GetInfo (InfoRequest) returns (Info) {}\n}\n\nmessage Image {\n    fixed64 sysv_offset = 1;\n    uint32 label_index = 2;\n    repeated int32 shape = 3;\n    uint64 size = 4;\n    string filename = 5;\n}\n\nmessage Info {\n    uint32 handle = 1;\n    uint64 sysv_key = 2;\n    repeated Image images = 3;\n    repeated string labels = 4;\n}\n\nmessage InfoRequest {\n    uint32 image_size = 1;\n}\n"
  },
  {
    "path": "examples/11_Protos/demo/inference.proto",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nsyntax = \"proto3\";\n\npackage ssd;\n\nservice Inference {\n   rpc Compute (BatchInput) returns (BatchPredictions) {}\n}\n\nmessage BatchInput {\n    uint32 engine_id = 1;\n    uint64 batch_id = 2;\n    uint32 batch_size = 3;\n\n    uint32 int_offset = 4;\n    uint64 sysv_offset = 5;\n    bytes data = 6;\n}\n\nmessage BatchPredictions {\n    repeated Element elements = 1;\n    uint64 batch_id = 2;\n    float compute_time = 3;\n    float total_time = 4;\n    repeated Timer timers = 5;\n}\n\nmessage Element {\n    repeated Prediction predictions = 2;\n}\n\nmessage Bbox {\n    float x = 1;  // upper left\n    float y = 2;  // upper left\n    float width = 3;\n    float height = 4;\n    uint32 class_id = 5;\n}\n\nmessage Prediction {\n    uint32 class_id = 1;\n    string class_str = 2;\n    float score = 3;\n    Bbox bbox = 4;\n}\n\nmessage Timer {\n    string name = 1;\n    float time = 2;\n    enum TimerUnit {\n        SECONDS = 0;\n        MILLI = 1;\n        MICRO = 2;\n        NANO = 3;\n    }\n    TimerUnit unit = 3;\n}\n"
  },
  {
    "path": "examples/11_Protos/echo/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nINCLUDE(GRPCGenerateCPP)\n\nPROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS \n    echo.proto\n)\n\nPROTOBUF_GENERATE_GRPC_CPP(PROTO_GRPC_SRCS PROTO_GRPC_HDRS \n    echo.proto\n)\n\nadd_library(echo-protos\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS}\n)\n\ntarget_link_libraries(echo-protos\n  PUBLIC\n  ${_PROTOBUF_LIBPROTOBUF}\n)\n\ntarget_include_directories(echo-protos PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\n"
  },
  {
    "path": "examples/11_Protos/echo/echo.proto",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nsyntax = \"proto3\";\n\npackage simple;\n\nservice Inference {\n   rpc Compute (Input) returns (Output) {}\n   rpc Bidirectional (stream Input) returns (stream Output) {}\n   rpc BatchedCompute (stream Input) returns (stream Output) {}\n}\n\nmessage SystemV {\n    uint64 shm_id = 1;\n    uint64 offset = 2;\n    uint64 size = 3;\n}\n\nmessage Input {\n    uint64 batch_id = 1;\n    oneof data {\n        bytes raw_bytes = 2;\n        SystemV sysv = 3;\n    }\n}\n\nmessage Output {\n    uint64 batch_id = 1;\n}\n\n"
  },
  {
    "path": "examples/11_Protos/inference/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nINCLUDE(GRPCGenerateCPP)\n\nPROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS \n    nvidia_inference.proto\n    api.proto\n    model_config.proto\n    request_status.proto\n    server_status.proto\n)\n\nPROTOBUF_GENERATE_GRPC_CPP(PROTO_GRPC_SRCS PROTO_GRPC_HDRS \n    nvidia_inference.proto\n)\n\nadd_library(nv-inference-protos\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS}\n)\n\ntarget_link_libraries(nv-inference-protos\n  PUBLIC\n  ${_PROTOBUF_LIBPROTOBUF}\n)\n\ntarget_include_directories(nv-inference-protos PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\n"
  },
  {
    "path": "examples/11_Protos/inference/api.proto",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nsyntax = \"proto3\";\n\npackage nvidia.inferenceserver;\n\n// Request header for inferencing. The actual input data is delivered\n// separate from the header.\nmessage InferRequestHeader {\n  // Input...\n  message Input {\n    // Name of the input.\n    string name = 1;\n\n    // Size of the input, in bytes. This is the size for one instance\n    // of the input, not the entire size of a batch of the input.\n    uint64 byte_size = 2;\n  }\n\n  // Output...\n  message Output {\n    // Name of the output.\n    string name = 1;\n\n    // Size of the output, in bytes. This is the size for one instance\n    // of the output, not the entire size of a batch of the output.\n    uint64 byte_size = 2;\n\n    // Class result format. The output must be a vector. Output values\n    // will be interpreted as probabilities and the highest 'count'\n    // values will be returned.\n    message Class {\n      // Return the 'count' highest valued results.\n      uint32 count = 1;\n    }\n\n    // Optional. If defined return this result as a classification\n    // instead of raw data.\n    Class cls = 3;\n  }\n\n  // Batch size of the inference inputs.\n  uint32 batch_size = 1;\n\n  // Inference inputs.\n  repeated Input input = 2;\n\n  // Inference outputs that are being requested.\n  repeated Output output = 3;\n}\n\n// Response header for inferencing. Any raw response data (i.e. tensor\n// values) is delivered separately from the header.\nmessage InferResponseHeader {\n  // Output...\n  message Output {\n    // Name of the output.\n    string name = 1;\n\n    // Raw result\n    message Raw {\n      // Size of the output, in bytes. This is the size for one\n      // instance of the output, not the entire size of a batch of the\n      // output.\n      uint64 byte_size = 1;\n    }\n\n    // Classification result\n    message Class {\n      // The index in the output tensor.\n      int32 idx = 1;\n      // The value of the class as a float (typically a probability).\n      float value = 2;\n      // The label for the class (optional, only available if provided\n      // by the model).\n      string label = 3;\n    }\n    message Classes {\n      // The topk classes for this output\n      repeated Class cls = 1;\n    }\n\n    // Result format for this output. Only one of these may be\n    // specified. For 'batch_classes' there should be one entry for\n    // each output of the batch.\n    Raw raw = 2;\n    repeated Classes batch_classes = 3;\n  }\n\n  // Name of the model that produced the results.\n  string model_name = 1;\n\n  // Version of the model that produced the results.\n  uint32 model_version = 2;\n\n  // Batch size of the inference outputs.\n  uint32 batch_size = 3;\n\n  // The outputs\n  repeated Output output = 4;\n}\n"
  },
  {
    "path": "examples/11_Protos/inference/model_config.proto",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n// Copyright (c) 2018-2019, TensorFlow Authors. All rights reserved.\n\nsyntax = \"proto3\";\n\npackage nvidia.inferenceserver;\n\n// Data types supported for input and output tensors.\nenum DataType {\n  TYPE_INVALID = 0;\n\n  TYPE_BOOL = 1;\n\n  TYPE_UINT8 = 2;\n  TYPE_UINT16 = 3;\n  TYPE_UINT32 = 4;\n  TYPE_UINT64 = 5;\n\n  TYPE_INT8 = 6;\n  TYPE_INT16 = 7;\n  TYPE_INT32 = 8;\n  TYPE_INT64 = 9;\n\n  TYPE_FP16 = 10;\n  TYPE_FP32 = 11;\n  TYPE_FP64 = 12;\n}\n\n// A group of one or more instances of a model and resources made\n// available for those instances.\nmessage ModelInstanceGroup {\n  // Kind of this instance group.\n  enum Kind {\n    // This instance group represents instances that can run on either\n    // CPU or GPU. If all GPUs listed in 'gpus' are available then\n    // instances will be create on GPU(s), otherwise instances will be\n    // created on CPU.\n    KIND_AUTO = 0;\n\n    // This instance group represents instances that must run on the\n    // GPU.\n    KIND_GPU = 1;\n\n    // This instance group represents instances that must run on the\n    // CPU.\n    KIND_CPU = 2;\n  }\n\n  // Optional name of this group of instances. If not specified the\n  // name will be formed as <model name>_<group number>. The name of\n  // individual instances will be further formed by a unique instance\n  // number and GPU index:\n  //   <name>_<instance number>_gpu<gpu index>\n  string name = 1;\n\n  // The kind of this instance group. Default is KIND_AUTO. If\n  // KIND_AUTO or KIND_GPU then both 'count' and 'gpu' are valid and\n  // may be specified. If KIND_CPU only 'count' is valid and 'gpu'\n  // cannot be specified.\n  Kind kind = 4;\n\n  // Number of instances in this group created for each GPU listed in\n  // 'gpus'. Default is 1.\n  int32 count = 2;\n\n  // GPU(s) where instances should be available. For each GPU listed,\n  // 'count' instances of the model will be available. Setting 'gpus'\n  // to empty (or not specifying at all) is eqivalent to listing all\n  // system GPUs.\n  repeated int32 gpus = 3;\n}\n\n// Input tensor for the model\nmessage ModelInput {\n  // Format for the input.\n  enum Format {\n    // The input has no specific format.\n    FORMAT_NONE = 0;\n\n    // Image formats. Tensors with this format require 3 dimensions if\n    // the model does not support batching (max_batch_size = 0) or 4\n    // dimensions if the model does support batching (max_batch_size\n    // >= 1). In either case the 'dims' below should only specify the\n    // 3 non-batch dimensions (i.e. HWC or CHW).\n    FORMAT_NHWC = 1;\n    FORMAT_NCHW = 2;\n  }\n\n  string name = 1;\n  DataType data_type = 2;\n  Format format = 3;\n  repeated int64 dims = 4;\n}\n\n// Output tensor for the model\nmessage ModelOutput {\n  string name = 1;\n  DataType data_type = 2;\n  repeated int64 dims = 3;\n\n  // Label file for this output (optional).\n  string label_filename = 4;\n}\n\n// Policy indicating which versions of a model should be made\n// available by the inference server.\nmessage ModelVersionPolicy {\n  // Serve only the 'num_versions' highest-numbered versions.  This is\n  // the default policy and the default value of 'num_versions' is 1,\n  // indicating that by default only the highest-number version of a\n  // model will be served.\n  message Latest {\n    uint32 num_versions = 1;\n  }\n\n  // Serve all versions of the model.\n  message All {\n  }\n\n  // Serve only a specific set of versions of the model.\n  message Specific {\n    repeated int64 versions = 1;\n  }\n\n  // Each model must implement only a single policy. The default\n  // policy is 'Latest'.\n  oneof policy_choice {\n    Latest latest = 1;\n    All all = 2;\n    Specific specific = 3;\n  }\n}\n\n// Model configuration.\nmessage ModelConfig {\n  // Name of the model.\n  string name = 1;\n\n  // Type of model (e.g. \"tensorflow\").\n  string platform = 2;\n\n  // Policy indicating which version(s) of the model will be served.\n  ModelVersionPolicy version_policy = 3;\n\n  // Maximum batch size allowed for inference. This can only decrease\n  // what is allowed by the model itself. A value of 0 indicates that\n  // batching is not-allowed/is-disabled (for some input formats this\n  // has implications on the expected dimension of the inputs, see\n  // Format above).\n  int32 max_batch_size = 4;\n\n  // Inputs and outputs to the model.\n  repeated ModelInput input = 5;\n  repeated ModelOutput output = 6;\n\n  // Optional instances of this model. If not specified, one instance\n  // of the model will be instantiated on each available GPU.\n  repeated ModelInstanceGroup instance_group = 7;\n\n  // Optional filename of the model file to use if a\n  // compute-capability specific model is not specified in\n  // 'cc_model_names'. If not specified the default is model.graphdef\n  // for TF graphdef models and model.plan for TensorRT PLAN models.\n  string default_model_filename = 8;\n\n  // Optional map from CUDA compute capabilities to the filename of\n  // the model that supports that compute capability. The filename\n  // refers to a file within the model version directory.\n  map<string, string> cc_model_filenames = 9;\n }\n\n// List of model configurations.\nmessage ModelConfigList {\n  repeated ModelConfig config = 1;\n}\n"
  },
  {
    "path": "examples/11_Protos/inference/nvidia_inference.proto",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nsyntax = \"proto3\";\n\npackage nvidia.inferenceserver;\n\nimport \"api.proto\";\nimport \"request_status.proto\";\nimport \"server_status.proto\";\n\nservice GRPCService {\n  // Get server or model status\n  rpc Status(StatusRequest) returns (StatusResponse) {}\n\n  // Control server profiling\n  rpc Profile(ProfileRequest) returns (ProfileResponse) {}\n\n  // Health check\n  rpc Health(HealthRequest) returns (HealthResponse) {}\n\n  // Perform inference. [ Set the maximum message size (default 4 MB)\n  // and transmit in one pass Seems like Tensorflow uses this approach\n  // to transfer tensor which can be large\n  // https://github.com/grpc/grpc/issues/8975 ]\n  rpc Infer(InferRequest) returns (InferResponse) {}\n}\n\n// Request message for server status.\nmessage StatusRequest {\n  // The specific model status to be returned. Return status for all\n  // models if empty.\n  string model_name = 1;\n}\n\n// Response message for server status.\nmessage StatusResponse {\n  RequestStatus request_status = 1;\n  ServerStatus server_status = 2;\n}\n\n// Request message for profile.\nmessage ProfileRequest {\n  string cmd = 1;\n}\n\n// Response message for profile.\nmessage ProfileResponse{\n  RequestStatus request_status = 1;\n}\n\n// Request message for health.\nmessage HealthRequest {\n  string mode = 1;\n}\n\n// Response message for health.\nmessage HealthResponse{\n  RequestStatus request_status = 1;\n  bool health = 2;\n}\n\n// Request message for inference.\nmessage InferRequest {\n  // Name of model to use for inference\n  string model_name = 1;\n\n  // Version of the model to use for inference. If not specified use\n  // the latest/most-recent version of the model. [ Use string here so\n  // default value of empty indicates not specified].\n  string version = 2;\n\n  // Meta-data for the inference request.\n  InferRequestHeader meta_data = 3;\n\n  // Raw input tensor data in the order specified in 'meta_data'.\n  repeated bytes raw_input = 4;\n\n  uint64 batch_id = 100;\n  uint32 batch_size = 101;\n  uint64 sysv_offset = 102;\n}\n\n// Response message for inference.\nmessage InferResponse {\n  RequestStatus request_status = 1;\n\n  // Meta-data for the inference response.\n  InferResponseHeader meta_data = 2;\n\n  // Raw output tensor data in the order specified in 'meta_data'.\n  repeated bytes raw_output = 3;\n\n  uint64 batch_id = 100;\n  float compute_time = 101;\n  float request_time = 102;\n}\n"
  },
  {
    "path": "examples/11_Protos/inference/request_status.proto",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nsyntax = \"proto3\";\n\npackage nvidia.inferenceserver;\n\n// Status codes returned for inference server requests\nenum RequestStatusCode {\n  INVALID = 0;\n\n  SUCCESS = 1;\n  UNKNOWN = 2;\n  INTERNAL = 3;\n  NOT_FOUND = 4;\n  INVALID_ARG = 5;\n  UNAVAILABLE = 6;\n  UNSUPPORTED = 7;\n}\n\n// Status returned for all inference server requests\nmessage RequestStatus {\n  // Required status code\n  RequestStatusCode code = 1;\n\n  // Optional message\n  string msg = 2;\n\n  // Inference server identifier.\n  string server_id = 3;\n\n  // Unique identifier for the request. Value 0 (zero) indicates\n  // request ID is not known.\n  uint64 request_id = 4;\n}\n"
  },
  {
    "path": "examples/11_Protos/inference/server_status.proto",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nsyntax = \"proto3\";\n\npackage nvidia.inferenceserver;\n\nimport \"model_config.proto\";\n\n// Statistic collecting a duration metric\nmessage StatDuration {\n  // Cummulative number of times this metric occurred.\n  uint64 count = 1;\n\n  // Total collected duration of this metric in nanoseconds.\n  uint64 total_time_ns = 2;\n}\n\n// Stats collected for Status requests.\nmessage StatusRequestStats {\n  // Total time required to service api/status requests, not including\n  // HTTP or gRPC endpoint termination time.\n  StatDuration success = 1;\n}\n\n// Stats collected for Profile requests.\nmessage ProfileRequestStats {\n  // Total time required to service profile requests, not including\n  // HTTP or gRPC endpoint termination time.\n  StatDuration success = 1;\n}\n\n// Stats collected for Health requests.\nmessage HealthRequestStats {\n  // Total time required to service health requests, not including\n  // HTTP or gRPC endpoint termination time.\n  StatDuration success = 1;\n}\n\n// Stats collected for Infer requests.\nmessage InferRequestStats {\n  // Total time required to service successful inference requests,\n  // not including HTTP or gRPC endpoint termination time.\n  StatDuration success = 1;\n\n  // Total time required to service failed inference requests, not\n  // including HTTP or gRPC endpoint termination time.\n  StatDuration failed = 2;\n\n  // Time required to run inferencing including time waiting for an\n  // available model instance, time copying input tensors to GPU\n  // memory, time executing the model, and time copying output tensors\n  // from GPU memory. Wait time is also captured separately 'run_wait'\n  // so to get inferencing time not including wait time use 'run' -\n  // 'run_wait'.\n  StatDuration run = 3;\n\n  // Time waiting for an available model instance.\n  StatDuration run_wait = 4;\n}\n\n// Server readiness states.\nenum ModelReadyState {\n  MODEL_UNKNOWN = 0;\n  MODEL_READY = 1;\n  MODEL_UNAVAILABLE = 2;\n  MODEL_LOADING = 3;\n  MODEL_UNLOADING = 4;\n}\n\n// Status for a version of a model.\nmessage ModelVersionStatus {\n  // Current readiness state for the model version.\n  ModelReadyState ready_state = 1;\n\n  // Duration statistics for each batch size used for this version of\n  // the model.\n  map<uint32, InferRequestStats> infer_stats = 2;\n}\n\n// Status for a model.\nmessage ModelStatus {\n  // The configuration for the model.\n  ModelConfig config = 1;\n\n  // Duration statistics for each version of this model.\n  map<uint32, ModelVersionStatus> version_status = 2;\n}\n\n// Server readiness states.\nenum ServerReadyState {\n  SERVER_INVALID = 0;\n  SERVER_INITIALIZING = 1;\n  SERVER_READY = 2;\n  SERVER_EXITING = 3;\n\n  SERVER_FAILED_TO_INITIALIZE = 10;\n}\n\n// Status for inference server\nmessage ServerStatus {\n  // Server ID.\n  string id = 1;\n\n  // Server version.\n  string version = 2;\n\n  // Current readiness state for the server.\n  ServerReadyState ready_state = 7;\n\n  // Server uptime in nanoseconds\n  uint64 uptime_ns = 3;\n\n  // Status for each model on the server as map from <model name> ->\n  // ModelStatus.\n  map<string, ModelStatus> model_status = 4;\n\n  // Statistics for Status requests.\n  StatusRequestStats status_stats = 5;\n\n  // Statistics for Profile requests.\n  ProfileRequestStats profile_stats = 6;\n\n  // Statistics for Health requests.\n  HealthRequestStats health_stats = 8;\n}\n"
  },
  {
    "path": "examples/12_ConfigGenerator/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\npybind11_add_module(config_generator generator.cc)\n\ntarget_link_libraries(config_generator \n  PUBLIC\n     yais\n     nv-inference-protos\n)\n"
  },
  {
    "path": "examples/12_ConfigGenerator/README.md",
    "content": "# TensorRT Inference Server Model Store Builder\n\n- Ensure you built the project.\n- Run `./link.sh` in this directory\n\n## Design Requirements\n\nThis example consists of a ModelStore manager (Python) and a\nModelConfigGenerator (C++ w/ Python bindings).\n\nThe ModelConfigGenerator shall:\n  - [X] parse serialized TensorRT engine files\n  - [X] translate the necessary properties of the ICudaEngine to an\n    `::nvidia::inferenceserver::ModelConfig` protobuf message\n  - [ ] not require the presence of Cuda or a GPU to perform the actions\n\nThe ModelStore manager consists of a Python class for direct consumption and a\ncommand-line application that shall:\n  - [ ] create and manage a model-store in a user-supplied filesystem directory \n  - [X] add TensorRT model files to the model store using the\n    ModelConfigGenerator and user-specified arguments\n  - [ ] add new version of TensorRT models to a ModelStore\n  - [ ] remove versions of entire models from the ModelStore\n  - [ ] add, edit, update and remove Tensorflow models\n  - [ ] add, edit, update and remove PyTorch/Caffe2 models\n\n## Prototype Implementation\n\n```\n./ms_mgmt --help\nUsage: ms_mgmt [OPTIONS]\n\nOptions:\n  --engine PATH          TensorRT serialized engine  [required]\n  --concurrency INTEGER  max number of concurrency executions allowed\n  --name TEXT            model name; default to basename(engine) with the ext\n                         dropped\n  --version INTEGER      model version\n  --store-path TEXT      model store path; default to ./model-store\n  --help                 Show this message and exit.\n```\n\n```\n./ms_mgmt --store-path=/tmp/model-store --engine=/work/models/ResNet-50-b1-fp32.engine --name=overridden-model-name --version=1337 --concurrency=10\n\nls /tmp/model-store/\noverridden-model-name\n\nls /tmp/model-store/overridden-model-name/1337/\nResNet-50-b1-fp32.engine  model.plan\n\ncat /tmp/model-store/overridden-model-name/config.pbtxt\nname: \"overridden-model-name\"\nplatform: \"tensorrt_plan\"\nmax_batch_size: 1\ninput {\n  name: \"data\"\n  data_type: TYPE_FP32\n  dims: 3\n  dims: 224\n  dims: 224\n}\noutput {\n  name: \"prob\"\n  data_type: TYPE_FP32\n  dims: 1000\n  dims: 1\n  dims: 1\n}\ninstance_group {\n  count: 10\n  gpus: 0\n}\n```\n"
  },
  {
    "path": "examples/12_ConfigGenerator/generator.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <pybind11/pybind11.h>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"YAIS/TensorRT/TensorRT.h\"\n#include \"YAIS/YAIS.h\"\n\n// NVIDIA Inference Server Protos\n#include \"nvidia_inference.grpc.pb.h\"\n#include \"nvidia_inference.pb.h\"\n\nusing nvidia::inferenceserver::ModelConfig;\n\nusing trtlab::TensorRT::Runtime;\n\nstatic size_t DataTypeToBytes(nvidia::inferenceserver::DataType dataType)\n{\n    switch(dataType)\n    {\n        case nvidia::inferenceserver::TYPE_INVALID:\n            CHECK(false) << \"Invalid DataType used\";\n            return 0;\n        case nvidia::inferenceserver::TYPE_BOOL:\n        case nvidia::inferenceserver::TYPE_UINT8:\n        case nvidia::inferenceserver::TYPE_INT8:\n            return 1;\n        case nvidia::inferenceserver::TYPE_UINT16:\n        case nvidia::inferenceserver::TYPE_INT16:\n        case nvidia::inferenceserver::TYPE_FP16:\n            return 2;\n        case nvidia::inferenceserver::TYPE_UINT32:\n        case nvidia::inferenceserver::TYPE_INT32:\n        case nvidia::inferenceserver::TYPE_FP32:\n            return 4;\n        case nvidia::inferenceserver::TYPE_UINT64:\n        case nvidia::inferenceserver::TYPE_INT64:\n        case nvidia::inferenceserver::TYPE_FP64:\n            return 8;\n        default:\n            CHECK(false) << \"Invalid DataType used\";\n            return 0;\n    }\n}\n\nstatic nvidia::inferenceserver::DataType ConvertTensorRTDataType(nvinfer1::DataType trt_datatype)\n{\n    switch(trt_datatype)\n    {\n        case nvinfer1::DataType::kFLOAT:\n            return nvidia::inferenceserver::TYPE_FP32;\n        case nvinfer1::DataType::kHALF:\n            return nvidia::inferenceserver::TYPE_FP16;\n        case nvinfer1::DataType::kINT8:\n            return nvidia::inferenceserver::TYPE_INT8;\n        case nvinfer1::DataType::kINT32:\n            return nvidia::inferenceserver::TYPE_INT32;\n        default:\n            LOG(FATAL) << \"Unknown TensorRT DataType\";\n    }\n}\n\nstd::string tensorrt_engine(std::string model_name, std::string engine, int concurrency)\n{\n    ModelConfig config;\n    auto model = trtlab::TensorRT::Runtime::DeserializeEngine(engine);\n    config.set_name(model_name);\n    config.set_platform(\"tensorrt_plan\");\n    config.set_max_batch_size(model->GetMaxBatchSize());\n\n    for(auto i : model->GetInputBindingIds())\n    {\n        const auto& binding = model->GetBinding(i);\n        auto input = config.add_input();\n        input->set_name(binding.name);\n        input->set_data_type(ConvertTensorRTDataType(binding.dtype));\n        for(auto d : binding.dims)\n        {\n            input->add_dims(d);\n        }\n    }\n\n    for(auto i : model->GetOutputBindingIds())\n    {\n        const auto& binding = model->GetBinding(i);\n        auto output = config.add_output();\n        output->set_name(binding.name);\n        output->set_data_type(ConvertTensorRTDataType(binding.dtype));\n        for(auto d : binding.dims)\n        {\n            output->add_dims(d);\n        }\n    }\n\n    auto instance_group = config.add_instance_group();\n    CHECK(concurrency > 0) << \"Concurrency must be >= 0\";\n    instance_group->set_count(concurrency);\n    instance_group->add_gpus(0);\n\n    return config.DebugString();\n}\n\nnamespace py = pybind11;\n\nPYBIND11_MODULE(config_generator, m)\n{\n    m.doc() = R\"pbdoc(\n        Pybind11 Yais plugin\n        --------------------\n        .. currentmodule:: config_generator\n        .. autosummary::\n           :toctree: _generate\n           tensorrt_engine\n    )pbdoc\";\n\n    m.def(\"tensorrt_engine\", &tensorrt_engine, R\"pbdoc(\n        Generate a TensorRT Inference Server ModelConfig from a serialized engine file\n    )pbdoc\");\n\n#ifdef VERSION_INFO\n    m.attr(\"__version__\") = VERSION_INFO;\n#else\n    m.attr(\"__version__\") = \"dev\";\n#endif\n}\n"
  },
  {
    "path": "examples/12_ConfigGenerator/link.sh",
    "content": "#!/bin/bash\n\nln -s /work/build/examples/12_ConfigGenerator/config_generator.cpython-35m-x86_64-linux-gnu.so\n"
  },
  {
    "path": "examples/12_ConfigGenerator/ms_mgmt",
    "content": "#!/usr/bin/env python3\nimport os\nimport pathlib\nimport shutil\n\nfrom contextlib import contextmanager\n\nimport click\nimport config_generator as cg\n\nFileType = click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)\nPathType = click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)\n\n@contextmanager\ndef cd(newdir):\n    prevdir = os.getcwd()\n    os.chdir(os.path.expanduser(newdir))\n    try:\n        yield\n    finally:\n        os.chdir(prevdir)\n\n# Path(exists=False, file_okay=True, dir_okay=True, writable=False, readable=True, resolve_path=False)\n\nclass ModelStore:\n\n    def __init__(self, *, path, create=False, validate=False):\n        if not os.path.isdir(path):\n            pathlib.Path(path).mkdir(parents=create, exist_ok=create)\n        self.path = os.path.abspath(path)\n        self.name = os.path.basename(self.path)\n\n    def model_name(self, *, engine, name=None):\n        base = os.path.basename(engine)\n        model = name or base.replace(\".engine\", \"\")\n        return model\n\n    def model_path(self, *, name):\n        return os.path.join(self.path, name)\n\n    def engine_path(self, *, name, version=0):\n        return os.path.join(self.model_path(name=name), str(version))\n\n    def create_engine_path(self, *, name, version):\n        engine_path = self.engine_path(name=name, version=version)\n        if os.path.exists(engine_path):\n            raise RuntimeError(\"{} already exists in the model store\".format(model))\n        pathlib.Path(engine_path).mkdir(parents=True, exist_ok=True)\n        return engine_path\n\n    def copy_and_link_engine(self, *, name, version, engine):\n        engine_path = self.create_engine_path(name=name, version=version)\n        shutil.copy(engine, engine_path)\n        with cd(engine_path):\n            os.symlink(os.path.basename(engine), \"model.plan\")\n\n    def add_tensorrt_engine(self, *, engine, name=None, concurrency=1, version=0):\n        engine = os.path.abspath(engine)\n        if not os.path.isfile(engine):\n            raise RuntimeError(\"{} engine does not exist\".format(engine))\n        name = self.model_name(engine=engine, name=name)\n        model_path = self.model_path(name=name)\n        self.copy_and_link_engine(name=name, version=version, engine=engine)\n        config = cg.tensorrt_engine(name, engine, concurrency)\n        with cd(model_path), open(\"config.pbtxt\", \"w\") as file:\n            file.write(config)\n\n@click.command()\n@click.option(\"--engine\", type=FileType, required=True, help=\"TensorRT serialized engine\")\n@click.option(\"--concurrency\", type=int, default=1, help=\"max number of concurrency executions allowed\")\n@click.option(\"--name\", default=None, help=\"model name; default to basename(engine) with the ext dropped\")\n@click.option(\"--version\", type=int, default=0, help=\"model version\")\n@click.option(\"--store-path\", default=None, help=\"model store path; default to ./model-store\")\ndef main(engine, concurrency, name, store_path, version):\n    store_path = store_path or \"model-store\"\n    store = ModelStore(path=store_path, create=True)\n    base = os.path.basename(engine)\n    name = name or base.replace(\".engine\", \"\")\n    store.add_tensorrt_engine(engine=engine, name=name, concurrency=concurrency, version=version)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/12_FlatBuffers/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(Flatbuffers)\n\n# This module defines\n#  FLATBUFFERS_INCLUDE_DIR, directory containing headers\n#  FLATBUFFERS_LIBS, directory containing flatbuffers libraries\n#  FLATBUFFERS_STATIC_LIB, path to libflatbuffers.a\n#  FLATBUFFERS_FOUND, whether flatbuffers has been found\n\n\nadd_library(example-fbs \n  example.grpc.fb.cc\n)\n\ntarget_link_libraries(example-fbs PUBLIC\n  flatbuffers\n)\n\ntarget_include_directories(example-fbs PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\n\nadd_executable(fb-server.x\n    server.cc)\n\ntarget_link_libraries(fb-server.x\n    nvrpc\n    example-fbs\n    gflags\n)\n\nadd_executable(fb-client.x\n    client.cc)\n\ntarget_link_libraries(fb-client.x\n    nvrpc\n    example-fbs\n    gflags\n)\n"
  },
  {
    "path": "examples/12_FlatBuffers/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"example.grpc.fb.h\"\n#include \"example_generated.h\"\n\nusing Input = flatbuffers::grpc::Message<HelloRequest>;\nusing Output = flatbuffers::grpc::Message<HelloReply>;\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\n\nclass SimpleClient\n{\n  public:\n    SimpleClient(std::shared_ptr<Channel> channel) : stub_(Greeter::NewStub(channel)) {}\n\n    // Assembles the client's payload, sends it and presents the response back\n    // from the server.\n    std::string Compute(const int batch_id)\n    {\n        flatbuffers::grpc::MessageBuilder mb;\n\n        // Data we are sending to the server.\n        auto name_offset = mb.CreateString(std::to_string(batch_id));\n        auto request_offset = CreateHelloRequest(mb, name_offset);\n        mb.Finish(request_offset);\n        auto request = mb.ReleaseMessage<HelloRequest>();\n\n        // Container for the data we expect from the server.\n        Output reply;\n\n        // Context for the client. It could be used to convey extra information to\n        // the server and/or tweak certain RPC behaviors.\n        ClientContext context;\n\n        // The actual RPC.\n        Status status = stub_->SayHello(&context, request, &reply);\n\n        // Act upon its status.\n        if(status.ok())\n        {\n            const HelloReply* output = reply.GetRoot();\n            return output->message()->str();\n        }\n        else\n        {\n            std::cout << status.error_code() << \": \" << status.error_message() << std::endl;\n            return \"Fail!\";\n        }\n    }\n\n  private:\n    std::unique_ptr<Greeter::Stub> stub_;\n};\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    SimpleClient client(grpc::CreateChannel(\"localhost:50051\", grpc::InsecureChannelCredentials()));\n    auto start = std::chrono::steady_clock::now();\n    for(int i = 0; i < FLAGS_count; i++)\n    {\n        auto reply = client.Compute(i);\n        LOG_FIRST_N(INFO, 20) << reply;\n    }\n    auto end = std::chrono::steady_clock::now();\n    float elapsed = std::chrono::duration<float>(end - start).count();\n    std::cout << FLAGS_count << \" requests in \" << elapsed << \"seconds\" << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "examples/12_FlatBuffers/example.fbs",
    "content": "table HelloReply {\n  message:string;\n}\n\ntable HelloRequest {\n  name:string;\n}\n\ntable ManyHellosRequest {\n  name:string;\n  num_greetings:int;\n}\n\nrpc_service Greeter {\n  SayHello(HelloRequest):HelloReply;\n  SayManyHellos(ManyHellosRequest):HelloReply (streaming: \"server\");\n}\n"
  },
  {
    "path": "examples/12_FlatBuffers/example.grpc.fb.cc",
    "content": "// Generated by the gRPC C++ plugin.\n// If you make any local change, they will be lost.\n// source: example\n\n#include \"example.grpc.fb.h\"\n#include \"example_generated.h\"\n\n#include <grpc++/impl/codegen/async_stream.h>\n#include <grpc++/impl/codegen/async_unary_call.h>\n#include <grpc++/impl/codegen/channel_interface.h>\n#include <grpc++/impl/codegen/client_unary_call.h>\n#include <grpc++/impl/codegen/method_handler_impl.h>\n#include <grpc++/impl/codegen/rpc_service_method.h>\n#include <grpc++/impl/codegen/service_type.h>\n#include <grpc++/impl/codegen/sync_stream.h>\n\nstatic const char* Greeter_method_names[] = {\n    \"/Greeter/SayHello\",\n    \"/Greeter/SayManyHellos\",\n};\n\nstd::unique_ptr<Greeter::Stub>\n    Greeter::NewStub(const std::shared_ptr<::grpc::ChannelInterface>& channel,\n                     const ::grpc::StubOptions& options)\n{\n    std::unique_ptr<Greeter::Stub> stub(new Greeter::Stub(channel));\n    return stub;\n}\n\nGreeter::Stub::Stub(const std::shared_ptr<::grpc::ChannelInterface>& channel)\n    : channel_(channel), rpcmethod_SayHello_(Greeter_method_names[0],\n                                             ::grpc::internal::RpcMethod::NORMAL_RPC, channel),\n      rpcmethod_SayManyHellos_(Greeter_method_names[1],\n                               ::grpc::internal::RpcMethod::SERVER_STREAMING, channel)\n{\n}\n\n::grpc::Status Greeter::Stub::SayHello(::grpc::ClientContext* context,\n                                       const flatbuffers::grpc::Message<HelloRequest>& request,\n                                       flatbuffers::grpc::Message<HelloReply>* response)\n{\n    return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_SayHello_, context,\n                                               request, response);\n}\n\n::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>*\n    Greeter::Stub::AsyncSayHelloRaw(::grpc::ClientContext* context,\n                                    const flatbuffers::grpc::Message<HelloRequest>& request,\n                                    ::grpc::CompletionQueue* cq)\n{\n    return ::grpc::internal::ClientAsyncResponseReaderFactory<\n        flatbuffers::grpc::Message<HelloReply>>::Create(channel_.get(), cq, rpcmethod_SayHello_,\n                                                        context, request, true);\n}\n\n::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>*\n    Greeter::Stub::PrepareAsyncSayHelloRaw(::grpc::ClientContext* context,\n                                           const flatbuffers::grpc::Message<HelloRequest>& request,\n                                           ::grpc::CompletionQueue* cq)\n{\n    return ::grpc::internal::ClientAsyncResponseReaderFactory<\n        flatbuffers::grpc::Message<HelloReply>>::Create(channel_.get(), cq, rpcmethod_SayHello_,\n                                                        context, request, false);\n}\n\n::grpc::ClientReader<flatbuffers::grpc::Message<HelloReply>>*\n    Greeter::Stub::SayManyHellosRaw(::grpc::ClientContext* context,\n                                    const flatbuffers::grpc::Message<ManyHellosRequest>& request)\n{\n    return ::grpc::internal::ClientReaderFactory<flatbuffers::grpc::Message<HelloReply>>::Create(\n        channel_.get(), rpcmethod_SayManyHellos_, context, request);\n}\n\n::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>*\n    Greeter::Stub::AsyncSayManyHellosRaw(\n        ::grpc::ClientContext* context,\n        const flatbuffers::grpc::Message<ManyHellosRequest>& request, ::grpc::CompletionQueue* cq,\n        void* tag)\n{\n    return ::grpc::internal::ClientAsyncReaderFactory<\n        flatbuffers::grpc::Message<HelloReply>>::Create(channel_.get(), cq,\n                                                        rpcmethod_SayManyHellos_, context, request,\n                                                        true, tag);\n}\n\n::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>*\n    Greeter::Stub::PrepareAsyncSayManyHellosRaw(\n        ::grpc::ClientContext* context,\n        const flatbuffers::grpc::Message<ManyHellosRequest>& request, ::grpc::CompletionQueue* cq)\n{\n    return ::grpc::internal::ClientAsyncReaderFactory<\n        flatbuffers::grpc::Message<HelloReply>>::Create(channel_.get(), cq,\n                                                        rpcmethod_SayManyHellos_, context, request,\n                                                        false, nullptr);\n}\n\nGreeter::Service::Service()\n{\n    AddMethod(new ::grpc::internal::RpcServiceMethod(\n        Greeter_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC,\n        new ::grpc::internal::RpcMethodHandler<Greeter::Service,\n                                               flatbuffers::grpc::Message<HelloRequest>,\n                                               flatbuffers::grpc::Message<HelloReply>>(\n            std::mem_fn(&Greeter::Service::SayHello), this)));\n    AddMethod(new ::grpc::internal::RpcServiceMethod(\n        Greeter_method_names[1], ::grpc::internal::RpcMethod::SERVER_STREAMING,\n        new ::grpc::internal::ServerStreamingHandler<Greeter::Service,\n                                                     flatbuffers::grpc::Message<ManyHellosRequest>,\n                                                     flatbuffers::grpc::Message<HelloReply>>(\n            std::mem_fn(&Greeter::Service::SayManyHellos), this)));\n}\n\nGreeter::Service::~Service() {}\n\n::grpc::Status Greeter::Service::SayHello(::grpc::ServerContext* context,\n                                          const flatbuffers::grpc::Message<HelloRequest>* request,\n                                          flatbuffers::grpc::Message<HelloReply>* response)\n{\n    (void)context;\n    (void)request;\n    (void)response;\n    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n}\n\n::grpc::Status Greeter::Service::SayManyHellos(\n    ::grpc::ServerContext* context, const flatbuffers::grpc::Message<ManyHellosRequest>* request,\n    ::grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>>* writer)\n{\n    (void)context;\n    (void)request;\n    (void)writer;\n    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n}\n"
  },
  {
    "path": "examples/12_FlatBuffers/example.grpc.fb.h",
    "content": "// Generated by the gRPC C++ plugin.\n// If you make any local change, they will be lost.\n// source: example\n#ifndef GRPC_example__INCLUDED\n#define GRPC_example__INCLUDED\n\n#include \"example_generated.h\"\n#include \"flatbuffers/grpc.h\"\n\n#include <grpc++/impl/codegen/async_stream.h>\n#include <grpc++/impl/codegen/async_unary_call.h>\n#include <grpc++/impl/codegen/method_handler_impl.h>\n#include <grpc++/impl/codegen/proto_utils.h>\n#include <grpc++/impl/codegen/rpc_method.h>\n#include <grpc++/impl/codegen/service_type.h>\n#include <grpc++/impl/codegen/status.h>\n#include <grpc++/impl/codegen/stub_options.h>\n#include <grpc++/impl/codegen/sync_stream.h>\n\nnamespace grpc {\nclass CompletionQueue;\nclass Channel;\nclass ServerCompletionQueue;\nclass ServerContext;\n} // namespace grpc\n\nclass Greeter final\n{\n  public:\n    static constexpr char const* service_full_name() { return \"Greeter\"; }\n    class StubInterface\n    {\n      public:\n        virtual ~StubInterface() {}\n        virtual ::grpc::Status SayHello(::grpc::ClientContext* context,\n                                        const flatbuffers::grpc::Message<HelloRequest>& request,\n                                        flatbuffers::grpc::Message<HelloReply>* response) = 0;\n        std::unique_ptr<\n            ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>>\n            AsyncSayHello(::grpc::ClientContext* context,\n                          const flatbuffers::grpc::Message<HelloRequest>& request,\n                          ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>>(\n                AsyncSayHelloRaw(context, request, cq));\n        }\n        std::unique_ptr<\n            ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>>\n            PrepareAsyncSayHello(::grpc::ClientContext* context,\n                                 const flatbuffers::grpc::Message<HelloRequest>& request,\n                                 ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>>(\n                PrepareAsyncSayHelloRaw(context, request, cq));\n        }\n        std::unique_ptr<::grpc::ClientReaderInterface<flatbuffers::grpc::Message<HelloReply>>>\n            SayManyHellos(::grpc::ClientContext* context,\n                          const flatbuffers::grpc::Message<ManyHellosRequest>& request)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientReaderInterface<flatbuffers::grpc::Message<HelloReply>>>(\n                SayManyHellosRaw(context, request));\n        }\n        std::unique_ptr<::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>>\n            AsyncSayManyHellos(::grpc::ClientContext* context,\n                               const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                               ::grpc::CompletionQueue* cq, void* tag)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>>(\n                AsyncSayManyHellosRaw(context, request, cq, tag));\n        }\n        std::unique_ptr<::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>>\n            PrepareAsyncSayManyHellos(::grpc::ClientContext* context,\n                                      const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                                      ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>>(\n                PrepareAsyncSayManyHellosRaw(context, request, cq));\n        }\n\n      private:\n        virtual ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>*\n            AsyncSayHelloRaw(::grpc::ClientContext* context,\n                             const flatbuffers::grpc::Message<HelloRequest>& request,\n                             ::grpc::CompletionQueue* cq) = 0;\n        virtual ::grpc::ClientAsyncResponseReaderInterface<flatbuffers::grpc::Message<HelloReply>>*\n            PrepareAsyncSayHelloRaw(::grpc::ClientContext* context,\n                                    const flatbuffers::grpc::Message<HelloRequest>& request,\n                                    ::grpc::CompletionQueue* cq) = 0;\n        virtual ::grpc::ClientReaderInterface<flatbuffers::grpc::Message<HelloReply>>*\n            SayManyHellosRaw(::grpc::ClientContext* context,\n                             const flatbuffers::grpc::Message<ManyHellosRequest>& request) = 0;\n        virtual ::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>*\n            AsyncSayManyHellosRaw(::grpc::ClientContext* context,\n                                  const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                                  ::grpc::CompletionQueue* cq, void* tag) = 0;\n        virtual ::grpc::ClientAsyncReaderInterface<flatbuffers::grpc::Message<HelloReply>>*\n            PrepareAsyncSayManyHellosRaw(\n                ::grpc::ClientContext* context,\n                const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                ::grpc::CompletionQueue* cq) = 0;\n    };\n    class Stub final : public StubInterface\n    {\n      public:\n        Stub(const std::shared_ptr<::grpc::ChannelInterface>& channel);\n        ::grpc::Status SayHello(::grpc::ClientContext* context,\n                                const flatbuffers::grpc::Message<HelloRequest>& request,\n                                flatbuffers::grpc::Message<HelloReply>* response) override;\n        std::unique_ptr<::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>>\n            AsyncSayHello(::grpc::ClientContext* context,\n                          const flatbuffers::grpc::Message<HelloRequest>& request,\n                          ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>>(\n                AsyncSayHelloRaw(context, request, cq));\n        }\n        std::unique_ptr<::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>>\n            PrepareAsyncSayHello(::grpc::ClientContext* context,\n                                 const flatbuffers::grpc::Message<HelloRequest>& request,\n                                 ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>>(\n                PrepareAsyncSayHelloRaw(context, request, cq));\n        }\n        std::unique_ptr<::grpc::ClientReader<flatbuffers::grpc::Message<HelloReply>>>\n            SayManyHellos(::grpc::ClientContext* context,\n                          const flatbuffers::grpc::Message<ManyHellosRequest>& request)\n        {\n            return std::unique_ptr<::grpc::ClientReader<flatbuffers::grpc::Message<HelloReply>>>(\n                SayManyHellosRaw(context, request));\n        }\n        std::unique_ptr<::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>>\n            AsyncSayManyHellos(::grpc::ClientContext* context,\n                               const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                               ::grpc::CompletionQueue* cq, void* tag)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>>(\n                AsyncSayManyHellosRaw(context, request, cq, tag));\n        }\n        std::unique_ptr<::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>>\n            PrepareAsyncSayManyHellos(::grpc::ClientContext* context,\n                                      const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                                      ::grpc::CompletionQueue* cq)\n        {\n            return std::unique_ptr<\n                ::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>>(\n                PrepareAsyncSayManyHellosRaw(context, request, cq));\n        }\n\n      private:\n        std::shared_ptr<::grpc::ChannelInterface> channel_;\n        ::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>*\n            AsyncSayHelloRaw(::grpc::ClientContext* context,\n                             const flatbuffers::grpc::Message<HelloRequest>& request,\n                             ::grpc::CompletionQueue* cq) override;\n        ::grpc::ClientAsyncResponseReader<flatbuffers::grpc::Message<HelloReply>>*\n            PrepareAsyncSayHelloRaw(::grpc::ClientContext* context,\n                                    const flatbuffers::grpc::Message<HelloRequest>& request,\n                                    ::grpc::CompletionQueue* cq) override;\n        ::grpc::ClientReader<flatbuffers::grpc::Message<HelloReply>>*\n            SayManyHellosRaw(::grpc::ClientContext* context,\n                             const flatbuffers::grpc::Message<ManyHellosRequest>& request) override;\n        ::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>*\n            AsyncSayManyHellosRaw(::grpc::ClientContext* context,\n                                  const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                                  ::grpc::CompletionQueue* cq, void* tag) override;\n        ::grpc::ClientAsyncReader<flatbuffers::grpc::Message<HelloReply>>*\n            PrepareAsyncSayManyHellosRaw(\n                ::grpc::ClientContext* context,\n                const flatbuffers::grpc::Message<ManyHellosRequest>& request,\n                ::grpc::CompletionQueue* cq) override;\n        const ::grpc::internal::RpcMethod rpcmethod_SayHello_;\n        const ::grpc::internal::RpcMethod rpcmethod_SayManyHellos_;\n    };\n    static std::unique_ptr<Stub>\n        NewStub(const std::shared_ptr<::grpc::ChannelInterface>& channel,\n                const ::grpc::StubOptions& options = ::grpc::StubOptions());\n\n    class Service : public ::grpc::Service\n    {\n      public:\n        Service();\n        virtual ~Service();\n        virtual ::grpc::Status SayHello(::grpc::ServerContext* context,\n                                        const flatbuffers::grpc::Message<HelloRequest>* request,\n                                        flatbuffers::grpc::Message<HelloReply>* response);\n        virtual ::grpc::Status\n            SayManyHellos(::grpc::ServerContext* context,\n                          const flatbuffers::grpc::Message<ManyHellosRequest>* request,\n                          ::grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>>* writer);\n    };\n    template<class BaseClass>\n    class WithAsyncMethod_SayHello : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithAsyncMethod_SayHello() { ::grpc::Service::MarkMethodAsync(0); }\n        ~WithAsyncMethod_SayHello() override { BaseClassMustBeDerivedFromService(this); }\n        // disable synchronous version of this method\n        ::grpc::Status SayHello(::grpc::ServerContext* context,\n                                const flatbuffers::grpc::Message<HelloRequest>* request,\n                                flatbuffers::grpc::Message<HelloReply>* response) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n        void RequestSayHello(\n            ::grpc::ServerContext* context, flatbuffers::grpc::Message<HelloRequest>* request,\n            ::grpc::ServerAsyncResponseWriter<flatbuffers::grpc::Message<HelloReply>>* response,\n            ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq,\n            void* tag)\n        {\n            ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq,\n                                               notification_cq, tag);\n        }\n    };\n    template<class BaseClass>\n    class WithAsyncMethod_SayManyHellos : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithAsyncMethod_SayManyHellos() { ::grpc::Service::MarkMethodAsync(1); }\n        ~WithAsyncMethod_SayManyHellos() override { BaseClassMustBeDerivedFromService(this); }\n        // disable synchronous version of this method\n        ::grpc::Status SayManyHellos(\n            ::grpc::ServerContext* context,\n            const flatbuffers::grpc::Message<ManyHellosRequest>* request,\n            ::grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>>* writer) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n        void RequestSayManyHellos(\n            ::grpc::ServerContext* context, flatbuffers::grpc::Message<ManyHellosRequest>* request,\n            ::grpc::ServerAsyncWriter<flatbuffers::grpc::Message<HelloReply>>* writer,\n            ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq,\n            void* tag)\n        {\n            ::grpc::Service::RequestAsyncServerStreaming(1, context, request, writer, new_call_cq,\n                                                         notification_cq, tag);\n        }\n    };\n    typedef WithAsyncMethod_SayHello<WithAsyncMethod_SayManyHellos<Service>> AsyncService;\n    template<class BaseClass>\n    class WithGenericMethod_SayHello : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithGenericMethod_SayHello() { ::grpc::Service::MarkMethodGeneric(0); }\n        ~WithGenericMethod_SayHello() override { BaseClassMustBeDerivedFromService(this); }\n        // disable synchronous version of this method\n        ::grpc::Status SayHello(::grpc::ServerContext* context,\n                                const flatbuffers::grpc::Message<HelloRequest>* request,\n                                flatbuffers::grpc::Message<HelloReply>* response) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n    };\n    template<class BaseClass>\n    class WithGenericMethod_SayManyHellos : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithGenericMethod_SayManyHellos() { ::grpc::Service::MarkMethodGeneric(1); }\n        ~WithGenericMethod_SayManyHellos() override { BaseClassMustBeDerivedFromService(this); }\n        // disable synchronous version of this method\n        ::grpc::Status SayManyHellos(\n            ::grpc::ServerContext* context,\n            const flatbuffers::grpc::Message<ManyHellosRequest>* request,\n            ::grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>>* writer) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n    };\n    template<class BaseClass>\n    class WithStreamedUnaryMethod_SayHello : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithStreamedUnaryMethod_SayHello()\n        {\n            ::grpc::Service::MarkMethodStreamed(\n                0,\n                new ::grpc::internal::StreamedUnaryHandler<flatbuffers::grpc::Message<HelloRequest>,\n                                                           flatbuffers::grpc::Message<HelloReply>>(\n                    std::bind(&WithStreamedUnaryMethod_SayHello<BaseClass>::StreamedSayHello, this,\n                              std::placeholders::_1, std::placeholders::_2)));\n        }\n        ~WithStreamedUnaryMethod_SayHello() override { BaseClassMustBeDerivedFromService(this); }\n        // disable regular version of this method\n        ::grpc::Status SayHello(::grpc::ServerContext* context,\n                                const flatbuffers::grpc::Message<HelloRequest>* request,\n                                flatbuffers::grpc::Message<HelloReply>* response) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n        // replace default version of method with streamed unary\n        virtual ::grpc::Status\n            StreamedSayHello(::grpc::ServerContext* context,\n                             ::grpc::ServerUnaryStreamer<flatbuffers::grpc::Message<HelloRequest>,\n                                                         flatbuffers::grpc::Message<HelloReply>>*\n                                 server_unary_streamer) = 0;\n    };\n    typedef WithStreamedUnaryMethod_SayHello<Service> StreamedUnaryService;\n    template<class BaseClass>\n    class WithSplitStreamingMethod_SayManyHellos : public BaseClass\n    {\n      private:\n        void BaseClassMustBeDerivedFromService(const Service* service) {}\n\n      public:\n        WithSplitStreamingMethod_SayManyHellos()\n        {\n            ::grpc::Service::MarkMethodStreamed(\n                1, new ::grpc::internal::SplitServerStreamingHandler<\n                       flatbuffers::grpc::Message<ManyHellosRequest>,\n                       flatbuffers::grpc::Message<HelloReply>>(std::bind(\n                       &WithSplitStreamingMethod_SayManyHellos<BaseClass>::StreamedSayManyHellos,\n                       this, std::placeholders::_1, std::placeholders::_2)));\n        }\n        ~WithSplitStreamingMethod_SayManyHellos() override\n        {\n            BaseClassMustBeDerivedFromService(this);\n        }\n        // disable regular version of this method\n        ::grpc::Status SayManyHellos(\n            ::grpc::ServerContext* context,\n            const flatbuffers::grpc::Message<ManyHellosRequest>* request,\n            ::grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>>* writer) final override\n        {\n            abort();\n            return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n        }\n        // replace default version of method with split streamed\n        virtual ::grpc::Status StreamedSayManyHellos(\n            ::grpc::ServerContext* context,\n            ::grpc::ServerSplitStreamer<flatbuffers::grpc::Message<ManyHellosRequest>,\n                                        flatbuffers::grpc::Message<HelloReply>>*\n                server_split_streamer) = 0;\n    };\n    typedef WithSplitStreamingMethod_SayManyHellos<Service> SplitStreamedService;\n    typedef WithStreamedUnaryMethod_SayHello<WithSplitStreamingMethod_SayManyHellos<Service>>\n        StreamedService;\n};\n\n#endif // GRPC_example__INCLUDED\n"
  },
  {
    "path": "examples/12_FlatBuffers/example_generated.h",
    "content": "// automatically generated by the FlatBuffers compiler, do not modify\n\n#ifndef FLATBUFFERS_GENERATED_EXAMPLE_H_\n#define FLATBUFFERS_GENERATED_EXAMPLE_H_\n\n#include \"flatbuffers/flatbuffers.h\"\n\nstruct HelloReply;\n\nstruct HelloRequest;\n\nstruct ManyHellosRequest;\n\nstruct HelloReply FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table\n{\n    enum\n    {\n        VT_MESSAGE = 4\n    };\n    const flatbuffers::String* message() const\n    {\n        return GetPointer<const flatbuffers::String*>(VT_MESSAGE);\n    }\n    bool Verify(flatbuffers::Verifier& verifier) const\n    {\n        return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_MESSAGE) &&\n               verifier.VerifyString(message()) && verifier.EndTable();\n    }\n};\n\nstruct HelloReplyBuilder\n{\n    flatbuffers::FlatBufferBuilder& fbb_;\n    flatbuffers::uoffset_t start_;\n    void add_message(flatbuffers::Offset<flatbuffers::String> message)\n    {\n        fbb_.AddOffset(HelloReply::VT_MESSAGE, message);\n    }\n    explicit HelloReplyBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb)\n    {\n        start_ = fbb_.StartTable();\n    }\n    HelloReplyBuilder& operator=(const HelloReplyBuilder&);\n    flatbuffers::Offset<HelloReply> Finish()\n    {\n        const auto end = fbb_.EndTable(start_);\n        auto o = flatbuffers::Offset<HelloReply>(end);\n        return o;\n    }\n};\n\ninline flatbuffers::Offset<HelloReply>\n    CreateHelloReply(flatbuffers::FlatBufferBuilder& _fbb,\n                     flatbuffers::Offset<flatbuffers::String> message = 0)\n{\n    HelloReplyBuilder builder_(_fbb);\n    builder_.add_message(message);\n    return builder_.Finish();\n}\n\ninline flatbuffers::Offset<HelloReply> CreateHelloReplyDirect(flatbuffers::FlatBufferBuilder& _fbb,\n                                                              const char* message = nullptr)\n{\n    return CreateHelloReply(_fbb, message ? _fbb.CreateString(message) : 0);\n}\n\nstruct HelloRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table\n{\n    enum\n    {\n        VT_NAME = 4\n    };\n    const flatbuffers::String* name() const\n    {\n        return GetPointer<const flatbuffers::String*>(VT_NAME);\n    }\n    bool Verify(flatbuffers::Verifier& verifier) const\n    {\n        return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&\n               verifier.VerifyString(name()) && verifier.EndTable();\n    }\n};\n\nstruct HelloRequestBuilder\n{\n    flatbuffers::FlatBufferBuilder& fbb_;\n    flatbuffers::uoffset_t start_;\n    void add_name(flatbuffers::Offset<flatbuffers::String> name)\n    {\n        fbb_.AddOffset(HelloRequest::VT_NAME, name);\n    }\n    explicit HelloRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb)\n    {\n        start_ = fbb_.StartTable();\n    }\n    HelloRequestBuilder& operator=(const HelloRequestBuilder&);\n    flatbuffers::Offset<HelloRequest> Finish()\n    {\n        const auto end = fbb_.EndTable(start_);\n        auto o = flatbuffers::Offset<HelloRequest>(end);\n        return o;\n    }\n};\n\ninline flatbuffers::Offset<HelloRequest>\n    CreateHelloRequest(flatbuffers::FlatBufferBuilder& _fbb,\n                       flatbuffers::Offset<flatbuffers::String> name = 0)\n{\n    HelloRequestBuilder builder_(_fbb);\n    builder_.add_name(name);\n    return builder_.Finish();\n}\n\ninline flatbuffers::Offset<HelloRequest>\n    CreateHelloRequestDirect(flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr)\n{\n    return CreateHelloRequest(_fbb, name ? _fbb.CreateString(name) : 0);\n}\n\nstruct ManyHellosRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table\n{\n    enum\n    {\n        VT_NAME = 4,\n        VT_NUM_GREETINGS = 6\n    };\n    const flatbuffers::String* name() const\n    {\n        return GetPointer<const flatbuffers::String*>(VT_NAME);\n    }\n    int32_t num_greetings() const { return GetField<int32_t>(VT_NUM_GREETINGS, 0); }\n    bool Verify(flatbuffers::Verifier& verifier) const\n    {\n        return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) &&\n               verifier.VerifyString(name()) && VerifyField<int32_t>(verifier, VT_NUM_GREETINGS) &&\n               verifier.EndTable();\n    }\n};\n\nstruct ManyHellosRequestBuilder\n{\n    flatbuffers::FlatBufferBuilder& fbb_;\n    flatbuffers::uoffset_t start_;\n    void add_name(flatbuffers::Offset<flatbuffers::String> name)\n    {\n        fbb_.AddOffset(ManyHellosRequest::VT_NAME, name);\n    }\n    void add_num_greetings(int32_t num_greetings)\n    {\n        fbb_.AddElement<int32_t>(ManyHellosRequest::VT_NUM_GREETINGS, num_greetings, 0);\n    }\n    explicit ManyHellosRequestBuilder(flatbuffers::FlatBufferBuilder& _fbb) : fbb_(_fbb)\n    {\n        start_ = fbb_.StartTable();\n    }\n    ManyHellosRequestBuilder& operator=(const ManyHellosRequestBuilder&);\n    flatbuffers::Offset<ManyHellosRequest> Finish()\n    {\n        const auto end = fbb_.EndTable(start_);\n        auto o = flatbuffers::Offset<ManyHellosRequest>(end);\n        return o;\n    }\n};\n\ninline flatbuffers::Offset<ManyHellosRequest>\n    CreateManyHellosRequest(flatbuffers::FlatBufferBuilder& _fbb,\n                            flatbuffers::Offset<flatbuffers::String> name = 0,\n                            int32_t num_greetings = 0)\n{\n    ManyHellosRequestBuilder builder_(_fbb);\n    builder_.add_num_greetings(num_greetings);\n    builder_.add_name(name);\n    return builder_.Finish();\n}\n\ninline flatbuffers::Offset<ManyHellosRequest>\n    CreateManyHellosRequestDirect(flatbuffers::FlatBufferBuilder& _fbb, const char* name = nullptr,\n                                  int32_t num_greetings = 0)\n{\n    return CreateManyHellosRequest(_fbb, name ? _fbb.CreateString(name) : 0, num_greetings);\n}\n\n#endif // FLATBUFFERS_GENERATED_EXAMPLE_H_\n"
  },
  {
    "path": "examples/12_FlatBuffers/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n\n#include \"example.grpc.fb.h\"\n#include \"example_generated.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::Resources;\n\nusing Request = flatbuffers::grpc::Message<HelloRequest>;\nusing Response = flatbuffers::grpc::Message<HelloReply>;\n\nstruct SimpleResources : public Resources\n{\n};\n\nclass SimpleContext final : public Context<Request, Response, SimpleResources>\n{\n    void ExecuteRPC(Request& input, Response& output) final override\n    {\n        flatbuffers::grpc::MessageBuilder mb_;\n\n        // We call GetRoot to \"parse\" the message. Verification is already\n        // performed by default. See the notes below for more details.\n        const HelloRequest* request = input.GetRoot();\n\n        // Fields are retrieved as usual with FlatBuffers\n        const std::string& name = request->name()->str();\n\n        // `flatbuffers::grpc::MessageBuilder` is a `FlatBufferBuilder` with a\n        // special allocator for efficient gRPC buffer transfer, but otherwise\n        // usage is the same as usual.\n        auto msg_offset = mb_.CreateString(\"Hello, \" + name);\n        auto hello_offset = CreateHelloReply(mb_, msg_offset);\n        mb_.Finish(hello_offset);\n\n        // The `ReleaseMessage<T>()` function detaches the message from the\n        // builder, so we can transfer the resopnse to gRPC while simultaneously\n        // detaching that memory buffer from the builer.\n        output = mb_.ReleaseMessage<HelloReply>();\n        CHECK(output.Verify());\n        this->FinishResponse();\n    }\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"flatbuffer service\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // A server will bind an IP:PORT to listen on\n    Server server(\"0.0.0.0:50051\");\n\n    // A server can host multiple services\n    auto simpleInference = server.RegisterAsyncService<Greeter>();\n\n    auto rpcCompute =\n        simpleInference->RegisterRPC<SimpleContext>(&Greeter::AsyncService::RequestSayHello);\n\n    auto rpcResources = std::make_shared<SimpleResources>();\n    auto executor = server.RegisterExecutor(new Executor(1));\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {\n        // This is a timeout loop executed every 2seconds\n        // Run() with no arguments will run an empty timeout loop every 5 seconds.\n        // RunAsync() will return immediately, its your responsibility to ensure the\n        // server doesn't go out of scope or a Shutdown will be triggered on your services.\n    });\n}\n"
  },
  {
    "path": "examples/30_PyTensorRT/README.md",
    "content": "# Python Inference Example\n\n\n"
  },
  {
    "path": "examples/30_PyTensorRT/client.py",
    "content": "#!/usr/bin/env python3\nimport os\nimport time\n\nimport numpy as np\n\nimport infer\nimport infer_test_utils as utils\n\n\ndef main():\n    manager = infer.RemoteInferenceManager(hostname=\"localhost:50052\")\n    models = manager.get_models()\n    print(models)\n\n    mnist = manager.infer_runner(\"mnist\")\n\n    print(\"Input Bindings: {}\".format(mnist.input_bindings()))\n    print(\"Output Bindings: {}\".format(mnist.output_bindings()))\n\n    inputs = utils.load_inputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n    expected = utils.load_outputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n\n    start = time.process_time()\n    results = [mnist.infer(Input3=input) for input in inputs]\n    results = [r.get() for r in results]\n    print(\"Compute Time: {}\".format(time.process_time() - start))\n    print(results)\n\n#   for r, e in zip(results, expected):\n#       for key, val in r.items():\n#           print(\"Output Binding Name: {}; shape{}\".format(key, val.shape))\n#           r = val.reshape((1,10))\n#           np.testing.assert_almost_equal(r, e, decimal=3) \n\n#   models.serve()\n    #mnist_model = models.get_model(\"mnist\")\n    #benchmark = infer.InferBench(models)\n    #benchmark.run(mnist_model, 1, 0.1)\n    #print(results)\n \n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/30_PyTensorRT/compute.py",
    "content": "#!/usr/bin/env python3\nimport itertools\nimport os\nimport time\n\nimport numpy as np\n\nimport trtlab\nimport infer_test_utils as utils\n\n\ndef main():\n    models = trtlab.InferenceManager(max_exec_concurrency=1)\n    mnist = models.register_tensorrt_engine(\"mnist\", \"/work/models/onnx/mnist-v1.3/mnist-v1.3.engine\")\n    models.update_resources()\n\n    print(\"Input Bindings: {}\".format(mnist.input_bindings()))\n    print(\"Output Bindings: {}\".format(mnist.output_bindings()))\n\n    inputs = utils.load_inputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n    expected = utils.load_outputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n\n    start = time.process_time()\n    while True:\n        futures = [mnist.infer(Input3=inputs[0]) for _ in range(100)]\n        results = [f.get() for f in futures]\n#   while True:\n#       results = [mnist.infer(Input3=input) for input in itertools.repeat(inputs[0], 1000)]\n#       results = [r.get() for r in results]\n#       time.sleep(0.1)\n    print(\"Compute Time: {}\".format(time.process_time() - start))\n    \n#   for r, e in zip(results, expected):\n#       for key, val in r.items():\n#           print(\"Output Binding Name: {}; shape{}\".format(key, val.shape))\n#           r = val.reshape((1,10))\n#           np.testing.assert_almost_equal(r, e, decimal=3) \n\n    #mnist_model = models.get_model(\"mnist\")\n    #benchmark = infer.InferBench(models)\n    #benchmark.run(mnist_model, 1, 0.1)\n    #print(results)\n \n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/30_PyTensorRT/infer_test_utils.py",
    "content": "#!/usr/bin/env python3\nimport glob\nimport os\n\nimport onnx\nfrom onnx import numpy_helper\nfrom matplotlib import pyplot as plt\nimport numpy as np\n\ndef load_inputs(test_data_dir):\n    # Load inputs\n    inputs = []\n    inputs_num = len(glob.glob(os.path.join(test_data_dir, 'input_*.pb')))\n    for i in range(inputs_num):\n        input_file = os.path.join(test_data_dir, 'input_{}.pb'.format(i))\n        tensor = onnx.TensorProto()\n        with open(input_file, 'rb') as f:\n            tensor.ParseFromString(f.read())\n        inputs.append(numpy_helper.to_array(tensor))\n    return inputs\n\ndef load_outputs(test_data_dir):\n    # Load reference outputs\n    ref_outputs = []\n    ref_outputs_num = len(glob.glob(os.path.join(test_data_dir, 'output_*.pb')))\n    for i in range(ref_outputs_num):\n        output_file = os.path.join(test_data_dir, 'output_{}.pb'.format(i))\n        tensor = onnx.TensorProto()\n        with open(output_file, 'rb') as f:\n            tensor.ParseFromString(f.read())\n        ref_outputs.append(numpy_helper.to_array(tensor))\n    return ref_outputs\n\ndef mnist_image(data):\n    two_d = (np.reshape(data, (28, 28))).astype(np.uint8)\n    plt.imshow(two_d, interpolation='nearest')\n    return plt\n\ndef softmax(x):\n    \"\"\"Compute softmax values for each sets of scores in x.\"\"\"\n    e_x = np.exp(x - np.max(x))\n    return e_x / e_x.sum()\n"
  },
  {
    "path": "examples/30_PyTensorRT/rebuild.sh",
    "content": "#!/bin/bash\ncd /work/build/tensorrt-laboratory/python\nmake -j\ncd /work/examples/30_PyTensorRT\nif [ ! -e infer.cpython-35m-x86_64-linux-gnu.so ]; then\n  ln -s /work/build/tensorrt-laboratory/python/tensorrt/infer.cpython-35m-x86_64-linux-gnu.so\nfi\n"
  },
  {
    "path": "examples/30_PyTensorRT/server.py",
    "content": "#!/usr/bin/env python3\nimport os\nimport time\n\nimport numpy as np\n\nimport infer\nimport infer_test_utils as utils\n\n\ndef main():\n    models = infer.InferenceManager(max_exec_concurrency=2)\n    mnist = models.register_tensorrt_engine(\"mnist\", \"/work/models/onnx/mnist-v1.3/mnist-v1.3.engine\")\n    models.update_resources()\n\n    print(\"Input Bindings: {}\".format(mnist.input_bindings()))\n    print(\"Output Bindings: {}\".format(mnist.output_bindings()))\n\n    inputs = utils.load_inputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n    expected = utils.load_outputs(\"/work/models/onnx/mnist-v1.3/test_data_set_0\")\n\n    start = time.process_time()\n    results = [mnist.infer(Input3=input) for input in inputs]\n    results = [r.get() for r in results]\n    print(\"Compute Time: {}\".format(time.process_time() - start))\n\n    for r, e in zip(results, expected):\n        for key, val in r.items():\n            print(\"Output Binding Name: {}; shape{}\".format(key, val.shape))\n            r = val.reshape((1,10))\n            np.testing.assert_almost_equal(r, e, decimal=3) \n\n    models.serve()\n    #mnist_model = models.get_model(\"mnist\")\n    #benchmark = infer.InferBench(models)\n    #benchmark.run(mnist_model, 1, 0.1)\n    #print(results)\n \n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/90_Kubernetes/README.md",
    "content": "# Kubernetes\n\nUsing [Kubernetes on NVIDIA GPUs, aka KONG](https://developer.nvidia.com/kubernetes-gpu) is a great\nway of deploying GPU accelerated microservices.  This page will act as a guide for\nfor both development and production deployment.\n\n* For development, we will use [minikube](https://kubernetes.io/docs/setup/minikube/) to deploy a single-node\nKubernetes cluster.\n* For production, we will use a Kubernetes cluster installed by the \n[DeepOps project](https://github.com/nvidia/deepops).\n\n## Prerequisites\n\n* [Kubernetes v1.10.0](https://kubernetes.io) \n* [NVIDIA GPU Device Plugin](https://github.com/NVIDIA/k8s-device-plugin#preparing-your-gpu-nodes)\n* [Helm](https://helm.sh)\n* [prometheus-operator](https://github.com/coreos/prometheus-operator)\n  ```\n  helm repo add coreos https://s3-eu-west-1.amazonaws.com/coreos-charts/stable/\n  ```\n\n## Setup\n\nThe following packages will be installed on your Kubernetes cluster:\n* [CoreOS's Prometheus Operator](https://github.com/coreos/prometheus-operator) for gathering and monitoring metrics\n* [Istio v0.8](https://istio.io) for ingress and load-balancing\n\nAfter the installation of those packages, we will deploy the following:\n* Scalable [K8s Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)\nof the [TensorRT GRPC example](../02_TensorRT_GRPC) `inference-grpc.x` \n* YAIS specific instance of a Prometheus server that will scrape any Pods labeled `scrape: yais`\n* Istio `Gateway` and `VirtualService` to route load-balanced traffic to our gRPC service.\n\n## Install\n\nStarting at this point, you should have a Kubernetes cluter with all the prerequisites.\n\nIf you use the [minikube setup](minikube/README.md) you can simply run:\n```\n./bootstrap-minikube.sh\n```\n\nOtherwise, you can choose to install each of the components manually.\n\n### Prometheus Operator\n\nInitialize Helm and install the `prometheus-operator` and `kube-prometheus`\n\n```\ncd ../prometheus\n./bootstrap.sh\ncd ..\n```\n\nMonitor `kubectl get pods -n monitoring` and wait everything to come up.\n\nCustomize any settings in the [custom-settings.yml](prometheus/custom-settings.yml)\nfile.  This project is exposing the Grafana server as a `NodePort` and providing custom \ndatasource and dashboards for YAIS metrics.\n\n### Istio\n\nInitialize Istio.  I've provided the Istio v0.8 `istio-demo.yml` modified to use a `NodePort`\nas `istio/minikube.yml`  If you are using a cloude instance, you can change to a `LoadBalancer`.\n\n```\nkubectl create namespace istio-system\nkubectl apply -f istio/istio-v1.0-minikube.yml\nkubectl label namespace default istio-injection=enabled\n```\n\n### YAIS Service\n\n```\nkubectl apply -f yais-deploy.yml\n```\n\nThis does the following:\n* `Deployment` - launches the service and resources\n* `Service` - provides access policy to the deployment pods\n* `ServiceMonitor` - tells our Prometheus server to scrape YAIS metrics\n* `Gateway` - ingress host, port and protocol\n* `VirtualService - routing ingress to services\n\n### Test the Service\n\nUse the [`devel.sh`](devel.sh) script in the project's root directory.\n\n```\n# from project root\n./devel.sh\ncd build/examples/02_TensorRT_GRPC\n./siege.x --port 31380 --rate=1000\n```\n\n`31380` is the default `NodePort` for the Istio `ingressgateway`.\n\nNote: If you get errors, sometime it takes a short period of time before the ingress gateway\nis updated to reflect the routing. \n\n### Check the Metrics\n\n```\nkubectl get svc -n monitoring | grep grafana\n```\n\nThe default login is `admin/admin`.  Navigate to the `YAIS` dashboard.  Celebrate.\n"
  },
  {
    "path": "examples/90_Kubernetes/bootstrap-minikube.sh",
    "content": "#!/bin/bash\n\nif ! [ -x \"$(command -v helm)\" ]; then\n  echo 'Error: helm is not installed.' >&2\n  exit 1\nfi\n\n# minikube\n(cd minikube && ./bootstrap.sh)\n\n# prometheus-operator\n(cd prometheus && ./bootstrap.sh)\n\n# istio\nkubectl create namespace istio-system\nkubectl apply -f istio/istio-v1.0-minikube.yml\n\nsleep 30\nkubectl label namespace default istio-injection=enabled\n\n# deploy yais example\nkubectl apply -f yais-deploy.yml\n\n# sleep 15\n# kubectl label namespace default istio-injection-\n"
  },
  {
    "path": "examples/90_Kubernetes/deploy/build-and-run.sh",
    "content": "#!/bin/bash\n\ndefault_engine=/work/models/ResNet-152-b8-fp16.engine\nconcurrency=${YAIS_CONCURRENCY:-1}\nengine=${YAIS_TRT_ENGINE:-$default_engine}\n\nif [ \"$engine\" = \"$default_engine\" ]; then\n  if [ ! -e $engine ]; then\n    cd /work/models\n    ./setup.py\n  fi\nfi\n\n/work/build/examples/02_TensorRT_GRPC/inference-grpc.x \\\n    --engine=${engine} \\\n    --contexts=${concurrency}\n"
  },
  {
    "path": "examples/90_Kubernetes/devel/README.md",
    "content": "\n## Round 1: External Service\n\nBefore deploying a YAIS service with Kubernetes, we will first setup a developer environment\nwhere we will execute our service in a Docker development container. We can still use our\nKubernetes/Prometheus/Grafana environment to gather and visualize metrics.  To do so, we\nwill create an external service pointing at our host.\n\nEdit the `yais-devel.yml` and modify the IP address of the `Endpoint` to point at the host machine running\nminikube (`sudo minikube ip`). \n\n```\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: yais-devel\nsubsets:\n- addresses:\n  - ip: 10.0.0.10  # <== ChangeMe\n  ports:\n  - name: metrics\n    port: 50078\n```\n\n```\nkubectl apply -f yais-devel.yml\n```\n\nThis will create a Prometheus `ServiceMonitor` that will scrape from the external service, i.e. the \nDocker development container.  This is a good first start at integrating your service into Kubernetes\nwithout having to do a full blown deployment.\n\nCongrats, your minikube cluster now looking for services labeled `scrape: yais` and if found, will\nautomatically start scraped the port labels `metrics`.  \n\nThe final step is to bring an inference service online and to generate some load on that service.\nLaunch the YAIS developement container using the `devel.sh` script in the project's root directory.\nMake sure all the examples have been built and models have been build, \nsee [README::Quickstart](README.md#quickstart). \n\n```\ncd examples/97_SingleProcessMultiSteam\n\nroot@dgx:/work/examples/97_SingleProcessMultiSteam# ./launch_service.sh 1 1 /work/models/ResNet-50-b1-fp32.engine\nI0709 10:13:41.175212   468 Server.cc:37] gRPC listening on: 0.0.0.0:50051\nI0709 10:13:41.175477   468 server.cc:229] Register Service (flowers::Inference) with Server\nI0709 10:13:41.175492   468 server.cc:238] Register RPC (flowers::Inference::Compute) with Service (flowers::Inference)\nI0709 10:13:41.175500   468 server.cc:243] Initializing Resources for RPC (flowers::Inference::Compute)\nI0709 10:13:41.273568   468 TensorRT.cc:561] -- Initialzing TensorRT Resource Manager --\nI0709 10:13:41.273602   468 TensorRT.cc:562] Maximum Execution Concurrency: 1\nI0709 10:13:41.273609   468 TensorRT.cc:563] Maximum Copy Concurrency: 3\nI0709 10:13:42.596443   468 TensorRT.cc:628] -- Registering Model: flowers --\nI0709 10:13:42.596500   468 TensorRT.cc:629] Input/Output Tensors require 591.9 KiB\nI0709 10:13:42.596511   468 TensorRT.cc:630] Execution Activations require 7.8 MiB\nI0709 10:13:42.604210   468 TensorRT.cc:652] -- Allocating TensorRT Resources --\nI0709 10:13:42.604228   468 TensorRT.cc:653] Creating 1 TensorRT execution tokens.\nI0709 10:13:42.604236   468 TensorRT.cc:654] Creating a Pool of 3 Host/Device Memory Stacks\nI0709 10:13:42.604248   468 TensorRT.cc:655] Each Host Stack contains 608.0 KiB\nI0709 10:13:42.604256   468 TensorRT.cc:656] Each Device Stack contains 8.5 MiB\nI0709 10:13:42.604264   468 TensorRT.cc:657] Total GPU Memory: 25.5 MiB\nI0709 10:13:42.606546   468 server.cc:255] Initializing Executor\nI0709 10:13:42.606832   468 server.cc:259] Registering Execution Contexts for RPC (flowers::Inference::Compute) with Executor\nI0709 10:13:42.606889   468 server.cc:262] Running Server\n\nwarmup with client-async.x\n1000 requests in 2.60522seconds; inf/sec: 383.845\n\nStarting a shell keeping the services and load-balancer running...\nTry /work/build/examples/02_TensorRT_GRPC/siege.x --rate=2000 --port=50051\n\n1 x /work/models/ResNet-50-b1-fp32.engine Subshell:\n```\n\nUse `telegraf` and watch the scrape count; the `yais-devel` scraper is set to pull metrics every 2 seconds.\nIt can up to a minute or so until you see scraping from your k8s cluster.\n\n```\n1 x /work/models/ResNet-50-b1-fp32.engine Subshell: telegraf -test -config /work/examples/91_Prometheus/scrape.conf\n...\n> exposer_bytes_transferred,host=dgx,url=http://localhost:50078/metrics counter=0 1531131559000000000 # <== watch the counter\n...\n```\n\n## Round 2: Package and Deploy\n\nTODO - We could use some community help here.\n\n## Round 3: Optimize Deploy Contaienr\n\nTODO - We could use some community help here.\n"
  },
  {
    "path": "examples/90_Kubernetes/devel/yais-devel.yml",
    "content": "---\napiVersion: v1\nkind: Service\nmetadata:\n  name: yais-devel\n  labels:\n    app: yais-devel\nspec:\n  ports:\n  - name: metrics\n    port: 51078\n    targetPort: 50078\n---\napiVersion: v1\nkind: Endpoints\nmetadata:\n  name: yais-devel\nsubsets:\n- addresses:\n  - ip: 10.0.0.10\n  ports:\n  - name: metrics\n    port: 50078\n---\n# this will get scraped by the default kube-prometheus\n# and the yais-metric prometheus service (if it is running)\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: yais-devel\n  labels:\n    scrape: yais\nspec:\n  selector:\n    matchLabels:\n      app: yais-devel\n  endpoints:\n  - port: metrics\n    interval: 2s\n    honorLabels: true\n"
  },
  {
    "path": "examples/90_Kubernetes/istio/README.md",
    "content": "# Istio\n\n## Install\n\n```\n# Download the latest release\ncurl -L https://git.io/getLatestIstio | sh -\n\n# Istio 1.0\nhelm template install/kubernetes/helm/istio --name istio --namespace istio-system \\\n  --set gateways.istio-ingressgateway.type=NodePort \\\n  --set gateways.istio-egressgateway.type=NodePort  > istio-v1.0-minikube.yml\n```\n\nInstall Istio and enable the default namespace for injection; however, only\npods with the proper annotations will have sidecars injected.\n\n```\nkubectl create namespace istio-system\nkubectl apply -f istio-v1.0-minikube.yml\nkubectl label namespace default istio-injection=enabled\nkubectl get namespace -L istio-injection\n```\n\nThe annotation required for sidecar injection:\n```\napiVersion: extensions/v1beta1\nkind: Deployment\n...\nspec:\n  template:\n    metadata:\n      annotations:                         # <== sidecar\n        sidecar.istio.io/inject: \"false\"   # <== annotation\n...\n```\n"
  },
  {
    "path": "examples/90_Kubernetes/istio/rendered/istio-v0.8-minikube.yml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n name: istio-system\n---\n# Source: istio/charts/mixer/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    app: istio-statsd-prom-bridge\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: mixer\ndata:\n  mapping.conf: |-\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-mixer-custom-resources\n  namespace: istio-system\n  labels:\n    app: istio-mixer\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: mixer\ndata:\n  custom-resources.yaml: |-    \n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: attributemanifest\n    metadata:\n      name: istioproxy\n      namespace: istio-system\n    spec:\n      attributes:\n        origin.ip:\n          valueType: IP_ADDRESS\n        origin.uid:\n          valueType: STRING\n        origin.user:\n          valueType: STRING\n        request.headers:\n          valueType: STRING_MAP\n        request.id:\n          valueType: STRING\n        request.host:\n          valueType: STRING\n        request.method:\n          valueType: STRING\n        request.path:\n          valueType: STRING\n        request.reason:\n          valueType: STRING\n        request.referer:\n          valueType: STRING\n        request.scheme:\n          valueType: STRING\n        request.total_size:\n              valueType: INT64\n        request.size:\n          valueType: INT64\n        request.time:\n          valueType: TIMESTAMP\n        request.useragent:\n          valueType: STRING\n        response.code:\n          valueType: INT64\n        response.duration:\n          valueType: DURATION\n        response.headers:\n          valueType: STRING_MAP\n        response.total_size:\n              valueType: INT64\n        response.size:\n          valueType: INT64\n        response.time:\n          valueType: TIMESTAMP\n        source.uid:\n          valueType: STRING\n        source.user:\n          valueType: STRING\n        destination.uid:\n          valueType: STRING\n        connection.id:\n          valueType: STRING\n        connection.received.bytes:\n          valueType: INT64\n        connection.received.bytes_total:\n          valueType: INT64\n        connection.sent.bytes:\n          valueType: INT64\n        connection.sent.bytes_total:\n          valueType: INT64\n        connection.duration:\n          valueType: DURATION\n        connection.mtls:\n          valueType: BOOL\n        context.protocol:\n          valueType: STRING\n        context.timestamp:\n          valueType: TIMESTAMP\n        context.time:\n          valueType: TIMESTAMP\n        api.service:\n          valueType: STRING\n        api.version:\n          valueType: STRING\n        api.operation:\n          valueType: STRING\n        api.protocol:\n          valueType: STRING\n        request.auth.principal:\n          valueType: STRING\n        request.auth.audiences:\n          valueType: STRING\n        request.auth.presenter:\n          valueType: STRING\n        request.auth.claims:\n          valueType: STRING_MAP\n        request.auth.raw_claims:\n          valueType: STRING\n        request.api_key:\n          valueType: STRING\n    \n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: attributemanifest\n    metadata:\n      name: kubernetes\n      namespace: istio-system\n    spec:\n      attributes:\n        source.ip:\n          valueType: IP_ADDRESS\n        source.labels:\n          valueType: STRING_MAP\n        source.name:\n          valueType: STRING\n        source.namespace:\n          valueType: STRING\n        source.service:\n          valueType: STRING\n        source.serviceAccount:\n          valueType: STRING\n        destination.ip:\n          valueType: IP_ADDRESS\n        destination.labels:\n          valueType: STRING_MAP\n        destination.name:\n          valueType: STRING\n        destination.namespace:\n          valueType: STRING\n        destination.service:\n          valueType: STRING\n        destination.serviceAccount:\n          valueType: STRING\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: stdio\n    metadata:\n      name: handler\n      namespace: istio-system\n    spec:\n      outputAsJson: true\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: logentry\n    metadata:\n      name: accesslog\n      namespace: istio-system\n    spec:\n      severity: '\"Info\"'\n      timestamp: request.time\n      variables:\n        originIp: origin.ip | ip(\"0.0.0.0\")\n        sourceIp: source.ip | ip(\"0.0.0.0\")\n        sourceService: source.service | \"\"\n        sourceUser: source.user | source.uid | \"\"\n        sourceNamespace: source.namespace | \"\"\n        destinationIp: destination.ip | ip(\"0.0.0.0\")\n        destinationService: destination.service | \"\"\n        destinationNamespace: destination.namespace | \"\"\n        apiName: api.service | \"\"\n        apiVersion: api.version | \"\"\n        apiClaims: request.headers[\"sec-istio-auth-userinfo\"]| \"\"\n        apiKey: request.api_key | request.headers[\"x-api-key\"] | \"\"\n        requestOperation: api.operation | \"\"\n        protocol: request.scheme | \"http\"\n        method: request.method | \"\"\n        url: request.path | \"\"\n        responseCode: response.code | 0\n        responseSize: response.size | 0\n        requestSize: request.size | 0\n        latency: response.duration | \"0ms\"\n        connectionMtls: connection.mtls | false\n        userAgent: request.useragent | \"\"\n        responseTimestamp: response.time\n        receivedBytes: request.total_size | connection.received.bytes | 0\n        sentBytes: response.total_size | connection.sent.bytes | 0\n        referer: request.referer | \"\"\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: rule\n    metadata:\n      name: stdio\n      namespace: istio-system\n    spec:\n      match: \"true\" # If omitted match is true.\n      actions:\n      - handler: handler.stdio\n        instances:\n        - accesslog.logentry\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: requestcount\n      namespace: istio-system\n    spec:\n      value: \"1\"\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        response_code: response.code | 200\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: requestduration\n      namespace: istio-system\n    spec:\n      value: response.duration | \"0ms\"\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        response_code: response.code | 200\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: requestsize\n      namespace: istio-system\n    spec:\n      value: request.size | 0\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        response_code: response.code | 200\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: responsesize\n      namespace: istio-system\n    spec:\n      value: response.size | 0\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        response_code: response.code | 200\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: tcpbytesent\n      namespace: istio-system\n      labels:\n        istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp\n    spec:\n      value: connection.sent.bytes | 0\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: metric\n    metadata:\n      name: tcpbytereceived\n      namespace: istio-system\n      labels:\n        istio-protocol: tcp # needed so that mixer will only generate when context.protocol == tcp\n    spec:\n      value: connection.received.bytes | 0\n      dimensions:\n        source_service: source.service | \"unknown\"\n        source_version: source.labels[\"version\"] | \"unknown\"\n        destination_service: destination.service | \"unknown\"\n        destination_version: destination.labels[\"version\"] | \"unknown\"\n        connection_mtls: connection.mtls | false\n      monitored_resource_type: '\"UNSPECIFIED\"'\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: prometheus\n    metadata:\n      name: handler\n      namespace: istio-system\n    spec:\n      metrics:\n      - name: request_count\n        instance_name: requestcount.metric.istio-system\n        kind: COUNTER\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - response_code\n        - connection_mtls\n      - name: request_duration\n        instance_name: requestduration.metric.istio-system\n        kind: DISTRIBUTION\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - response_code\n        - connection_mtls\n        buckets:\n          explicit_buckets:\n            bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]\n      - name: request_size\n        instance_name: requestsize.metric.istio-system\n        kind: DISTRIBUTION\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - response_code\n        - connection_mtls\n        buckets:\n          exponentialBuckets:\n            numFiniteBuckets: 8\n            scale: 1\n            growthFactor: 10\n      - name: response_size\n        instance_name: responsesize.metric.istio-system\n        kind: DISTRIBUTION\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - response_code\n        - connection_mtls\n        buckets:\n          exponentialBuckets:\n            numFiniteBuckets: 8\n            scale: 1\n            growthFactor: 10\n      - name: tcp_bytes_sent\n        instance_name: tcpbytesent.metric.istio-system\n        kind: COUNTER\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - connection_mtls\n      - name: tcp_bytes_received\n        instance_name: tcpbytereceived.metric.istio-system\n        kind: COUNTER\n        label_names:\n        - source_service\n        - source_version\n        - destination_service\n        - destination_version\n        - connection_mtls\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: rule\n    metadata:\n      name: promhttp\n      namespace: istio-system\n      labels:\n        istio-protocol: http\n    spec:\n      actions:\n      - handler: handler.prometheus\n        instances:\n        - requestcount.metric\n        - requestduration.metric\n        - requestsize.metric\n        - responsesize.metric\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: rule\n    metadata:\n      name: promtcp\n      namespace: istio-system\n      labels:\n        istio-protocol: tcp # needed so that mixer will only execute when context.protocol == TCP\n    spec:\n      actions:\n      - handler: handler.prometheus\n        instances:\n        - tcpbytesent.metric\n        - tcpbytereceived.metric\n    ---\n    \n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: kubernetesenv\n    metadata:\n      name: handler\n      namespace: istio-system\n    spec:\n      # when running from mixer root, use the following config after adding a\n      # symbolic link to a kubernetes config file via:\n      #\n      # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig\n      #\n      # kubeconfig_path: \"mixer/adapter/kubernetes/kubeconfig\"\n    \n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: rule\n    metadata:\n      name: kubeattrgenrulerule\n      namespace: istio-system\n    spec:\n      actions:\n      - handler: handler.kubernetesenv\n        instances:\n        - attributes.kubernetes\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: rule\n    metadata:\n      name: tcpkubeattrgenrulerule\n      namespace: istio-system\n    spec:\n      match: context.protocol == \"tcp\"\n      actions:\n      - handler: handler.kubernetesenv\n        instances:\n        - attributes.kubernetes\n    ---\n    apiVersion: \"config.istio.io/v1alpha2\"\n    kind: kubernetes\n    metadata:\n      name: attributes\n      namespace: istio-system\n    spec:\n      # Pass the required attribute data to the adapter\n      source_uid: source.uid | \"\"\n      source_ip: source.ip | ip(\"0.0.0.0\") # default to unspecified ip addr\n      destination_uid: destination.uid | \"\"\n      origin_uid: '\"\"'\n      origin_ip: ip(\"0.0.0.0\") # default to unspecified ip addr\n      attribute_bindings:\n        # Fill the new attributes from the adapter produced output.\n        # $out refers to an instance of OutputTemplate message\n        source.ip: $out.source_pod_ip | ip(\"0.0.0.0\")\n        source.labels: $out.source_labels | emptyStringMap()\n        source.namespace: $out.source_namespace | \"default\"\n        source.service: $out.source_service | \"unknown\"\n        source.serviceAccount: $out.source_service_account_name | \"unknown\"\n        destination.ip: $out.destination_pod_ip | ip(\"0.0.0.0\")\n        destination.labels: $out.destination_labels | emptyStringMap()\n        destination.namespace: $out.destination_namespace | \"default\"\n        destination.service: $out.destination_service | \"unknown\"\n        destination.serviceAccount: $out.destination_service_account_name | \"unknown\"\n    ---\n    # Configuration needed by Mixer.\n    # Mixer cluster is delivered via CDS\n    # Specify mixer cluster settings\n    apiVersion: networking.istio.io/v1alpha3\n    kind: DestinationRule\n    metadata:\n      name: istio-policy\n      namespace: istio-system\n    spec:\n      host: istio-policy.istio-system.svc.cluster.local\n      trafficPolicy:\n        connectionPool:\n          http:\n            http2MaxRequests: 10000\n            maxRequestsPerConnection: 10000\n    ---\n    apiVersion: networking.istio.io/v1alpha3\n    kind: DestinationRule\n    metadata:\n      name: istio-telemetry\n      namespace: istio-system\n    spec:\n      host: istio-telemetry.istio-system.svc.cluster.local\n      trafficPolicy:\n        connectionPool:\n          http:\n            http2MaxRequests: 10000\n            maxRequestsPerConnection: 10000\n    ---\n    \n\n---\n# Source: istio/charts/prometheus/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  labels:\n    app: prometheus\n    chart: prometheus-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\ndata:\n  prometheus.yml: |-\n    global:\n      scrape_interval: 15s\n    scrape_configs:\n\n    - job_name: 'istio-mesh'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n\n      kubernetes_sd_configs:\n      - role: endpoints\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-system;istio-telemetry;prometheus\n\n    - job_name: 'envoy'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-system;istio-statsd-prom-bridge;statsd-prom\n\n    - job_name: 'istio-policy'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-system;istio-policy;http-monitoring\n\n    - job_name: 'istio-telemetry'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-system;istio-telemetry;http-monitoring\n\n    - job_name: 'pilot'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-system;istio-pilot;http-monitoring\n\n    # scrape config for API servers\n    - job_name: 'kubernetes-apiservers'\n      kubernetes_sd_configs:\n      - role: endpoints\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: default;kubernetes;https\n\n    # scrape config for nodes (kubelet)\n    - job_name: 'kubernetes-nodes'\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      kubernetes_sd_configs:\n      - role: node\n      relabel_configs:\n      - action: labelmap\n        regex: __meta_kubernetes_node_label_(.+)\n      - target_label: __address__\n        replacement: kubernetes.default.svc:443\n      - source_labels: [__meta_kubernetes_node_name]\n        regex: (.+)\n        target_label: __metrics_path__\n        replacement: /api/v1/nodes/${1}/proxy/metrics\n\n    # Scrape config for Kubelet cAdvisor.\n    #\n    # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics\n    # (those whose names begin with 'container_') have been removed from the\n    # Kubelet metrics endpoint.  This job scrapes the cAdvisor endpoint to\n    # retrieve those metrics.\n    #\n    # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor\n    # HTTP endpoint; use \"replacement: /api/v1/nodes/${1}:4194/proxy/metrics\"\n    # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with\n    # the --cadvisor-port=0 Kubelet flag).\n    #\n    # This job is not necessary and should be removed in Kubernetes 1.6 and\n    # earlier versions, or it will cause the metrics to be scraped twice.\n    - job_name: 'kubernetes-cadvisor'\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      kubernetes_sd_configs:\n      - role: node\n      relabel_configs:\n      - action: labelmap\n        regex: __meta_kubernetes_node_label_(.+)\n      - target_label: __address__\n        replacement: kubernetes.default.svc:443\n      - source_labels: [__meta_kubernetes_node_name]\n        regex: (.+)\n        target_label: __metrics_path__\n        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor\n\n    # scrape config for service endpoints.\n    - job_name: 'kubernetes-service-endpoints'\n      kubernetes_sd_configs:\n      - role: endpoints\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]\n        action: keep\n        regex: true\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]\n        action: replace\n        target_label: __scheme__\n        regex: (https?)\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]\n        action: replace\n        target_label: __metrics_path__\n        regex: (.+)\n      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]\n        action: replace\n        target_label: __address__\n        regex: ([^:]+)(?::\\d+)?;(\\d+)\n        replacement: $1:$2\n      - action: labelmap\n        regex: __meta_kubernetes_service_label_(.+)\n      - source_labels: [__meta_kubernetes_namespace]\n        action: replace\n        target_label: kubernetes_namespace\n      - source_labels: [__meta_kubernetes_service_name]\n        action: replace\n        target_label: kubernetes_name\n\n    # Example scrape config for pods\n    - job_name: 'kubernetes-pods'\n      kubernetes_sd_configs:\n      - role: pod\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]\n        action: keep\n        regex: true\n      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]\n        action: replace\n        target_label: __metrics_path__\n        regex: (.+)\n      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]\n        action: replace\n        regex: ([^:]+)(?::\\d+)?;(\\d+)\n        replacement: $1:$2\n        target_label: __address__\n      - action: labelmap\n        regex: __meta_kubernetes_pod_label_(.+)\n      - source_labels: [__meta_kubernetes_namespace]\n        action: replace\n        target_label: namespace\n      - source_labels: [__meta_kubernetes_pod_name]\n        action: replace\n        target_label: pod_name\n\n---\n# Source: istio/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio\n  namespace: istio-system\n  labels:\n    app: istio\n    chart: istio-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\ndata:\n  mesh: |-\n    #\n    # Edit this list to avoid using mTLS to connect to these services.\n    # Typically, these are control services (e.g kubernetes API server) that don't have istio sidecar\n    # to transparently terminate mTLS authentication.\n    # mtlsExcludedServices: [\"kubernetes.default.svc.cluster.local\"]\n\n    # Set the following variable to true to disable policy checks by the Mixer.\n    # Note that metrics will still be reported to the Mixer.\n    disablePolicyChecks: false\n    # Set enableTracing to false to disable request tracing.\n    enableTracing: true\n    #\n    # To disable the mixer completely (including metrics), comment out\n    # the following lines\n    mixerCheckServer: istio-policy.istio-system.svc.cluster.local:15004\n    mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:15004\n    # This is the ingress service name, update if you used a different name\n    ingressService: istio-ingress\n    #\n    # Along with discoveryRefreshDelay, this setting determines how\n    # frequently should Envoy fetch and update its internal configuration\n    # from istio Pilot. Lower refresh delay results in higher CPU\n    # utilization and potential performance loss in exchange for faster\n    # convergence. Tweak this value according to your setup.\n    rdsRefreshDelay: 10s\n    #\n    defaultConfig:\n      # NOTE: If you change any values in this section, make sure to make\n      # the same changes in start up args in istio-ingress pods.\n      # See rdsRefreshDelay for explanation about this setting.\n      discoveryRefreshDelay: 10s\n      #\n      # TCP connection timeout between Envoy & the application, and between Envoys.\n      connectTimeout: 10s\n      #\n      ### ADVANCED SETTINGS #############\n      # Where should envoy's configuration be stored in the istio-proxy container\n      configPath: \"/etc/istio/proxy\"\n      binaryPath: \"/usr/local/bin/envoy\"\n      # The pseudo service name used for Envoy.\n      serviceCluster: istio-proxy\n      # These settings that determine how long an old Envoy\n      # process should be kept alive after an occasional reload.\n      drainDuration: 45s\n      parentShutdownDuration: 1m0s\n      #\n      # The mode used to redirect inbound connections to Envoy. This setting\n      # has no effect on outbound traffic: iptables REDIRECT is always used for\n      # outbound connections.\n      # If \"REDIRECT\", use iptables REDIRECT to NAT and redirect to Envoy.\n      # The \"REDIRECT\" mode loses source addresses during redirection.\n      # If \"TPROXY\", use iptables TPROXY to redirect to Envoy.\n      # The \"TPROXY\" mode preserves both the source and destination IP\n      # addresses and ports, so that they can be used for advanced filtering\n      # and manipulation.\n      # The \"TPROXY\" mode also configures the sidecar to run with the\n      # CAP_NET_ADMIN capability, which is required to use TPROXY.\n      #interceptionMode: REDIRECT\n      #\n      # Port where Envoy listens (on local host) for admin commands\n      # You can exec into the istio-proxy container in a pod and\n      # curl the admin port (curl http://localhost:15000/) to obtain\n      # diagnostic information from Envoy. See\n      # https://lyft.github.io/envoy/docs/operations/admin.html\n      # for more details\n      proxyAdminPort: 15000\n      #\n      # Zipkin trace collector\n      zipkinAddress: zipkin.istio-system:9411\n      #\n      # Statsd metrics collector converts statsd metrics into Prometheus metrics.\n      statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125\n      #\n      # Mutual TLS authentication between sidecars and istio control plane.\n      controlPlaneAuthPolicy: NONE\n      #\n      # Address where istio Pilot service is running\n      discoveryAddress: istio-pilot.istio-system:15007\n\n---\n# Source: istio/templates/sidecar-injector-configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: istio\n    chart: istio-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: sidecar-injector\ndata:\n  config: |-\n    policy: enabled\n    template: |-\n      initContainers:\n      - name: istio-init\n        image: docker.io/istio/proxy_init:0.8.0\n        args:\n        - \"-p\"\n        - [[ .MeshConfig.ProxyListenPort ]]\n        - \"-u\"\n        - 1337\n        - \"-m\"\n        - [[ or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String ]]\n        - \"-i\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeOutboundIPRanges\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeOutboundIPRanges\"  ]]\"\n        [[ else -]]\n        - \"*\"\n        [[ end -]]\n        - \"-x\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeOutboundIPRanges\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeOutboundIPRanges\"  ]]\"\n        [[ else -]]\n        - \"\"\n        [[ end -]]\n        - \"-b\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeInboundPorts\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeInboundPorts\"  ]]\"\n        [[ else -]]\n        - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]]\n        - \"-d\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeInboundPorts\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeInboundPorts\" ]]\"\n        [[ else -]]\n        - \"\"\n        [[ end -]]\n        imagePullPolicy: IfNotPresent\n        securityContext:\n          capabilities:\n            add:\n            - NET_ADMIN\n          privileged: true\n        restartPolicy: Always\n      \n      containers:\n      - name: istio-proxy\n        image: [[ if (isset .ObjectMeta.Annotations \"sidecar.istio.io/proxyImage\") -]]\n        \"[[ index .ObjectMeta.Annotations \"sidecar.istio.io/proxyImage\" ]]\"\n        [[ else -]]\n        docker.io/istio/proxyv2:0.8.0\n        [[ end -]]\n        args:\n        - proxy\n        - sidecar\n        - --configPath\n        - [[ .ProxyConfig.ConfigPath ]]\n        - --binaryPath\n        - [[ .ProxyConfig.BinaryPath ]]\n        - --serviceCluster\n        [[ if ne \"\" (index .ObjectMeta.Labels \"app\") -]]\n        - [[ index .ObjectMeta.Labels \"app\" ]]\n        [[ else -]]\n        - \"istio-proxy\"\n        [[ end -]]\n        - --drainDuration\n        - [[ formatDuration .ProxyConfig.DrainDuration ]]\n        - --parentShutdownDuration\n        - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]]\n        - --discoveryAddress\n        - [[ .ProxyConfig.DiscoveryAddress ]]\n        - --discoveryRefreshDelay\n        - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]]\n        - --zipkinAddress\n        - [[ .ProxyConfig.ZipkinAddress ]]\n        - --connectTimeout\n        - [[ formatDuration .ProxyConfig.ConnectTimeout ]]\n        - --statsdUdpAddress\n        - [[ .ProxyConfig.StatsdUdpAddress ]]\n        - --proxyAdminPort\n        - [[ .ProxyConfig.ProxyAdminPort ]]\n        - --controlPlaneAuthPolicy\n        - [[ .ProxyConfig.ControlPlaneAuthPolicy ]]\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              fieldPath: status.podIP\n        - name: ISTIO_META_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n        - name: ISTIO_META_INTERCEPTION_MODE\n          value: [[ or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String ]]\n        imagePullPolicy: IfNotPresent\n        securityContext:\n            privileged: false\n            readOnlyRootFilesystem: true\n            [[ if eq (or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String) \"TPROXY\" -]]\n            capabilities:\n              add:\n              - NET_ADMIN\n            [[ else -]]\n            runAsUser: 1337\n            [[ end -]]\n        restartPolicy: Always\n        resources:\n          requests:\n            cpu: 100m\n            memory: 128Mi\n          \n        volumeMounts:\n        - mountPath: /etc/istio/proxy\n          name: istio-envoy\n        - mountPath: /etc/certs/\n          name: istio-certs\n          readOnly: true\n      volumes:\n      - emptyDir:\n          medium: Memory\n        name: istio-envoy\n      - name: istio-certs\n        secret:\n          optional: true\n          [[ if eq .Spec.ServiceAccountName \"\" -]]\n          secretName: istio.default\n          [[ else -]]\n          secretName: [[ printf \"istio.%s\" .Spec.ServiceAccountName ]]\n          [[ end -]]\n\n\n---\n# Source: istio/charts/egressgateway/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-egressgateway-service-account\n  namespace: istio-system\n  labels:\n    app: egressgateway\n    chart: egressgateway-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/ingressgateway/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-ingressgateway-service-account\n  namespace: istio-system\n  labels:\n    app: ingressgateway\n    chart: ingressgateway-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/mixer/templates/create-custom-resources-job.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-mixer-post-install-account\n  namespace: istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-mixer-post-install-istio-system\n  namespace: istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"config.istio.io\"] # istio CRD watcher\n  resources: [\"*\"]\n  verbs: [\"create\", \"get\", \"list\", \"watch\", \"patch\"]\n- apiGroups: [\"networking.istio.io\"] # needed to create mixer destination rules\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"apiextensions.k8s.io\"]\n  resources: [\"customresourcedefinitions\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources: [\"configmaps\", \"endpoints\", \"pods\", \"services\", \"namespaces\", \"secrets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-mixer-post-install-role-binding-istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-mixer-post-install-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-mixer-post-install-account\n    namespace: istio-system\n---\n\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name: istio-mixer-post-install\n  namespace: istio-system\n  annotations:\n    \"helm.sh/hook\": post-install\n    \"helm.sh/hook-delete-policy\": before-hook-creation\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  template:\n    metadata:\n      name: istio-mixer-post-install\n      labels:\n        app: mixer\n        release: RELEASE-NAME\n    spec:\n      serviceAccountName: istio-mixer-post-install-account\n      containers:\n        - name: hyperkube\n          image: \"quay.io/coreos/hyperkube:v1.7.6_coreos.0\"\n          command:\n            - ./kubectl\n            - apply\n            - -f\n            - /tmp/mixer/custom-resources.yaml\n          volumeMounts:\n            - mountPath: \"/tmp/mixer\"\n              name: tmp-configmap-mixer\n      volumes:\n        - name: tmp-configmap-mixer\n          configMap:\n            name: istio-mixer-custom-resources\n      restartPolicy: Never # CRD might take some time till they are available to consume\n\n---\n# Source: istio/charts/mixer/templates/serviceaccount.yaml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-mixer-service-account\n  namespace: istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/pilot/templates/serviceaccount.yaml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-pilot-service-account\n  namespace: istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/prometheus/templates/serviceaccount.yaml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: prometheus\n  namespace: istio-system\n\n---\n# Source: istio/charts/security/templates/serviceaccount.yaml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-citadel-service-account\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-cleanup-old-ca-service-account\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-sidecar-injector-service-account\n  namespace: istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\n\n---\n# Source: istio/charts/mixer/templates/crds.yaml\n# Mixer CRDs\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: rules.config.istio.io\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: core\nspec:\n  group: config.istio.io\n  names:\n    kind: rule\n    plural: rules\n    singular: rule\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: attributemanifests.config.istio.io\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: core\nspec:\n  group: config.istio.io\n  names:\n    kind: attributemanifest\n    plural: attributemanifests\n    singular: attributemanifest\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: circonuses.config.istio.io\n  labels:\n    app: mixer\n    package: circonus\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: circonus\n    plural: circonuses\n    singular: circonus\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: deniers.config.istio.io\n  labels:\n    app: mixer\n    package: denier\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: denier\n    plural: deniers\n    singular: denier\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: fluentds.config.istio.io\n  labels:\n    app: mixer\n    package: fluentd\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: fluentd\n    plural: fluentds\n    singular: fluentd\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: kubernetesenvs.config.istio.io\n  labels:\n    app: mixer\n    package: kubernetesenv\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: kubernetesenv\n    plural: kubernetesenvs\n    singular: kubernetesenv\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: listcheckers.config.istio.io\n  labels:\n    app: mixer\n    package: listchecker\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: listchecker\n    plural: listcheckers\n    singular: listchecker\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: memquotas.config.istio.io\n  labels:\n    app: mixer\n    package: memquota\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: memquota\n    plural: memquotas\n    singular: memquota\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: noops.config.istio.io\n  labels:\n    app: mixer\n    package: noop\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: noop\n    plural: noops\n    singular: noop\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: opas.config.istio.io\n  labels:\n    app: mixer\n    package: opa\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: opa\n    plural: opas\n    singular: opa\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: prometheuses.config.istio.io\n  labels:\n    app: mixer\n    package: prometheus\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: prometheus\n    plural: prometheuses\n    singular: prometheus\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: rbacs.config.istio.io\n  labels:\n    app: mixer\n    package: rbac\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: rbac\n    plural: rbacs\n    singular: rbac\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicecontrols.config.istio.io\n  labels:\n    app: mixer\n    package: servicecontrol\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: servicecontrol\n    plural: servicecontrols\n    singular: servicecontrol\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: solarwindses.config.istio.io\n  labels:\n    app: mixer\n    package: solarwinds\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: solarwinds\n    plural: solarwindses\n    singular: solarwinds\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: stackdrivers.config.istio.io\n  labels:\n    app: mixer\n    package: stackdriver\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: stackdriver\n    plural: stackdrivers\n    singular: stackdriver\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: statsds.config.istio.io\n  labels:\n    app: mixer\n    package: statsd\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: statsd\n    plural: statsds\n    singular: statsd\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: stdios.config.istio.io\n  labels:\n    app: mixer\n    package: stdio\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: stdio\n    plural: stdios\n    singular: stdio\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: apikeys.config.istio.io\n  labels:\n    app: mixer\n    package: apikey\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: apikey\n    plural: apikeys\n    singular: apikey\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: authorizations.config.istio.io\n  labels:\n    app: mixer\n    package: authorization\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: authorization\n    plural: authorizations\n    singular: authorization\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: checknothings.config.istio.io\n  labels:\n    app: mixer\n    package: checknothing\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: checknothing\n    plural: checknothings\n    singular: checknothing\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: kuberneteses.config.istio.io\n  labels:\n    app: mixer\n    package: adapter.template.kubernetes\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: kubernetes\n    plural: kuberneteses\n    singular: kubernetes\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: listentries.config.istio.io\n  labels:\n    app: mixer\n    package: listentry\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: listentry\n    plural: listentries\n    singular: listentry\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: logentries.config.istio.io\n  labels:\n    app: mixer\n    package: logentry\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: logentry\n    plural: logentries\n    singular: logentry\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: metrics.config.istio.io\n  labels:\n    app: mixer\n    package: metric\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: metric\n    plural: metrics\n    singular: metric\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: quotas.config.istio.io\n  labels:\n    app: mixer\n    package: quota\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: quota\n    plural: quotas\n    singular: quota\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: reportnothings.config.istio.io\n  labels:\n    app: mixer\n    package: reportnothing\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: reportnothing\n    plural: reportnothings\n    singular: reportnothing\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicecontrolreports.config.istio.io\n  labels:\n    app: mixer\n    package: servicecontrolreport\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: servicecontrolreport\n    plural: servicecontrolreports\n    singular: servicecontrolreport\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: tracespans.config.istio.io\n  labels:\n    app: mixer\n    package: tracespan\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: tracespan\n    plural: tracespans\n    singular: tracespan\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: serviceroles.config.istio.io\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: rbac\nspec:\n  group: config.istio.io\n  names:\n    kind: ServiceRole\n    plural: serviceroles\n    singular: servicerole\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicerolebindings.config.istio.io\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: rbac\nspec:\n  group: config.istio.io\n  names:\n    kind: ServiceRoleBinding\n    plural: servicerolebindings\n    singular: servicerolebinding\n  scope: Namespaced\n  version: v1alpha2\n\n---\n# Source: istio/charts/pilot/templates/crds.yaml\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: destinationpolicies.config.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: config.istio.io\n  names:\n    kind: DestinationPolicy\n    listKind: DestinationPolicyList\n    plural: destinationpolicies\n    singular: destinationpolicy\n  scope: Namespaced\n  version: v1alpha2\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: egressrules.config.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: config.istio.io\n  names:\n    kind: EgressRule\n    listKind: EgressRuleList\n    plural: egressrules\n    singular: egressrule\n  scope: Namespaced\n  version: v1alpha2\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: routerules.config.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: config.istio.io\n  names:\n    kind: RouteRule\n    listKind: RouteRuleList\n    plural: routerules\n    singular: routerule\n  scope: Namespaced\n  version: v1alpha2\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: virtualservices.networking.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: VirtualService\n    listKind: VirtualServiceList\n    plural: virtualservices\n    singular: virtualservice\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: destinationrules.networking.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: DestinationRule\n    listKind: DestinationRuleList\n    plural: destinationrules\n    singular: destinationrule\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: serviceentries.networking.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: ServiceEntry\n    listKind: ServiceEntryList\n    plural: serviceentries\n    singular: serviceentry\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: gateways.networking.istio.io\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: Gateway\n    plural: gateways\n    singular: gateway\n  scope: Namespaced\n  version: v1alpha3\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: policies.authentication.istio.io\nspec:\n  group: authentication.istio.io\n  names:\n    kind: Policy\n    plural: policies\n    singular: policy\n  scope: Namespaced\n  version: v1alpha1\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: httpapispecbindings.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: HTTPAPISpecBinding\n    plural: httpapispecbindings\n    singular: httpapispecbinding\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: httpapispecs.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: HTTPAPISpec\n    plural: httpapispecs\n    singular: httpapispec\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: quotaspecbindings.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: QuotaSpecBinding\n    plural: quotaspecbindings\n    singular: quotaspecbinding\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: quotaspecs.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: QuotaSpec\n    plural: quotaspecs\n    singular: quotaspec\n  scope: Namespaced\n  version: v1alpha2\n\n\n---\n# Source: istio/charts/mixer/templates/clusterrole.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-mixer-istio-system\n  namespace: istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"config.istio.io\"] # istio CRD watcher\n  resources: [\"*\"]\n  verbs: [\"create\", \"get\", \"list\", \"watch\", \"patch\"]\n- apiGroups: [\"apiextensions.k8s.io\"]\n  resources: [\"customresourcedefinitions\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources: [\"configmaps\", \"endpoints\", \"pods\", \"services\", \"namespaces\", \"secrets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n\n---\n# Source: istio/charts/pilot/templates/clusterrole.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-pilot-istio-system\n  namespace: istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"config.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"networking.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"authentication.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"apiextensions.k8s.io\"]\n  resources: [\"customresourcedefinitions\"]\n  verbs: [\"*\"]\n- apiGroups: [\"extensions\"]\n  resources: [\"thirdpartyresources\", \"thirdpartyresources.extensions\", \"ingresses\", \"ingresses/status\"]\n  verbs: [\"*\"]\n- apiGroups: [\"\"]\n  resources: [\"configmaps\"]\n  verbs: [\"create\", \"get\", \"list\", \"watch\", \"update\"]\n- apiGroups: [\"\"]\n  resources: [\"endpoints\", \"pods\", \"services\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources: [\"namespaces\", \"nodes\", \"secrets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n\n---\n# Source: istio/charts/prometheus/templates/clusterrole.yaml\n\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: prometheus-istio-system\n  namespace: istio-system\nrules:\n- apiGroups: [\"\"]\n  resources:\n  - nodes\n  - services\n  - endpoints\n  - pods\n  - nodes/proxy\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources:\n  - configmaps\n  verbs: [\"get\"]\n- nonResourceURLs: [\"/metrics\"]\n  verbs: [\"get\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: prometheus-istio-system\n  namespace: istio-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: prometheus-istio-system\nsubjects:\n- kind: ServiceAccount\n  name: prometheus\n  namespace: istio-system\n---\n\n\n---\n# Source: istio/charts/security/templates/clusterrole.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-citadel-istio-system\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"\"]\n  resources: [\"secrets\"]\n  verbs: [\"create\", \"get\", \"watch\", \"list\", \"update\", \"delete\"]\n- apiGroups: [\"\"]\n  resources: [\"serviceaccounts\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n- apiGroups: [\"\"]\n  resources: [\"services\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: Role\nmetadata:\n  name: istio-cleanup-old-ca-istio-system\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"\"]\n  resources: [\"deployments\", \"serviceaccounts\", \"services\"]\n  verbs: [\"get\", \"delete\"]\n- apiGroups: [\"extensions\"]\n  resources: [\"deployments\", \"replicasets\"]\n  verbs: [\"get\", \"list\", \"update\", \"delete\"]\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-sidecar-injector-istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nrules:\n- apiGroups: [\"*\"]\n  resources: [\"configmaps\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"admissionregistration.k8s.io\"]\n  resources: [\"mutatingwebhookconfigurations\"]\n  verbs: [\"get\", \"list\", \"watch\", \"patch\"]\n\n---\n# Source: istio/charts/mixer/templates/clusterrolebinding.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-mixer-admin-role-binding-istio-system\n  labels:\n    app: mixer\n    chart: mixer-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-mixer-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-mixer-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/pilot/templates/clusterrolebinding.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-pilot-istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-pilot-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-pilot-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/security/templates/clusterrolebinding.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-citadel-istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-citadel-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-citadel-service-account\n    namespace: istio-system\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: RoleBinding\nmetadata:\n  name: istio-cleanup-old-ca-istio-system\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: istio-cleanup-old-ca-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-cleanup-old-ca-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-sidecar-injector-admin-role-binding-istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-0.8.0\n    heritage: Tiller\n    release: RELEASE-NAME\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-sidecar-injector-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-sidecar-injector-service-account\n    namespace: istio-system\n---\n# Source: istio/charts/egressgateway/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-egressgateway\n  namespace: istio-system    \n  labels:\n    chart: egressgateway-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: egressgateway\nspec:\n  type: ClusterIP\n  selector:\n    istio: egressgateway\n  ports:\n    -\n      name: http\n      port: 80\n    -\n      name: https\n      port: 443\n\n---\n# Source: istio/charts/grafana/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: grafana\n  namespace: istio-system\n  annotations:\n    auth.istio.io/3000: NONE\n  labels:\n    app: grafana\n    chart: grafana-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  type: ClusterIP\n  ports:\n    - port: 3000\n      targetPort: 3000\n      protocol: TCP\n      name: http\n  selector:\n    app: grafana\n\n---\n# Source: istio/charts/ingressgateway/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-ingressgateway\n  namespace: istio-system    \n  labels:\n    chart: ingressgateway-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: ingressgateway\nspec:\n  type: NodePort\n  selector:\n    istio: ingressgateway\n  ports:\n    -\n      name: http\n      nodePort: 31380\n      port: 80\n    -\n      name: https\n      nodePort: 31390\n      port: 443\n    -\n      name: tcp\n      nodePort: 31400\n      port: 31400\n\n---\n# Source: istio/charts/mixer/templates/service.yaml\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-policy\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: mixer\nspec:\n  ports:\n  - name: grpc-mixer\n    port: 9091\n  - name: grpc-mixer-mtls\n    port: 15004\n  - name: http-monitoring\n    port: 9093\n  selector:\n    istio: mixer\n    istio-mixer-type: policy\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-telemetry\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: mixer\nspec:\n  ports:\n  - name: grpc-mixer\n    port: 9091\n  - name: grpc-mixer-mtls\n    port: 15004\n  - name: http-monitoring\n    port: 9093\n  - name: prometheus\n    port: 42422\n  selector:\n    istio: mixer\n    istio-mixer-type: telemetry\n---\n\n---\n# Source: istio/charts/mixer/templates/statsdtoprom.yaml\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: statsd-prom-bridge\nspec:\n  ports:\n  - name: statsd-prom\n    port: 9102\n  - name: statsd-udp\n    port: 9125\n    protocol: UDP\n  selector:\n    istio: statsd-prom-bridge\n\n---\n\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: mixer\nspec:\n  template:\n    metadata:\n      labels:\n        istio: statsd-prom-bridge\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio-statsd-prom-bridge\n      containers:\n      - name: statsd-prom-bridge\n        image: \"prom/statsd-exporter:latest\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9102\n        - containerPort: 9125\n          protocol: UDP\n        args:\n        - '-statsd.mapping-config=/etc/statsd/mapping.conf'\n        resources:\n            {}\n            \n        volumeMounts:\n        - name: config-volume\n          mountPath: /etc/statsd\n\n---\n# Source: istio/charts/pilot/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-pilot\n  namespace: istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  ports:\n  - port: 15003\n    name: http-old-discovery # mTLS or non-mTLS depending on auth setting\n  - port: 15005\n    name: https-discovery # always mTLS\n  - port: 15007\n    name: http-discovery # always plain-text\n  - port: 15010\n    name: grpc-xds # direct\n  - port: 15011\n    name: https-xds # mTLS\n  - port: 8080\n    name: http-legacy-discovery # direct\n  - port: 9093\n    name: http-monitoring\n  selector:\n    istio: pilot\n\n---\n# Source: istio/charts/prometheus/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  annotations:\n    prometheus.io/scrape: 'true'\n  labels:\n    name: prometheus\nspec:\n  selector:\n    app: prometheus\n  ports:\n  - name: http-prometheus\n    protocol: TCP\n    port: 9090\n\n---\n# Source: istio/charts/security/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  # we use the normal name here (e.g. 'prometheus')\n  # as grafana is configured to use this as a data source\n  name: istio-citadel\n  namespace: istio-system\n  labels:\n    app: istio-citadel\nspec:\n  ports:\n    - name: grpc-citadel\n      port: 8060\n      targetPort: 8060\n      protocol: TCP\n    - name: http-monitoring\n      port: 9093\n  selector:\n    istio: citadel\n\n---\n# Source: istio/charts/servicegraph/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: servicegraph\n  namespace: istio-system\n  labels:\n    app: servicegraph\n    chart: servicegraph-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  type: ClusterIP\n  ports:\n    - port: 8088\n      targetPort: 8088\n      protocol: TCP\n      name: http\n  selector:\n    app: servicegraph\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    istio: sidecar-injector\nspec:\n  ports:\n  - port: 443\n  selector:\n    istio: sidecar-injector\n\n---\n# Source: istio/charts/egressgateway/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-egressgateway\n  namespace: istio-system\n  labels:\n    app: egressgateway\n    chart: egressgateway-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: egressgateway\nspec:\n  replicas: \n  template:\n    metadata:\n      labels:\n        istio: egressgateway\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-egressgateway-service-account\n      containers:\n        - name: egressgateway\n          image: \"docker.io/istio/proxyv2:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 80\n            - containerPort: 443\n          args:\n          - proxy\n          - router\n          - -v\n          - \"2\"\n          - --discoveryRefreshDelay\n          - '1s' #discoveryRefreshDelay\n          - --drainDuration\n          - '45s' #drainDuration\n          - --parentShutdownDuration\n          - '1m0s' #parentShutdownDuration\n          - --connectTimeout\n          - '10s' #connectTimeout\n          - --serviceCluster\n          - istio-egressgateway\n          - --zipkinAddress\n          - zipkin:9411\n          - --statsdUdpAddress\n          - istio-statsd-prom-bridge:9125\n          - --proxyAdminPort\n          - \"15000\"\n          - --controlPlaneAuthPolicy\n          - NONE\n          - --discoveryAddress\n          - istio-pilot:8080\n          resources:\n            {}\n            \n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                fieldPath: status.podIP\n          - name: ISTIO_META_POD_NAME\n            valueFrom:\n              fieldRef:\n                fieldPath: metadata.name\n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: \"istio.default\"\n          optional: true\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/grafana/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: grafana\n  namespace: istio-system\n  labels:\n    app: grafana\n    chart: grafana-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: grafana\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      containers:\n        - name: grafana\n          image: \"docker.io/istio/grafana:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 3000\n          readinessProbe:\n            httpGet:\n              path: /login\n              port: 3000\n          env:\n          - name: GRAFANA_PORT\n            value: \"3000\"\n          - name: GF_AUTH_BASIC_ENABLED\n            value: \"false\"\n          - name: GF_AUTH_ANONYMOUS_ENABLED\n            value: \"true\"\n          - name: GF_AUTH_ANONYMOUS_ORG_ROLE\n            value: Admin\n          - name: GF_PATHS_DATA\n            value: /data/grafana\n          resources:\n            {}\n            \n          volumeMounts:\n          - name: data\n            mountPath: /data/grafana\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n      volumes:\n      - name: data\n        emptyDir: {}\n---\n# Source: istio/charts/ingressgateway/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-ingressgateway\n  namespace: istio-system\n  labels:\n    app: ingressgateway\n    chart: ingressgateway-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: ingressgateway\nspec:\n  replicas: \n  template:\n    metadata:\n      labels:\n        istio: ingressgateway\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-ingressgateway-service-account\n      containers:\n        - name: ingressgateway\n          image: \"docker.io/istio/proxyv2:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 80\n            - containerPort: 443\n            - containerPort: 31400\n          args:\n          - proxy\n          - router\n          - -v\n          - \"2\"\n          - --discoveryRefreshDelay\n          - '1s' #discoveryRefreshDelay\n          - --drainDuration\n          - '45s' #drainDuration\n          - --parentShutdownDuration\n          - '1m0s' #parentShutdownDuration\n          - --connectTimeout\n          - '10s' #connectTimeout\n          - --serviceCluster\n          - istio-ingressgateway\n          - --zipkinAddress\n          - zipkin:9411\n          - --statsdUdpAddress\n          - istio-statsd-prom-bridge:9125\n          - --proxyAdminPort\n          - \"15000\"\n          - --controlPlaneAuthPolicy\n          - NONE\n          - --discoveryAddress\n          - istio-pilot:8080\n          resources:\n            {}\n            \n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: status.podIP\n          - name: ISTIO_META_POD_NAME\n            valueFrom:\n              fieldRef:\n                fieldPath: metadata.name\n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n          - name: ingressgateway-certs\n            mountPath: \"/etc/istio/ingressgateway-certs\"\n            readOnly: true\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: \"istio.default\"\n          optional: true\n      - name: ingressgateway-certs\n        secret:\n          secretName: \"istio-ingressgateway-certs\"\n          optional: true\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/mixer/templates/deployment.yaml\n\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-policy\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: mixer\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: mixer\n        istio-mixer-type: policy\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-mixer-service-account\n          optional: true\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n      containers:\n      - name: mixer\n        image: \"docker.io/istio/mixer:0.8.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9092\n        - containerPort: 9093\n        - containerPort: 42422\n        args:\n          - --address\n          - tcp://127.0.0.1:9092\n          - --configStoreURL=k8s://\n          - --configDefaultNamespace=istio-system\n          - --trace_zipkin_url=http://zipkin:9411/api/v1/spans\n        resources:\n            {}\n            \n      - name: istio-proxy\n        image: \"docker.io/istio/proxyv2:0.8.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9091\n        - containerPort: 15004\n        args:\n        - proxy\n        - --serviceCluster\n        - istio-policy\n        - --templateFile\n        - /etc/istio/proxy/envoy_policy.yaml.tmpl\n        - --controlPlaneAuthPolicy\n        - NONE\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: status.podIP\n        resources:\n            requests:\n              cpu: 100m\n              memory: 128Mi\n            \n        volumeMounts:\n        - name: istio-certs\n          mountPath: /etc/certs\n          readOnly: true\n\n---\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-telemetry\n  namespace: istio-system\n  labels:\n    chart: mixer-0.8.0\n    release: RELEASE-NAME\n    istio: mixer\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: mixer\n        istio-mixer-type: telemetry\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-mixer-service-account\n          optional: true\n      containers:\n      - name: mixer\n        image: \"docker.io/istio/mixer:0.8.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9092\n        - containerPort: 9093\n        - containerPort: 42422\n        args:\n          - --address\n          - tcp://127.0.0.1:9092\n          - --configStoreURL=k8s://\n          - --configDefaultNamespace=istio-system\n          - --trace_zipkin_url=http://zipkin:9411/api/v1/spans\n        resources:\n            {}\n            \n      - name: istio-proxy\n        image: \"docker.io/istio/proxyv2:0.8.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9091\n        - containerPort: 15004\n        args:\n        - proxy\n        - --serviceCluster\n        - istio-telemetry\n        - --templateFile\n        - /etc/istio/proxy/envoy_telemetry.yaml.tmpl\n        - --controlPlaneAuthPolicy\n        - NONE\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: status.podIP\n        resources:\n            requests:\n              cpu: 100m\n              memory: 128Mi\n            \n        volumeMounts:\n        - name: istio-certs\n          mountPath: /etc/certs\n          readOnly: true\n\n--- \n\n---\n# Source: istio/charts/pilot/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-pilot\n  namespace: istio-system\n  # TODO: default tempate doesn't have this, which one is right ?\n  labels:\n    app: istio-pilot\n    chart: pilot-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: pilot\n  annotations:\n    checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: pilot\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-pilot-service-account\n      containers:\n        - name: discovery\n          image: \"docker.io/istio/pilot:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n          - \"discovery\"\n# TODO(sdake) remove when secrets are automagically registered\n          ports:\n          - containerPort: 8080\n          - containerPort: 15010\n          readinessProbe:\n            httpGet:\n              path: /v1/registration\n              port: 8080\n            initialDelaySeconds: 30\n            periodSeconds: 30\n            timeoutSeconds: 5\n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: PILOT_THROTTLE\n            value: \"500\"\n          - name: PILOT_CACHE_SQUASH\n            value: \"5\"\n          resources:\n            {}\n            \n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/istio/config\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n        - name: istio-proxy\n          image: \"docker.io/istio/proxyv2:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n          - containerPort: 15003\n          - containerPort: 15005\n          - containerPort: 15007\n          - containerPort: 15011\n          args:\n          - proxy\n          - --serviceCluster\n          - istio-pilot\n          - --templateFile\n          - /etc/istio/proxy/envoy_pilot.yaml.tmpl\n          - --controlPlaneAuthPolicy\n          - NONE\n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: status.podIP\n          resources:\n            requests:\n              cpu: 100m\n              memory: 128Mi\n            \n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio\n      - name: istio-certs\n        secret:\n          secretName: \"istio.istio-pilot-service-account\"\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/prometheus/templates/deployment.yaml\n# TODO: the original template has service account, roles, etc\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  labels:\n    app: prometheus\n    chart: prometheus-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: prometheus\n  template:\n    metadata:\n      labels:\n        app: prometheus\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: prometheus\n\n      containers:\n        - name: prometheus\n          image: \"docker.io/prom/prometheus:latest\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - '--storage.tsdb.retention=6h'\n            - '--config.file=/etc/prometheus/prometheus.yml'\n          ports:\n            - containerPort: 9090\n              name: http\n          livenessProbe:\n            httpGet:\n              path: /-/healthy\n              port: 9090\n          readinessProbe:\n            httpGet:\n              path: /-/ready\n              port: 9090\n          resources:\n            {}\n            \n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/prometheus\n      volumes:\n      - name: config-volume\n        configMap:\n          name: prometheus\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/security/templates/deployment.yaml\n# istio CA watching all namespaces\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-citadel\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: citadel\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: citadel\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-citadel-service-account\n      containers:\n        - name: citadel\n          image: \"docker.io/istio/citadel:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - --append-dns-names=true\n            - --grpc-port=8060\n            - --grpc-hostname=citadel\n            - --self-signed-ca=true\n            - --citadel-storage-namespace=istio-system\n          resources:\n            {}\n            \n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/servicegraph/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: servicegraph\n  namespace: istio-system\n  labels:\n    app: servicegraph\n    chart: servicegraph-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: servicegraph\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      containers:\n        - name: servicegraph\n          image: \"docker.io/istio/servicegraph:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 8088\n          args:\n          - --prometheusAddr=http://prometheus:9090\n          livenessProbe:\n            httpGet:\n              path: /graph\n              port: 8088\n          readinessProbe:\n            httpGet:\n              path: /graph\n              port: 8088\n          resources:\n            {}\n            \n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: sidecarInjectorWebhook\n    chart: sidecarInjectorWebhook-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\n    istio: sidecar-injector\nspec:\n  replicas: \n  template:\n    metadata:\n      labels:\n        istio: sidecar-injector\n    spec:\n      serviceAccountName: istio-sidecar-injector-service-account\n      containers:\n        - name: sidecar-injector-webhook\n          image: \"docker.io/istio/sidecar_injector:0.8.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - --caCertFile=/etc/istio/certs/root-cert.pem\n            - --tlsCertFile=/etc/istio/certs/cert-chain.pem\n            - --tlsKeyFile=/etc/istio/certs/key.pem\n            - --injectConfig=/etc/istio/inject/config\n            - --meshConfig=/etc/istio/config/mesh\n            - --healthCheckInterval=2s\n            - --healthCheckFile=/health\n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/istio/config\n            readOnly: true\n          - name: certs\n            mountPath: /etc/istio/certs\n            readOnly: true\n          - name: inject-config\n            mountPath: /etc/istio/inject\n            readOnly: true\n          livenessProbe:\n            exec:\n              command:\n                - /usr/local/bin/sidecar-injector\n                - probe\n                - --probe-path=/health\n                - --interval=2s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n          readinessProbe:\n            exec:\n              command:\n                - /usr/local/bin/sidecar-injector\n                - probe\n                - --probe-path=/health\n                - --interval=2s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio\n      - name: certs\n        secret:\n          secretName: istio.istio-sidecar-injector-service-account\n      - name: inject-config\n        configMap:\n          name: istio-sidecar-injector\n          items:\n          - key: config\n            path: config\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/tracing/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-tracing\n  namespace: istio-system\n  labels:\n    app: istio-tracing\n    chart: tracing-0.1.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: jaeger\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      containers:\n        - name: jaeger\n          image: \"jaegertracing/all-in-one:1.5\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 9411\n            - containerPort: 16686\n            - containerPort: 5775\n              protocol: UDP\n            - containerPort: 6831\n              protocol: UDP\n            - containerPort: 6832\n              protocol: UDP\n          env:\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: COLLECTOR_ZIPKIN_HTTP_PORT\n            value: \"9411\"\n          - name: MEMORY_MAX_TRACES\n            value: \"50000\"\n          livenessProbe:\n            httpGet:\n              path: /\n              port: 16686\n          readinessProbe:\n            httpGet:\n              path: /\n              port: 16686\n          resources:\n            {}\n            \n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/security/templates/cleanup-old-ca.yaml\n\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name: istio-cleanup-old-ca\n  namespace: istio-system\n  annotations:\n    \"helm.sh/hook\": post-install\n    \"helm.sh/hook-delete-policy\": hook-succeeded\n  labels:\n    app: security\n    chart: security-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\nspec:\n  template:\n    metadata:\n      name: istio-cleanup-old-ca\n      labels:\n        app: security\n        release: RELEASE-NAME\n    spec:\n      serviceAccountName: istio-cleanup-old-ca-service-account\n      containers:\n        - name: hyperkube\n          image: \"quay.io/coreos/hyperkube:v1.7.6_coreos.0\"\n          command:\n          - /bin/bash\n          - -c\n          - >\n              NS=\"-n istio-system\";\n              ./kubectl get deploy istio-ca $NS;\n              if [[ $? = 0 ]]; then ./kubectl delete deploy istio-ca $NS; fi;\n              ./kubectl get serviceaccount istio-ca-service-account $NS;\n              if [[ $? = 0 ]]; then ./kubectl delete serviceaccount istio-ca-service-account $NS; fi;\n              ./kubectl get service istio-ca-ilb $NS;\n              if [[ $? = 0 ]]; then ./kubectl delete service istio-ca-ilb $NS; fi\n      restartPolicy: Never\n---\n# Source: istio/charts/egressgateway/templates/autoscale.yaml\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-egressgateway\n    namespace: istio-system\nspec:\n    maxReplicas: 1\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-egressgateway\n    metrics:\n      - type: Resource\n        resource:\n          name: cpu\n          targetAverageUtilization: 80\n\n\n---\n# Source: istio/charts/ingressgateway/templates/autoscale.yaml\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-ingressgateway\n    namespace: istio-system\nspec:\n    maxReplicas: 1\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-ingressgateway\n    metrics:\n      - type: Resource\n        resource:\n          name: cpu\n          targetAverageUtilization: 80\n\n\n---\n# Source: istio/charts/tracing/templates/service.yaml\napiVersion: v1\nkind: List\nitems:\n- apiVersion: v1\n  kind: Service\n  metadata:\n    name: zipkin\n    namespace: istio-system\n    labels:\n      app: jaeger\n      chart: tracing-0.1.0\n      release: RELEASE-NAME\n      heritage: Tiller\n  spec:\n    type: ClusterIP\n    ports:\n      - port: 9411\n        targetPort: 9411\n        protocol: TCP\n        name: http\n    selector:\n      app: jaeger\n- apiVersion: v1\n  kind: Service\n  metadata:\n    name: tracing\n    namespace: istio-system\n    labels:\n      app: jaeger\n      chart: tracing-0.1.0\n      release: RELEASE-NAME\n      heritage: Tiller\n  spec:\n    ports:\n      - name: query-http\n        port: 80\n        protocol: TCP\n        targetPort: 16686\n    selector:\n      app: jaeger\n    type: LoadBalancer\n\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml\napiVersion: admissionregistration.k8s.io/v1beta1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-0.8.0\n    release: RELEASE-NAME\n    heritage: Tiller\nwebhooks:\n  - name: sidecar-injector.istio.io\n    clientConfig:\n      service:\n        name: istio-sidecar-injector\n        namespace: istio-system\n        path: \"/inject\"\n      caBundle: \"\"\n    rules:\n      - operations: [ \"CREATE\" ]\n        apiGroups: [\"\"]\n        apiVersions: [\"v1\"]\n        resources: [\"pods\"]\n    failurePolicy: Fail\n    namespaceSelector:\n      matchLabels:\n        istio-injection: enabled\n\n---\n# Source: istio/charts/grafana/templates/ingress.yaml\n\n---\n# Source: istio/charts/mixer/templates/config.yaml\n\n\n---\n# Source: istio/charts/prometheus/templates/ingress.yaml\n\n---\n# Source: istio/charts/servicegraph/templates/ingress.yaml\n\n---\n# Source: istio/charts/tracing/templates/ingress.yaml\n\n---\n# Source: istio/charts/tracing/templates/service-jaeger.yaml\n\n\n\n"
  },
  {
    "path": "examples/90_Kubernetes/istio/rendered/istio-v1.0-minikube.yml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n name: istio-system\n---\n# Source: istio/charts/galley/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-galley-configuration\n  namespace: istio-system\n  labels:\n    app: istio-galley\n    chart: galley-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: mixer\ndata:\n  validatingwebhookconfiguration.yaml: |-    \n    apiVersion: admissionregistration.k8s.io/v1beta1\n    kind: ValidatingWebhookConfiguration\n    metadata:\n      name: istio-galley\n      namespace: istio-system\n      labels:\n        app: istio-galley\n        chart: galley-1.0.0\n        release: istio\n        heritage: Tiller\n    webhooks:\n      - name: pilot.validation.istio.io\n        clientConfig:\n          service:\n            name: istio-galley\n            namespace: istio-system\n            path: \"/admitpilot\"\n          caBundle: \"\"\n        rules:\n          - operations:\n            - CREATE\n            - UPDATE\n            apiGroups:\n            - config.istio.io\n            apiVersions:\n            - v1alpha2\n            resources:\n            - httpapispecs\n            - httpapispecbindings\n            - quotaspecs\n            - quotaspecbindings\n          - operations:\n            - CREATE\n            - UPDATE\n            apiGroups:\n            - rbac.istio.io\n            apiVersions:\n            - \"*\"\n            resources:\n            - \"*\"\n          - operations:\n            - CREATE\n            - UPDATE\n            apiGroups:\n            - authentication.istio.io\n            apiVersions:\n            - \"*\"\n            resources:\n            - \"*\"\n          - operations:\n            - CREATE\n            - UPDATE\n            apiGroups:\n            - networking.istio.io\n            apiVersions:\n            - \"*\"\n            resources:\n            - destinationrules\n            - envoyfilters\n            - gateways\n            # disabled per @costinm's request\n            # - serviceentries\n            - virtualservices\n        failurePolicy: Fail\n      - name: mixer.validation.istio.io\n        clientConfig:\n          service:\n            name: istio-galley\n            namespace: istio-system\n            path: \"/admitmixer\"\n          caBundle: \"\"\n        rules:\n          - operations:\n            - CREATE\n            - UPDATE\n            apiGroups:\n            - config.istio.io\n            apiVersions:\n            - v1alpha2\n            resources:\n            - rules\n            - attributemanifests\n            - circonuses\n            - deniers\n            - fluentds\n            - kubernetesenvs\n            - listcheckers\n            - memquotas\n            - noops\n            - opas\n            - prometheuses\n            - rbacs\n            - servicecontrols\n            - solarwindses\n            - stackdrivers\n            - statsds\n            - stdios\n            - apikeys\n            - authorizations\n            - checknothings\n            # - kuberneteses\n            - listentries\n            - logentries\n            - metrics\n            - quotas\n            - reportnothings\n            - servicecontrolreports\n            - tracespans\n        failurePolicy: Fail\n\n\n---\n# Source: istio/charts/mixer/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    app: istio-statsd-prom-bridge\n    chart: mixer-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: mixer\ndata:\n  mapping.conf: |-\n\n---\n# Source: istio/charts/prometheus/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  labels:\n    app: prometheus\n    chart: prometheus-0.1.0\n    release: istio\n    heritage: Tiller\ndata:\n  prometheus.yml: |-\n    global:\n      scrape_interval: 15s\n    scrape_configs:\n\n    - job_name: 'istio-mesh'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-telemetry;prometheus\n\n    - job_name: 'envoy'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-statsd-prom-bridge;statsd-prom\n\n    - job_name: 'istio-policy'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-policy;http-monitoring\n\n    - job_name: 'istio-telemetry'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-telemetry;http-monitoring\n\n    - job_name: 'pilot'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-pilot;http-monitoring\n\n    - job_name: 'galley'\n      # Override the global default and scrape targets from this job every 5 seconds.\n      scrape_interval: 5s\n      # metrics_path defaults to '/metrics'\n      # scheme defaults to 'http'.\n\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - istio-system\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: istio-galley;http-monitoring\n\n    # scrape config for API servers\n    - job_name: 'kubernetes-apiservers'\n      kubernetes_sd_configs:\n      - role: endpoints\n        namespaces:\n          names:\n          - default\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]\n        action: keep\n        regex: kubernetes;https\n\n    # scrape config for nodes (kubelet)\n    - job_name: 'kubernetes-nodes'\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      kubernetes_sd_configs:\n      - role: node\n      relabel_configs:\n      - action: labelmap\n        regex: __meta_kubernetes_node_label_(.+)\n      - target_label: __address__\n        replacement: kubernetes.default.svc:443\n      - source_labels: [__meta_kubernetes_node_name]\n        regex: (.+)\n        target_label: __metrics_path__\n        replacement: /api/v1/nodes/${1}/proxy/metrics\n\n    # Scrape config for Kubelet cAdvisor.\n    #\n    # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics\n    # (those whose names begin with 'container_') have been removed from the\n    # Kubelet metrics endpoint.  This job scrapes the cAdvisor endpoint to\n    # retrieve those metrics.\n    #\n    # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor\n    # HTTP endpoint; use \"replacement: /api/v1/nodes/${1}:4194/proxy/metrics\"\n    # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with\n    # the --cadvisor-port=0 Kubelet flag).\n    #\n    # This job is not necessary and should be removed in Kubernetes 1.6 and\n    # earlier versions, or it will cause the metrics to be scraped twice.\n    - job_name: 'kubernetes-cadvisor'\n      scheme: https\n      tls_config:\n        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token\n      kubernetes_sd_configs:\n      - role: node\n      relabel_configs:\n      - action: labelmap\n        regex: __meta_kubernetes_node_label_(.+)\n      - target_label: __address__\n        replacement: kubernetes.default.svc:443\n      - source_labels: [__meta_kubernetes_node_name]\n        regex: (.+)\n        target_label: __metrics_path__\n        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor\n\n    # scrape config for service endpoints.\n    - job_name: 'kubernetes-service-endpoints'\n      kubernetes_sd_configs:\n      - role: endpoints\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]\n        action: keep\n        regex: true\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]\n        action: replace\n        target_label: __scheme__\n        regex: (https?)\n      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]\n        action: replace\n        target_label: __metrics_path__\n        regex: (.+)\n      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]\n        action: replace\n        target_label: __address__\n        regex: ([^:]+)(?::\\d+)?;(\\d+)\n        replacement: $1:$2\n      - action: labelmap\n        regex: __meta_kubernetes_service_label_(.+)\n      - source_labels: [__meta_kubernetes_namespace]\n        action: replace\n        target_label: kubernetes_namespace\n      - source_labels: [__meta_kubernetes_service_name]\n        action: replace\n        target_label: kubernetes_name\n\n    # Example scrape config for pods\n    - job_name: 'kubernetes-pods'\n      kubernetes_sd_configs:\n      - role: pod\n\n      relabel_configs:\n      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]\n        action: keep\n        regex: true\n      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]\n        action: replace\n        target_label: __metrics_path__\n        regex: (.+)\n      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]\n        action: replace\n        regex: ([^:]+)(?::\\d+)?;(\\d+)\n        replacement: $1:$2\n        target_label: __address__\n      - action: labelmap\n        regex: __meta_kubernetes_pod_label_(.+)\n      - source_labels: [__meta_kubernetes_namespace]\n        action: replace\n        target_label: namespace\n      - source_labels: [__meta_kubernetes_pod_name]\n        action: replace\n        target_label: pod_name\n\n---\n# Source: istio/charts/security/templates/configmap.yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-security-custom-resources\n  namespace: istio-system\n  labels:\n    app: istio-security\n    chart: security-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: security\ndata:\n  custom-resources.yaml: |-\n  run.sh: |-    \n    #!/bin/sh\n    \n    set -x\n    \n    if [ \"$#\" -ne \"1\" ]; then\n        echo \"first argument should be path to custom resource yaml\"\n        exit 1\n    fi\n    \n    pathToResourceYAML=${1}\n    \n    /kubectl get validatingwebhookconfiguration istio-galley 2>/dev/null\n    if [ \"$?\" -eq 0 ]; then\n        echo \"istio-galley validatingwebhookconfiguration found - waiting for istio-galley deployment to be ready\"\n        while true; do\n            /kubectl -n istio-system get deployment istio-galley 2>/dev/null\n            if [ \"$?\" -eq 0 ]; then\n                break\n            fi\n            sleep 1\n        done\n        /kubectl -n istio-system rollout status deployment istio-galley\n        if [ \"$?\" -ne 0 ]; then\n            echo \"istio-galley deployment rollout status check failed\"\n            exit 1\n        fi\n        echo \"istio-galley deployment ready for configuration validation\"\n    fi\n    sleep 5\n    /kubectl apply -f ${pathToResourceYAML}\n    \n\n---\n# Source: istio/templates/configmap.yaml\n\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio\n  namespace: istio-system\n  labels:\n    app: istio\n    chart: istio-1.0.0\n    release: istio\n    heritage: Tiller\ndata:\n  mesh: |-\n    # Set the following variable to true to disable policy checks by the Mixer.\n    # Note that metrics will still be reported to the Mixer.\n    disablePolicyChecks: false\n\n    # Set enableTracing to false to disable request tracing.\n    enableTracing: true\n\n    # Set accessLogFile to empty string to disable access log.\n    accessLogFile: \"/dev/stdout\"\n    #\n    # Deprecated: mixer is using EDS\n    mixerCheckServer: istio-policy.istio-system.svc.cluster.local:9091\n    mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:9091\n\n    # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get\n    # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. \n    sdsUdsPath: \"\"\n    \n    # How frequently should Envoy fetch key/cert from NodeAgent.\n    sdsRefreshDelay: 15s\n\n    #\n    defaultConfig:\n      #\n      # TCP connection timeout between Envoy & the application, and between Envoys.\n      connectTimeout: 10s\n      #\n      ### ADVANCED SETTINGS #############\n      # Where should envoy's configuration be stored in the istio-proxy container\n      configPath: \"/etc/istio/proxy\"\n      binaryPath: \"/usr/local/bin/envoy\"\n      # The pseudo service name used for Envoy.\n      serviceCluster: istio-proxy\n      # These settings that determine how long an old Envoy\n      # process should be kept alive after an occasional reload.\n      drainDuration: 45s\n      parentShutdownDuration: 1m0s\n      #\n      # The mode used to redirect inbound connections to Envoy. This setting\n      # has no effect on outbound traffic: iptables REDIRECT is always used for\n      # outbound connections.\n      # If \"REDIRECT\", use iptables REDIRECT to NAT and redirect to Envoy.\n      # The \"REDIRECT\" mode loses source addresses during redirection.\n      # If \"TPROXY\", use iptables TPROXY to redirect to Envoy.\n      # The \"TPROXY\" mode preserves both the source and destination IP\n      # addresses and ports, so that they can be used for advanced filtering\n      # and manipulation.\n      # The \"TPROXY\" mode also configures the sidecar to run with the\n      # CAP_NET_ADMIN capability, which is required to use TPROXY.\n      #interceptionMode: REDIRECT\n      #\n      # Port where Envoy listens (on local host) for admin commands\n      # You can exec into the istio-proxy container in a pod and\n      # curl the admin port (curl http://localhost:15000/) to obtain\n      # diagnostic information from Envoy. See\n      # https://lyft.github.io/envoy/docs/operations/admin.html\n      # for more details\n      proxyAdminPort: 15000\n      #\n      # Zipkin trace collector\n      zipkinAddress: zipkin.istio-system:9411\n      #\n      # Statsd metrics collector converts statsd metrics into Prometheus metrics.\n      statsdUdpAddress: istio-statsd-prom-bridge.istio-system:9125\n      #\n      # Mutual TLS authentication between sidecars and istio control plane.\n      controlPlaneAuthPolicy: NONE\n      #\n      # Address where istio Pilot service is running\n      discoveryAddress: istio-pilot.istio-system:15007\n\n---\n# Source: istio/templates/sidecar-injector-configmap.yaml\n\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: istio\n    chart: istio-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: sidecar-injector\ndata:\n  config: |-\n    policy: enabled\n    template: |-\n      initContainers:\n      - name: istio-init\n        image: \"docker.io/istio/proxy_init:1.0.0\"\n        args:\n        - \"-p\"\n        - [[ .MeshConfig.ProxyListenPort ]]\n        - \"-u\"\n        - 1337\n        - \"-m\"\n        - [[ or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String ]]\n        - \"-i\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeOutboundIPRanges\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeOutboundIPRanges\"  ]]\"\n        [[ else -]]\n        - \"*\"\n        [[ end -]]\n        - \"-x\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeOutboundIPRanges\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeOutboundIPRanges\"  ]]\"\n        [[ else -]]\n        - \"\"\n        [[ end -]]\n        - \"-b\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeInboundPorts\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/includeInboundPorts\"  ]]\"\n        [[ else -]]\n        - [[ range .Spec.Containers -]][[ range .Ports -]][[ .ContainerPort -]], [[ end -]][[ end -]][[ end]]\n        - \"-d\"\n        [[ if (isset .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeInboundPorts\") -]]\n        - \"[[ index .ObjectMeta.Annotations \"traffic.sidecar.istio.io/excludeInboundPorts\" ]]\"\n        [[ else -]]\n        - \"\"\n        [[ end -]]\n        imagePullPolicy: IfNotPresent\n        securityContext:\n          capabilities:\n            add:\n            - NET_ADMIN\n          privileged: true\n        restartPolicy: Always\n      \n      containers:\n      - name: istio-proxy\n        image: [[ if (isset .ObjectMeta.Annotations \"sidecar.istio.io/proxyImage\") -]]\n        \"[[ index .ObjectMeta.Annotations \"sidecar.istio.io/proxyImage\" ]]\"\n        [[ else -]]\n        docker.io/istio/proxyv2:1.0.0\n        [[ end -]]\n        args:\n        - proxy\n        - sidecar\n        - --configPath\n        - [[ .ProxyConfig.ConfigPath ]]\n        - --binaryPath\n        - [[ .ProxyConfig.BinaryPath ]]\n        - --serviceCluster\n        [[ if ne \"\" (index .ObjectMeta.Labels \"app\") -]]\n        - [[ index .ObjectMeta.Labels \"app\" ]]\n        [[ else -]]\n        - \"istio-proxy\"\n        [[ end -]]\n        - --drainDuration\n        - [[ formatDuration .ProxyConfig.DrainDuration ]]\n        - --parentShutdownDuration\n        - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]]\n        - --discoveryAddress\n        - [[ .ProxyConfig.DiscoveryAddress ]]\n        - --discoveryRefreshDelay\n        - [[ formatDuration .ProxyConfig.DiscoveryRefreshDelay ]]\n        - --zipkinAddress\n        - [[ .ProxyConfig.ZipkinAddress ]]\n        - --connectTimeout\n        - [[ formatDuration .ProxyConfig.ConnectTimeout ]]\n        - --statsdUdpAddress\n        - [[ .ProxyConfig.StatsdUdpAddress ]]\n        - --proxyAdminPort\n        - [[ .ProxyConfig.ProxyAdminPort ]]\n        - --controlPlaneAuthPolicy\n        - [[ or (index .ObjectMeta.Annotations \"sidecar.istio.io/controlPlaneAuthPolicy\") .ProxyConfig.ControlPlaneAuthPolicy ]]\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              fieldPath: status.podIP\n        - name: ISTIO_META_POD_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: metadata.name\n        - name: ISTIO_META_INTERCEPTION_MODE\n          value: [[ or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String ]]\n        imagePullPolicy: IfNotPresent\n        securityContext:\n          privileged: false\n          readOnlyRootFilesystem: true\n          [[ if eq (or (index .ObjectMeta.Annotations \"sidecar.istio.io/interceptionMode\") .ProxyConfig.InterceptionMode.String) \"TPROXY\" -]]\n          capabilities:\n            add:\n            - NET_ADMIN\n          runAsGroup: 1337\n          [[ else -]]\n          runAsUser: 1337\n          [[ end -]]\n        restartPolicy: Always\n        resources:\n          [[ if (isset .ObjectMeta.Annotations \"sidecar.istio.io/proxyCPU\") -]]\n          requests:\n            cpu: \"[[ index .ObjectMeta.Annotations \"sidecar.istio.io/proxyCPU\" ]]\"\n            memory: \"[[ index .ObjectMeta.Annotations \"sidecar.istio.io/proxyMemory\" ]]\"\n        [[ else -]]\n          requests:\n            cpu: 10m\n          \n        [[ end -]]\n        volumeMounts:\n        - mountPath: /etc/istio/proxy\n          name: istio-envoy\n        - mountPath: /etc/certs/\n          name: istio-certs\n          readOnly: true\n      volumes:\n      - emptyDir:\n          medium: Memory\n        name: istio-envoy\n      - name: istio-certs\n        secret:\n          optional: true\n          [[ if eq .Spec.ServiceAccountName \"\" -]]\n          secretName: istio.default\n          [[ else -]]\n          secretName: [[ printf \"istio.%s\" .Spec.ServiceAccountName ]]\n          [[ end -]]\n\n---\n# Source: istio/charts/galley/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-galley-service-account\n  namespace: istio-system\n  labels:\n    app: istio-galley\n    chart: galley-1.0.0\n    heritage: Tiller\n    release: istio\n\n---\n# Source: istio/charts/gateways/templates/serviceaccount.yaml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-egressgateway-service-account\n  namespace: istio-system\n  labels:\n    app: egressgateway\n    chart: gateways-1.0.0\n    heritage: Tiller\n    release: istio\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-ingressgateway-service-account\n  namespace: istio-system\n  labels:\n    app: ingressgateway\n    chart: gateways-1.0.0\n    heritage: Tiller\n    release: istio\n---\n\n---\n# Source: istio/charts/mixer/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-mixer-service-account\n  namespace: istio-system\n  labels:\n    app: mixer\n    chart: mixer-1.0.0\n    heritage: Tiller\n    release: istio\n\n---\n# Source: istio/charts/pilot/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-pilot-service-account\n  namespace: istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-1.0.0\n    heritage: Tiller\n    release: istio\n\n---\n# Source: istio/charts/prometheus/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: prometheus\n  namespace: istio-system\n\n---\n# Source: istio/charts/security/templates/cleanup-secrets.yaml\n# The reason for creating a ServiceAccount and ClusterRole specifically for this\n# post-delete hooked job is because the citadel ServiceAccount is being deleted\n# before this hook is launched. On the other hand, running this hook before the\n# deletion of the citadel (e.g. pre-delete) won't delete the secrets because they\n# will be re-created immediately by the to-be-deleted citadel.\n#\n# It's also important that the ServiceAccount, ClusterRole and ClusterRoleBinding\n# will be ready before running the hooked Job therefore the hook weights.\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-cleanup-secrets-service-account\n  namespace: istio-system\n  annotations:\n    \"helm.sh/hook\": post-delete\n    \"helm.sh/hook-delete-policy\": hook-succeeded\n    \"helm.sh/hook-weight\": \"1\"\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-cleanup-secrets-istio-system\n  annotations:\n    \"helm.sh/hook\": post-delete\n    \"helm.sh/hook-delete-policy\": hook-succeeded\n    \"helm.sh/hook-weight\": \"1\"\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"\"]\n  resources: [\"secrets\"]\n  verbs: [\"list\", \"delete\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-cleanup-secrets-istio-system\n  annotations:\n    \"helm.sh/hook\": post-delete\n    \"helm.sh/hook-delete-policy\": hook-succeeded\n    \"helm.sh/hook-weight\": \"2\"\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-cleanup-secrets-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-cleanup-secrets-service-account\n    namespace: istio-system\n---\napiVersion: batch/v1\nkind: Job\nmetadata:\n  name: istio-cleanup-secrets\n  namespace: istio-system\n  annotations:\n    \"helm.sh/hook\": post-delete\n    \"helm.sh/hook-delete-policy\": hook-succeeded\n    \"helm.sh/hook-weight\": \"3\"\n  labels:\n    app: security\n    chart: security-1.0.0\n    release: istio\n    heritage: Tiller\nspec:\n  template:\n    metadata:\n      name: istio-cleanup-secrets\n      labels:\n        app: security\n        release: istio\n    spec:\n      serviceAccountName: istio-cleanup-secrets-service-account\n      containers:\n        - name: hyperkube\n          image: \"quay.io/coreos/hyperkube:v1.7.6_coreos.0\"\n          command:\n          - /bin/bash\n          - -c\n          - >\n              kubectl get secret --all-namespaces | grep \"istio.io/key-and-cert\" |  while read -r entry; do\n                ns=$(echo $entry | awk '{print $1}');\n                name=$(echo $entry | awk '{print $2}');\n                kubectl delete secret $name -n $ns;\n              done\n      restartPolicy: OnFailure\n\n---\n# Source: istio/charts/security/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-citadel-service-account\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: istio-sidecar-injector-service-account\n  namespace: istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-1.0.0\n    heritage: Tiller\n    release: istio\n\n---\n# Source: istio/templates/crds.yaml\n# \n# these CRDs only make sense when pilot is enabled\n#\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: virtualservices.networking.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: VirtualService\n    listKind: VirtualServiceList\n    plural: virtualservices\n    singular: virtualservice\n    categories:\n    - istio-io\n    - networking-istio-io\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: destinationrules.networking.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: DestinationRule\n    listKind: DestinationRuleList\n    plural: destinationrules\n    singular: destinationrule\n    categories:\n    - istio-io\n    - networking-istio-io\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: serviceentries.networking.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: ServiceEntry\n    listKind: ServiceEntryList\n    plural: serviceentries\n    singular: serviceentry\n    categories:\n    - istio-io\n    - networking-istio-io\n  scope: Namespaced\n  version: v1alpha3\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: gateways.networking.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n    \"helm.sh/hook-weight\": \"-5\"\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: Gateway\n    plural: gateways\n    singular: gateway\n    categories:\n    - istio-io\n    - networking-istio-io\n  scope: Namespaced\n  version: v1alpha3 \n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: envoyfilters.networking.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: istio-pilot\nspec:\n  group: networking.istio.io\n  names:\n    kind: EnvoyFilter\n    plural: envoyfilters\n    singular: envoyfilter\n    categories:\n    - istio-io\n    - networking-istio-io\n  scope: Namespaced\n  version: v1alpha3\n---\n#\n\n# these CRDs only make sense when security is enabled\n#\n\n#\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  annotations:\n    \"helm.sh/hook\": crd-install\n  name: httpapispecbindings.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: HTTPAPISpecBinding\n    plural: httpapispecbindings\n    singular: httpapispecbinding\n    categories:\n    - istio-io\n    - apim-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  annotations:\n    \"helm.sh/hook\": crd-install\n  name: httpapispecs.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: HTTPAPISpec\n    plural: httpapispecs\n    singular: httpapispec\n    categories:\n    - istio-io\n    - apim-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  annotations:\n    \"helm.sh/hook\": crd-install\n  name: quotaspecbindings.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: QuotaSpecBinding\n    plural: quotaspecbindings\n    singular: quotaspecbinding\n    categories:\n    - istio-io\n    - apim-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  annotations:\n    \"helm.sh/hook\": crd-install\n  name: quotaspecs.config.istio.io\nspec:\n  group: config.istio.io\n  names:\n    kind: QuotaSpec\n    plural: quotaspecs\n    singular: quotaspec\n    categories:\n    - istio-io\n    - apim-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\n# Mixer CRDs\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: rules.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: core\nspec:\n  group: config.istio.io\n  names:\n    kind: rule\n    plural: rules\n    singular: rule\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: attributemanifests.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: core\nspec:\n  group: config.istio.io\n  names:\n    kind: attributemanifest\n    plural: attributemanifests\n    singular: attributemanifest\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: bypasses.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: bypass\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: bypass\n    plural: bypasses\n    singular: bypass\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: circonuses.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: circonus\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: circonus\n    plural: circonuses\n    singular: circonus\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: deniers.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: denier\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: denier\n    plural: deniers\n    singular: denier\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: fluentds.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: fluentd\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: fluentd\n    plural: fluentds\n    singular: fluentd\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: kubernetesenvs.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: kubernetesenv\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: kubernetesenv\n    plural: kubernetesenvs\n    singular: kubernetesenv\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: listcheckers.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: listchecker\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: listchecker\n    plural: listcheckers\n    singular: listchecker\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: memquotas.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: memquota\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: memquota\n    plural: memquotas\n    singular: memquota\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: noops.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: noop\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: noop\n    plural: noops\n    singular: noop\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: opas.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: opa\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: opa\n    plural: opas\n    singular: opa\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: prometheuses.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: prometheus\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: prometheus\n    plural: prometheuses\n    singular: prometheus\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: rbacs.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: rbac\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: rbac\n    plural: rbacs\n    singular: rbac\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: redisquotas.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    package: redisquota\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: redisquota\n    plural: redisquotas\n    singular: redisquota\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicecontrols.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: servicecontrol\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: servicecontrol\n    plural: servicecontrols\n    singular: servicecontrol\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: signalfxs.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: signalfx\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: signalfx\n    plural: signalfxs\n    singular: signalfx\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: solarwindses.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: solarwinds\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: solarwinds\n    plural: solarwindses\n    singular: solarwinds\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: stackdrivers.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: stackdriver\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: stackdriver\n    plural: stackdrivers\n    singular: stackdriver\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: statsds.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: statsd\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: statsd\n    plural: statsds\n    singular: statsd\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: stdios.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: stdio\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: stdio\n    plural: stdios\n    singular: stdio\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: apikeys.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: apikey\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: apikey\n    plural: apikeys\n    singular: apikey\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: authorizations.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: authorization\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: authorization\n    plural: authorizations\n    singular: authorization\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: checknothings.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: checknothing\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: checknothing\n    plural: checknothings\n    singular: checknothing\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: kuberneteses.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: adapter.template.kubernetes\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: kubernetes\n    plural: kuberneteses\n    singular: kubernetes\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: listentries.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: listentry\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: listentry\n    plural: listentries\n    singular: listentry\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: logentries.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: logentry\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: logentry\n    plural: logentries\n    singular: logentry\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: edges.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: edge\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: edge\n    plural: edges\n    singular: edge\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: metrics.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: metric\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: metric\n    plural: metrics\n    singular: metric\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: quotas.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: quota\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: quota\n    plural: quotas\n    singular: quota\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: reportnothings.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: reportnothing\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: reportnothing\n    plural: reportnothings\n    singular: reportnothing\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicecontrolreports.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: servicecontrolreport\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: servicecontrolreport\n    plural: servicecontrolreports\n    singular: servicecontrolreport\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: tracespans.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: tracespan\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: tracespan\n    plural: tracespans\n    singular: tracespan\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: rbacconfigs.rbac.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: rbac\nspec:\n  group: rbac.istio.io\n  names:\n    kind: RbacConfig\n    plural: rbacconfigs\n    singular: rbacconfig\n    categories:\n    - istio-io\n    - rbac-istio-io\n  scope: Namespaced\n  version: v1alpha1\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: serviceroles.rbac.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: rbac\nspec:\n  group: rbac.istio.io\n  names:\n    kind: ServiceRole\n    plural: serviceroles\n    singular: servicerole\n    categories:\n    - istio-io\n    - rbac-istio-io\n  scope: Namespaced\n  version: v1alpha1\n---\n\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: servicerolebindings.rbac.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: istio.io.mixer\n    istio: rbac\nspec:\n  group: rbac.istio.io\n  names:\n    kind: ServiceRoleBinding\n    plural: servicerolebindings\n    singular: servicerolebinding\n    categories:\n    - istio-io\n    - rbac-istio-io\n  scope: Namespaced\n  version: v1alpha1\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: adapters.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: adapter\n    istio: mixer-adapter\nspec:\n  group: config.istio.io\n  names:\n    kind: adapter\n    plural: adapters\n    singular: adapter\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: instances.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: instance\n    istio: mixer-instance\nspec:\n  group: config.istio.io\n  names:\n    kind: instance\n    plural: instances\n    singular: instance\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: templates.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: template\n    istio: mixer-template\nspec:\n  group: config.istio.io\n  names:\n    kind: template\n    plural: templates\n    singular: template\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\nkind: CustomResourceDefinition\napiVersion: apiextensions.k8s.io/v1beta1\nmetadata:\n  name: handlers.config.istio.io\n  annotations:\n    \"helm.sh/hook\": crd-install\n  labels:\n    app: mixer\n    package: handler\n    istio: mixer-handler\nspec:\n  group: config.istio.io\n  names:\n    kind: handler\n    plural: handlers\n    singular: handler\n    categories:\n    - istio-io\n    - policy-istio-io\n  scope: Namespaced\n  version: v1alpha2\n---\n#\n# \n---\n# Source: istio/charts/galley/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-galley-istio-system\n  labels:\n    app: istio-galley\n    chart: galley-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"admissionregistration.k8s.io\"]\n  resources: [\"validatingwebhookconfigurations\"]\n  verbs: [\"*\"]\n- apiGroups: [\"config.istio.io\"] # istio mixer CRD watcher\n  resources: [\"*\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"*\"]\n  resources: [\"deployments\"]\n  resourceNames: [\"istio-galley\"]\n  verbs: [\"get\"]\n\n---\n# Source: istio/charts/gateways/templates/clusterrole.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  labels:\n    app: gateways\n    chart: gateways-1.0.0\n    heritage: Tiller\n    release: istio\n  name: istio-egressgateway-istio-system\nrules:\n- apiGroups: [\"extensions\"]\n  resources: [\"thirdpartyresources\", \"virtualservices\", \"destinationrules\", \"gateways\"]\n  verbs: [\"get\", \"watch\", \"list\", \"update\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  labels:\n    app: gateways\n    chart: gateways-1.0.0\n    heritage: Tiller\n    release: istio\n  name: istio-ingressgateway-istio-system\nrules:\n- apiGroups: [\"extensions\"]\n  resources: [\"thirdpartyresources\", \"virtualservices\", \"destinationrules\", \"gateways\"]\n  verbs: [\"get\", \"watch\", \"list\", \"update\"]\n---\n\n---\n# Source: istio/charts/mixer/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-mixer-istio-system\n  labels:\n    app: mixer\n    chart: mixer-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"config.istio.io\"] # istio CRD watcher\n  resources: [\"*\"]\n  verbs: [\"create\", \"get\", \"list\", \"watch\", \"patch\"]\n- apiGroups: [\"rbac.istio.io\"] # istio RBAC watcher\n  resources: [\"*\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"apiextensions.k8s.io\"]\n  resources: [\"customresourcedefinitions\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources: [\"configmaps\", \"endpoints\", \"pods\", \"services\", \"namespaces\", \"secrets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"extensions\"]\n  resources: [\"replicasets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"apps\"]\n  resources: [\"replicasets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n\n---\n# Source: istio/charts/pilot/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-pilot-istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"config.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"rbac.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n- apiGroups: [\"networking.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"authentication.istio.io\"]\n  resources: [\"*\"]\n  verbs: [\"*\"]\n- apiGroups: [\"apiextensions.k8s.io\"]\n  resources: [\"customresourcedefinitions\"]\n  verbs: [\"*\"]\n- apiGroups: [\"extensions\"]\n  resources: [\"thirdpartyresources\", \"thirdpartyresources.extensions\", \"ingresses\", \"ingresses/status\"]\n  verbs: [\"*\"]\n- apiGroups: [\"\"]\n  resources: [\"configmaps\"]\n  verbs: [\"create\", \"get\", \"list\", \"watch\", \"update\"]\n- apiGroups: [\"\"]\n  resources: [\"endpoints\", \"pods\", \"services\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources: [\"namespaces\", \"nodes\", \"secrets\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n\n---\n# Source: istio/charts/prometheus/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: prometheus-istio-system\nrules:\n- apiGroups: [\"\"]\n  resources:\n  - nodes\n  - services\n  - endpoints\n  - pods\n  - nodes/proxy\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources:\n  - configmaps\n  verbs: [\"get\"]\n- nonResourceURLs: [\"/metrics\"]\n  verbs: [\"get\"]\n\n---\n# Source: istio/charts/security/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-citadel-istio-system\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"\"]\n  resources: [\"secrets\"]\n  verbs: [\"create\", \"get\", \"watch\", \"list\", \"update\", \"delete\"]\n- apiGroups: [\"\"]\n  resources: [\"serviceaccounts\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n- apiGroups: [\"\"]\n  resources: [\"services\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: istio-sidecar-injector-istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-1.0.0\n    heritage: Tiller\n    release: istio\nrules:\n- apiGroups: [\"*\"]\n  resources: [\"configmaps\"]\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"admissionregistration.k8s.io\"]\n  resources: [\"mutatingwebhookconfigurations\"]\n  verbs: [\"get\", \"list\", \"watch\", \"patch\"]\n\n---\n# Source: istio/charts/galley/templates/clusterrolebinding.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-galley-admin-role-binding-istio-system\n  labels:\n    app: istio-galley\n    chart: galley-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-galley-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-galley-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/gateways/templates/clusterrolebindings.yaml\n\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-egressgateway-istio-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-egressgateway-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-egressgateway-service-account\n    namespace: istio-system\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-ingressgateway-istio-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-ingressgateway-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-ingressgateway-service-account\n    namespace: istio-system\n---\n\n---\n# Source: istio/charts/mixer/templates/clusterrolebinding.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-mixer-admin-role-binding-istio-system\n  labels:\n    app: mixer\n    chart: mixer-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-mixer-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-mixer-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/pilot/templates/clusterrolebinding.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-pilot-istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-pilot-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-pilot-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/prometheus/templates/clusterrolebindings.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: prometheus-istio-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: prometheus-istio-system\nsubjects:\n- kind: ServiceAccount\n  name: prometheus\n  namespace: istio-system\n\n---\n# Source: istio/charts/security/templates/clusterrolebinding.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-citadel-istio-system\n  labels:\n    app: security\n    chart: security-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-citadel-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-citadel-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: istio-sidecar-injector-admin-role-binding-istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-1.0.0\n    heritage: Tiller\n    release: istio\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: istio-sidecar-injector-istio-system\nsubjects:\n  - kind: ServiceAccount\n    name: istio-sidecar-injector-service-account\n    namespace: istio-system\n\n---\n# Source: istio/charts/galley/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-galley\n  namespace: istio-system\n  labels:\n    istio: galley\nspec:\n  ports:\n  - port: 443\n    name: https-validation\n  - port: 9093\n    name: http-monitoring\n  selector:\n    istio: galley\n\n---\n# Source: istio/charts/gateways/templates/service.yaml\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-egressgateway\n  namespace: istio-system\n  annotations:\n  labels:\n    chart: gateways-1.0.0\n    release: istio\n    heritage: Tiller\n    app: istio-egressgateway\n    istio: egressgateway\nspec:\n  type: NodePort\n  selector:\n    app: istio-egressgateway\n    istio: egressgateway\n  ports:\n    -\n      name: http2\n      port: 80\n    -\n      name: https\n      port: 443\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-ingressgateway\n  namespace: istio-system\n  annotations:\n  labels:\n    chart: gateways-1.0.0\n    release: istio\n    heritage: Tiller\n    app: istio-ingressgateway\n    istio: ingressgateway\nspec:\n  type: NodePort\n  selector:\n    app: istio-ingressgateway\n    istio: ingressgateway\n  ports:\n    -\n      name: http2\n      nodePort: 31380\n      port: 80\n      targetPort: 80\n    -\n      name: https\n      nodePort: 31390\n      port: 443\n    -\n      name: tcp\n      nodePort: 31400\n      port: 31400\n    -\n      name: tcp-pilot-grpc-tls\n      port: 15011\n      targetPort: 15011\n    -\n      name: tcp-citadel-grpc-tls\n      port: 8060\n      targetPort: 8060\n    -\n      name: http2-prometheus\n      port: 15030\n      targetPort: 15030\n    -\n      name: http2-grafana\n      port: 15031\n      targetPort: 15031\n---\n\n---\n# Source: istio/charts/mixer/templates/service.yaml\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-policy\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: mixer\nspec:\n  ports:\n  - name: grpc-mixer\n    port: 9091\n  - name: grpc-mixer-mtls\n    port: 15004\n  - name: http-monitoring\n    port: 9093\n  selector:\n    istio: mixer\n    istio-mixer-type: policy\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-telemetry\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: mixer\nspec:\n  ports:\n  - name: grpc-mixer\n    port: 9091\n  - name: grpc-mixer-mtls\n    port: 15004\n  - name: http-monitoring\n    port: 9093\n  - name: prometheus\n    port: 42422\n  selector:\n    istio: mixer\n    istio-mixer-type: telemetry\n---\n\n---\n# Source: istio/charts/mixer/templates/statsdtoprom.yaml\n\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: statsd-prom-bridge\nspec:\n  ports:\n  - name: statsd-prom\n    port: 9102\n  - name: statsd-udp\n    port: 9125\n    protocol: UDP\n  selector:\n    istio: statsd-prom-bridge\n\n---\n\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-statsd-prom-bridge\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: mixer\nspec:\n  template:\n    metadata:\n      labels:\n        istio: statsd-prom-bridge\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio-statsd-prom-bridge\n      containers:\n      - name: statsd-prom-bridge\n        image: \"docker.io/prom/statsd-exporter:v0.6.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9102\n        - containerPort: 9125\n          protocol: UDP\n        args:\n        - '-statsd.mapping-config=/etc/statsd/mapping.conf'\n        resources:\n          requests:\n            cpu: 10m\n          \n        volumeMounts:\n        - name: config-volume\n          mountPath: /etc/statsd\n\n---\n# Source: istio/charts/pilot/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-pilot\n  namespace: istio-system\n  labels:\n    app: istio-pilot\n    chart: pilot-1.0.0\n    release: istio\n    heritage: Tiller\nspec:\n  ports:\n  - port: 15010\n    name: grpc-xds # direct\n  - port: 15011\n    name: https-xds # mTLS\n  - port: 8080\n    name: http-legacy-discovery # direct\n  - port: 9093\n    name: http-monitoring\n  selector:\n    istio: pilot\n\n---\n# Source: istio/charts/prometheus/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  annotations:\n    prometheus.io/scrape: 'true'\n  labels:\n    name: prometheus\nspec:\n  selector:\n    app: prometheus\n  ports:\n  - name: http-prometheus\n    protocol: TCP\n    port: 9090\n\n---\n# Source: istio/charts/security/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  # we use the normal name here (e.g. 'prometheus')\n  # as grafana is configured to use this as a data source\n  name: istio-citadel\n  namespace: istio-system\n  labels:\n    app: istio-citadel\nspec:\n  ports:\n    - name: grpc-citadel\n      port: 8060\n      targetPort: 8060\n      protocol: TCP\n    - name: http-monitoring\n      port: 9093\n  selector:\n    istio: citadel\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    istio: sidecar-injector\nspec:\n  ports:\n  - port: 443\n  selector:\n    istio: sidecar-injector\n\n---\n# Source: istio/charts/galley/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-galley\n  namespace: istio-system\n  labels:\n    app: galley\n    chart: galley-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: galley\nspec:\n  replicas: 1\n  strategy:\n    rollingUpdate:\n      maxSurge: 1\n      maxUnavailable: 0\n  template:\n    metadata:\n      labels:\n        istio: galley\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-galley-service-account\n      containers:\n        - name: validator\n          image: \"docker.io/istio/galley:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n          - containerPort: 443\n          - containerPort: 9093\n          command:\n          - /usr/local/bin/galley\n          - validator\n          - --deployment-namespace=istio-system\n          - --caCertFile=/etc/istio/certs/root-cert.pem\n          - --tlsCertFile=/etc/istio/certs/cert-chain.pem\n          - --tlsKeyFile=/etc/istio/certs/key.pem\n          - --healthCheckInterval=2s\n          - --healthCheckFile=/health\n          - --webhook-config-file\n          - /etc/istio/config/validatingwebhookconfiguration.yaml\n          volumeMounts:\n          - name: certs\n            mountPath: /etc/istio/certs\n            readOnly: true\n          - name: config\n            mountPath: /etc/istio/config\n            readOnly: true\n          livenessProbe:\n            exec:\n              command:\n                - /usr/local/bin/galley\n                - probe\n                - --probe-path=/health\n                - --interval=4s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n          readinessProbe:\n            exec:\n              command:\n                - /usr/local/bin/galley\n                - probe\n                - --probe-path=/health\n                - --interval=4s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n          resources:\n            requests:\n              cpu: 10m\n            \n      volumes:\n      - name: certs\n        secret:\n          secretName: istio.istio-galley-service-account\n      - name: config\n        configMap:\n          name: istio-galley-configuration\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/gateways/templates/deployment.yaml\n\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-egressgateway\n  namespace: istio-system\n  labels:\n    app: egressgateway\n    chart: gateways-1.0.0\n    release: istio\n    heritage: Tiller\n    app: istio-egressgateway\n    istio: egressgateway\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: istio-egressgateway\n        istio: egressgateway\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-egressgateway-service-account\n      containers:\n        - name: egressgateway\n          image: \"docker.io/istio/proxyv2:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 80\n            - containerPort: 443\n          args:\n          - proxy\n          - router\n          - -v\n          - \"2\"\n          - --discoveryRefreshDelay\n          - '1s' #discoveryRefreshDelay\n          - --drainDuration\n          - '45s' #drainDuration\n          - --parentShutdownDuration\n          - '1m0s' #parentShutdownDuration\n          - --connectTimeout\n          - '10s' #connectTimeout\n          - --serviceCluster\n          - istio-egressgateway\n          - --zipkinAddress\n          - zipkin:9411\n          - --statsdUdpAddress\n          - istio-statsd-prom-bridge:9125\n          - --proxyAdminPort\n          - \"15000\"\n          - --controlPlaneAuthPolicy\n          - NONE\n          - --discoveryAddress\n          - istio-pilot.istio-system:8080\n          resources:\n            requests:\n              cpu: 10m\n            \n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: status.podIP\n          - name: ISTIO_META_POD_NAME\n            valueFrom:\n              fieldRef:\n                fieldPath: metadata.name\n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n          - name: egressgateway-certs\n            mountPath: \"/etc/istio/egressgateway-certs\"\n            readOnly: true\n          - name: egressgateway-ca-certs\n            mountPath: \"/etc/istio/egressgateway-ca-certs\"\n            readOnly: true\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-egressgateway-service-account\n          optional: true\n      - name: egressgateway-certs\n        secret:\n          secretName: \"istio-egressgateway-certs\"\n          optional: true\n      - name: egressgateway-ca-certs\n        secret:\n          secretName: \"istio-egressgateway-ca-certs\"\n          optional: true\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n---\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-ingressgateway\n  namespace: istio-system\n  labels:\n    app: ingressgateway\n    chart: gateways-1.0.0\n    release: istio\n    heritage: Tiller\n    app: istio-ingressgateway\n    istio: ingressgateway\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: istio-ingressgateway\n        istio: ingressgateway\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-ingressgateway-service-account\n      containers:\n        - name: ingressgateway\n          image: \"docker.io/istio/proxyv2:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 80\n            - containerPort: 443\n            - containerPort: 31400\n            - containerPort: 15011\n            - containerPort: 8060\n            - containerPort: 15030\n            - containerPort: 15031\n          args:\n          - proxy\n          - router\n          - -v\n          - \"2\"\n          - --discoveryRefreshDelay\n          - '1s' #discoveryRefreshDelay\n          - --drainDuration\n          - '45s' #drainDuration\n          - --parentShutdownDuration\n          - '1m0s' #parentShutdownDuration\n          - --connectTimeout\n          - '10s' #connectTimeout\n          - --serviceCluster\n          - istio-ingressgateway\n          - --zipkinAddress\n          - zipkin:9411\n          - --statsdUdpAddress\n          - istio-statsd-prom-bridge:9125\n          - --proxyAdminPort\n          - \"15000\"\n          - --controlPlaneAuthPolicy\n          - NONE\n          - --discoveryAddress\n          - istio-pilot.istio-system:8080\n          resources:\n            requests:\n              cpu: 10m\n            \n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: status.podIP\n          - name: ISTIO_META_POD_NAME\n            valueFrom:\n              fieldRef:\n                fieldPath: metadata.name\n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n          - name: ingressgateway-certs\n            mountPath: \"/etc/istio/ingressgateway-certs\"\n            readOnly: true\n          - name: ingressgateway-ca-certs\n            mountPath: \"/etc/istio/ingressgateway-ca-certs\"\n            readOnly: true\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-ingressgateway-service-account\n          optional: true\n      - name: ingressgateway-certs\n        secret:\n          secretName: \"istio-ingressgateway-certs\"\n          optional: true\n      - name: ingressgateway-ca-certs\n        secret:\n          secretName: \"istio-ingressgateway-ca-certs\"\n          optional: true\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n---\n\n---\n# Source: istio/charts/mixer/templates/deployment.yaml\n\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-policy\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: mixer\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: policy\n        istio: mixer\n        istio-mixer-type: policy\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-mixer-service-account\n          optional: true\n      - name: uds-socket\n        emptyDir: {}\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n      containers:\n      - name: mixer\n        image: \"docker.io/istio/mixer:1.0.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9093\n        - containerPort: 42422\n        args:\n          - --address\n          - unix:///sock/mixer.socket\n          - --configStoreURL=k8s://\n          - --configDefaultNamespace=istio-system\n          - --trace_zipkin_url=http://zipkin:9411/api/v1/spans\n        resources:\n          requests:\n            cpu: 10m\n          \n        volumeMounts:\n        - name: uds-socket\n          mountPath: /sock\n        livenessProbe:\n          httpGet:\n            path: /version\n            port: 9093\n          initialDelaySeconds: 5\n          periodSeconds: 5\n      - name: istio-proxy\n        image: \"docker.io/istio/proxyv2:1.0.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9091\n        - containerPort: 15004\n        args:\n        - proxy\n        - --serviceCluster\n        - istio-policy\n        - --templateFile\n        - /etc/istio/proxy/envoy_policy.yaml.tmpl\n        - --controlPlaneAuthPolicy\n        - NONE\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: status.podIP\n        resources:\n          requests:\n            cpu: 10m\n          \n        volumeMounts:\n        - name: istio-certs\n          mountPath: /etc/certs\n          readOnly: true\n        - name: uds-socket\n          mountPath: /sock\n\n---\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-telemetry\n  namespace: istio-system\n  labels:\n    chart: mixer-1.0.0\n    release: istio\n    istio: mixer\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: telemetry\n        istio: mixer\n        istio-mixer-type: telemetry\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-mixer-service-account\n      volumes:\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-mixer-service-account\n          optional: true\n      - name: uds-socket\n        emptyDir: {}\n      containers:\n      - name: mixer\n        image: \"docker.io/istio/mixer:1.0.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9093\n        - containerPort: 42422\n        args:\n          - --address\n          - unix:///sock/mixer.socket\n          - --configStoreURL=k8s://\n          - --configDefaultNamespace=istio-system\n          - --trace_zipkin_url=http://zipkin:9411/api/v1/spans\n        resources:\n          requests:\n            cpu: 10m\n          \n        volumeMounts:\n        - name: uds-socket\n          mountPath: /sock\n        livenessProbe:\n          httpGet:\n            path: /version\n            port: 9093\n          initialDelaySeconds: 5\n          periodSeconds: 5\n      - name: istio-proxy\n        image: \"docker.io/istio/proxyv2:1.0.0\"\n        imagePullPolicy: IfNotPresent\n        ports:\n        - containerPort: 9091\n        - containerPort: 15004\n        args:\n        - proxy\n        - --serviceCluster\n        - istio-telemetry\n        - --templateFile\n        - /etc/istio/proxy/envoy_telemetry.yaml.tmpl\n        - --controlPlaneAuthPolicy\n        - NONE\n        env:\n        - name: POD_NAME\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.name\n        - name: POD_NAMESPACE\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: metadata.namespace\n        - name: INSTANCE_IP\n          valueFrom:\n            fieldRef:\n              apiVersion: v1\n              fieldPath: status.podIP\n        resources:\n          requests:\n            cpu: 10m\n          \n        volumeMounts:\n        - name: istio-certs\n          mountPath: /etc/certs\n          readOnly: true\n        - name: uds-socket\n          mountPath: /sock\n\n--- \n\n---\n# Source: istio/charts/pilot/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-pilot\n  namespace: istio-system\n  # TODO: default template doesn't have this, which one is right ?\n  labels:\n    app: istio-pilot\n    chart: pilot-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: pilot\n  annotations:\n    checksum/config-volume: f8da08b6b8c170dde721efd680270b2901e750d4aa186ebb6c22bef5b78a43f9\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: pilot\n        app: pilot\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-pilot-service-account\n      containers:\n        - name: discovery\n          image: \"docker.io/istio/pilot:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n          - \"discovery\"\n          ports:\n          - containerPort: 8080\n          - containerPort: 15010\n          readinessProbe:\n            httpGet:\n              path: /debug/endpointz\n              port: 8080\n            initialDelaySeconds: 30\n            periodSeconds: 30\n            timeoutSeconds: 5\n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: PILOT_THROTTLE\n            value: \"500\"\n          - name: PILOT_CACHE_SQUASH\n            value: \"5\"\n          - name: PILOT_TRACE_SAMPLING\n            value: \"100\"\n          resources:\n            requests:\n              cpu: 500m\n              memory: 2048Mi\n            \n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/istio/config\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n        - name: istio-proxy\n          image: \"docker.io/istio/proxyv2:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          ports:\n          - containerPort: 15003\n          - containerPort: 15005\n          - containerPort: 15007\n          - containerPort: 15011\n          args:\n          - proxy\n          - --serviceCluster\n          - istio-pilot\n          - --templateFile\n          - /etc/istio/proxy/envoy_pilot.yaml.tmpl\n          - --controlPlaneAuthPolicy\n          - NONE\n          env:\n          - name: POD_NAME\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.name\n          - name: POD_NAMESPACE\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: metadata.namespace\n          - name: INSTANCE_IP\n            valueFrom:\n              fieldRef:\n                apiVersion: v1\n                fieldPath: status.podIP\n          resources:\n            requests:\n              cpu: 10m\n            \n          volumeMounts:\n          - name: istio-certs\n            mountPath: /etc/certs\n            readOnly: true\n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio\n      - name: istio-certs\n        secret:\n          secretName: istio.istio-pilot-service-account\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/prometheus/templates/deployment.yaml\n# TODO: the original template has service account, roles, etc\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: prometheus\n  namespace: istio-system\n  labels:\n    app: prometheus\n    chart: prometheus-0.1.0\n    release: istio\n    heritage: Tiller\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: prometheus\n  template:\n    metadata:\n      labels:\n        app: prometheus\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: prometheus\n      containers:\n        - name: prometheus\n          image: \"docker.io/prom/prometheus:v2.3.1\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - '--storage.tsdb.retention=6h'\n            - '--config.file=/etc/prometheus/prometheus.yml'\n          ports:\n            - containerPort: 9090\n              name: http\n          livenessProbe:\n            httpGet:\n              path: /-/healthy\n              port: 9090\n          readinessProbe:\n            httpGet:\n              path: /-/ready\n              port: 9090\n          resources:\n            requests:\n              cpu: 10m\n            \n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/prometheus\n      volumes:\n      - name: config-volume\n        configMap:\n          name: prometheus\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/security/templates/deployment.yaml\n# istio CA watching all namespaces\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-citadel\n  namespace: istio-system\n  labels:\n    app: security\n    chart: security-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: citadel\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: citadel\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-citadel-service-account\n      containers:\n        - name: citadel\n          image: \"docker.io/istio/citadel:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - --append-dns-names=true\n            - --grpc-port=8060\n            - --grpc-hostname=citadel\n            - --citadel-storage-namespace=istio-system\n            - --self-signed-ca=true\n          resources:\n            requests:\n              cpu: 10m\n            \n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: sidecarInjectorWebhook\n    chart: sidecarInjectorWebhook-1.0.0\n    release: istio\n    heritage: Tiller\n    istio: sidecar-injector\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        istio: sidecar-injector\n      annotations:\n        sidecar.istio.io/inject: \"false\"\n        scheduler.alpha.kubernetes.io/critical-pod: \"\"\n    spec:\n      serviceAccountName: istio-sidecar-injector-service-account\n      containers:\n        - name: sidecar-injector-webhook\n          image: \"docker.io/istio/sidecar_injector:1.0.0\"\n          imagePullPolicy: IfNotPresent\n          args:\n            - --caCertFile=/etc/istio/certs/root-cert.pem\n            - --tlsCertFile=/etc/istio/certs/cert-chain.pem\n            - --tlsKeyFile=/etc/istio/certs/key.pem\n            - --injectConfig=/etc/istio/inject/config\n            - --meshConfig=/etc/istio/config/mesh\n            - --healthCheckInterval=2s\n            - --healthCheckFile=/health\n          volumeMounts:\n          - name: config-volume\n            mountPath: /etc/istio/config\n            readOnly: true\n          - name: certs\n            mountPath: /etc/istio/certs\n            readOnly: true\n          - name: inject-config\n            mountPath: /etc/istio/inject\n            readOnly: true\n          livenessProbe:\n            exec:\n              command:\n                - /usr/local/bin/sidecar-injector\n                - probe\n                - --probe-path=/health\n                - --interval=4s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n          readinessProbe:\n            exec:\n              command:\n                - /usr/local/bin/sidecar-injector\n                - probe\n                - --probe-path=/health\n                - --interval=4s\n            initialDelaySeconds: 4\n            periodSeconds: 4\n          resources:\n            requests:\n              cpu: 10m\n            \n      volumes:\n      - name: config-volume\n        configMap:\n          name: istio\n      - name: certs\n        secret:\n          secretName: istio.istio-sidecar-injector-service-account\n      - name: inject-config\n        configMap:\n          name: istio-sidecar-injector\n          items:\n          - key: config\n            path: config\n      affinity:      \n        nodeAffinity:\n          requiredDuringSchedulingIgnoredDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n                - ppc64le\n                - s390x\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - amd64\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - ppc64le\n          - weight: 2\n            preference:\n              matchExpressions:\n              - key: beta.kubernetes.io/arch\n                operator: In\n                values:\n                - s390x\n\n---\n# Source: istio/charts/pilot/templates/gateway.yaml\napiVersion: networking.istio.io/v1alpha3\nkind: Gateway\nmetadata:\n  name: istio-autogenerated-k8s-ingress\n  namespace: istio-system\nspec:\n  selector:\n    istio: ingress\n  servers:\n  - port:\n      number: 80\n      protocol: HTTP2\n      name: http\n    hosts:\n    - \"*\"\n\n---\n\n---\n# Source: istio/charts/gateways/templates/autoscale.yaml\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-egressgateway\n    namespace: istio-system\nspec:\n    maxReplicas: 5\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-egressgateway\n    metrics:\n      - type: Resource\n        resource:\n          name: cpu\n          targetAverageUtilization: 60\n---\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-ingressgateway\n    namespace: istio-system\nspec:\n    maxReplicas: 5\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-ingressgateway\n    metrics:\n      - type: Resource\n        resource:\n          name: cpu\n          targetAverageUtilization: 60\n---\n\n---\n# Source: istio/charts/mixer/templates/autoscale.yaml\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-policy\n    namespace: istio-system\nspec:\n    maxReplicas: 5\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-policy\n    metrics:\n    - type: Resource\n      resource:\n        name: cpu\n        targetAverageUtilization: 80\n---\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-telemetry\n    namespace: istio-system\nspec:\n    maxReplicas: 5\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-telemetry\n    metrics:\n    - type: Resource\n      resource:\n        name: cpu\n        targetAverageUtilization: 80\n---\n\n---\n# Source: istio/charts/pilot/templates/autoscale.yaml\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n    name: istio-pilot\nspec:\n    maxReplicas: 1\n    minReplicas: 1\n    scaleTargetRef:\n      apiVersion: apps/v1beta1\n      kind: Deployment\n      name: istio-pilot\n    metrics:\n      - type: Resource\n        resource:\n          name: cpu\n          targetAverageUtilization: 55\n---\n\n---\n# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml\napiVersion: admissionregistration.k8s.io/v1beta1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: istio-sidecar-injector\n  namespace: istio-system\n  labels:\n    app: istio-sidecar-injector\n    chart: sidecarInjectorWebhook-1.0.0\n    release: istio\n    heritage: Tiller\nwebhooks:\n  - name: sidecar-injector.istio.io\n    clientConfig:\n      service:\n        name: istio-sidecar-injector\n        namespace: istio-system\n        path: \"/inject\"\n      caBundle: \"\"\n    rules:\n      - operations: [ \"CREATE\" ]\n        apiGroups: [\"\"]\n        apiVersions: [\"v1\"]\n        resources: [\"pods\"]\n    failurePolicy: Fail\n    namespaceSelector:\n      matchLabels:\n        istio-injection: enabled\n\n\n---\n# Source: istio/charts/galley/templates/validatingwehookconfiguration.yaml.tpl\n\n\n---\n# Source: istio/charts/pilot/templates/meshexpansion.yaml\n\n\n---\n# Source: istio/charts/security/templates/create-custom-resources-job.yaml\n\n\n---\n# Source: istio/charts/security/templates/enable-mesh-mtls.yaml\n\n\n---\n# Source: istio/charts/security/templates/meshexpansion.yaml\n\n\n---\n\n---\n# Source: istio/charts/telemetry-gateway/templates/gateway.yaml\n\n\n---\n# Source: istio/templates/install-custom-resources.sh.tpl\n\n\n---\n# Source: istio/charts/mixer/templates/config.yaml\napiVersion: \"config.istio.io/v1alpha2\"\nkind: attributemanifest\nmetadata:\n  name: istioproxy\n  namespace: istio-system\nspec:\n  attributes:\n    origin.ip:\n      valueType: IP_ADDRESS\n    origin.uid:\n      valueType: STRING\n    origin.user:\n      valueType: STRING\n    request.headers:\n      valueType: STRING_MAP\n    request.id:\n      valueType: STRING\n    request.host:\n      valueType: STRING\n    request.method:\n      valueType: STRING\n    request.path:\n      valueType: STRING\n    request.reason:\n      valueType: STRING\n    request.referer:\n      valueType: STRING\n    request.scheme:\n      valueType: STRING\n    request.total_size:\n          valueType: INT64\n    request.size:\n      valueType: INT64\n    request.time:\n      valueType: TIMESTAMP\n    request.useragent:\n      valueType: STRING\n    response.code:\n      valueType: INT64\n    response.duration:\n      valueType: DURATION\n    response.headers:\n      valueType: STRING_MAP\n    response.total_size:\n          valueType: INT64\n    response.size:\n      valueType: INT64\n    response.time:\n      valueType: TIMESTAMP\n    source.uid:\n      valueType: STRING\n    source.user: # DEPRECATED\n      valueType: STRING\n    source.principal:\n      valueType: STRING\n    destination.uid:\n      valueType: STRING\n    destination.principal:\n      valueType: STRING\n    destination.port:\n      valueType: INT64\n    connection.event:\n      valueType: STRING\n    connection.id:\n      valueType: STRING\n    connection.received.bytes:\n      valueType: INT64\n    connection.received.bytes_total:\n      valueType: INT64\n    connection.sent.bytes:\n      valueType: INT64\n    connection.sent.bytes_total:\n      valueType: INT64\n    connection.duration:\n      valueType: DURATION\n    connection.mtls:\n      valueType: BOOL\n    context.protocol:\n      valueType: STRING\n    context.timestamp:\n      valueType: TIMESTAMP\n    context.time:\n      valueType: TIMESTAMP\n    # Deprecated, kept for compatibility\n    context.reporter.local:\n      valueType: BOOL\n    context.reporter.kind:\n      valueType: STRING\n    context.reporter.uid:\n      valueType: STRING\n    api.service:\n      valueType: STRING\n    api.version:\n      valueType: STRING\n    api.operation:\n      valueType: STRING\n    api.protocol:\n      valueType: STRING\n    request.auth.principal:\n      valueType: STRING\n    request.auth.audiences:\n      valueType: STRING\n    request.auth.presenter:\n      valueType: STRING\n    request.auth.claims:\n      valueType: STRING_MAP\n    request.auth.raw_claims:\n      valueType: STRING\n    request.api_key:\n      valueType: STRING\n\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: attributemanifest\nmetadata:\n  name: kubernetes\n  namespace: istio-system\nspec:\n  attributes:\n    source.ip:\n      valueType: IP_ADDRESS\n    source.labels:\n      valueType: STRING_MAP\n    source.metadata:\n      valueType: STRING_MAP\n    source.name:\n      valueType: STRING\n    source.namespace:\n      valueType: STRING\n    source.owner:\n      valueType: STRING\n    source.service:  # DEPRECATED\n      valueType: STRING\n    source.serviceAccount:\n      valueType: STRING\n    source.services:\n      valueType: STRING\n    source.workload.uid:\n      valueType: STRING\n    source.workload.name:\n      valueType: STRING\n    source.workload.namespace:\n      valueType: STRING\n    destination.ip:\n      valueType: IP_ADDRESS\n    destination.labels:\n      valueType: STRING_MAP\n    destination.metadata:\n      valueType: STRING_MAP\n    destination.owner:\n      valueType: STRING\n    destination.name:\n      valueType: STRING\n    destination.container.name:\n      valueType: STRING\n    destination.namespace:\n      valueType: STRING\n    destination.service: # DEPRECATED\n      valueType: STRING\n    destination.service.uid:\n      valueType: STRING\n    destination.service.name:\n      valueType: STRING\n    destination.service.namespace:\n      valueType: STRING\n    destination.service.host:\n      valueType: STRING\n    destination.serviceAccount:\n      valueType: STRING\n    destination.workload.uid:\n      valueType: STRING\n    destination.workload.name:\n      valueType: STRING\n    destination.workload.namespace:\n      valueType: STRING\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: stdio\nmetadata:\n  name: handler\n  namespace: istio-system\nspec:\n  outputAsJson: true\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: logentry\nmetadata:\n  name: accesslog\n  namespace: istio-system\nspec:\n  severity: '\"Info\"'\n  timestamp: request.time\n  variables:\n    sourceIp: source.ip | ip(\"0.0.0.0\")\n    sourceApp: source.labels[\"app\"] | \"\"\n    sourcePrincipal: source.principal | \"\"\n    sourceName: source.name | \"\"\n    sourceWorkload: source.workload.name | \"\"\n    sourceNamespace: source.namespace | \"\"\n    sourceOwner: source.owner | \"\"\n    destinationApp: destination.labels[\"app\"] | \"\"\n    destinationIp: destination.ip | ip(\"0.0.0.0\")\n    destinationServiceHost: destination.service.host | \"\"\n    destinationWorkload: destination.workload.name | \"\"\n    destinationName: destination.name | \"\"\n    destinationNamespace: destination.namespace | \"\"\n    destinationOwner: destination.owner | \"\"\n    destinationPrincipal: destination.principal | \"\"\n    apiClaims: request.auth.raw_claims | \"\"\n    apiKey: request.api_key | request.headers[\"x-api-key\"] | \"\"\n    protocol: request.scheme | context.protocol | \"http\"\n    method: request.method | \"\"\n    url: request.path | \"\"\n    responseCode: response.code | 0\n    responseSize: response.size | 0\n    requestSize: request.size | 0\n    requestId: request.headers[\"x-request-id\"] | \"\"\n    clientTraceId: request.headers[\"x-client-trace-id\"] | \"\"\n    latency: response.duration | \"0ms\"\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n    userAgent: request.useragent | \"\"\n    responseTimestamp: response.time\n    receivedBytes: request.total_size | 0\n    sentBytes: response.total_size | 0\n    referer: request.referer | \"\"\n    httpAuthority: request.headers[\":authority\"] | request.host | \"\"\n    xForwardedFor: request.headers[\"x-forwarded-for\"] | \"0.0.0.0\"\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n  monitored_resource_type: '\"global\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: logentry\nmetadata:\n  name: tcpaccesslog\n  namespace: istio-system\nspec:\n  severity: '\"Info\"'\n  timestamp: context.time | timestamp(\"2017-01-01T00:00:00Z\")\n  variables:\n    connectionEvent: connection.event | \"\"\n    sourceIp: source.ip | ip(\"0.0.0.0\")\n    sourceApp: source.labels[\"app\"] | \"\"\n    sourcePrincipal: source.principal | \"\"\n    sourceName: source.name | \"\"\n    sourceWorkload: source.workload.name | \"\"\n    sourceNamespace: source.namespace | \"\"\n    sourceOwner: source.owner | \"\"\n    destinationApp: destination.labels[\"app\"] | \"\"\n    destinationIp: destination.ip | ip(\"0.0.0.0\")\n    destinationServiceHost: destination.service.host | \"\"\n    destinationWorkload: destination.workload.name | \"\"\n    destinationName: destination.name | \"\"\n    destinationNamespace: destination.namespace | \"\"\n    destinationOwner: destination.owner | \"\"\n    destinationPrincipal: destination.principal | \"\"\n    protocol: context.protocol | \"tcp\"\n    connectionDuration: connection.duration | \"0ms\"\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n    receivedBytes: connection.received.bytes | 0\n    sentBytes: connection.sent.bytes | 0\n    totalReceivedBytes: connection.received.bytes_total | 0\n    totalSentBytes: connection.sent.bytes_total | 0\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n  monitored_resource_type: '\"global\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: stdio\n  namespace: istio-system\nspec:\n  match: context.protocol == \"http\" || context.protocol == \"grpc\"\n  actions:\n  - handler: handler.stdio\n    instances:\n    - accesslog.logentry\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: stdiotcp\n  namespace: istio-system\nspec:\n  match: context.protocol == \"tcp\"\n  actions:\n  - handler: handler.stdio\n    instances:\n    - tcpaccesslog.logentry\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: requestcount\n  namespace: istio-system\nspec:\n  value: \"1\"\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.host | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    request_protocol: api.protocol | context.protocol | \"unknown\"\n    response_code: response.code | 200\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: requestduration\n  namespace: istio-system\nspec:\n  value: response.duration | \"0ms\"\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.host | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    request_protocol: api.protocol | context.protocol | \"unknown\"\n    response_code: response.code | 200\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: requestsize\n  namespace: istio-system\nspec:\n  value: request.size | 0\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.host | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    request_protocol: api.protocol | context.protocol | \"unknown\"\n    response_code: response.code | 200\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: responsesize\n  namespace: istio-system\nspec:\n  value: response.size | 0\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.host | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    request_protocol: api.protocol | context.protocol | \"unknown\"\n    response_code: response.code | 200\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: tcpbytesent\n  namespace: istio-system\nspec:\n  value: connection.sent.bytes | 0\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.name | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: metric\nmetadata:\n  name: tcpbytereceived\n  namespace: istio-system\nspec:\n  value: connection.received.bytes | 0\n  dimensions:\n    reporter: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"source\", \"destination\")\n    source_workload: source.workload.name | \"unknown\"\n    source_workload_namespace: source.workload.namespace | \"unknown\"\n    source_principal: source.principal | \"unknown\"\n    source_app: source.labels[\"app\"] | \"unknown\"\n    source_version: source.labels[\"version\"] | \"unknown\"\n    destination_workload: destination.workload.name | \"unknown\"\n    destination_workload_namespace: destination.workload.namespace | \"unknown\"\n    destination_principal: destination.principal | \"unknown\"\n    destination_app: destination.labels[\"app\"] | \"unknown\"\n    destination_version: destination.labels[\"version\"] | \"unknown\"\n    destination_service: destination.service.name | \"unknown\"\n    destination_service_name: destination.service.name | \"unknown\"\n    destination_service_namespace: destination.service.namespace | \"unknown\"\n    connection_security_policy: conditional((context.reporter.kind | \"inbound\") == \"outbound\", \"unknown\", conditional(connection.mtls | false, \"mutual_tls\", \"none\"))\n  monitored_resource_type: '\"UNSPECIFIED\"'\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: prometheus\nmetadata:\n  name: handler\n  namespace: istio-system\nspec:\n  metrics:\n  - name: requests_total\n    instance_name: requestcount.metric.istio-system\n    kind: COUNTER\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - request_protocol\n    - response_code\n    - connection_security_policy\n  - name: request_duration_seconds\n    instance_name: requestduration.metric.istio-system\n    kind: DISTRIBUTION\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - request_protocol\n    - response_code\n    - connection_security_policy\n    buckets:\n      explicit_buckets:\n        bounds: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]\n  - name: request_bytes\n    instance_name: requestsize.metric.istio-system\n    kind: DISTRIBUTION\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - request_protocol\n    - response_code\n    - connection_security_policy\n    buckets:\n      exponentialBuckets:\n        numFiniteBuckets: 8\n        scale: 1\n        growthFactor: 10\n  - name: response_bytes\n    instance_name: responsesize.metric.istio-system\n    kind: DISTRIBUTION\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - request_protocol\n    - response_code\n    - connection_security_policy\n    buckets:\n      exponentialBuckets:\n        numFiniteBuckets: 8\n        scale: 1\n        growthFactor: 10\n  - name: tcp_sent_bytes_total\n    instance_name: tcpbytesent.metric.istio-system\n    kind: COUNTER\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - connection_security_policy\n  - name: tcp_received_bytes_total\n    instance_name: tcpbytereceived.metric.istio-system\n    kind: COUNTER\n    label_names:\n    - reporter\n    - source_app\n    - source_principal\n    - source_workload\n    - source_workload_namespace\n    - source_version\n    - destination_app\n    - destination_principal\n    - destination_workload\n    - destination_workload_namespace\n    - destination_version\n    - destination_service\n    - destination_service_name\n    - destination_service_namespace\n    - connection_security_policy\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: promhttp\n  namespace: istio-system\nspec:\n  match: context.protocol == \"http\" || context.protocol == \"grpc\"\n  actions:\n  - handler: handler.prometheus\n    instances:\n    - requestcount.metric\n    - requestduration.metric\n    - requestsize.metric\n    - responsesize.metric\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: promtcp\n  namespace: istio-system\nspec:\n  match: context.protocol == \"tcp\"\n  actions:\n  - handler: handler.prometheus\n    instances:\n    - tcpbytesent.metric\n    - tcpbytereceived.metric\n---\n\napiVersion: \"config.istio.io/v1alpha2\"\nkind: kubernetesenv\nmetadata:\n  name: handler\n  namespace: istio-system\nspec:\n  # when running from mixer root, use the following config after adding a\n  # symbolic link to a kubernetes config file via:\n  #\n  # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig\n  #\n  # kubeconfig_path: \"mixer/adapter/kubernetes/kubeconfig\"\n\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: kubeattrgenrulerule\n  namespace: istio-system\nspec:\n  actions:\n  - handler: handler.kubernetesenv\n    instances:\n    - attributes.kubernetes\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: rule\nmetadata:\n  name: tcpkubeattrgenrulerule\n  namespace: istio-system\nspec:\n  match: context.protocol == \"tcp\"\n  actions:\n  - handler: handler.kubernetesenv\n    instances:\n    - attributes.kubernetes\n---\napiVersion: \"config.istio.io/v1alpha2\"\nkind: kubernetes\nmetadata:\n  name: attributes\n  namespace: istio-system\nspec:\n  # Pass the required attribute data to the adapter\n  source_uid: source.uid | \"\"\n  source_ip: source.ip | ip(\"0.0.0.0\") # default to unspecified ip addr\n  destination_uid: destination.uid | \"\"\n  destination_port: destination.port | 0\n  attribute_bindings:\n    # Fill the new attributes from the adapter produced output.\n    # $out refers to an instance of OutputTemplate message\n    source.ip: $out.source_pod_ip | ip(\"0.0.0.0\")\n    source.uid: $out.source_pod_uid | \"unknown\"\n    source.labels: $out.source_labels | emptyStringMap()\n    source.name: $out.source_pod_name | \"unknown\"\n    source.namespace: $out.source_namespace | \"default\"\n    source.owner: $out.source_owner | \"unknown\"\n    source.serviceAccount: $out.source_service_account_name | \"unknown\"\n    source.workload.uid: $out.source_workload_uid | \"unknown\"\n    source.workload.name: $out.source_workload_name | \"unknown\"\n    source.workload.namespace: $out.source_workload_namespace | \"unknown\"\n    destination.ip: $out.destination_pod_ip | ip(\"0.0.0.0\")\n    destination.uid: $out.destination_pod_uid | \"unknown\"\n    destination.labels: $out.destination_labels | emptyStringMap()\n    destination.name: $out.destination_pod_name | \"unknown\"\n    destination.container.name: $out.destination_container_name | \"unknown\"\n    destination.namespace: $out.destination_namespace | \"default\"\n    destination.owner: $out.destination_owner | \"unknown\"\n    destination.serviceAccount: $out.destination_service_account_name | \"unknown\"\n    destination.workload.uid: $out.destination_workload_uid | \"unknown\"\n    destination.workload.name: $out.destination_workload_name | \"unknown\"\n    destination.workload.namespace: $out.destination_workload_namespace | \"unknown\"\n\n---\n# Configuration needed by Mixer.\n# Mixer cluster is delivered via CDS\n# Specify mixer cluster settings\napiVersion: networking.istio.io/v1alpha3\nkind: DestinationRule\nmetadata:\n  name: istio-policy\n  namespace: istio-system\nspec:\n  host: istio-policy.istio-system.svc.cluster.local\n  trafficPolicy:\n    connectionPool:\n      http:\n        http2MaxRequests: 10000\n        maxRequestsPerConnection: 10000\n---\napiVersion: networking.istio.io/v1alpha3\nkind: DestinationRule\nmetadata:\n  name: istio-telemetry\n  namespace: istio-system\nspec:\n  host: istio-telemetry.istio-system.svc.cluster.local\n  trafficPolicy:\n    connectionPool:\n      http:\n        http2MaxRequests: 10000\n        maxRequestsPerConnection: 10000\n---\n\n"
  },
  {
    "path": "examples/90_Kubernetes/minikube/README.md",
    "content": "# Development with Minikube\n\n## Install `minikube`, `kubectl`, and `helm`\n\nThis only need to be done one time, or periodically if you wish to upgrade.\n\n```\nsudo apt update && sudo apt install -y --no-install-recommends socat\n\ncurl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/\n\ncurl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin\n\ncurl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh\nchmod 700 get_helm.sh\n./get_helm.sh\n```\n\nAdd the `coreos/prometheus-operator` repo:\n```\nhelm repo add coreos https://s3-eu-west-1.amazonaws.com/coreos-charts/stable/\n```\n\n## Launch a Kubernetes Cluster\n\n```\n./bootstrap.sh\n```\n\nCheck configurations:\n```\nkubectl get all\nkubectl get all --all-namespaces\nkubectl get nodes -o=custom-columns=NAME:.metadata.name,GPUs:.status.capacity.'nvidia\\.com/gpu'\n# last command should report the number of GPUs on your system\n# this make take some time - coffee?!\n```\n\n"
  },
  {
    "path": "examples/90_Kubernetes/minikube/bootstrap.sh",
    "content": "#!/bin/bash\n\nmkdir -p $HOME/.kube\ntouch $HOME/.kube/config\n\nexport MINIKUBE_HOME=$HOME\nexport CHANGE_MINIKUBE_NONE_USER=true\nexport KUBECONFIG=$HOME/.kube/config\n\nversion=v1.10\n\nsudo minikube start \\\n  --feature-gates=DevicePlugins=true \\\n  --vm-driver=none \\\n  --kubernetes-version=${version}.0 \\\n  --bootstrapper=kubeadm \\\n  --extra-config=kubelet.authentication-token-webhook=true \\\n  --extra-config=kubelet.authorization-mode=Webhook \\\n  --extra-config=scheduler.address=0.0.0.0 \\\n  --extra-config=controller-manager.address=0.0.0.0 \\\n  --extra-config=controller-manager.cluster-signing-cert-file=\"/var/lib/localkube/certs/ca.crt\" \\\n  --extra-config=controller-manager.cluster-signing-key-file=\"/var/lib/localkube/certs/ca.key\" \\\n  --extra-config=apiserver.admission-control=\"NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota\" \n\nif [ ! -e $HOME/.kube ]; then\n  sudo mv /root/.kube $HOME/.kube > /dev/null 2>&1 ||: # this will write over any previous configuration\n  sudo chown -R $USER $HOME/.kube > /dev/null 2>&1 ||:\n  sudo chgrp -R $USER $HOME/.kube > /dev/null 2>&1 ||:\nfi\n\nif [ ! -e $HOME/.minikube ]; then\n  sudo mv /root/.minikube $HOME/.minikube # > /dev/null 2>&1 ||: this will write over any previous configuration\n  sudo chown -R $USER $HOME/.minikube > /dev/null 2>&1 ||:\n  sudo chgrp -R $USER $HOME/.minikube > /dev/null 2>&1 ||:\nfi\n\nkubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/${version}/nvidia-device-plugin.yml\n\n# dns fix for dgx-stations using ubuntu's network manager\nkubectl apply -f https://raw.githubusercontent.com/ryanolson/k8s-upstream-dns/master/dns.yml\n"
  },
  {
    "path": "examples/90_Kubernetes/prometheus/bootstrap.sh",
    "content": "#!/bin/bash\n\nkubectl create -f service-account.yml\n\nhelm init --wait --service-account tiller\n\nhelm repo add coreos https://s3-eu-west-1.amazonaws.com/coreos-charts/stable/\n\nhelm install coreos/prometheus-operator \\\n  --name prometheus-operator \\\n  --namespace monitoring\n\nhelm install coreos/kube-prometheus \\\n  --name kube-prometheus \\\n  --namespace monitoring \\\n  -f custom-settings.yml\n\nkubectl apply -f yais-metrics.yml\n"
  },
  {
    "path": "examples/90_Kubernetes/prometheus/custom-settings.yml",
    "content": "global:\n  rbacEnable: true\n\n#prometheus:\n#  service:\n#    type: NodePort\n\ngrafana:\n# image:\n#   tag: 5.2.1\n  service:\n    type: NodePort\n  dataSource:\n    yais-datasource.json: |+\n      {\n        \"access\": \"proxy\",\n        \"basicAuth\": false,\n        \"name\": \"yais\",\n        \"type\": \"prometheus\",\n        \"url\": \"http://yais-metrics.default:9090\"\n      }\n  serverDashboardFiles:\n    yais-dashboard.json: |+\n      {\n        \"dashboard\": \n        {\n          \"__inputs\": [\n            {\n              \"name\": \"DS_YAIS\",\n              \"label\": \"yais\",\n              \"description\": \"\",\n              \"type\": \"datasource\",\n              \"pluginId\": \"prometheus\",\n              \"pluginName\": \"Prometheus\"\n            }\n          ],\n          \"__requires\": [\n            {\n              \"type\": \"grafana\",\n              \"id\": \"grafana\",\n              \"name\": \"Grafana\",\n              \"version\": \"5.0.0\"\n            },\n            {\n              \"type\": \"panel\",\n              \"id\": \"graph\",\n              \"name\": \"Graph\",\n              \"version\": \"5.0.0\"\n            },\n            {\n              \"type\": \"panel\",\n              \"id\": \"heatmap\",\n              \"name\": \"Heatmap\",\n              \"version\": \"5.0.0\"\n            },\n            {\n              \"type\": \"datasource\",\n              \"id\": \"prometheus\",\n              \"name\": \"Prometheus\",\n              \"version\": \"5.0.0\"\n            }\n          ],\n          \"annotations\": {\n            \"list\": [\n              {\n                \"builtIn\": 1,\n                \"datasource\": \"-- Grafana --\",\n                \"enable\": true,\n                \"hide\": true,\n                \"iconColor\": \"rgba(0, 211, 255, 1)\",\n                \"name\": \"Annotations & Alerts\",\n                \"type\": \"dashboard\"\n              }\n            ]\n          },\n          \"editable\": true,\n          \"gnetId\": null,\n          \"graphTooltip\": 0,\n          \"id\": null,\n          \"links\": [],\n          \"panels\": [\n            {\n              \"aliasColors\": {},\n              \"bars\": true,\n              \"dashLength\": 10,\n              \"dashes\": false,\n              \"datasource\": \"${DS_YAIS}\",\n              \"fill\": 1,\n              \"gridPos\": {\n                \"h\": 9,\n                \"w\": 12,\n                \"x\": 0,\n                \"y\": 0\n              },\n              \"id\": 8,\n              \"legend\": {\n                \"avg\": false,\n                \"current\": false,\n                \"max\": false,\n                \"min\": false,\n                \"show\": false,\n                \"total\": false,\n                \"values\": false\n              },\n              \"lines\": true,\n              \"linewidth\": 1,\n              \"links\": [],\n              \"nullPointMode\": \"null\",\n              \"percentage\": false,\n              \"pointradius\": 5,\n              \"points\": false,\n              \"renderer\": \"flot\",\n              \"seriesOverrides\": [],\n              \"spaceLength\": 10,\n              \"stack\": true,\n              \"steppedLine\": false,\n              \"targets\": [\n                {\n                  \"expr\": \"irate(yais_inference_load_ratio_count[5s])\",\n                  \"format\": \"time_series\",\n                  \"intervalFactor\": 1,\n                  \"refId\": \"A\"\n                },\n                {\n                  \"expr\": \"\",\n                  \"format\": \"time_series\",\n                  \"intervalFactor\": 1,\n                  \"refId\": \"B\"\n                }\n              ],\n              \"thresholds\": [],\n              \"timeFrom\": null,\n              \"timeShift\": null,\n              \"title\": \"Inference Rate (FPS)\",\n              \"tooltip\": {\n                \"shared\": true,\n                \"sort\": 0,\n                \"value_type\": \"individual\"\n              },\n              \"type\": \"graph\",\n              \"xaxis\": {\n                \"buckets\": null,\n                \"mode\": \"time\",\n                \"name\": null,\n                \"show\": true,\n                \"values\": []\n              },\n              \"yaxes\": [\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                },\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                }\n              ],\n              \"yaxis\": {\n                \"align\": false,\n                \"alignLevel\": null\n              }\n            },\n            {\n              \"aliasColors\": {},\n              \"bars\": false,\n              \"dashLength\": 10,\n              \"dashes\": false,\n              \"datasource\": \"${DS_YAIS}\",\n              \"fill\": 1,\n              \"gridPos\": {\n                \"h\": 9,\n                \"w\": 12,\n                \"x\": 12,\n                \"y\": 0\n              },\n              \"id\": 4,\n              \"legend\": {\n                \"avg\": false,\n                \"current\": false,\n                \"max\": false,\n                \"min\": false,\n                \"show\": false,\n                \"total\": false,\n                \"values\": false\n              },\n              \"lines\": true,\n              \"linewidth\": 1,\n              \"links\": [],\n              \"nullPointMode\": \"null\",\n              \"percentage\": false,\n              \"pointradius\": 5,\n              \"points\": false,\n              \"renderer\": \"flot\",\n              \"seriesOverrides\": [],\n              \"spaceLength\": 10,\n              \"stack\": true,\n              \"steppedLine\": true,\n              \"targets\": [\n                {\n                  \"expr\": \"yais_gpus_power_usage\",\n                  \"format\": \"time_series\",\n                  \"intervalFactor\": 1,\n                  \"refId\": \"A\"\n                }\n              ],\n              \"thresholds\": [],\n              \"timeFrom\": null,\n              \"timeShift\": null,\n              \"title\": \"GPU Power (Watts)\",\n              \"tooltip\": {\n                \"shared\": true,\n                \"sort\": 0,\n                \"value_type\": \"individual\"\n              },\n              \"type\": \"graph\",\n              \"xaxis\": {\n                \"buckets\": null,\n                \"mode\": \"time\",\n                \"name\": null,\n                \"show\": true,\n                \"values\": []\n              },\n              \"yaxes\": [\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                },\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                }\n              ],\n              \"yaxis\": {\n                \"align\": false,\n                \"alignLevel\": null\n              }\n            },\n            {\n              \"aliasColors\": {},\n              \"bars\": false,\n              \"dashLength\": 10,\n              \"dashes\": false,\n              \"datasource\": \"${DS_YAIS}\",\n              \"fill\": 1,\n              \"gridPos\": {\n                \"h\": 9,\n                \"w\": 12,\n                \"x\": 0,\n                \"y\": 9\n              },\n              \"id\": 2,\n              \"legend\": {\n                \"avg\": false,\n                \"current\": false,\n                \"max\": false,\n                \"min\": false,\n                \"show\": false,\n                \"total\": false,\n                \"values\": false\n              },\n              \"lines\": true,\n              \"linewidth\": 1,\n              \"links\": [],\n              \"nullPointMode\": \"null\",\n              \"percentage\": false,\n              \"pointradius\": 5,\n              \"points\": false,\n              \"renderer\": \"flot\",\n              \"seriesOverrides\": [],\n              \"spaceLength\": 10,\n              \"stack\": false,\n              \"steppedLine\": false,\n              \"targets\": [\n                {\n                  \"expr\": \"yais_executor_queue_depth\",\n                  \"format\": \"time_series\",\n                  \"intervalFactor\": 1,\n                  \"refId\": \"A\"\n                }\n              ],\n              \"thresholds\": [],\n              \"timeFrom\": null,\n              \"timeShift\": null,\n              \"title\": \"Queue Depth\",\n              \"tooltip\": {\n                \"shared\": true,\n                \"sort\": 0,\n                \"value_type\": \"individual\"\n              },\n              \"type\": \"graph\",\n              \"xaxis\": {\n                \"buckets\": null,\n                \"mode\": \"time\",\n                \"name\": null,\n                \"show\": true,\n                \"values\": []\n              },\n              \"yaxes\": [\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                },\n                {\n                  \"format\": \"short\",\n                  \"label\": null,\n                  \"logBase\": 1,\n                  \"max\": null,\n                  \"min\": null,\n                  \"show\": true\n                }\n              ],\n              \"yaxis\": {\n                \"align\": false,\n                \"alignLevel\": null\n              }\n            },\n            {\n              \"cards\": {\n                \"cardPadding\": null,\n                \"cardRound\": null\n              },\n              \"color\": {\n                \"cardColor\": \"#b4ff00\",\n                \"colorScale\": \"sqrt\",\n                \"colorScheme\": \"interpolateOranges\",\n                \"exponent\": 0.5,\n                \"mode\": \"spectrum\"\n              },\n              \"dataFormat\": \"timeseries\",\n              \"datasource\": \"${DS_YAIS}\",\n              \"gridPos\": {\n                \"h\": 9,\n                \"w\": 12,\n                \"x\": 12,\n                \"y\": 9\n              },\n              \"heatmap\": {},\n              \"highlightCards\": true,\n              \"id\": 10,\n              \"interval\": \"\",\n              \"legend\": {\n                \"show\": false\n              },\n              \"links\": [],\n              \"targets\": [\n                {\n                  \"expr\": \"irate(yais_inference_load_ratio_bucket[15s])\",\n                  \"format\": \"time_series\",\n                  \"intervalFactor\": 1,\n                  \"legendFormat\": \"\",\n                  \"refId\": \"A\"\n                }\n              ],\n              \"title\": \"Load Ratio (Ideal 0-1)\",\n              \"tooltip\": {\n                \"show\": true,\n                \"showHistogram\": false\n              },\n              \"type\": \"heatmap\",\n              \"xAxis\": {\n                \"show\": true\n              },\n              \"xBucketNumber\": null,\n              \"xBucketSize\": null,\n              \"yAxis\": {\n                \"decimals\": null,\n                \"format\": \"short\",\n                \"logBase\": 10,\n                \"max\": null,\n                \"min\": \"0\",\n                \"show\": true,\n                \"splitFactor\": 2\n              },\n              \"yBucketNumber\": null,\n              \"yBucketSize\": null\n            }\n          ],\n          \"refresh\": \"5s\",\n          \"schemaVersion\": 16,\n          \"style\": \"dark\",\n          \"tags\": [],\n          \"templating\": {\n            \"list\": []\n          },\n          \"time\": {\n            \"from\": \"now-30m\",\n            \"to\": \"now\"\n          },\n          \"timepicker\": {\n            \"refresh_intervals\": [\n              \"5s\",\n              \"10s\",\n              \"30s\",\n              \"1m\",\n              \"5m\",\n              \"15m\",\n              \"30m\",\n              \"1h\",\n              \"2h\",\n              \"1d\"\n            ],\n            \"time_options\": [\n              \"5m\",\n              \"15m\",\n              \"1h\",\n              \"6h\",\n              \"12h\",\n              \"24h\",\n              \"2d\",\n              \"7d\",\n              \"30d\"\n            ]\n          },\n          \"timezone\": \"\",\n          \"title\": \"YAIS\",\n          \"uid\": \"3WLjQkdmk\",\n          \"version\": 1\n        },\n        \"inputs\": [\n          {\n            \"name\": \"DS_YAIS\",\n            \"pluginId\": \"prometheus\",\n            \"type\": \"datasource\",\n            \"value\": \"yais\"\n          }\n        ],\n        \"overwrite\": true\n      }\n"
  },
  {
    "path": "examples/90_Kubernetes/prometheus/service-account.yml",
    "content": "# Create a service account for Helm and grant the cluster admin role.\n# It is assumed that helm should be installed with this service account\n# (tiller).\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: tiller\n  namespace: kube-system\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: tiller\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n  name: tiller\n  namespace: kube-system\n"
  },
  {
    "path": "examples/90_Kubernetes/prometheus/yais-dashboard.json",
    "content": "{\n  \"__inputs\": [\n    {\n      \"name\": \"DS_YAIS\",\n      \"label\": \"yais\",\n      \"description\": \"\",\n      \"type\": \"datasource\",\n      \"pluginId\": \"prometheus\",\n      \"pluginName\": \"Prometheus\"\n    }\n  ],\n  \"__requires\": [\n    {\n      \"type\": \"grafana\",\n      \"id\": \"grafana\",\n      \"name\": \"Grafana\",\n      \"version\": \"5.2.1\"\n    },\n    {\n      \"type\": \"panel\",\n      \"id\": \"graph\",\n      \"name\": \"Graph\",\n      \"version\": \"5.0.0\"\n    },\n    {\n      \"type\": \"datasource\",\n      \"id\": \"prometheus\",\n      \"name\": \"Prometheus\",\n      \"version\": \"5.0.0\"\n    }\n  ],\n  \"annotations\": {\n    \"list\": [\n      {\n        \"builtIn\": 1,\n        \"datasource\": \"-- Grafana --\",\n        \"enable\": true,\n        \"hide\": true,\n        \"iconColor\": \"rgba(0, 211, 255, 1)\",\n        \"name\": \"Annotations & Alerts\",\n        \"type\": \"dashboard\"\n      }\n    ]\n  },\n  \"editable\": true,\n  \"gnetId\": null,\n  \"graphTooltip\": 0,\n  \"id\": null,\n  \"links\": [],\n  \"panels\": [\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"${DS_YAIS}\",\n      \"fill\": 1,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 0\n      },\n      \"id\": 8,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"percentage\": false,\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"rate(yais_inference_load_ratio_count[5s])\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"refId\": \"A\"\n        },\n        {\n          \"expr\": \"irate(yais_inference_load_ratio_count[5s])\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"refId\": \"B\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeShift\": null,\n      \"title\": \"Inference Rate (FPS)\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 0,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"${DS_YAIS}\",\n      \"fill\": 1,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 12,\n        \"y\": 0\n      },\n      \"id\": 4,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"percentage\": false,\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"yais_gpus_power_usage\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeShift\": null,\n      \"title\": \"GPU Power (Watts)\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 0,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    },\n    {\n      \"aliasColors\": {},\n      \"bars\": false,\n      \"dashLength\": 10,\n      \"dashes\": false,\n      \"datasource\": \"${DS_YAIS}\",\n      \"fill\": 1,\n      \"gridPos\": {\n        \"h\": 9,\n        \"w\": 12,\n        \"x\": 0,\n        \"y\": 9\n      },\n      \"id\": 2,\n      \"legend\": {\n        \"avg\": false,\n        \"current\": false,\n        \"max\": false,\n        \"min\": false,\n        \"show\": true,\n        \"total\": false,\n        \"values\": false\n      },\n      \"lines\": true,\n      \"linewidth\": 1,\n      \"links\": [],\n      \"nullPointMode\": \"null\",\n      \"percentage\": false,\n      \"pointradius\": 5,\n      \"points\": false,\n      \"renderer\": \"flot\",\n      \"seriesOverrides\": [],\n      \"spaceLength\": 10,\n      \"stack\": false,\n      \"steppedLine\": false,\n      \"targets\": [\n        {\n          \"expr\": \"yais_executor_queue_depth\",\n          \"format\": \"time_series\",\n          \"intervalFactor\": 1,\n          \"refId\": \"A\"\n        }\n      ],\n      \"thresholds\": [],\n      \"timeFrom\": null,\n      \"timeShift\": null,\n      \"title\": \"Queue Depth\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 0,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    }\n  ],\n  \"schemaVersion\": 16,\n  \"style\": \"dark\",\n  \"tags\": [],\n  \"templating\": {\n    \"list\": []\n  },\n  \"time\": {\n    \"from\": \"now-15m\",\n    \"to\": \"now\"\n  },\n  \"timepicker\": {\n    \"refresh_intervals\": [\n      \"5s\",\n      \"10s\",\n      \"30s\",\n      \"1m\",\n      \"5m\",\n      \"15m\",\n      \"30m\",\n      \"1h\",\n      \"2h\",\n      \"1d\"\n    ],\n    \"time_options\": [\n      \"5m\",\n      \"15m\",\n      \"1h\",\n      \"6h\",\n      \"12h\",\n      \"24h\",\n      \"2d\",\n      \"7d\",\n      \"30d\"\n    ]\n  },\n  \"timezone\": \"\",\n  \"title\": \"YAIS\",\n  \"uid\": \"3WLjQkdmk\",\n  \"version\": 1\n}\n"
  },
  {
    "path": "examples/90_Kubernetes/prometheus/yais-metrics.yml",
    "content": "#\n# Create a Service Account, Role, Role Binding\n# YAIS Specific Prometheus (via Operator) and Service\n#\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: prometheus\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: prometheus\nrules:\n- apiGroups: [\"\"]\n  resources:\n  - nodes\n  - services\n  - endpoints\n  - pods\n  verbs: [\"get\", \"list\", \"watch\"]\n- apiGroups: [\"\"]\n  resources:\n  - configmaps\n  verbs: [\"get\"]\n- nonResourceURLs: [\"/metrics\"]\n  verbs: [\"get\"]\n---\napiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: prometheus\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: prometheus\nsubjects:\n- kind: ServiceAccount\n  name: prometheus\n  namespace: default\n---\napiVersion: monitoring.coreos.com/v1\nkind: Prometheus\nmetadata:\n  name: yais-metrics\nspec:\n  serviceAccountName: prometheus\n  serviceMonitorSelector:\n    matchLabels:\n      scrape: yais\n  resources:\n    requests:\n      memory: 400Mi\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: yais-metrics\nspec:\n  ports:\n  - name: web\n    port: 9090\n  selector:\n    prometheus: yais-metrics\n"
  },
  {
    "path": "examples/90_Kubernetes/yais-deploy.yml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: yais-example\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: yais-example\n  template:\n    metadata:\n      labels:\n        app: yais-example\n      annotations:\n        sidecar.istio.io/inject: \"true\"\n    spec:\n      containers:\n      - name: yais-example\n        image: yais\n        command: [\"/work/examples/90_Kubernetes/deploy/build-and-run.sh\"]\n        imagePullPolicy: IfNotPresent # Always\n        env:\n        - name: YAIS_CONCURRENCY\n          value: \"8\"\n        resources:\n          limits:\n            nvidia.com/gpu: 1\n        ports:\n        - name: grpc\n          containerPort: 50051\n        - name: metrics\n          containerPort: 50078\n        livenessProbe:\n          tcpSocket:\n            port: 50051\n          initialDelaySeconds: 5\n          periodSeconds: 5\n        readinessProbe:\n          tcpSocket:\n            port: 50051\n          initialDelaySeconds: 5\n          periodSeconds: 5\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: yais-example\n  labels:\n    app: yais-example\nspec:\n  selector:\n    app: yais-example\n  ports:\n  - name: grpc\n    port: 50051\n    targetPort: grpc\n  - name: metrics\n    port: 50078\n    targetPort: metrics\n---\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: yais-example\n  labels:\n    scrape: yais\nspec:\n  selector:\n    matchLabels:\n      app: yais-example\n  endpoints:\n  - port: metrics\n    interval: 2s\n    honorLabels: true\n---\napiVersion: networking.istio.io/v1alpha3\nkind: Gateway\nmetadata:\n  name: yais-gateway\nspec:\n  selector:\n    istio: ingressgateway # use istio default controller\n  servers:\n  - hosts:\n    - \"*\"\n    port:\n      name: grpc\n      number: 80\n      protocol: grpc\n---\napiVersion: networking.istio.io/v1alpha3\nkind: VirtualService\nmetadata:\n  name: yais-virtual-service\nspec:\n  hosts:\n  - \"*\"\n  gateways:\n  - yais-gateway\n  http:\n  - match:\n    - uri:\n        prefix: /\n    route:\n    - destination:\n        host: yais-example.default.svc.cluster.local\n        port:\n          number: 50051\n"
  },
  {
    "path": "examples/91_Prometheus/README.md",
    "content": "# Prometheus\n\nWIP\n"
  },
  {
    "path": "examples/91_Prometheus/scrape.conf",
    "content": "[[inputs.prometheus]]\n  urls = [\"http://localhost:50078/metrics\"]\n[[outputs.file]]\n  files = [\"stdout\"]\n"
  },
  {
    "path": "examples/97_SingleProcessMultiSteam/launch_service.sh",
    "content": "#!/bin/bash -e\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\ncleanup() {\n  kill $(jobs -p) ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\nENG=${1:-/work/models/ResNet-50-b1-fp32.engine}\nNCTX=${2:-1}\n\nif [ ! -e $ENG ]; then\n    echo \"$ENG not found\"\n    exit 911\nfi\n\nport=50051\n/work/build/examples/02_TensorRT_GRPC/inference-grpc.x --port=$port --engine=${ENG} --contexts=$NCTX &\nwait-for-it.sh localhost:$port --timeout=0 -- echo \"YAIS Service is ready.\" > /dev/null 2>&1\n\necho \"warmup with client-async.x\"\n/work/build/examples/02_TensorRT_GRPC/client-async.x --count=1000 --port=$port\n\necho\necho \"Starting a shell keeping the services and load-balancer running...\"\necho \"Try /work/build/examples/02_TensorRT_GRPC/siege.x --rate=2000 --port=$port\"\nbash --rcfile <(echo \"PS1='$NCTX x $ENG Subshell: '\")\n"
  },
  {
    "path": "examples/98_MultiProcessSingleStream/README.md",
    "content": "# MPS Examples\n\n`run_throughput_test ncopies batch_size engine_file MPS/NOMPS`\n\nV100 - 16GB - DGX-1V\n\nProcesses | MPS | FPS | Batch | Model\n--------- | --- | --- | ----- | -----\n1 | N | 383 | 1 | RN50\n8 | N | 365 | 1 | RN50\n8 | Y | 929 | 1 | RN50\n\n```\nroot@dgx11:/work/src/Examples/98_MultiProcessSingleStream# ./run_throughput_test 8 1 /work/models/ResNet-50-b1-fp32.engine MPS\nstarting 8 inference services\nstarting load balancer\nload balancing over ports:  ['50051', '50052', '50053', '50054', '50055', '50056', '50057', '50058']\nrunning test client\n1000 requests in 1.07632seconds; inf/sec: 929.095\n\nroot@dgx11:/work/src/Examples/98_MultiProcessSingleStream# ./run_throughput_test 8 1 /work/models/ResNet-50-b1-fp32.engine NOMPS\nstarting 8 inference services\nstarting load balancer\nload balancing over ports:  ['50051', '50052', '50053', '50054', '50055', '50056', '50057', '50058']\nrunning test client\n1000 requests in 2.74228seconds; inf/sec: 364.66\n\nroot@dgx11:/work/src/Examples/98_MultiProcessSingleStream# ./run_throughput_test 1 1 /work/models/ResNet-50-b1-fp32.engine NOMPS\nstarting 1 inference services\nstarting load balancer\nload balancing over ports:  ['50051']\nrunning test client\n1000 requests in 2.60915seconds; inf/sec: 383.267\n```\n"
  },
  {
    "path": "examples/98_MultiProcessSingleStream/run_latency_test",
    "content": "#!/bin/bash -e\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\ntrap 'kill $(jobs -p)' EXIT\n\nBS=${1:-1}\nENG=${2:-/work/models/ResNet-50-b2-int8.engine}\n\nif [ ! -e $END ]; then\n    echo \"$ENG not found\"\n    exit 911\nfi\n\necho \"starting inference service\"\nport=50100\n/work/build/examples/02_TensorRT_GRPC/inference-grpc.x --port $port --engine=${ENG} & # > /dev/null 2>&1 &\nwait-for-it.sh localhost:$port --timeout=0 -- echo \"Server ${i} is ready.\" > /dev/null 2>&1\n\necho \"running latency client\"\n/work/build/examples/02_TensorRT_GRPC/client-sync.x --port=$port\n\n"
  },
  {
    "path": "examples/98_MultiProcessSingleStream/run_throughput_test",
    "content": "#!/bin/bash -e\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\ncleanup() {\n  kill $(jobs -p) ||:\n  echo quit | nvidia-cuda-mps-control > /dev/null 2>&1 ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\nNCTX=${1:-1}\nBS=${2:-1}\nENG=${3:-/work/models/ResNet-50-b1-fp32.engine}\nMPS=${4:-\"MPS\"}\n\nif [ ! -e $ENG ]; then\n    echo \"$ENG not found\"\n    exit 911\nfi\n\nif [ \"$MPS\" = \"MPS\" ]; then\n  nvidia-cuda-mps-control -d ||:\nfi\n\nsleep 1\n\necho \"starting $NCTX inference services\"\nfor i in $(seq 1 $NCTX);\ndo\n  port=$(echo \"50050 + $i\" | bc)\n  /work/build/examples/02_TensorRT_GRPC/inference-grpc.x --port $port --engine=${ENG} > /dev/null 2>&1 &\n  wait-for-it.sh localhost:$port --timeout=0 -- echo \"Server ${i} is ready.\" > /dev/null 2>&1\ndone\n\necho \"starting load balancer\"\n../99_LoadBalancer/run_loadbalancer.py -n $NCTX \n# envoy -c /tmp/lb-envoy.yaml --disable-hot-restart > /dev/null 2>&1 &\nenvoy -c /tmp/lb-envoy.yaml > /dev/null 2>&1 &\nwait-for-it.sh localhost:50050 --timeout=0 -- echo \"Load balancer is ready.\" > /dev/null 2>&1\n\necho \"running test client\"\n/work/build/examples/02_TensorRT_GRPC/client-async.x --count=1000 --port=50050\n\necho\necho \"Starting a shell keeping the services and load-balancer running...\"\necho \"Try /work/build/examples/02_TensorRT_GRPC/siege.x --rate=2000 --port=50050\"\nbash --rcfile <(echo \"PS1='Throughput Subshell: '\")\n"
  },
  {
    "path": "examples/98_MultiProcessSingleStream/setup.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nimport os\nimport subprocess\n\nmodels = [\n    (\"ResNet-50-deploy.prototxt\", \"prob\"),\n#   (\"ResNet-152-deploy.prototxt\", \"prob\"),\n]\n\nprecisions = [\n    (\"fp32\", \"\"),\n    (\"fp16\", \"--fp16\"),\n    (\"int8\", \"--int8\")\n]\n\ndef main():\n    for model, o in models:\n        for name, p in precisions:\n            for b in [1]: #, 2, 4, 8]:\n                n = \"b{}-{}\".format(b, name)\n                e = model.replace(\"prototxt\", \"engine\")\n                e = e.replace(\"deploy\", n)\n                m = os.path.join(\"/work/models\", model)\n                if os.path.isfile(e):\n                    continue\n                subprocess.call(\"giexec --deploy={} --batch={} --output={} {} --engine={}\".format(\n                    m, b, o, p, e\n                ), shell=True)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "examples/99_LoadBalancer/README.md",
    "content": "# Envoy Load Balancer\n\nVery basic Envoy Proxy L7 load balancer for testing purposes.\n\n`run_loadbalancer.py -n <number of instances>` will start a copy of envoy \nlistening on port `50050` and load-balancing over ports `[50051, 50051+n-1]`.\n\nYou are responsible for spinning up the backend services.\n\n## Notes\n\nThe load-balancer overhead appears to be about 150us.  Running the `client-sync.x`\ndirectly to a backend vs. through the load-balancer shows about 150us overhead per\ntransaction.\n\n```\n# direct\nThroughput Subshell: /work/build/examples/02_TensorRT_GRPC/client-sync.x --port 50051\n1000 requests in 2.69029 seconds; inf/sec: 371.707\n\n# proxied via envoy load-balancer\nThroughput Subshell: /work/build/examples/02_TensorRT_GRPC/client-sync.x --port 50050\n1000 requests in 2.8411 seconds; inf/sec: 351.977\n```"
  },
  {
    "path": "examples/99_LoadBalancer/lb-envoy.j2",
    "content": "{#-\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n-#}\nstatic_resources:\n  listeners:\n  - address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 50050\n    filter_chains:\n    - filters:\n      - name: envoy.http_connection_manager\n        config:\n          codec_type: auto\n          stat_prefix: ingress_http\n          route_config:\n            name: local_route\n            virtual_hosts:\n            - name: backend\n              domains:\n              - \"*\"\n              routes:\n              - match:\n                  prefix: \"/\"\n                  headers:\n                  - name: content-type\n                    value: application/grpc\n                route:\n                  cluster: inference\n          http_filters:\n          - name: envoy.router\n            config: {}\n  clusters:\n  - name: inference\n    connect_timeout: 0.25s\n    type: strict_dns\n    lb_policy: round_robin\n    http2_protocol_options: {}\n    hosts:\n{% for port in ports %}\n    - socket_address:\n        address: 127.0.0.1\n        port_value: {{ port }}\n{% endfor %}\n\nadmin:\n  access_log_path: \"/dev/null\"\n  address:\n    socket_address:\n      address: 0.0.0.0\n      port_value: 8001\n"
  },
  {
    "path": "examples/99_LoadBalancer/run_loadbalancer.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nimport os\nimport inspect\nimport shutil\nimport tempfile\n\nimport click\nfrom jinja2 import Environment, FileSystemLoader, Template\n\ndef render(template_path, data=None, extensions=None, strict=False):\n    data = data or {}\n    extensions = extensions or []\n    env = Environment(\n        loader=FileSystemLoader(os.path.dirname(template_path)),\n        extensions=extensions,\n        keep_trailing_newline=True,\n    )\n    if strict:\n        from jinja2 import StrictUndefined\n        env.undefined = StrictUndefined\n\n    # Add environ global\n    env.globals['environ'] = os.environ.get\n\n    return env.get_template(os.path.basename(template_path)).render(data)\n\nscript_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\nFileType = click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)\n\n@click.command()\n@click.option(\"-n\", default=1)\n@click.option(\"--template\", type=FileType, default=os.path.join(script_path, \"lb-envoy.j2\"))\ndef main(n, template):\n    envoy = shutil.which(\"envoy\")\n    if not os.path.isfile(envoy):\n        raise RuntimeError(\"envoy executable not found in currently directory: {}\".format(envoy))\n    ports = [50051 + p for p in range(n)]\n    print(\"load balancing over ports: \", [str(p) for p in ports])\n    with open(\"/tmp/lb-envoy.yaml\", \"w\") as file:\n        file.write(render(template, data={\"ports\": ports}))\n#   os.system(\"{} -c /tmp/lb-envoy.yaml\".format(envoy))\n\nif __name__ == \"__main__\":\n    main()\n    \n"
  },
  {
    "path": "examples/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(gflags 2.2.1 REQUIRED)\n\nadd_subdirectory(nvRPC)\nadd_subdirectory(Deployment)\n\nadd_subdirectory(00_TensorRT)\nadd_subdirectory(01_Basic_GRPC)\nadd_subdirectory(02_TensorRT_GRPC)\n#add_subdirectory(03_Batching)\nadd_subdirectory(04_Middleman)\nadd_subdirectory(10_Internals)\nadd_subdirectory(11_Protos)\nadd_subdirectory(12_FlatBuffers)\n#add_subdirectory(30_PyTensorRT)\n"
  },
  {
    "path": "examples/Deployment/CMakeLists.txt",
    "content": "add_subdirectory(ImageClient)\nadd_subdirectory(RouteRequests)\n"
  },
  {
    "path": "examples/Deployment/ImageClient/CMakeLists.txt",
    "content": "set(protobuf_MODULE_COMPATIBLE TRUE)\nfind_package(Protobuf CONFIG REQUIRED)\nmessage(STATUS \"Using protobuf ${protobuf_VERSION}\")\nset(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)\nset(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)\n\nINCLUDE(GRPCGenerateCPP)\n\nPROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS \n    api.proto\n)\n\nPROTOBUF_GENERATE_GRPC_CPP(PROTO_GRPC_SRCS PROTO_GRPC_HDRS \n    api.proto\n)\n\nadd_library(deploy-image-client-protos\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS}\n)\n\ntarget_link_libraries(deploy-image-client-protos\n  PUBLIC\n  ${_PROTOBUF_LIBPROTOBUF}\n)\n\ntarget_include_directories(deploy-image-client-protos PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\npybind11_add_module(deploy_image_client\n  client.cc\n)\n\ntarget_link_libraries(deploy_image_client\nPUBLIC\n  nvrpc-client\n  deploy-image-client-protos\n)\n"
  },
  {
    "path": "examples/Deployment/ImageClient/api.proto",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nsyntax = \"proto3\";\n\npackage trtlab.deploy.image_client;\n \nservice Inference {\n   rpc Classify (ImageInfo) returns (Classifications) {}\n   rpc Detection (ImageInfo) returns (Detections) {}\n\n   rpc ClassifyStream (stream ImageInfo) returns (stream Classifications) {}\n   rpc DetectionSream (stream ImageInfo) returns (stream Detections) {}\n}\n \nmessage ImageInfo {\n    string api_key = 1;\n    string image_uuid = 2;\n    string model_name = 3;\n}\n\nmessage Classifications\n{\n    string image_uuid = 1;\n    repeated Score scores =2;\n    Details details = 3;\n}\n\nmessage Detections\n{\n    string image_uuid = 1;\n    repeated Object objects = 2;\n    Details details = 3;\n}\n\nmessage Score\n{\n    int32 class_idx = 1;\n    float score = 2;\n}\n\nmessage Object\n{\n    string class_name = 1;\n    float upper_left_x = 2;  // [0, 1] normalized on width\n    float upper_left_y = 3;  // [0, 1] normalized on height\n    float width = 4;         // [0, 1] normalized on width\n    float height = 5;        // [0, 1] normalized on height\n}\n\n// this is where you can customize what details your service\n// returns to the user\nmessage Details\n{\n    float request_time = 1;\n    float compute_time = 2;\n}"
  },
  {
    "path": "examples/Deployment/ImageClient/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <pybind11/pybind11.h>\n#include <pybind11/stl.h>\n#include <pybind11/stl_bind.h>\n\n#include \"client.h\"\n\nusing namespace trtlab;\nusing namespace nvrpc;\n\nnamespace py = pybind11;\n\nusing deploy::image_client::Classifications;\nusing deploy::image_client::Detections;\nusing deploy::image_client::ImageInfo;\nusing deploy::image_client::Inference;\n\nImageClient::ImageClient(std::string hostname)\n{\n    auto executor = std::make_shared<client::Executor>(1);\n\n    auto channel = grpc::CreateChannel(hostname, grpc::InsecureChannelCredentials());\n    std::shared_ptr<Inference::Stub> stub = Inference::NewStub(channel);\n\n    auto classify_prepare_fn = [stub](::grpc::ClientContext * context, const ImageInfo& request,\n                                      ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncClassify(context, request, cq));\n    };\n\n    auto detection_prepare_fn = [stub](::grpc::ClientContext * context, const ImageInfo& request,\n                                       ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncDetection(context, request, cq));\n    };\n\n    m_ClassifyClient = std::make_unique<client::ClientUnary<ImageInfo, Classifications>>(\n        classify_prepare_fn, executor);\n    m_DetectionClient = std::make_unique<client::ClientUnary<ImageInfo, Detections>>(\n        detection_prepare_fn, executor);\n}\n\nstd::shared_future<ClassifyResult> ImageClient::Classify(const std::string& model_name,\n                                                         const std::string& image_uuid)\n{\n    ImageInfo image_info;\n    image_info.set_model_name(model_name);\n    image_info.set_image_uuid(image_uuid);\n    std::map<std::string, std::string> headers = {{\"custom-metadata-model-name\", model_name}};\n    auto post = [](ImageInfo& input, Classifications& output,\n                   ::grpc::Status& status) -> ClassifyResult {\n        ClassifyResult results(output);\n        return std::move(results);\n    };\n    return m_ClassifyClient->Enqueue(std::move(image_info), post, headers);\n}\n\nstd::shared_future<DetectionResult> ImageClient::Detection(const std::string& model_name,\n                                                           const std::string& image_uuid)\n{\n    ImageInfo image_info;\n    image_info.set_model_name(model_name);\n    image_info.set_image_uuid(image_uuid);\n    std::map<std::string, std::string> headers = {{\"custom-metadata-model-name\", model_name}};\n    auto post = [](ImageInfo& input, Detections& output,\n                   ::grpc::Status& status) -> DetectionResult {\n        DetectionResult results(output);\n        return std::move(results);\n    };\n    return m_DetectionClient->Enqueue(std::move(image_info), post, headers);\n}\n\nClassifyResult::ClassifyResult(const ::trtlab::deploy::image_client::Classifications& pb)\n    : m_UUID(pb.image_uuid())\n{\n}\n\nDetectionResult::DetectionResult(const ::trtlab::deploy::image_client::Detections& pb)\n    : m_UUID(pb.image_uuid())\n{\n}\n\nusing PyClassifyFuture = std::shared_future<ClassifyResult>;\nusing PyDetectionFuture = std::shared_future<DetectionResult>;\n\nPYBIND11_MAKE_OPAQUE(PyClassifyFuture);\nPYBIND11_MAKE_OPAQUE(PyDetectionFuture);\n\nPYBIND11_MODULE(deploy_image_client, m)\n{\n    py::class_<ImageClient, std::shared_ptr<ImageClient>>(m, \"ImageClient\")\n        .def(py::init<std::string>(), py::arg(\"hostname\") = \"trt.lab\")\n        .def(\"classify\", &ImageClient::Classify)\n        .def(\"detection\", &ImageClient::Detection);\n\n    py::class_<PyClassifyFuture, std::shared_ptr<PyClassifyFuture>>(m, \"ClassifyFuture\")\n        .def(\"wait\", &PyClassifyFuture::wait, py::call_guard<py::gil_scoped_release>())\n        .def(\"get\", &PyClassifyFuture::get, py::call_guard<py::gil_scoped_release>());\n\n    py::class_<PyDetectionFuture, std::shared_ptr<PyDetectionFuture>>(m, \"DetectionFuture\")\n        .def(\"wait\", &PyDetectionFuture::wait, py::call_guard<py::gil_scoped_release>())\n        .def(\"get\", &PyDetectionFuture::get, py::call_guard<py::gil_scoped_release>());\n\n    py::class_<ClassifyResult, std::shared_ptr<ClassifyResult>>(m, \"ClassifyResult\")\n        .def_property_readonly(\"uuid\", &ClassifyResult::UUID);\n\n    py::class_<DetectionResult, std::shared_ptr<DetectionResult>>(m, \"DetectionResult\")\n        .def_property_readonly(\"uuid\", &DetectionResult::UUID);\n}"
  },
  {
    "path": "examples/Deployment/ImageClient/client.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <future>\n#include <memory>\n#include <string>\n\n#include \"nvrpc/client/client_unary.h\"\n\n#include \"api.grpc.pb.h\"\n#include \"api.pb.h\"\n\nclass ClassifyResult\n{\n  public:\n    ClassifyResult(const ::trtlab::deploy::image_client::Classifications&);\n    const std::string& UUID() const { return m_UUID; }\n\n  private:\n    std::string m_UUID;\n};\n\nstruct DetectionResult\n{\n  public:\n    DetectionResult(const ::trtlab::deploy::image_client::Detections&);\n    const std::string& UUID() const { return m_UUID; }\n\n  private:\n    std::string m_UUID;\n};\n\nclass ImageClient\n{\n  public:\n    ImageClient(std::string);\n    ~ImageClient() {}\n\n    std::shared_future<ClassifyResult> Classify(const std::string&, const std::string&);\n    std::shared_future<DetectionResult> Detection(const std::string&, const std::string&);\n\n  private:\n    using ImageInfo = ::trtlab::deploy::image_client::ImageInfo;\n    using Classifications = ::trtlab::deploy::image_client::Classifications;\n    using Detections = ::trtlab::deploy::image_client::Detections;\n\n    std::unique_ptr<::nvrpc::client::ClientUnary<ImageInfo, Classifications>> m_ClassifyClient;\n    std::unique_ptr<::nvrpc::client::ClientUnary<ImageInfo, Detections>> m_DetectionClient;\n};\n"
  },
  {
    "path": "examples/Deployment/ImageClient/client.py",
    "content": "## Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n##\n## Redistribution and use in source and binary forms, with or without\n## modification, are permitted provided that the following conditions\n## are met:\n##  * Redistributions of source code must retain the above copyright\n##    notice, this list of conditions and the following disclaimer.\n##  * Redistributions in binary form must reproduce the above copyright\n##    notice, this list of conditions and the following disclaimer in the\n##    documentation and/or other materials provided with the distribution.\n##  * Neither the name of NVIDIA CORPORATION nor the names of its\n##    contributors may be used to endorse or promote products derived\n##    from this software without specific prior written permission.\n##\n## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\nimport os\nimport uuid\n\nimport boto3\nimport deploy_image_client as client\n\nclass ImageClient:\n\n    def __init__(self, *, hostname = \"trt.lab\"):\n        self._cpp_client = client.ImageClient(hostname)\n        self._s3_client = self._get_s3_client()\n\n    def classify(self, image_path, model):\n        key = self._upload_to_s3(image_path)\n        return self._cpp_client.classify(key, model)\n\n    def object_detection(self, image_path, model):\n        key = self._upload_to_s3(image_path)\n        return self._cpp_client.object_detection(key, model)\n\n    def _get_s3_client(self):\n        kwargs = {}\n        if os.environ.get(\"AWS_ENDPOINT_URL\"):\n            kwargs = {\n                endpoint_url: os.environ.get(\"AWS_ENDPOINT_URL\"),\n                use_ssl: False,\n                verify: False,\n            }\n        return boto3.client(\"s3\", **kwargs)\n\n    def _check_if_file(self, file_path):\n        if not os.path.isfile(file_path):\n            raise RuntimeError(\"{} is not a file\".format(file_path))\n\n    def _upload_to_s3(self, image_path):\n        self._check_if_file(image_path)\n        key = str(uuid.uuid4())\n        with open(image_path, \"rb\") as data:\n            self._s3_client.upload_fileobj(data, 'images', key)\n        return key\n"
  },
  {
    "path": "examples/Deployment/Kubernetes/basic-trtis-deployment/deploy.yml",
    "content": "---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: basic-trtis-deployment\n  namespace: trtlab\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: basic-trtis-deployment\n  template:\n    metadata:\n      labels:\n        app: basic-trtis-deployment\n      annotations:\n        sidecar.istio.io/inject: \"true\"\n    spec:\n      containers:\n      - name: trtis\n        image: nvcr.io/nvidia/tensorrtserver:19.02-py3\n        command: [\"trtserver\", \"--model-store=/tmp/models\"]\n        imagePullPolicy: IfNotPresent\n        resources:\n          limits:\n            nvidia.com/gpu: 1\n        ports:\n        - name: http\n          containerPort: 8000\n        - name: grpc\n          containerPort: 8001\n        - name: metrics\n          containerPort: 8002\n        livenessProbe:\n          httpGet:\n            path: /api/health/live\n            port: http\n          initialDelaySeconds: 10\n          periodSeconds: 5\n        readinessProbe:\n          httpGet:\n            path: /api/health/ready\n            port: http\n          initialDelaySeconds: 10\n          periodSeconds: 5\n        volumeMounts:\n        - mountPath: /tmp/models\n          name: model-store\n      volumes:\n      - name: model-store\n        hostPath:\n          path: /shared/trtis/example-model-store\n          type: Directory\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: basic-trtis-deployment\n  namespace: trtlab\n  labels:\n    app: basic-trtis-deployment\nspec:\n  selector:\n    app: basic-trtis-deployment\n  ports:\n  - name: http\n    port: 8000\n    targetPort: http\n  - name: grpc\n    port: 8001\n    targetPort: grpc\n  - name: metrics\n    port: 8002\n    targetPort: metrics\n"
  },
  {
    "path": "examples/Deployment/Kubernetes/basic-trtis-deployment/istio-ingress.yml",
    "content": "---\napiVersion: networking.istio.io/v1alpha3\nkind: Gateway\nmetadata:\n  name: basic-trtis-deployment-gateway\n  namespace: trtlab\nspec:\n  selector:\n    istio: ingressgateway\n  servers:\n  - port:\n      name: http\n      number: 80\n      protocol: grpc\n    hosts:\n    - \"trt.lab\"\n---\napiVersion: networking.istio.io/v1alpha3\nkind: VirtualService\nmetadata:\n  name: basic-trtis-deployment-virtual-service\n  namespace: trtlab\nspec:\n  hosts:\n  - \"trt.lab\"\n  gateways:\n  - basic-trtis-deployment-gateway\n  http:\n  - match:\n    - uri:\n        prefix: /api/health/\n    route:\n    - destination:\n        host: basic-trtis-deployment\n        port:\n          number: 8000\n  - match:\n    - uri:\n        prefix: /\n    route:\n    - destination:\n        host: basic-trtis-deployment\n        port:\n          number: 8001\n---\napiVersion: networking.istio.io/v1alpha3\nkind: DestinationRule\nmetadata:\n  name: basic-trtis-deployment-load-balancer\n  namespace: trtlab\nspec:\n  host: basic-trtis-deployment\n  trafficPolicy:\n    loadBalancer:\n      simple: LEAST_CONN\n"
  },
  {
    "path": "examples/Deployment/Kubernetes/basic-trtis-deployment/scrape-metrics.yml",
    "content": "---\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: basic-trtis-deployment\n  namespace: trtlab\n  labels:\n    scrape: nv-inference-metrics\nspec:\n  selector:\n    matchLabels:\n      app: basic-trtis-deployment\n  endpoints:\n  - port: metrics\n    interval: 2s\n    honorLabels: true\n"
  },
  {
    "path": "examples/Deployment/ObjectStore/README.md",
    "content": "# Object Store\n\nIn the Image Service example, the ImageClient separates out an inference request\ninto two components: \n- a bulk data transfers to a backend store, \n- a gRPC request that contains the details of the request (model, file_handle, etc.)\n\nTo implement this concept, we will use an S3-compatible Object Store. The\nexample should work equally well on AWS S3 or via Rook's S3 CephObjectStore\nimplementation running locally a Kubernetes cluster. For more details on\nhow Kubernetes and Rook were installed, see the [NVIDIA DeepOps Project](https://github.com/nvidia/deepops).\n\nThis folder contains some basic configuration files and scripts for preparing the\nObjectStore for our Image Service.\n\n## AWS S3\n\nSimply sent your AWS API configuration or export the following environment variables.\n\n```\nexport AWS_ACCESS_KEY_ID=<your-aws-access-key>\nexport AWS_SECRET_ACCESS_KEY=<your-super-secret-access-key>\n```\n\n## Rook + Kubernetes\n\nYou will need to modify some of the configuration files for your cluster.\n\n- `rook-s3.yml` options:\n  - requires 3 unique hosts with bluestore backed OSDs\n  - creates a `trtlab` user\n\nIf you modify the name of the ObjectStore (`trtlab-s3`) and or the username (`trtlab`),\nbe aware the `get_rook_s3_keys.sh` needs to be modified.\n\nSimilarly, the examples uses `s3.trt.lab` as the endpoint on which the storage\nis hosted. If you change this, you will need to modify `get_rook_s3_keys.sh` to\noutput the proper `AWS_ENDPOINT_URL`. You will also need to modify the ingress\nexamples with the proper hostname.\n\n```\nkubectl apply -f rook-s3.yml\nkubectl apply -f ingress-nginx.yml\n```\n\n### Setup your environment\n```\neval $(./get_rook_s3_keys.sh)\n```\n\n### Prepare your Image bucket\n\nNote: you will need to have python3 and boto installed.  This does not have be done\ninside the container.\n\n```\npython3 create_buckets.py\n```\n\n## TODOs\n\n- [ ] Export S3 keys to a Kubernetes Secret\n- [ ] Scripts for bucket maintenance: probably some k8s CronJobs\n- [ ] Update Istio ingress example"
  },
  {
    "path": "examples/Deployment/ObjectStore/create_buckets.py",
    "content": "import os\nimport boto3\n\ns3 = boto3.client(\"s3\", use_ssl=False, verify=False, \n                  endpoint_url=os.environ.get(\"AWS_ENDPOINT_URL\"))\n\nresponse = s3.list_buckets()\n\nbuckets = [b[\"Name\"] for b in response[\"Buckets\"]]\n\nif \"images\" not in buckets:\n    s3.create_bucket(Bucket=\"images\")\n\nresponse = s3.list_buckets()\nbuckets = [b[\"Name\"] for b in response[\"Buckets\"]]\n\nprint(buckets)\n"
  },
  {
    "path": "examples/Deployment/ObjectStore/get_rook_s3_keys.sh",
    "content": "#!/bin/bash\nobjstore=trtlab-s3\nuser=trtlab\necho -n export AWS_ACCESS_KEY_ID=\nkubectl -n rook-ceph get secret rook-ceph-object-user-${objstore}-${user} -o yaml | grep AccessKey | awk '{print $2}' | base64 --decode\necho\necho -n export AWS_SECRET_ACCESS_KEY=\nkubectl -n rook-ceph get secret rook-ceph-object-user-${objstore}-${user} -o yaml | grep SecretKey | awk '{print $2}' | base64 --decode\necho\necho export AWS_ENDPOINT_URL=http://s3.trt.lab\necho\n"
  },
  {
    "path": "examples/Deployment/ObjectStore/ingress-istio.yml",
    "content": "# not working yet\n---\napiVersion: networking.istio.io/v1alpha3\nkind: Gateway\nmetadata:\n  name: trtlab-s3-gateway\nspec:\n  selector:\n    app: trtlab-s3\n    istio: ingressgateway\n  servers:\n  - hosts:\n    - \"s3.trt.lab\"\n    port:\n      number: 80\n      name: http\n      protocol: HTTP\n---\napiVersion: networking.istio.io/v1alpha3\nkind: VirtualService\nmetadata:\n  name: trtlab-s3-virtualservice\nspec:\n  hosts:\n  - \"s3.trt.lab\"\n  gateways:\n  - trtlab-s3-gateway\n  http:\n  - match:\n    - uri:\n        prefix: /\n    route:\n    - destination:\n        host: rook-ceph-rgw-trtlab-s3.rook-ceph\n        port:\n          number: 80\n"
  },
  {
    "path": "examples/Deployment/ObjectStore/ingress-nginx.yml",
    "content": "apiVersion: extensions/v1beta1\nkind: Ingress\nmetadata:\n  annotations:\n    nginx.ingress.kubernetes.io/proxy-body-size: \"0\"\n    nginx.ingress.kubernetes.io/proxy-read-timeout: \"600\"\n    nginx.ingress.kubernetes.io/proxy-send-timeout: \"600\"\n  name: trtlab-s3-ingress\n  namespace: rook-ceph\nspec:\n  rules:\n  - host: s3.trt.lab\n    http:\n      paths:\n      - backend:\n          serviceName: rook-ceph-rgw-trtlab-s3\n          servicePort: 80\n        path: /\n"
  },
  {
    "path": "examples/Deployment/ObjectStore/rook-s3.yml",
    "content": "---\napiVersion: ceph.rook.io/v1\nkind: CephObjectStore\nmetadata:\n  name: trtlab-s3\n  namespace: rook-ceph\nspec:\n  metadataPool:\n    failureDomain: host\n    replicated:\n      size: 3\n  dataPool:\n    failureDomain: host\n    erasureCoded:\n      dataChunks: 2\n      codingChunks: 1\n  gateway:\n    type: s3\n    sslCertificateRef:\n    port: 80\n    securePort:\n    instances: 1\n    allNodes: false\n---\napiVersion: ceph.rook.io/v1\nkind: CephObjectStoreUser\nmetadata:\n  name: trtlab\n  namespace: rook-ceph\nspec:\n  store: trtlab-s3\n  displayName: \"TensorRT Laboratory\"\n"
  },
  {
    "path": "examples/Deployment/README.md",
    "content": "# Deploying Inference Services\n\nThis document/example folder is a work in progress. Its intent is to cover\nvarious aspect of deployment including strategies, limitations, services and\nkubernetes examples of deploying inference services.\n\nOver the course of this guide, we will build a full end-to-end image processing\nservice deployed on Kubernetes.\n\nLet us start by assuming all your models can be served/deployed with the\n[TensorRT Inference Server, aka TRTIS](https://github.com/nvidia/tensorrt-inference-server).\nOne of the primary advantages of TRTIS is the ability to host multiple models in\na single linux process. Given the capabilities of modern GPUs, this is the most\nefficient way to for multiple models to efficiently share of both compute and\nmemory resources.\n\nNext, lets dive a little deeper into the features of TRTIS that gives this effiency advantage.\n\n  - _Concurrent Executions_ allow for multiple independent inference batches to be\n    in-flight on the device at a given time. This could be multiple batches of\n    the same model or single batches of different models, or any combination\n    imaginable. \n    - Running on a Tesla V100 GPU with ResNet-152 Batch8\n      - Allowing only 1 in-flight batch8 yields XXX images/sec with a compute\n        latency of YYY.\n      - Allowing 8 concurrency batch8 executions increases the throughput to\n        2500 images/sec; however, the compute latency per batch increases to\n        ZZZ.\n    - To evaluate the performance of TensorRT models a function of concurrent\n      in-flight executions we provide the [TensorRT/ConcurrentExecution](../TensorRT/ConcurrentExecution)\n      example.\n      ```bash\n      infer.x --engine=/external/models/ResNet-152-b8-fp16.engine --concurrency=8\n      ```\n    - The value of concurrent executions will differ depending on the compute\n      requirements of the model and the GPU on which it executes. The best\n      practice is to benchmark and evaluates performance.\n\n  - _Tunable Concurency_ enables you to specify on a per model basis the number\n    of concurreny copies that can be executed at any given time. Follow the guidelines\n    Concurrent Executions to tune this option on a per model basis.\n\n  - _Dynamic Batching_ allows individual requests from either same or different\n    clients to be multiplexed into a single mini-batch and infered. Dynamic\n    Batching is performed on a per-model basis and can have a max\n    `preferred_batch_size` and a `max_queue_delay_microseconds` which specific\n    how long of a delay messages are allowed to accumulate. Batching is one of\n    the best ways to improve throughput. Depending on your needs, you will want\n    to balance the added latency required for batching vs the throughput\n    improvements achieved.\n    - Note: in scale-out deployments where unary (send/recv, not streaming)\n      requests are being load-balanced across multiple TRTIS instances, the\n      value of dynamic batching in the TRTIS decreases as the number of replicas  \n      increases.\n    - TODO: We address this issue by creating Dynamic Batching Services that sit\n      infront of the Load-Balancer. Add a discussion and update the [examples/03_Batching]\n      example with the latest streaming Server/Client\n\n  - _Custom Metrics_ provide application-level metrics on how the TRTIS service\n    is performing. Analyzing these metrics can provide insight on when a service\n    is being overloaded and when to add more resources. TRTIS and some TRTLAB\n    examples expose Prometheus Metrics.\n     - [examples/90_Kubernetes/prometheus] is one exmaple of how to use\n       Kubernetes + Prometheus + Grafana to scrape and visualize metrics from\n       running TRTIS services.\n     - TODO: Document and clean up examples.\n\nThe goal of this project is to provide supplementary support to TRTIS by\nproviding buildings blocks that help you build companion microservices that\nworth with TRTIS, as well as example deployment scenarios.\n\n## Configure a TRTIS Kubernetes Deployment\n\nIn Kubernetes, a\n[Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)\nallows you to define a [Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)\nand the number of copies of that pod, i.e.\n[ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)\nthat you would like deployed on your cluster.\n\n### Build a Model Store\n\nThe [TRTIS Model Store] is the collection of models that will be loaded and\nserved by a TRTIS instance. For details on how to build a model store, see the [Deployment/ModelStore]\nexample.\n\nIn order to define our Kubernetes Deployment, we need to map our model store\ninto our TRTIS Pod. There are multiple ways this can be achieved.\n- Extend the TRTIS container image and add the model store to the image\n- Mount an External Volume into the TRTIS Pod\n- Use another container in the same TRTIS Pod that will dynamically generate a\n  model store from some external data sources, e.g. S3.\n  - TODO: Add this example\n\nMy Kubernetes cluster has an NFS mount at `/shared` on every node. For this\nexample, our model store will be located at `/shared/trtis/example-model-store`\n\n### Deploy TRTIS Pods\n\n\n\n\n## Configure Multiple TRTIS Deployments with Different Sets of Models\n\nNow suppose you are serving more models than you can allocate on a single GPU.  In this scenario, we can split our list of models into groups and spread those groups out over multiple TRTIS `Deployments`\n\n## Scenario #1: 2 Models, 10 Servers, 20 GPUs\n\nAssume you have two computer vision models, e.g. classification, object\ndetection, segmentation, that you wish to deploy on 10 servers.\n\nProbably the first questions you might ask yourself is what is the breakdown of\nload expected for each model. Is it 50/50? Or is it 90/10? Does it vary by time\nof day? Is it predictive?\n\nThe strategy with TRTIS is simple, you deploy 20 replicas of the TRTIS service\nacross 10 servers, 1 TRTIS service per GPU and tell your load-balancer to\nround-robin requests across your services.\n\nHowever, unless you customize TRTIS, by default, TRTIS only accepts raw tensors\nas inputs and returns raw tensors an outputs.\n\nWhat are your inputs?  And what's a reasonable expectation for the rest of the\ninference pipeline?\n\nLet's assume you are receiving JPEG images. First, you need to decode the images to\nraw pixels, then you need to prepare the images to be inferred. To keep things\nsimple, let's assume that both models use the same input preprocessing method.\n\nWhat is the compression ratio of your JPEG images? Assuming the images are\n8-bit, then\n[a blog post by Graphics Mill](https://www.graphicsmill.com/blog/2014/11/06/Compression-ratio-for-different-JPEG-quality-values#.XHtdPpNKiXE_)\nmeasured the compression ratio to be 1:5.27 for JPEG Quality 100 (Q=100) and\n1:43.27 for Q=55. For this discussion we wil focus on Q=80, which was measured\nto be a 1:25 ratio. This is the decompression ratio for JPEG bytes to INT8 pixel\nvalues. However, most DNN models after normalization accept tensors that are\nfp32 values as inputs. This means that we have a 1:100 an increased ratio of\ninput bytes to bytes of input tensors.\n\nA 100KiB image becomes a 9.75MiB data structure that needs to be provided to\nTRTIS. This 100x increase in size is big, but not unreasonably large. If your\nimages are coming in over the Internet/WAN, then your LAN connction is likely to\nbe 100x faster. However, if this was video, that compression ratio per frame\nwould be MUCH larger. To future-proof our implementation, we are going to do our\nbest to minimize the amount of data we move around.\n\nNext, what is it that our users are providing to us beside just the image to be\ninferred. The client must inform the server which model should be used for the\nrequest. And similarly, the server probably also wants to know some details\nabout the user. In this example, we will using a user API key to authenticate\nthe user.\n\nNow let's look at the data payload the client will be sending our server. We are\ngoing to break down an image inference request into two parts:\n- the bulk image data\n- the request metadata: api key, image_uuid, model_name\n\nThis separation allows us to commmunicate and move each component more\noptimally. We will send the JPEG image bytes directly to an object store and we\nwill use a gRPC message to communicate the metadata for the request.\n\nWhy not embed the image directly into the gRPC message? While this is certainly\na possibility, we are chosing this separation because in our optimial pipeline,\nour client request message will go through several services before the bulk\nimage data is needed. These services include an ingress router/load-balancer and\nan external batching service before they are sent to the image pre-processing\nservice. This separate helps us future-proof our implementation by avoiding\nunnecessary data movement.\n\nLet's break down our client implementation:\n- 1) writes the jpeg image data to an S3-compatible object store as some UUID.jpg\n- 2) creates an async gRPC unary (send/recv) RPC request to our inference service.\n  - the message payload consists of our client api key, image uuid and model_name\n  - add custom headers that will enable our ingress router/load-balancer to\n    properly route the message to the correct target without the need to\n    deserialize the request payload. this allows us to route message directly to\n    services specify to some metadata. In this case, we will add the model name\n    to the headers so we can eventually route requests to batching services\n    unique to that model.\n\nThis means our client can continue to issue async inference requests with the\npromise that the results will returned in some future time.\n\nOn the server side, this data move break down the inference request into two\ncomponents, the data and the request.\n\nLet's assume our incoming data transport is very effficient. The images will\nbe deposited into an S3-compatible object store.  On my Kubernetes cluster,\nI'll be using [Rook's Mino/S3 Operator](https://rook.io), but it would work\nequally well on AWS.\n\n"
  },
  {
    "path": "examples/Deployment/RouteRequests/CMakeLists.txt",
    "content": "add_executable(test_image_service.x\n  test_service.cc\n)\n\ntarget_link_libraries(test_image_service.x\nPUBLIC\n  nvrpc\n  deploy-image-client-protos\n  gflags\n)\n"
  },
  {
    "path": "examples/Deployment/RouteRequests/README.md",
    "content": "# Routing Requests\n\nIf we have multiple instances of TRTIS each with different models, we need a way\nto route requests to the proper service. There are two convenient options:\nrouting by subdomain or routing by headers.\n\nIn this example, we will have three unique pools of TRTIS services:\n- Pool A: only handles `model_a` `Classify` requests\n- Pool B: only handles `model_b` requests (`Classify` or `Detection`)\n- General Pool: handles all other requests\n\nIn our hypothetical deployment scenario, both `model_a` and `model_b` are\nparticularly active so we have dedicated resources to handle those requests.\nSimilarly, our general pool has it's own fixed size. Later, we will show out to\nauto-scale pods based on TRTIS and GPU metrics.\n\nA simple approach would be to host `model_a.trt.lab`, `model_b.trt.lab` and\n`general_pool.trt.lab` and have the client make the decision sender side on\nwhere to send the requests. However, changest to the service layout would\nrequire updates to the clients software which makes this option less appealing.\n\nIdeally, we want our entire service to be hosted on a single endpoint `trt.lab`.  \n\nTo ensure our requests arrive at the proper destination server-side, we have our\nclient add [Custom Metadata](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md) to each gRPC request.\n\n```c++\nstd::map<std::string, std::string> headers = {{\"custom-metadata-model-name\", model_name}};\n```\n\nwhich inside our client library\n\n```c++\nfor (auto& header : headers)\n{\n    // add headers to ::grpc::ClientContext\n    ctx->m_Context.AddMetadata(header.first, header.second);\n}\n```\n\nTo test routing, we have provided an `envoy_config.yaml` configuration. The\nload-balancer/router listens on port 50050 and routes to three sample services\nrunning on 51051, 51052 and 51053.\n\nTo differentiate by endpoint, `Classify` or `Detection`, we can match routes on their `uri`.\n\nHere is the relevant parts of the envoy config:\n```yaml\n- match:\n    prefix: /trtlab.deploy.image_client.Inference/Classify\n    headers:\n    - name: custom-metadata-model-name\n      exact_match: model_a\n    grpc:\n  route:\n    cluster: classify_model_a\n- match:\n    prefix: /\n    headers:\n    - name: custom-metadata-model-name\n      exact_match: model_b\n    grpc:\n  route:\n    cluster: model_b\n- match:\n    prefix: /\n    grpc:\n  route:\n    cluster: general_pool\n```\n\n`test_routing.sh` provides a convenient means to test the configuration. It will\ncompile a simple implementation of the ImageClient service, bring up an instance\nof Envoy, 3 instances of the test_service, then send both `Classify` and\n`Detection` requests with three different models at the router. The service\nimplementation simple returns which named service handled the request.\n\n```s\nroot@5e8ffb38df87:/work/examples/Deployment/RouteRequests# ./test_routing.sh \n... some start up output ...\nTesting Classify RPC\nI0307 13:41:36.614954   355 test_service.cc:74] model_a served by model_a\nI0307 13:41:36.616070   359 test_service.cc:74] model_b served by model_b\nI0307 13:41:36.617031   362 test_service.cc:74] model_c served by general_pool\nTesting Detection RPC\nI0307 13:41:36.617636   362 test_service.cc:74] model_a served by general_pool\nI0307 13:41:36.618005   359 test_service.cc:74] model_b served by model_b\nI0307 13:41:36.618367   362 test_service.cc:74] model_c served by general_pool\n\n**** Test Passed ****\n```\n\nWhile we are using Envoy (v1.9) directly in this example, we will later show how\nthis can be accomplished in Istio. A major TODO in this project is to build a\nTRTIS operator while will provide Kubernetes CRD that will be able to\ndynamically manage the routes as a function of where the model will be loaded on\nthe cluster. Whereas this example shows static placement, we eventually want to\nget to fully dynamic routes."
  },
  {
    "path": "examples/Deployment/RouteRequests/envoy_config.yaml",
    "content": "static_resources:\n  listeners:\n  - name: listener_0\n    address:\n      socket_address: { address: 0.0.0.0, port_value: 50050 }\n    filter_chains:\n    - filters:\n      - name: envoy.http_connection_manager\n        config:\n          codec_type: auto\n          stat_prefix: ingress_http\n          route_config:\n            name: local_route\n            virtual_hosts:\n            - name: backend\n              domains:\n              - \"*\"\n              routes:\n              - match:\n                  prefix: /trtlab.deploy.image_client.Inference/Classify\n                  headers:\n#                 - name: content-type\n#                   value: application/grpc\n                  - name: custom-metadata-model-name\n                    exact_match: model_a\n                  grpc:\n                route:\n                  cluster: classify_model_a\n              - match:\n                  prefix: /\n                  headers:\n#                 - name: content-type\n#                   value: application/grpc\n                  - name: custom-metadata-model-name\n                    exact_match: model_b\n                  grpc:\n                route:\n                  cluster: model_b\n              - match:\n                  prefix: /\n#                 headers:\n#                 - name: content-type\n#                   value: application/grpc\n                  grpc:\n                route:\n                  cluster: general_pool\n          http_filters:\n          - name: envoy.router\n            config: {}\n  clusters:\n  - name: classify_model_a\n    connect_timeout: 0.25s\n    type: strict_dns\n    lb_policy: round_robin\n    http2_protocol_options: {}\n    hosts:\n    - socket_address:\n        address: 127.0.0.1\n        port_value: 51051\n  - name: model_b\n    connect_timeout: 0.25s\n    type: strict_dns\n    lb_policy: round_robin\n    http2_protocol_options: {}\n    hosts:\n    - socket_address:\n        address: 127.0.0.1\n        port_value: 51052\n  - name: general_pool\n    connect_timeout: 0.25s\n    type: strict_dns\n    lb_policy: round_robin\n    http2_protocol_options: {}\n    hosts:\n    - socket_address:\n        address: 127.0.0.1\n        port_value: 51053\n\nadmin:\n  access_log_path: \"/dev/null\"\n  address:\n    socket_address:\n      address: 0.0.0.0\n      port_value: 8001\n"
  },
  {
    "path": "examples/Deployment/RouteRequests/test_client.py",
    "content": "import os\n\nimport deploy_image_client as cpp_client\n\n\ndef main():\n    if not os.environ.get(\"TRTLAB_ROUTING_TEST\"):\n        raise RuntimeError(\n            \"Plese run this script in the environment setup by test_routing.sh\")\n    router = cpp_client.ImageClient(\"localhost:50050\")\n\n    print(\"Testing Classify RPC\")\n\n    a = router.classify(\"model_a\", \"via_router_uuid1\").get()\n    b = router.classify(\"model_b\", \"via_router_uuid2\").get()\n    c = router.classify(\"model_c\", \"via_router_uuid3\").get()\n\n    assert a.uuid == \"model_a\"\n    assert b.uuid == \"model_b\"\n    assert c.uuid == \"general_pool\"\n\n    print(\"Testing Detection RPC\")\n\n    a = router.detection(\"model_a\", \"via_router_uuid1\").get()\n    b = router.detection(\"model_b\", \"via_router_uuid2\").get()\n    c = router.detection(\"model_c\", \"via_router_uuid3\").get()\n\n    assert a.uuid == \"general_pool\"\n    assert b.uuid == \"model_b\"\n    assert c.uuid == \"general_pool\"\n\n    print(\"\\n**** Test Passed ****\\n\")\n\n\nif __name__ == \"__main__\":\n    try:\n        main()\n    except RuntimeError as e:\n        print(\"\\n**** Error ****\")\n        print(e)\n        print()\n"
  },
  {
    "path": "examples/Deployment/RouteRequests/test_routing.sh",
    "content": "#!/bin/bash\n\ncleanup() {\n  kill $(jobs -p) ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\n(cd /work/build/examples/Deployment/ImageClient; make)\n(cd /work/build/examples/Deployment/RouteRequests; make)\n\nexport PYTHONPATH=$PYTHONPATH:/work/build/examples/Deployment/ImageClient\n\nexe=/work/build/examples/Deployment/RouteRequests/test_image_service.x\n\n$exe --hostname=\"model_a\" --ip_port=\"0.0.0.0:51051\" & #> /dev/null 2>&1 &\n$exe --hostname=\"model_b\" --ip_port=\"0.0.0.0:51052\" & #> /dev/null 2>&1 &\n$exe --hostname=\"general_pool\" --ip_port=\"0.0.0.0:51053\" & #> /dev/null 2>&1 &\nenvoy -c envoy_config.yaml > /dev/null 2>&1 &\n\nwait-for-it.sh localhost:50050 --timeout=0 -- echo \"Envoy on 50050 ready\"\nwait-for-it.sh localhost:51051 --timeout=0 -- echo \"ModelA on 51051 ready\"\nwait-for-it.sh localhost:51052 --timeout=0 -- echo \"ModelB on 51052 ready\"\nwait-for-it.sh localhost:51053 --timeout=0 -- echo \"General Pool on 51053 ready\"\n\nexport TRTLAB_ROUTING_TEST=True\n\npython3 test_client.py\n\n"
  },
  {
    "path": "examples/Deployment/RouteRequests/test_service.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\n\n#include \"api.grpc.pb.h\"\n#include \"api.pb.h\"\n\nusing trtlab::deploy::image_client::Classifications;\nusing trtlab::deploy::image_client::Detections;\nusing trtlab::deploy::image_client::ImageInfo;\nusing trtlab::deploy::image_client::Inference;\n\n// CLI Options\nDEFINE_string(hostname, \"localhost\", \"Hostname\");\nDEFINE_string(ip_port, \"0.0.0.0:50051\", \"IP/Port on which to listen\");\n\nclass TestResources : public Resources\n{\n  public:\n    TestResources(const std::string& hostname) : m_Hostname(hostname) {}\n    const std::string& Hostname() const { return m_Hostname; }\n\n  private:\n    std::string m_Hostname;\n};\n\ntemplate<typename Output>\nclass TestContext final : public Context<ImageInfo, Output, TestResources>\n{\n    void ExecuteRPC(ImageInfo& input, Output& output) final override\n    {\n        LOG(INFO) << input.model_name() << \" served by \" << this->GetResources()->Hostname();\n        output.set_image_uuid(this->GetResources()->Hostname());\n        this->FinishResponse();\n    }\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"test_deploy_client\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    Server server(FLAGS_ip_port);\n    auto service = server.RegisterAsyncService<Inference>();\n    auto rpc_classify = service->RegisterRPC<TestContext<Classifications>>(\n        &Inference::AsyncService::RequestClassify);\n    auto rpc_detection =\n        service->RegisterRPC<TestContext<Detections>>(&Inference::AsyncService::RequestDetection);\n\n    auto resources = std::make_shared<TestResources>(FLAGS_hostname);\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    executor->RegisterContexts(rpc_classify, resources, 1);\n    executor->RegisterContexts(rpc_detection, resources, 1);\n\n    server.Run(std::chrono::milliseconds(2000), [] {});\n}\n"
  },
  {
    "path": "examples/Deployment/batcher.cc",
    "content": "\n\ntemplate<typename Request, typename Response>\nclass BatchingService\n{\n  public:\n    using PrepareFn =\n        std::function<std::unique_ptr<::grpc::ClientAsyncReaderWriter<Request, Response>>(\n            ::grpc::ClientContext*, ::grpc::CompletionQueue*)>;\n    using Callback = std::function<void(bool)>;\n\n    struct MessageType\n    {\n        Request& request;\n        Response& response;\n        Callback callback;\n    };\n\n    class Resources\n    {\n      public:\n        Resources(PrepareFn prepare_fn, std::shared_ptr<client::Executor> executor,\n                  std::shared_ptr<::trtlab::ThreadPool> post_process uint32_t max_batch_size,\n                  uint64_t timeout_in_us)\n            : m_PrepareFn(prepare_fn), m_Executor(executor), m_WaitAndDone(post_process),\n              m_MaxBatchSize(max_batch_size), m_Timeout(timeout_in_us)\n        {\n        }\n\n        std::shared_ptr<ClientStreaming<Request, Response>>\n            CreateClient(std::function<void(Response&&)> on_recv)\n        {\n            auto on_sent = [](Request&& request) {};\n\n            return std::make_shared<client::ClientStreaming<Request, Response>>(\n                m_PrepareFn, m_Executor, on_sent, on_recv);\n        }\n\n        void Enqueue(Request& req, Response& resp, Callback callback)\n        {\n            m_MessageQueue.enqueue(MessageType{req, resp, callback});\n        }\n\n      protected:\n        void BatchingEngine()\n        {\n            constexpr uint64_t quanta = 100;\n            const double timeout = static_cast<double>(m_Timeout - quanta) / 1000000.0;\n            const size_t max_batch_size = m_MaxBatchSize;\n            size_t total_count;\n            size_t max_deque;\n            std::shared_ptr<std::vector<MessageType>> messages;\n            std::chrono::time_point<std::chrono::high_resolution_clock> start;\n            thread_local ConsumerToken token(m_MessageQueue);\n\n            // clang-format off\n            auto elapsed_time =\n                [](std::chrono::time_point<std::chrono::high_resolution_clock>& start) -> double {\n                    return std::chrono::duration<double>(\n                        std::chrono::high_resolution_clock::now() - start).count();\n                };\n            // clang-format on\n\n            for(;;)\n            {\n                MessageType messages[m_MaxBatchsize];\n                max_batch = m_MaxBatchsize;\n                total_count = 0;\n\n                // pull 1 element from the queue and start timer\n                // if dequeue times outs, then restart the loop\n                total_count = m_MessageQueue.wait_dequeue_bulk_timed(\n                    token, &(*messages)[total_count], 1, quanta);\n                max_deque = max_batch_size - total_count;\n\n                if(count == 0)\n                {\n                    continue;\n                }\n\n                // Create a Corked Stream - Corked = buffered writes\n                stream = CreateClient([messages](Response&& response) mutable {\n                    CHECK(!messges.empty());\n                    DLOG(INFO) << \"Finishing Unary Response/Callback: \" << message.size()\n                               << \" remain on queue\";\n                    auto m = messages.front();\n                    m.response = std::move(response);\n                    m.callback();\n                    messages.erase(messages.begin());\n                });\n                stream->Corked(true);\n\n                // Continue to collect inference requests until we reach a maximum batch size\n                // or we hit the timeout.  We will eagerly forward our current batch items along\n                // the stream so the preprocessor can get ahead start\n                start = std::chrono::high_resolution_clock::now();\n                while(total_count < max_batch_size && elapsed(start) <)\n                {\n                    total_count += total_count = m_MessageQueue.wait_dequeue_bulk_timed(\n                        token, &(*messages)[total_count], max_deque, quanta);\n                    max_deque = max_batch_size - total_count;\n\n                    for(; isend < total_count; isend++)\n                    {\n                        auto& m = (*messages)[isend];\n                        stream->Write(m.request));\n                    }\n                }\n\n                // Batching complete\n                if(total_count)\n                {\n                    messages->resize(total_count);\n                    stream->Done();\n                    m_WaitAndFinish.enqueue([stream]() mutable {\n                        auto future = stream->Status();\n                        future.wait();\n                        streawm.reset();\n                    });\n                    messages.reset(new std::vector<MessageType>);\n                    messages->resize(max_batch_size);\n                }\n            }\n        }\n\n      private:\n        PrepareFn m_PrepareFn;\n        std::shared_ptr<client::Executor> m_Executor;\n        std::shared_ptr<::trtlab::ThreadPool> m_WaitAndDelete;\n        size_t m_MaxBatchsize;\n        uint64_t m_Timeout;\n        BlockingConcurrentQueue<MessageType> m_MessageQueue;\n    };\n\n    class BatchingContext : public Context<Request, Response, Resources>\n    {\n        void ExecuteRPC(Request& request, Response& response) final override\n        {\n            LOG(INFO) << \"incoming unary request\";\n            this->GetResources()->Enqueue(&request, &response, [this](bool ok) {\n                if(ok)\n                {\n                    this->FinishResponse();\n                }\n                else\n                {\n                    LOG(ERROR) << \"Upstream Error\";\n                    this->CancelResponse();\n                }\n            });\n        }\n    };\n};\n"
  },
  {
    "path": "examples/ONNX/resnet50/README.md",
    "content": "# TensorRT ResNet50 Example\n\n- `fetch.sh` downloads the onnx model, test data, and calibration images from S3\n  - after running this script the `resnet50` and `calibration_images` directories should be present in your\n    local path\n\n- Build (`build.py`) TensorRT engines from the `model.onnx` file\n  - cli options:\n    - `--batch` will select the batch size, multiple can be given, a separate\n      engine for each batch size will be generated.\n    - `--precision` can be `fp32`, `fp16`, or `int8`.  if multiple precision are given, an\n      engine for each will be created.  \n    - **Note**: To use `int8` precision, you will need a Turing, Volta, or Pascal GPU with compute capability 6.1.\n  - If you have a Turing or Volta GPU, then run the following commmand which will generates 4 engines:\n    ```\n    ./build.py --batch=1 --batch=8 --precision=fp16 --precision=int8 resnet50/model.onnx\n    ```\n  - If you have a Pascal GPU, run the following which generates 2 engines:\n    ```\n    ./build.py --batch=1 --batch=8 --precision=fp32 resnet50/model.onnx\n    ```\n- Functional Test\n  - `./run_onnx_tests.py model-b1-fp16.engine` will run the onnx tests \n\n- Benchmark TensorRT engines at different batch sizes and concurrent executions:\n  - `/work/build/examples/00_TensorRT/infer.x --engine=model-b1-fp16.engine --contexts=1`\n  - `/work/build/examples/00_TensorRT/infer.x --engine=model-b1-fp16.engine --contexts=8`\n  - `/work/build/examples/00_TensorRT/infer.x --engine=model-b8-fp16.engine --contexts=1`\n  - `/work/build/examples/00_TensorRT/infer.x --engine=model-b8-fp16.engine --contexts=6`\n\n- `./run_jpeg_test.py --image=images/broccoli-3784.jpg model-b1-fp16.engine`\n  - Note this example requires MxNet for image preprocessing: `pip install mxnet`\n  - On a V100 using FP16, your results should be close to\n  ```\n  *** Results ***\n  broccoli 0.9511453\n  ```\n- `./run_jpeg_test.py --image=images/broccoli-3784.jpg model-b1-int8.engine`\n  - When using INT8, your results should be close to\n  ```\n  *** Results ***\n  broccoli 0.9228073\n  ```\n\n## Credits\n\n - [broccoli image](https://www.openfotos.com/view/broccoli-3784) - OpenFotos\n   - https://www.openfotos.com/pages/open-fotos-license\n - [calibration images](calibration_images.csv) - Images from OpenFotos and Pixabay\n   - https://www.openfotos.com/pages/open-fotos-license\n   - https://pixabay.com/service/license/ \n\n## TODOs\n\n - [ ] Update `run_jpeg_test.py` to highlight the async interface.\n"
  },
  {
    "path": "examples/ONNX/resnet50/build.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nimport os\nimport subprocess\n\nimport click\nimport int8\n\nprecision_opts = {\n  \"fp32\": \"\",\n  \"fp16\": \"--fp16\",\n  \"int8\": \"--fp16 --int8\",\n}\n\nFile = click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)\n\n@click.command()\n@click.option(\"--batch\", type=click.IntRange(min=1, max=32), multiple=True)\n@click.option(\"--precision\", type=click.Choice([\"fp32\", \"fp16\", \"int8\"]), multiple=True)\n@click.argument(\"models\", type=File, nargs=-1)\ndef main(models, batch, precision):\n    for model in models:\n        #click.echo(model)\n        #click.echo(precision)\n        for p in precision:\n            #click.echo(p)\n            for b in batch:\n                #click.echo(b)\n                n = \"b{}-{}\".format(b, p)\n                m = os.path.basename(model)\n                m, ext = os.path.splitext(m)\n                e = \"{}-{}.{}\".format(m,n,\"engine\")\n\n                if os.path.isfile(e):\n                    print(\"A TensorRT engine {} already exists! Skipping...\".format(e))\n                    continue\n                elif p == \"int8\":\n                    assert os.path.isdir(\"./calibration_images\"), \"Need to download calibration images before creating INT8 engine!\"\n                    int8.build_int8_engine_onnx(model, \"./calibration_images\", b, 32, e)\n                else:\n                    subprocess.call(\"trtexec --onnx={} --batch={} {} --saveEngine={}\".format(model, b, precision_opts.get(p), e), shell=True)\n\nif __name__ == \"__main__\":\n    main()\n\n"
  },
  {
    "path": "examples/ONNX/resnet50/calibration_images.csv",
    "content": "url,license,label\nhttps://www.openfotos.com/pictures/red-rock-crab-1096.full.jpg,Open Fotos License,crab\nhttps://www.openfotos.com/pictures/lazy-cats-4109.full.jpg,Open Fotos License,cat\nhttps://www.openfotos.com/pictures/beautiful-elephants-4005.full.jpg,Open Fotos License,elephants\nhttps://www.openfotos.com/pictures/funny-wild-pigs-437.full.jpg,Open Fotos License,pig\nhttps://www.openfotos.com/pictures/hopping-5017.full.jpg,Open Fotos License,bird\nhttps://www.openfotos.com/pictures/old-car-4811.full.jpg,Open Fotos License,car\nhttps://www.openfotos.com/pictures/audi-4740.full.jpg,Open Fotos License,car\nhttps://www.openfotos.com/pictures/boarding-in-the-plane-4891.full.jpg,Open Fotos License,plane\nhttps://cdn.pixabay.com/photo/2016/03/09/09/28/bear-1245807_960_720.jpg,Pixabay License,bear\nhttps://cdn.pixabay.com/photo/2015/02/26/06/09/panda-649938_960_720.jpg,Pixabay License,giant panda\nhttps://cdn.pixabay.com/photo/2015/09/22/19/00/ship-952292_960_720.jpg,Pixabay License,boat\nhttps://cdn.pixabay.com/photo/2017/01/16/19/17/horses-1984977_960_720.jpg,Pixabay License,horse\nhttps://cdn.pixabay.com/photo/2015/03/26/09/54/pug-690566_960_720.jpg,Pixabay License,dog\nhttps://cdn.pixabay.com/photo/2016/08/19/15/23/lizard-1605515_960_720.jpg,Pixabay License,lizzard\nhttps://cdn.pixabay.com/photo/2016/07/09/12/16/apple-1506119_960_720.jpg,Pixabay License,apple\nhttps://cdn.pixabay.com/photo/2016/10/07/14/11/tangerines-1721633_960_720.jpg,Pixabay License,orange\nhttps://cdn.pixabay.com/photo/2015/06/19/16/48/watermelon-815072_960_720.jpg,Pixabay License,watermelon\nhttps://cdn.pixabay.com/photo/2017/06/09/16/39/carrots-2387394_960_720.jpg,Pixabay License,carrot\nhttps://cdn.pixabay.com/photo/2019/02/28/22/45/hippo-4027011_960_720.jpg,Pixabay License,hippo\nhttps://cdn.pixabay.com/photo/2012/03/04/00/09/africa-21787_960_720.jpg,Pixabay License,lion\nhttps://cdn.pixabay.com/photo/2015/07/27/19/47/turtle-863336_960_720.jpg,Pixabay License,turtle\nhttps://cdn.pixabay.com/photo/2018/04/15/17/45/fish-3322230_960_720.jpg,Pixabay License,fish\nhttps://cdn.pixabay.com/photo/2013/11/01/11/13/dolphin-203875_960_720.jpg,Pixabay License,dolphin\nhttps://cdn.pixabay.com/photo/2014/05/02/21/49/home-office-336373_960_720.jpg,Pixabay License,laptop\nhttps://cdn.pixabay.com/photo/2012/05/18/21/45/tiger-mosquito-49141_960_720.jpg,Pixabay License,mosquito\nhttps://cdn.pixabay.com/photo/2016/08/09/13/21/coffee-1580595_960_720.jpg,Pixabay License,cup\nhttps://cdn.pixabay.com/photo/2016/02/19/10/36/lemons-1209309_960_720.jpg,Pixabay License,lemon\nhttps://cdn.pixabay.com/photo/2018/12/14/02/41/chengdu-3874136_960_720.jpg,Pixabay License,hotpot\nhttps://cdn.pixabay.com/photo/2015/09/05/12/53/violin-924349_960_720.jpg,Pixabay License,violin\nhttps://cdn.pixabay.com/photo/2015/11/07/11/22/pillows-1031079_960_720.jpg,Pixabay License,pillow\nhttps://cdn.pixabay.com/photo/2016/11/18/22/26/animal-1837164_960_720.jpg,Pixabay License,rhino\nhttps://cdn.pixabay.com/photo/2016/12/04/21/58/rabbit-1882699_960_720.jpg,Pixabay License,rabbit\nhttps://cdn.pixabay.com/photo/2014/10/23/18/56/tiger-500118_960_720.jpg,Pixabay License,tiger\n"
  },
  {
    "path": "examples/ONNX/resnet50/calibrator.py",
    "content": "#\n# Copyright 1993-2019 NVIDIA Corporation.  All rights reserved.\n#\n# NOTICE TO LICENSEE:\n#\n# This source code and/or documentation (\"Licensed Deliverables\") are\n# subject to NVIDIA intellectual property rights under U.S. and\n# international Copyright laws.\n#\n# These Licensed Deliverables contained herein is PROPRIETARY and\n# CONFIDENTIAL to NVIDIA and is being provided under the terms and\n# conditions of a form of NVIDIA software license agreement by and\n# between NVIDIA and Licensee (\"License Agreement\") or electronically\n# accepted by Licensee.  Notwithstanding any terms or conditions to\n# the contrary in the License Agreement, reproduction or disclosure\n# of the Licensed Deliverables to any third party without the express\n# written consent of NVIDIA is prohibited.\n#\n# NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE\n# LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE\n# SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE.  IT IS\n# PROVIDED \"AS IS\" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.\n# NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED\n# DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,\n# NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.\n# NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE\n# LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY\n# SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY\n# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\n# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\n# OF THESE LICENSED DELIVERABLES.\n#\n# U.S. Government End Users.  These Licensed Deliverables are a\n# \"commercial item\" as that term is defined at 48 C.F.R. 2.101 (OCT\n# 1995), consisting of \"commercial computer software\" and \"commercial\n# computer software documentation\" as such terms are used in 48\n# C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government\n# only as a commercial end item.  Consistent with 48 C.F.R.12.212 and\n# 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all\n# U.S. Government End Users acquire the Licensed Deliverables with\n# only those rights set forth herein.\n#\n# Any use of the Licensed Deliverables in individual and commercial\n# software must include, in the user documentation and internal\n# comments to the code, the above Disclaimer and U.S. Government End\n# Users Notice.\n\nimport tensorrt as trt\nimport os\n\nimport pycuda.driver as cuda\nimport pycuda.autoinit\nimport matplotlib.pyplot as plt\n\nimport mxnet as mx\nfrom mxnet.gluon.data.vision import transforms\nimport numpy as np\nfrom random import shuffle\n\nclass ONNXEntropyCalibrator(trt.IInt8EntropyCalibrator):\n    def __init__(self, image_dir, batch_size, calibration_batches, cache_file):\n        # Whenever you specify a custom constructor for a TensorRT class,\n        # you MUST call the constructor of the parent explicitly.\n        trt.IInt8EntropyCalibrator.__init__(self)\n\n        self.cache_file = cache_file\n\n        # Get a list of all the images in the image directory.\n        image_files = [os.path.join(image_dir, f) for f in os.listdir(image_dir)]\n        shuffle(image_files)\n\n        if len(image_files) < calibration_batches * batch_size:\n            print(\"Only found enough images for {} batches instead of {}, continuing anyway...\".format(len(image_files) // batch_size, calibration_batches))\n            self.image_files = image_files\n        else:\n            self.image_files = image_files[:calibration_batches * batch_size]\n\n        # Keeps track of current image in image list\n        self.current_image = 0\n        self.batch_size = batch_size\n        self.input_size = [3,224,224]\n\n        # Each element of the calibration data is a float32.\n        self.device_input = cuda.mem_alloc(self.batch_size * self.input_size[0] * self.input_size[1] * self.input_size[2]  * trt.float32.itemsize)\n\n        # Create a generator that will give us batches. We can use next() to iterate over the result.\n        def load_batches():\n            while self.current_image < len(self.image_files):\n                data, images_read = self.read_image_batch()\n                self.current_image += images_read\n                yield data\n        self.batches = load_batches()\n\n\n    def transform_image(self, img):\n        transform_fn = transforms.Compose([\n            transforms.Resize(224),\n            transforms.CenterCrop(224),\n            transforms.ToTensor(),\n            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n        ])\n        img = transform_fn(mx.nd.array(img)).asnumpy()\n        return img\n\n\n    # This function is used to load calibration images into batches.\n    def read_image_batch(self):\n        # Depending on batch size and number of images, the final batch might only be partially full.\n        images_to_read = min(self.batch_size, len(self.image_files) - self.current_image)\n\n        host_buffer = np.zeros(shape=[self.batch_size]+self.input_size)\n        for i in range(images_to_read):\n            img = np.array(plt.imread(self.image_files[self.current_image]))\n            img = self.transform_image(img)\n            host_buffer[i,:,:,:] = img\n\n        return host_buffer, images_to_read\n\n    def get_batch_size(self):\n        return self.batch_size\n\n    # TensorRT passes along the names of the engine bindings to the get_batch function.\n    # You don't necessarily have to use them, but they can be useful to understand the order of\n    # the inputs. The bindings list is expected to have the same ordering as 'names'.\n    def get_batch(self, names):\n        try:\n            # Get a single batch.\n            data = np.ascontiguousarray(next(self.batches), np.float32)\n            # Copy to device, then return a list containing pointers to input device buffers.\n            cuda.memcpy_htod(self.device_input, data)\n            return [int(self.device_input)]\n        except StopIteration:\n            # When we're out of batches, we return either [] or None.\n            # This signals to TensorRT that there is no calibration data remaining.\n            return None\n\n    def read_calibration_cache(self):\n        # If there is a cache, use it instead of calibrating again. Otherwise, implicitly return None.\n        if os.path.exists(self.cache_file):\n            with open(self.cache_file, \"rb\") as f:\n                return f.read()\n\n    def write_calibration_cache(self, cache):\n        with open(self.cache_file, \"wb\") as f:\n            f.write(cache)\n"
  },
  {
    "path": "examples/ONNX/resnet50/fetch.sh",
    "content": "#!/bin/bash\n\nif [ ! -e \"resnet50.tar.gz\" ]; then\n  wget https://s3.amazonaws.com/download.onnx/models/opset_8/resnet50.tar.gz\nfi\n\nif [ ! -e \"open_source_images.tar.gz\" ]; then\n  wget https://s3-us-west-2.amazonaws.com/com.nvidia.tensorrt-laboratory/open_source_images.tar.gz\nfi\n\nif md5sum -c resnet50.md5; then\n  if [ ! -e \"resnet50\" ]; then\n    tar xzf resnet50.tar.gz\n  fi\n  echo \"ResNet50 download good\"\nelse\n  echo \"ResNet50 md5 checksum failed\"\n  exit 911\nfi\n\nif md5sum -c open_source_images.md5; then\n  if [ ! -e \"calibration_images\" ]; then\n    tar xf open_source_images.tar.gz\n  fi\n  echo \"All good - Continue to Build Phase\"\nelse\n  echo \"calibration_images md5 checksum failed\"\n  exit 911\nfi\n"
  },
  {
    "path": "examples/ONNX/resnet50/imagenet_labels.py",
    "content": "\nlabels = {0: 'tench, Tinca tinca',\n 1: 'goldfish, Carassius auratus',\n 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias',\n 3: 'tiger shark, Galeocerdo cuvieri',\n 4: 'hammerhead, hammerhead shark',\n 5: 'electric ray, crampfish, numbfish, torpedo',\n 6: 'stingray',\n 7: 'cock',\n 8: 'hen',\n 9: 'ostrich, Struthio camelus',\n 10: 'brambling, Fringilla montifringilla',\n 11: 'goldfinch, Carduelis carduelis',\n 12: 'house finch, linnet, Carpodacus mexicanus',\n 13: 'junco, snowbird',\n 14: 'indigo bunting, indigo finch, indigo bird, Passerina cyanea',\n 15: 'robin, American robin, Turdus migratorius',\n 16: 'bulbul',\n 17: 'jay',\n 18: 'magpie',\n 19: 'chickadee',\n 20: 'water ouzel, dipper',\n 21: 'kite',\n 22: 'bald eagle, American eagle, Haliaeetus leucocephalus',\n 23: 'vulture',\n 24: 'great grey owl, great gray owl, Strix nebulosa',\n 25: 'European fire salamander, Salamandra salamandra',\n 26: 'common newt, Triturus vulgaris',\n 27: 'eft',\n 28: 'spotted salamander, Ambystoma maculatum',\n 29: 'axolotl, mud puppy, Ambystoma mexicanum',\n 30: 'bullfrog, Rana catesbeiana',\n 31: 'tree frog, tree-frog',\n 32: 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui',\n 33: 'loggerhead, loggerhead turtle, Caretta caretta',\n 34: 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea',\n 35: 'mud turtle',\n 36: 'terrapin',\n 37: 'box turtle, box tortoise',\n 38: 'banded gecko',\n 39: 'common iguana, iguana, Iguana iguana',\n 40: 'American chameleon, anole, Anolis carolinensis',\n 41: 'whiptail, whiptail lizard',\n 42: 'agama',\n 43: 'frilled lizard, Chlamydosaurus kingi',\n 44: 'alligator lizard',\n 45: 'Gila monster, Heloderma suspectum',\n 46: 'green lizard, Lacerta viridis',\n 47: 'African chameleon, Chamaeleo chamaeleon',\n 48: 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis',\n 49: 'African crocodile, Nile crocodile, Crocodylus niloticus',\n 50: 'American alligator, Alligator mississipiensis',\n 51: 'triceratops',\n 52: 'thunder snake, worm snake, Carphophis amoenus',\n 53: 'ringneck snake, ring-necked snake, ring snake',\n 54: 'hognose snake, puff adder, sand viper',\n 55: 'green snake, grass snake',\n 56: 'king snake, kingsnake',\n 57: 'garter snake, grass snake',\n 58: 'water snake',\n 59: 'vine snake',\n 60: 'night snake, Hypsiglena torquata',\n 61: 'boa constrictor, Constrictor constrictor',\n 62: 'rock python, rock snake, Python sebae',\n 63: 'Indian cobra, Naja naja',\n 64: 'green mamba',\n 65: 'sea snake',\n 66: 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus',\n 67: 'diamondback, diamondback rattlesnake, Crotalus adamanteus',\n 68: 'sidewinder, horned rattlesnake, Crotalus cerastes',\n 69: 'trilobite',\n 70: 'harvestman, daddy longlegs, Phalangium opilio',\n 71: 'scorpion',\n 72: 'black and gold garden spider, Argiope aurantia',\n 73: 'barn spider, Araneus cavaticus',\n 74: 'garden spider, Aranea diademata',\n 75: 'black widow, Latrodectus mactans',\n 76: 'tarantula',\n 77: 'wolf spider, hunting spider',\n 78: 'tick',\n 79: 'centipede',\n 80: 'black grouse',\n 81: 'ptarmigan',\n 82: 'ruffed grouse, partridge, Bonasa umbellus',\n 83: 'prairie chicken, prairie grouse, prairie fowl',\n 84: 'peacock',\n 85: 'quail',\n 86: 'partridge',\n 87: 'African grey, African gray, Psittacus erithacus',\n 88: 'macaw',\n 89: 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita',\n 90: 'lorikeet',\n 91: 'coucal',\n 92: 'bee eater',\n 93: 'hornbill',\n 94: 'hummingbird',\n 95: 'jacamar',\n 96: 'toucan',\n 97: 'drake',\n 98: 'red-breasted merganser, Mergus serrator',\n 99: 'goose',\n 100: 'black swan, Cygnus atratus',\n 101: 'tusker',\n 102: 'echidna, spiny anteater, anteater',\n 103: 'platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus',\n 104: 'wallaby, brush kangaroo',\n 105: 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus',\n 106: 'wombat',\n 107: 'jellyfish',\n 108: 'sea anemone, anemone',\n 109: 'brain coral',\n 110: 'flatworm, platyhelminth',\n 111: 'nematode, nematode worm, roundworm',\n 112: 'conch',\n 113: 'snail',\n 114: 'slug',\n 115: 'sea slug, nudibranch',\n 116: 'chiton, coat-of-mail shell, sea cradle, polyplacophore',\n 117: 'chambered nautilus, pearly nautilus, nautilus',\n 118: 'Dungeness crab, Cancer magister',\n 119: 'rock crab, Cancer irroratus',\n 120: 'fiddler crab',\n 121: 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica',\n 122: 'American lobster, Northern lobster, Maine lobster, Homarus americanus',\n 123: 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish',\n 124: 'crayfish, crawfish, crawdad, crawdaddy',\n 125: 'hermit crab',\n 126: 'isopod',\n 127: 'white stork, Ciconia ciconia',\n 128: 'black stork, Ciconia nigra',\n 129: 'spoonbill',\n 130: 'flamingo',\n 131: 'little blue heron, Egretta caerulea',\n 132: 'American egret, great white heron, Egretta albus',\n 133: 'bittern',\n 134: 'crane',\n 135: 'limpkin, Aramus pictus',\n 136: 'European gallinule, Porphyrio porphyrio',\n 137: 'American coot, marsh hen, mud hen, water hen, Fulica americana',\n 138: 'bustard',\n 139: 'ruddy turnstone, Arenaria interpres',\n 140: 'red-backed sandpiper, dunlin, Erolia alpina',\n 141: 'redshank, Tringa totanus',\n 142: 'dowitcher',\n 143: 'oystercatcher, oyster catcher',\n 144: 'pelican',\n 145: 'king penguin, Aptenodytes patagonica',\n 146: 'albatross, mollymawk',\n 147: 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus',\n 148: 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca',\n 149: 'dugong, Dugong dugon',\n 150: 'sea lion',\n 151: 'Chihuahua',\n 152: 'Japanese spaniel',\n 153: 'Maltese dog, Maltese terrier, Maltese',\n 154: 'Pekinese, Pekingese, Peke',\n 155: 'Shih-Tzu',\n 156: 'Blenheim spaniel',\n 157: 'papillon',\n 158: 'toy terrier',\n 159: 'Rhodesian ridgeback',\n 160: 'Afghan hound, Afghan',\n 161: 'basset, basset hound',\n 162: 'beagle',\n 163: 'bloodhound, sleuthhound',\n 164: 'bluetick',\n 165: 'black-and-tan coonhound',\n 166: 'Walker hound, Walker foxhound',\n 167: 'English foxhound',\n 168: 'redbone',\n 169: 'borzoi, Russian wolfhound',\n 170: 'Irish wolfhound',\n 171: 'Italian greyhound',\n 172: 'whippet',\n 173: 'Ibizan hound, Ibizan Podenco',\n 174: 'Norwegian elkhound, elkhound',\n 175: 'otterhound, otter hound',\n 176: 'Saluki, gazelle hound',\n 177: 'Scottish deerhound, deerhound',\n 178: 'Weimaraner',\n 179: 'Staffordshire bullterrier, Staffordshire bull terrier',\n 180: 'American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier',\n 181: 'Bedlington terrier',\n 182: 'Border terrier',\n 183: 'Kerry blue terrier',\n 184: 'Irish terrier',\n 185: 'Norfolk terrier',\n 186: 'Norwich terrier',\n 187: 'Yorkshire terrier',\n 188: 'wire-haired fox terrier',\n 189: 'Lakeland terrier',\n 190: 'Sealyham terrier, Sealyham',\n 191: 'Airedale, Airedale terrier',\n 192: 'cairn, cairn terrier',\n 193: 'Australian terrier',\n 194: 'Dandie Dinmont, Dandie Dinmont terrier',\n 195: 'Boston bull, Boston terrier',\n 196: 'miniature schnauzer',\n 197: 'giant schnauzer',\n 198: 'standard schnauzer',\n 199: 'Scotch terrier, Scottish terrier, Scottie',\n 200: 'Tibetan terrier, chrysanthemum dog',\n 201: 'silky terrier, Sydney silky',\n 202: 'soft-coated wheaten terrier',\n 203: 'West Highland white terrier',\n 204: 'Lhasa, Lhasa apso',\n 205: 'flat-coated retriever',\n 206: 'curly-coated retriever',\n 207: 'golden retriever',\n 208: 'Labrador retriever',\n 209: 'Chesapeake Bay retriever',\n 210: 'German short-haired pointer',\n 211: 'vizsla, Hungarian pointer',\n 212: 'English setter',\n 213: 'Irish setter, red setter',\n 214: 'Gordon setter',\n 215: 'Brittany spaniel',\n 216: 'clumber, clumber spaniel',\n 217: 'English springer, English springer spaniel',\n 218: 'Welsh springer spaniel',\n 219: 'cocker spaniel, English cocker spaniel, cocker',\n 220: 'Sussex spaniel',\n 221: 'Irish water spaniel',\n 222: 'kuvasz',\n 223: 'schipperke',\n 224: 'groenendael',\n 225: 'malinois',\n 226: 'briard',\n 227: 'kelpie',\n 228: 'komondor',\n 229: 'Old English sheepdog, bobtail',\n 230: 'Shetland sheepdog, Shetland sheep dog, Shetland',\n 231: 'collie',\n 232: 'Border collie',\n 233: 'Bouvier des Flandres, Bouviers des Flandres',\n 234: 'Rottweiler',\n 235: 'German shepherd, German shepherd dog, German police dog, alsatian',\n 236: 'Doberman, Doberman pinscher',\n 237: 'miniature pinscher',\n 238: 'Greater Swiss Mountain dog',\n 239: 'Bernese mountain dog',\n 240: 'Appenzeller',\n 241: 'EntleBucher',\n 242: 'boxer',\n 243: 'bull mastiff',\n 244: 'Tibetan mastiff',\n 245: 'French bulldog',\n 246: 'Great Dane',\n 247: 'Saint Bernard, St Bernard',\n 248: 'Eskimo dog, husky',\n 249: 'malamute, malemute, Alaskan malamute',\n 250: 'Siberian husky',\n 251: 'dalmatian, coach dog, carriage dog',\n 252: 'affenpinscher, monkey pinscher, monkey dog',\n 253: 'basenji',\n 254: 'pug, pug-dog',\n 255: 'Leonberg',\n 256: 'Newfoundland, Newfoundland dog',\n 257: 'Great Pyrenees',\n 258: 'Samoyed, Samoyede',\n 259: 'Pomeranian',\n 260: 'chow, chow chow',\n 261: 'keeshond',\n 262: 'Brabancon griffon',\n 263: 'Pembroke, Pembroke Welsh corgi',\n 264: 'Cardigan, Cardigan Welsh corgi',\n 265: 'toy poodle',\n 266: 'miniature poodle',\n 267: 'standard poodle',\n 268: 'Mexican hairless',\n 269: 'timber wolf, grey wolf, gray wolf, Canis lupus',\n 270: 'white wolf, Arctic wolf, Canis lupus tundrarum',\n 271: 'red wolf, maned wolf, Canis rufus, Canis niger',\n 272: 'coyote, prairie wolf, brush wolf, Canis latrans',\n 273: 'dingo, warrigal, warragal, Canis dingo',\n 274: 'dhole, Cuon alpinus',\n 275: 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus',\n 276: 'hyena, hyaena',\n 277: 'red fox, Vulpes vulpes',\n 278: 'kit fox, Vulpes macrotis',\n 279: 'Arctic fox, white fox, Alopex lagopus',\n 280: 'grey fox, gray fox, Urocyon cinereoargenteus',\n 281: 'tabby, tabby cat',\n 282: 'tiger cat',\n 283: 'Persian cat',\n 284: 'Siamese cat, Siamese',\n 285: 'Egyptian cat',\n 286: 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor',\n 287: 'lynx, catamount',\n 288: 'leopard, Panthera pardus',\n 289: 'snow leopard, ounce, Panthera uncia',\n 290: 'jaguar, panther, Panthera onca, Felis onca',\n 291: 'lion, king of beasts, Panthera leo',\n 292: 'tiger, Panthera tigris',\n 293: 'cheetah, chetah, Acinonyx jubatus',\n 294: 'brown bear, bruin, Ursus arctos',\n 295: 'American black bear, black bear, Ursus americanus, Euarctos americanus',\n 296: 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus',\n 297: 'sloth bear, Melursus ursinus, Ursus ursinus',\n 298: 'mongoose',\n 299: 'meerkat, mierkat',\n 300: 'tiger beetle',\n 301: 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle',\n 302: 'ground beetle, carabid beetle',\n 303: 'long-horned beetle, longicorn, longicorn beetle',\n 304: 'leaf beetle, chrysomelid',\n 305: 'dung beetle',\n 306: 'rhinoceros beetle',\n 307: 'weevil',\n 308: 'fly',\n 309: 'bee',\n 310: 'ant, emmet, pismire',\n 311: 'grasshopper, hopper',\n 312: 'cricket',\n 313: 'walking stick, walkingstick, stick insect',\n 314: 'cockroach, roach',\n 315: 'mantis, mantid',\n 316: 'cicada, cicala',\n 317: 'leafhopper',\n 318: 'lacewing, lacewing fly',\n 319: \"dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk\",\n 320: 'damselfly',\n 321: 'admiral',\n 322: 'ringlet, ringlet butterfly',\n 323: 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus',\n 324: 'cabbage butterfly',\n 325: 'sulphur butterfly, sulfur butterfly',\n 326: 'lycaenid, lycaenid butterfly',\n 327: 'starfish, sea star',\n 328: 'sea urchin',\n 329: 'sea cucumber, holothurian',\n 330: 'wood rabbit, cottontail, cottontail rabbit',\n 331: 'hare',\n 332: 'Angora, Angora rabbit',\n 333: 'hamster',\n 334: 'porcupine, hedgehog',\n 335: 'fox squirrel, eastern fox squirrel, Sciurus niger',\n 336: 'marmot',\n 337: 'beaver',\n 338: 'guinea pig, Cavia cobaya',\n 339: 'sorrel',\n 340: 'zebra',\n 341: 'hog, pig, grunter, squealer, Sus scrofa',\n 342: 'wild boar, boar, Sus scrofa',\n 343: 'warthog',\n 344: 'hippopotamus, hippo, river horse, Hippopotamus amphibius',\n 345: 'ox',\n 346: 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis',\n 347: 'bison',\n 348: 'ram, tup',\n 349: 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis',\n 350: 'ibex, Capra ibex',\n 351: 'hartebeest',\n 352: 'impala, Aepyceros melampus',\n 353: 'gazelle',\n 354: 'Arabian camel, dromedary, Camelus dromedarius',\n 355: 'llama',\n 356: 'weasel',\n 357: 'mink',\n 358: 'polecat, fitch, foulmart, foumart, Mustela putorius',\n 359: 'black-footed ferret, ferret, Mustela nigripes',\n 360: 'otter',\n 361: 'skunk, polecat, wood pussy',\n 362: 'badger',\n 363: 'armadillo',\n 364: 'three-toed sloth, ai, Bradypus tridactylus',\n 365: 'orangutan, orang, orangutang, Pongo pygmaeus',\n 366: 'gorilla, Gorilla gorilla',\n 367: 'chimpanzee, chimp, Pan troglodytes',\n 368: 'gibbon, Hylobates lar',\n 369: 'siamang, Hylobates syndactylus, Symphalangus syndactylus',\n 370: 'guenon, guenon monkey',\n 371: 'patas, hussar monkey, Erythrocebus patas',\n 372: 'baboon',\n 373: 'macaque',\n 374: 'langur',\n 375: 'colobus, colobus monkey',\n 376: 'proboscis monkey, Nasalis larvatus',\n 377: 'marmoset',\n 378: 'capuchin, ringtail, Cebus capucinus',\n 379: 'howler monkey, howler',\n 380: 'titi, titi monkey',\n 381: 'spider monkey, Ateles geoffroyi',\n 382: 'squirrel monkey, Saimiri sciureus',\n 383: 'Madagascar cat, ring-tailed lemur, Lemur catta',\n 384: 'indri, indris, Indri indri, Indri brevicaudatus',\n 385: 'Indian elephant, Elephas maximus',\n 386: 'African elephant, Loxodonta africana',\n 387: 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens',\n 388: 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca',\n 389: 'barracouta, snoek',\n 390: 'eel',\n 391: 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch',\n 392: 'rock beauty, Holocanthus tricolor',\n 393: 'anemone fish',\n 394: 'sturgeon',\n 395: 'gar, garfish, garpike, billfish, Lepisosteus osseus',\n 396: 'lionfish',\n 397: 'puffer, pufferfish, blowfish, globefish',\n 398: 'abacus',\n 399: 'abaya',\n 400: \"academic gown, academic robe, judge's robe\",\n 401: 'accordion, piano accordion, squeeze box',\n 402: 'acoustic guitar',\n 403: 'aircraft carrier, carrier, flattop, attack aircraft carrier',\n 404: 'airliner',\n 405: 'airship, dirigible',\n 406: 'altar',\n 407: 'ambulance',\n 408: 'amphibian, amphibious vehicle',\n 409: 'analog clock',\n 410: 'apiary, bee house',\n 411: 'apron',\n 412: 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin',\n 413: 'assault rifle, assault gun',\n 414: 'backpack, back pack, knapsack, packsack, rucksack, haversack',\n 415: 'bakery, bakeshop, bakehouse',\n 416: 'balance beam, beam',\n 417: 'balloon',\n 418: 'ballpoint, ballpoint pen, ballpen, Biro',\n 419: 'Band Aid',\n 420: 'banjo',\n 421: 'bannister, banister, balustrade, balusters, handrail',\n 422: 'barbell',\n 423: 'barber chair',\n 424: 'barbershop',\n 425: 'barn',\n 426: 'barometer',\n 427: 'barrel, cask',\n 428: 'barrow, garden cart, lawn cart, wheelbarrow',\n 429: 'baseball',\n 430: 'basketball',\n 431: 'bassinet',\n 432: 'bassoon',\n 433: 'bathing cap, swimming cap',\n 434: 'bath towel',\n 435: 'bathtub, bathing tub, bath, tub',\n 436: 'beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon',\n 437: 'beacon, lighthouse, beacon light, pharos',\n 438: 'beaker',\n 439: 'bearskin, busby, shako',\n 440: 'beer bottle',\n 441: 'beer glass',\n 442: 'bell cote, bell cot',\n 443: 'bib',\n 444: 'bicycle-built-for-two, tandem bicycle, tandem',\n 445: 'bikini, two-piece',\n 446: 'binder, ring-binder',\n 447: 'binoculars, field glasses, opera glasses',\n 448: 'birdhouse',\n 449: 'boathouse',\n 450: 'bobsled, bobsleigh, bob',\n 451: 'bolo tie, bolo, bola tie, bola',\n 452: 'bonnet, poke bonnet',\n 453: 'bookcase',\n 454: 'bookshop, bookstore, bookstall',\n 455: 'bottlecap',\n 456: 'bow',\n 457: 'bow tie, bow-tie, bowtie',\n 458: 'brass, memorial tablet, plaque',\n 459: 'brassiere, bra, bandeau',\n 460: 'breakwater, groin, groyne, mole, bulwark, seawall, jetty',\n 461: 'breastplate, aegis, egis',\n 462: 'broom',\n 463: 'bucket, pail',\n 464: 'buckle',\n 465: 'bulletproof vest',\n 466: 'bullet train, bullet',\n 467: 'butcher shop, meat market',\n 468: 'cab, hack, taxi, taxicab',\n 469: 'caldron, cauldron',\n 470: 'candle, taper, wax light',\n 471: 'cannon',\n 472: 'canoe',\n 473: 'can opener, tin opener',\n 474: 'cardigan',\n 475: 'car mirror',\n 476: 'carousel, carrousel, merry-go-round, roundabout, whirligig',\n 477: \"carpenter's kit, tool kit\",\n 478: 'carton',\n 479: 'car wheel',\n 480: 'cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM',\n 481: 'cassette',\n 482: 'cassette player',\n 483: 'castle',\n 484: 'catamaran',\n 485: 'CD player',\n 486: 'cello, violoncello',\n 487: 'cellular telephone, cellular phone, cellphone, cell, mobile phone',\n 488: 'chain',\n 489: 'chainlink fence',\n 490: 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour',\n 491: 'chain saw, chainsaw',\n 492: 'chest',\n 493: 'chiffonier, commode',\n 494: 'chime, bell, gong',\n 495: 'china cabinet, china closet',\n 496: 'Christmas stocking',\n 497: 'church, church building',\n 498: 'cinema, movie theater, movie theatre, movie house, picture palace',\n 499: 'cleaver, meat cleaver, chopper',\n 500: 'cliff dwelling',\n 501: 'cloak',\n 502: 'clog, geta, patten, sabot',\n 503: 'cocktail shaker',\n 504: 'coffee mug',\n 505: 'coffeepot',\n 506: 'coil, spiral, volute, whorl, helix',\n 507: 'combination lock',\n 508: 'computer keyboard, keypad',\n 509: 'confectionery, confectionary, candy store',\n 510: 'container ship, containership, container vessel',\n 511: 'convertible',\n 512: 'corkscrew, bottle screw',\n 513: 'cornet, horn, trumpet, trump',\n 514: 'cowboy boot',\n 515: 'cowboy hat, ten-gallon hat',\n 516: 'cradle',\n 517: 'crane',\n 518: 'crash helmet',\n 519: 'crate',\n 520: 'crib, cot',\n 521: 'Crock Pot',\n 522: 'croquet ball',\n 523: 'crutch',\n 524: 'cuirass',\n 525: 'dam, dike, dyke',\n 526: 'desk',\n 527: 'desktop computer',\n 528: 'dial telephone, dial phone',\n 529: 'diaper, nappy, napkin',\n 530: 'digital clock',\n 531: 'digital watch',\n 532: 'dining table, board',\n 533: 'dishrag, dishcloth',\n 534: 'dishwasher, dish washer, dishwashing machine',\n 535: 'disk brake, disc brake',\n 536: 'dock, dockage, docking facility',\n 537: 'dogsled, dog sled, dog sleigh',\n 538: 'dome',\n 539: 'doormat, welcome mat',\n 540: 'drilling platform, offshore rig',\n 541: 'drum, membranophone, tympan',\n 542: 'drumstick',\n 543: 'dumbbell',\n 544: 'Dutch oven',\n 545: 'electric fan, blower',\n 546: 'electric guitar',\n 547: 'electric locomotive',\n 548: 'entertainment center',\n 549: 'envelope',\n 550: 'espresso maker',\n 551: 'face powder',\n 552: 'feather boa, boa',\n 553: 'file, file cabinet, filing cabinet',\n 554: 'fireboat',\n 555: 'fire engine, fire truck',\n 556: 'fire screen, fireguard',\n 557: 'flagpole, flagstaff',\n 558: 'flute, transverse flute',\n 559: 'folding chair',\n 560: 'football helmet',\n 561: 'forklift',\n 562: 'fountain',\n 563: 'fountain pen',\n 564: 'four-poster',\n 565: 'freight car',\n 566: 'French horn, horn',\n 567: 'frying pan, frypan, skillet',\n 568: 'fur coat',\n 569: 'garbage truck, dustcart',\n 570: 'gasmask, respirator, gas helmet',\n 571: 'gas pump, gasoline pump, petrol pump, island dispenser',\n 572: 'goblet',\n 573: 'go-kart',\n 574: 'golf ball',\n 575: 'golfcart, golf cart',\n 576: 'gondola',\n 577: 'gong, tam-tam',\n 578: 'gown',\n 579: 'grand piano, grand',\n 580: 'greenhouse, nursery, glasshouse',\n 581: 'grille, radiator grille',\n 582: 'grocery store, grocery, food market, market',\n 583: 'guillotine',\n 584: 'hair slide',\n 585: 'hair spray',\n 586: 'half track',\n 587: 'hammer',\n 588: 'hamper',\n 589: 'hand blower, blow dryer, blow drier, hair dryer, hair drier',\n 590: 'hand-held computer, hand-held microcomputer',\n 591: 'handkerchief, hankie, hanky, hankey',\n 592: 'hard disc, hard disk, fixed disk',\n 593: 'harmonica, mouth organ, harp, mouth harp',\n 594: 'harp',\n 595: 'harvester, reaper',\n 596: 'hatchet',\n 597: 'holster',\n 598: 'home theater, home theatre',\n 599: 'honeycomb',\n 600: 'hook, claw',\n 601: 'hoopskirt, crinoline',\n 602: 'horizontal bar, high bar',\n 603: 'horse cart, horse-cart',\n 604: 'hourglass',\n 605: 'iPod',\n 606: 'iron, smoothing iron',\n 607: \"jack-o'-lantern\",\n 608: 'jean, blue jean, denim',\n 609: 'jeep, landrover',\n 610: 'jersey, T-shirt, tee shirt',\n 611: 'jigsaw puzzle',\n 612: 'jinrikisha, ricksha, rickshaw',\n 613: 'joystick',\n 614: 'kimono',\n 615: 'knee pad',\n 616: 'knot',\n 617: 'lab coat, laboratory coat',\n 618: 'ladle',\n 619: 'lampshade, lamp shade',\n 620: 'laptop, laptop computer',\n 621: 'lawn mower, mower',\n 622: 'lens cap, lens cover',\n 623: 'letter opener, paper knife, paperknife',\n 624: 'library',\n 625: 'lifeboat',\n 626: 'lighter, light, igniter, ignitor',\n 627: 'limousine, limo',\n 628: 'liner, ocean liner',\n 629: 'lipstick, lip rouge',\n 630: 'Loafer',\n 631: 'lotion',\n 632: 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker system',\n 633: \"loupe, jeweler's loupe\",\n 634: 'lumbermill, sawmill',\n 635: 'magnetic compass',\n 636: 'mailbag, postbag',\n 637: 'mailbox, letter box',\n 638: 'maillot',\n 639: 'maillot, tank suit',\n 640: 'manhole cover',\n 641: 'maraca',\n 642: 'marimba, xylophone',\n 643: 'mask',\n 644: 'matchstick',\n 645: 'maypole',\n 646: 'maze, labyrinth',\n 647: 'measuring cup',\n 648: 'medicine chest, medicine cabinet',\n 649: 'megalith, megalithic structure',\n 650: 'microphone, mike',\n 651: 'microwave, microwave oven',\n 652: 'military uniform',\n 653: 'milk can',\n 654: 'minibus',\n 655: 'miniskirt, mini',\n 656: 'minivan',\n 657: 'missile',\n 658: 'mitten',\n 659: 'mixing bowl',\n 660: 'mobile home, manufactured home',\n 661: 'Model T',\n 662: 'modem',\n 663: 'monastery',\n 664: 'monitor',\n 665: 'moped',\n 666: 'mortar',\n 667: 'mortarboard',\n 668: 'mosque',\n 669: 'mosquito net',\n 670: 'motor scooter, scooter',\n 671: 'mountain bike, all-terrain bike, off-roader',\n 672: 'mountain tent',\n 673: 'mouse, computer mouse',\n 674: 'mousetrap',\n 675: 'moving van',\n 676: 'muzzle',\n 677: 'nail',\n 678: 'neck brace',\n 679: 'necklace',\n 680: 'nipple',\n 681: 'notebook, notebook computer',\n 682: 'obelisk',\n 683: 'oboe, hautboy, hautbois',\n 684: 'ocarina, sweet potato',\n 685: 'odometer, hodometer, mileometer, milometer',\n 686: 'oil filter',\n 687: 'organ, pipe organ',\n 688: 'oscilloscope, scope, cathode-ray oscilloscope, CRO',\n 689: 'overskirt',\n 690: 'oxcart',\n 691: 'oxygen mask',\n 692: 'packet',\n 693: 'paddle, boat paddle',\n 694: 'paddlewheel, paddle wheel',\n 695: 'padlock',\n 696: 'paintbrush',\n 697: \"pajama, pyjama, pj's, jammies\",\n 698: 'palace',\n 699: 'panpipe, pandean pipe, syrinx',\n 700: 'paper towel',\n 701: 'parachute, chute',\n 702: 'parallel bars, bars',\n 703: 'park bench',\n 704: 'parking meter',\n 705: 'passenger car, coach, carriage',\n 706: 'patio, terrace',\n 707: 'pay-phone, pay-station',\n 708: 'pedestal, plinth, footstall',\n 709: 'pencil box, pencil case',\n 710: 'pencil sharpener',\n 711: 'perfume, essence',\n 712: 'Petri dish',\n 713: 'photocopier',\n 714: 'pick, plectrum, plectron',\n 715: 'pickelhaube',\n 716: 'picket fence, paling',\n 717: 'pickup, pickup truck',\n 718: 'pier',\n 719: 'piggy bank, penny bank',\n 720: 'pill bottle',\n 721: 'pillow',\n 722: 'ping-pong ball',\n 723: 'pinwheel',\n 724: 'pirate, pirate ship',\n 725: 'pitcher, ewer',\n 726: \"plane, carpenter's plane, woodworking plane\",\n 727: 'planetarium',\n 728: 'plastic bag',\n 729: 'plate rack',\n 730: 'plow, plough',\n 731: \"plunger, plumber's helper\",\n 732: 'Polaroid camera, Polaroid Land camera',\n 733: 'pole',\n 734: 'police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria',\n 735: 'poncho',\n 736: 'pool table, billiard table, snooker table',\n 737: 'pop bottle, soda bottle',\n 738: 'pot, flowerpot',\n 739: \"potter's wheel\",\n 740: 'power drill',\n 741: 'prayer rug, prayer mat',\n 742: 'printer',\n 743: 'prison, prison house',\n 744: 'projectile, missile',\n 745: 'projector',\n 746: 'puck, hockey puck',\n 747: 'punching bag, punch bag, punching ball, punchball',\n 748: 'purse',\n 749: 'quill, quill pen',\n 750: 'quilt, comforter, comfort, puff',\n 751: 'racer, race car, racing car',\n 752: 'racket, racquet',\n 753: 'radiator',\n 754: 'radio, wireless',\n 755: 'radio telescope, radio reflector',\n 756: 'rain barrel',\n 757: 'recreational vehicle, RV, R.V.',\n 758: 'reel',\n 759: 'reflex camera',\n 760: 'refrigerator, icebox',\n 761: 'remote control, remote',\n 762: 'restaurant, eating house, eating place, eatery',\n 763: 'revolver, six-gun, six-shooter',\n 764: 'rifle',\n 765: 'rocking chair, rocker',\n 766: 'rotisserie',\n 767: 'rubber eraser, rubber, pencil eraser',\n 768: 'rugby ball',\n 769: 'rule, ruler',\n 770: 'running shoe',\n 771: 'safe',\n 772: 'safety pin',\n 773: 'saltshaker, salt shaker',\n 774: 'sandal',\n 775: 'sarong',\n 776: 'sax, saxophone',\n 777: 'scabbard',\n 778: 'scale, weighing machine',\n 779: 'school bus',\n 780: 'schooner',\n 781: 'scoreboard',\n 782: 'screen, CRT screen',\n 783: 'screw',\n 784: 'screwdriver',\n 785: 'seat belt, seatbelt',\n 786: 'sewing machine',\n 787: 'shield, buckler',\n 788: 'shoe shop, shoe-shop, shoe store',\n 789: 'shoji',\n 790: 'shopping basket',\n 791: 'shopping cart',\n 792: 'shovel',\n 793: 'shower cap',\n 794: 'shower curtain',\n 795: 'ski',\n 796: 'ski mask',\n 797: 'sleeping bag',\n 798: 'slide rule, slipstick',\n 799: 'sliding door',\n 800: 'slot, one-armed bandit',\n 801: 'snorkel',\n 802: 'snowmobile',\n 803: 'snowplow, snowplough',\n 804: 'soap dispenser',\n 805: 'soccer ball',\n 806: 'sock',\n 807: 'solar dish, solar collector, solar furnace',\n 808: 'sombrero',\n 809: 'soup bowl',\n 810: 'space bar',\n 811: 'space heater',\n 812: 'space shuttle',\n 813: 'spatula',\n 814: 'speedboat',\n 815: \"spider web, spider's web\",\n 816: 'spindle',\n 817: 'sports car, sport car',\n 818: 'spotlight, spot',\n 819: 'stage',\n 820: 'steam locomotive',\n 821: 'steel arch bridge',\n 822: 'steel drum',\n 823: 'stethoscope',\n 824: 'stole',\n 825: 'stone wall',\n 826: 'stopwatch, stop watch',\n 827: 'stove',\n 828: 'strainer',\n 829: 'streetcar, tram, tramcar, trolley, trolley car',\n 830: 'stretcher',\n 831: 'studio couch, day bed',\n 832: 'stupa, tope',\n 833: 'submarine, pigboat, sub, U-boat',\n 834: 'suit, suit of clothes',\n 835: 'sundial',\n 836: 'sunglass',\n 837: 'sunglasses, dark glasses, shades',\n 838: 'sunscreen, sunblock, sun blocker',\n 839: 'suspension bridge',\n 840: 'swab, swob, mop',\n 841: 'sweatshirt',\n 842: 'swimming trunks, bathing trunks',\n 843: 'swing',\n 844: 'switch, electric switch, electrical switch',\n 845: 'syringe',\n 846: 'table lamp',\n 847: 'tank, army tank, armored combat vehicle, armoured combat vehicle',\n 848: 'tape player',\n 849: 'teapot',\n 850: 'teddy, teddy bear',\n 851: 'television, television system',\n 852: 'tennis ball',\n 853: 'thatch, thatched roof',\n 854: 'theater curtain, theatre curtain',\n 855: 'thimble',\n 856: 'thresher, thrasher, threshing machine',\n 857: 'throne',\n 858: 'tile roof',\n 859: 'toaster',\n 860: 'tobacco shop, tobacconist shop, tobacconist',\n 861: 'toilet seat',\n 862: 'torch',\n 863: 'totem pole',\n 864: 'tow truck, tow car, wrecker',\n 865: 'toyshop',\n 866: 'tractor',\n 867: 'trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi',\n 868: 'tray',\n 869: 'trench coat',\n 870: 'tricycle, trike, velocipede',\n 871: 'trimaran',\n 872: 'tripod',\n 873: 'triumphal arch',\n 874: 'trolleybus, trolley coach, trackless trolley',\n 875: 'trombone',\n 876: 'tub, vat',\n 877: 'turnstile',\n 878: 'typewriter keyboard',\n 879: 'umbrella',\n 880: 'unicycle, monocycle',\n 881: 'upright, upright piano',\n 882: 'vacuum, vacuum cleaner',\n 883: 'vase',\n 884: 'vault',\n 885: 'velvet',\n 886: 'vending machine',\n 887: 'vestment',\n 888: 'viaduct',\n 889: 'violin, fiddle',\n 890: 'volleyball',\n 891: 'waffle iron',\n 892: 'wall clock',\n 893: 'wallet, billfold, notecase, pocketbook',\n 894: 'wardrobe, closet, press',\n 895: 'warplane, military plane',\n 896: 'washbasin, handbasin, washbowl, lavabo, wash-hand basin',\n 897: 'washer, automatic washer, washing machine',\n 898: 'water bottle',\n 899: 'water jug',\n 900: 'water tower',\n 901: 'whiskey jug',\n 902: 'whistle',\n 903: 'wig',\n 904: 'window screen',\n 905: 'window shade',\n 906: 'Windsor tie',\n 907: 'wine bottle',\n 908: 'wing',\n 909: 'wok',\n 910: 'wooden spoon',\n 911: 'wool, woolen, woollen',\n 912: 'worm fence, snake fence, snake-rail fence, Virginia fence',\n 913: 'wreck',\n 914: 'yawl',\n 915: 'yurt',\n 916: 'web site, website, internet site, site',\n 917: 'comic book',\n 918: 'crossword puzzle, crossword',\n 919: 'street sign',\n 920: 'traffic light, traffic signal, stoplight',\n 921: 'book jacket, dust cover, dust jacket, dust wrapper',\n 922: 'menu',\n 923: 'plate',\n 924: 'guacamole',\n 925: 'consomme',\n 926: 'hot pot, hotpot',\n 927: 'trifle',\n 928: 'ice cream, icecream',\n 929: 'ice lolly, lolly, lollipop, popsicle',\n 930: 'French loaf',\n 931: 'bagel, beigel',\n 932: 'pretzel',\n 933: 'cheeseburger',\n 934: 'hotdog, hot dog, red hot',\n 935: 'mashed potato',\n 936: 'head cabbage',\n 937: 'broccoli',\n 938: 'cauliflower',\n 939: 'zucchini, courgette',\n 940: 'spaghetti squash',\n 941: 'acorn squash',\n 942: 'butternut squash',\n 943: 'cucumber, cuke',\n 944: 'artichoke, globe artichoke',\n 945: 'bell pepper',\n 946: 'cardoon',\n 947: 'mushroom',\n 948: 'Granny Smith',\n 949: 'strawberry',\n 950: 'orange',\n 951: 'lemon',\n 952: 'fig',\n 953: 'pineapple, ananas',\n 954: 'banana',\n 955: 'jackfruit, jak, jack',\n 956: 'custard apple',\n 957: 'pomegranate',\n 958: 'hay',\n 959: 'carbonara',\n 960: 'chocolate sauce, chocolate syrup',\n 961: 'dough',\n 962: 'meat loaf, meatloaf',\n 963: 'pizza, pizza pie',\n 964: 'potpie',\n 965: 'burrito',\n 966: 'red wine',\n 967: 'espresso',\n 968: 'cup',\n 969: 'eggnog',\n 970: 'alp',\n 971: 'bubble',\n 972: 'cliff, drop, drop-off',\n 973: 'coral reef',\n 974: 'geyser',\n 975: 'lakeside, lakeshore',\n 976: 'promontory, headland, head, foreland',\n 977: 'sandbar, sand bar',\n 978: 'seashore, coast, seacoast, sea-coast',\n 979: 'valley, vale',\n 980: 'volcano',\n 981: 'ballplayer, baseball player',\n 982: 'groom, bridegroom',\n 983: 'scuba diver',\n 984: 'rapeseed',\n 985: 'daisy',\n 986: \"yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum\",\n 987: 'corn',\n 988: 'acorn',\n 989: 'hip, rose hip, rosehip',\n 990: 'buckeye, horse chestnut, conker',\n 991: 'coral fungus',\n 992: 'agaric',\n 993: 'gyromitra',\n 994: 'stinkhorn, carrion fungus',\n 995: 'earthstar',\n 996: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa',\n 997: 'bolete',\n 998: 'ear, spike, capitulum',\n 999: 'toilet tissue, toilet paper, bathroom tissue'}\n"
  },
  {
    "path": "examples/ONNX/resnet50/int8.py",
    "content": "import calibrator\nimport tensorrt as trt\n\n# Use TensorRT ONNX parser to parse model file, and enable INT8 calibration during engine construction\ndef build_int8_engine_onnx(model_file, image_dir, batch_size, calibration_batches, engine_file, cache_file='INT8CalibrationTable'):\n\n    TRT_LOGGER = trt.Logger(trt.Logger.WARNING)\n    with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.OnnxParser(network, TRT_LOGGER) as parser:\n        # Load the Onnx model and parse it in order to populate the TensorRT network.\n        with open(model_file, 'rb') as model:\n            parser.parse(model.read())\n\n        # Allow builder to use INT8 or FP16 kernels when building engine\n        builder.int8_mode = True\n        builder.fp16_mode = True\n        calib = calibrator.ONNXEntropyCalibrator(image_dir, batch_size, calibration_batches, cache_file)\n        builder.int8_calibrator = calib\n        builder.max_batch_size = batch_size\n\n        engine = builder.build_cuda_engine(network)\n\n        with open(engine_file, 'wb') as f:\n            f.write(engine.serialize())\n\n"
  },
  {
    "path": "examples/ONNX/resnet50/onnx_utils.py",
    "content": "#!/usr/bin/env python3\nimport glob\nimport os\n\nimport onnx\nfrom onnx import numpy_helper\nfrom matplotlib import pyplot as plt\nimport numpy as np\n\ndef load_inputs(test_data_dir):\n    # Load inputs\n    inputs = []\n    inputs_num = len(glob.glob(os.path.join(test_data_dir, 'input_*.pb')))\n    for i in range(inputs_num):\n        input_file = os.path.join(test_data_dir, 'input_{}.pb'.format(i))\n        tensor = onnx.TensorProto()\n        with open(input_file, 'rb') as f:\n            tensor.ParseFromString(f.read())\n        inputs.append(numpy_helper.to_array(tensor))\n    return inputs\n\ndef load_outputs(test_data_dir):\n    # Load reference outputs\n    ref_outputs = []\n    ref_outputs_num = len(glob.glob(os.path.join(test_data_dir, 'output_*.pb')))\n    for i in range(ref_outputs_num):\n        output_file = os.path.join(test_data_dir, 'output_{}.pb'.format(i))\n        tensor = onnx.TensorProto()\n        with open(output_file, 'rb') as f:\n            tensor.ParseFromString(f.read())\n        ref_outputs.append(numpy_helper.to_array(tensor))\n    return ref_outputs\n\ndef mnist_image(data):\n    two_d = (np.reshape(data, (28, 28))).astype(np.uint8)\n    plt.imshow(two_d, interpolation='nearest')\n    return plt\n\ndef softmax(x):\n    \"\"\"Compute softmax values for each sets of scores in x.\"\"\"\n    e_x = np.exp(x - np.max(x))\n    return e_x / e_x.sum()\n"
  },
  {
    "path": "examples/ONNX/resnet50/open_source_images.md5",
    "content": "6cd502bc217f3960cf34447ec4ede610  open_source_images.tar.gz\n"
  },
  {
    "path": "examples/ONNX/resnet50/resnet50.md5",
    "content": "0e8088c7b1a1a9b2d0a5ae05601cc55e  resnet50.tar.gz\n"
  },
  {
    "path": "examples/ONNX/resnet50/run_jpeg_test.py",
    "content": "#!/usr/bin/env python3\n\nimport os\nimport time\n\nimport trtlab\nimport onnx_utils as utils\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nimport mxnet as mx\nfrom mxnet.gluon.data.vision import transforms\n\nfrom imagenet_labels import labels\n\nimport click\n\ntests = {}\n\ndef tensorrt_init(engines):\n    manager = trtlab.InferenceManager(max_exec_concurrency=4)\n    runners = []\n    for engine in engines:\n        name, _ = os.path.splitext(os.path.basename(engine))\n        runners.append(manager.register_tensorrt_engine(name, engine))\n    manager.update_resources()\n    return runners\n\ndef infer_image(runner, image):\n    inputs = preprocess_image(runner, image)\n    future = runner.infer(**inputs)\n    result = future.get()\n    for name, tensor in result.items():\n        tensor = tensor.reshape(1000)\n        idx = np.argmax(tensor) \n        print(\"\\n*** Results ***\") \n        print(labels[idx], tensor[idx])\n        print(\"\") \n\ndef preprocess_image(runner, image_path):\n    inputs = runner.input_bindings()\n    keys = list(inputs.keys())\n    input_name = keys[0]\n    img = np.array(plt.imread(image_path))\n    img = transform_image(img)\n    return { input_name: img }\n\ndef transform_image(img):\n    transform_fn = transforms.Compose([\n        transforms.Resize(224),\n        transforms.CenterCrop(224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n    img = transform_fn(mx.nd.array(img)).asnumpy()\n    img = np.expand_dims(img, axis=0) # batchify\n    return img\n\n\ndef validate_results(computed, expected):\n    keys = list(computed.keys())\n    output_name = keys[0]\n    output_value = computed[output_name]\n    np.testing.assert_almost_equal(output_value, expected[0], decimal=3)\n    print(\"-- Test Passed: All outputs {} match within 3 decimals\".format(output_value.shape))\n\nFile = click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)\nPath = click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)\n\n@click.command()\n@click.option(\"--image\", type=File, multiple=True)\n@click.argument(\"engine\", type=File, nargs=1)\ndef main(engine, image):\n    runners = tensorrt_init([engine])\n    for runner in runners:\n        for img in image:\n            infer_image(runner, img) \n    \n\nif __name__ == \"__main__\":\n    main() \n"
  },
  {
    "path": "examples/ONNX/resnet50/run_onnx_tests.py",
    "content": "#!/usr/bin/env python3\n\nimport os\n\nimport trtlab\nimport numpy as np\n\nimport click\nimport onnx_utils as utils\n\ntests = {}\n\ndef tensorrt_init(engines):\n    manager = trtlab.InferenceManager(max_exec_concurrency=4)\n    runners = []\n    for engine in engines:\n        name, _ = os.path.splitext(os.path.basename(engine))\n        runners.append(manager.register_tensorrt_engine(name, engine))\n    manager.update_resources()\n    return runners\n\ndef test_data(test_path):\n    for path, dirs, files in os.walk(test_path):\n        if os.path.basename(path).startswith(\"test_\"):\n            tests[path] = files \n    for path, files in tests.items():\n        inputs = utils.load_inputs(path)\n        outputs = utils.load_outputs(path)\n        print(\"** Testing {} **\".format(path))\n        yield inputs, outputs\n\ndef run_test(runner, inputs, outputs):\n    inputs = preprocess_inputs(runner, inputs)\n    future = runner.infer(**inputs)\n    result = future.get()\n    validate_results(result, outputs)\n\ndef preprocess_inputs(runner, inputs):\n    expected_input = runner.input_bindings()\n    if len(expected_input) != len(inputs):\n        raise RuntimeError(\"mismatched number of inputs\")\n    keys = list(expected_input.keys())\n    input_name = keys[0]\n    info = expected_input[keys[0]]\n    shape = info['shape']\n    tensor = inputs[0]\n    batch_size = tensor.shape[0]\n    if list(shape) != list(tensor.shape[1:]):\n        raise RuntimeError(\"mismatched input dimensions\")\n    return { input_name: tensor }\n\ndef validate_results(computed, expected):\n    keys = list(computed.keys())\n    output_name = keys[0]\n    output_value = computed[output_name]\n    np.testing.assert_almost_equal(output_value, expected[0], decimal=3)\n    print(\"-- Test Passed: All outputs {} match within 3 decimals\".format(output_value.shape))\n\nFile = click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)\nPath = click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)\n\n@click.command()\n@click.option(\"--tests\", type=Path, default=\"resnet50\")\n@click.argument(\"engine\", type=File, nargs=1)\ndef main(engine, tests):\n    runners = tensorrt_init([engine])\n    for runner in runners:\n        for inputs, outputs in test_data(tests):\n            run_test(runner, inputs, outputs)\n    \n\nif __name__ == \"__main__\":\n    main() \n"
  },
  {
    "path": "examples/nvRPC/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_subdirectory(UnaryService)\nadd_subdirectory(StreamingService)\nadd_subdirectory(SharedMemoryService)\n\n# TODO: WIP\n# add_subdirectory(StreamingInOrderSendRecv)"
  },
  {
    "path": "examples/nvRPC/SharedMemoryService/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(sysv-nvrpc.x\n    server.cc)\n\ntarget_link_libraries(sysv-nvrpc.x\n    nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(sysv-client.x\n    client.cc)\n\ntarget_link_libraries(sysv-client.x\n    nvrpc\n    echo-protos\n    gflags\n)\n"
  },
  {
    "path": "examples/nvRPC/SharedMemoryService/README.md",
    "content": "# Shared Memory Service\n\nClient/Server service extending the Basic nvRPC example.\n\nThe client (`sysv-client.x`) creates a `CyclicAllocator<SystemV>` from which it\nallocates buffers of shared memory.\n\nThe client:\n  1. Write some data into shared memory (batch_id and 0xDEADBEEF), `data[0]` and `data[1]` respectively.\n  2. Packs the RPC message with the batch_id and the SystemV memory descriptor details\n  3. Initiates the RPC\n  4. Checks the value of the address in which it wrote 0xDEADBEEF to ensure that the server wrote it's response to the proper location.\n\nOn reciept of a client RPC, the server Aquires a `Descriptor<SystemV>` to the\noffset in the shared memory segment required in the RPC.  This is done via the\n`ExternalSharedMemoryManager`.\n\nThe server:\n  1. Aquires the `Descriptor<SystemV>` to the offset\n  2. Checks the values at `data[0]` and `data[1]` for `batch_id` and `0xDEADBEEF` respectively\n  3. Write the `batch_id` into `[1]` element\n  4. Returns the Response"
  },
  {
    "path": "examples/nvRPC/SharedMemoryService/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <algorithm>\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"tensorrt/laboratory/core/memory/cyclic_allocator.h\"\n#include \"tensorrt/laboratory/core/memory/system_v.h\"\n\n#include \"echo.grpc.pb.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\nusing simple::Inference;\nusing simple::Input;\nusing simple::Output;\n\nusing trtlab::CyclicAllocator;\nusing trtlab::SystemV;\n\nstatic constexpr size_t one_mb = 1024 * 1024;\n\nDEFINE_int32(count, 1, \"number of grpc messages to send\");\n\nclass SimpleClient final\n{\n  public:\n    SimpleClient(std::shared_ptr<Channel> channel)\n        : m_Stub(Inference::NewStub(channel)), m_Memory(5, one_mb)\n    {\n    }\n\n    // Generate and send RPC message\n    int Compute(const int batch_id)\n    {\n        // Allocate some SysV shared memory from the CyclicAllocator\n        CyclicAllocator<SystemV>::Descriptor mdesc = RandomAllocation();\n\n        // Populate the request object\n        Input request;\n        request.set_batch_id(batch_id);\n        auto sysv = request.mutable_sysv();\n        sysv->set_shm_id(mdesc->Stack().Memory().ShmID());\n        sysv->set_offset(mdesc->Offset());\n        sysv->set_size(mdesc->Size());\n\n        // Write the batch_id to the shared memory segment\n        // This will validated against the batch_id in the message body on the server\n        auto data = mdesc->CastToArray<size_t>();\n        data[0] = batch_id;\n        data[1] = 0xDEADBEEF;\n\n        // Container for the data we expect from the server.\n        Output reply;\n\n        // Context for the client. It could be used to convey extra information to\n        // the server and/or tweak certain RPC behaviors.\n        ClientContext context;\n\n        // The actual RPC.\n        Status status = m_Stub->Compute(&context, request, &reply);\n\n        if(status.ok())\n        {\n            CHECK_EQ(data[1], batch_id);\n            return reply.batch_id();\n        }\n        else\n        {\n            LOG(ERROR) << status.error_code() << \": \" << status.error_message();\n            return -1;\n        }\n    }\n\n  private:\n    CyclicAllocator<SystemV>::Descriptor RandomAllocation()\n    {\n        size_t bytes = rand() % (m_Memory.MaxAllocationSize() / 4);\n        bytes = std::max(bytes, 16UL); // guarantee at least 16 bytes (2x size_t)\n        DLOG(INFO) << \"RandomAllocation: \" << bytes << \" bytes\";\n        return m_Memory.Allocate(bytes);\n    }\n\n    std::unique_ptr<Inference::Stub> m_Stub;\n    CyclicAllocator<SystemV> m_Memory;\n};\n\nint main(int argc, char** argv)\n{\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    SimpleClient client(grpc::CreateChannel(\"localhost:50051\", grpc::InsecureChannelCredentials()));\n\n    auto start = std::chrono::steady_clock::now();\n    for(int i = 0; i < FLAGS_count; i++)\n    {\n        auto reply = client.Compute(i);\n        LOG_IF(INFO, reply == -1) << \"BatchId received: \" << reply;\n    }\n    auto end = std::chrono::steady_clock::now();\n    float elapsed = std::chrono::duration<float>(end - start).count();\n    std::cout << FLAGS_count << \" requests in \" << elapsed << \"seconds\" << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "examples/nvRPC/SharedMemoryService/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <map>\n#include <memory>\n#include <thread>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n#include \"tensorrt/laboratory/core/memory/descriptor.h\"\n#include \"tensorrt/laboratory/core/memory/system_v.h\"\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n#include \"tensorrt/laboratory/core/utils.h\"\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\nusing trtlab::Descriptor;\nusing trtlab::SystemV;\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\n/**\n * @brief SystemV Memory Manager\n *\n * This object does not allocate system v shared memory segments.  Instead, it attaches and manages\n * descriptors into shared memory segments allocated by an external source.\n */\nclass ExternalSharedMemoryManager final\n{\n    class PartialSegmentDescriptor final : public Descriptor<SystemV>\n    {\n      public:\n        PartialSegmentDescriptor(const std::shared_ptr<SystemV>& segment, size_t offset,\n                                 size_t size)\n            : Descriptor<SystemV>((*segment)[offset], size, \"PartialSysVSegment\"),\n              m_Segment(segment)\n        {\n        }\n\n        PartialSegmentDescriptor(PartialSegmentDescriptor&& other)\n            : Descriptor<SystemV>(std::move(other)), m_Segment{\n                                                         std::exchange(other.m_Segment, nullptr)}\n        {\n        }\n\n        PartialSegmentDescriptor& operator=(PartialSegmentDescriptor&&) = delete;\n        DELETE_COPYABILITY(PartialSegmentDescriptor);\n\n        virtual ~PartialSegmentDescriptor() override {}\n\n      private:\n        std::shared_ptr<SystemV> m_Segment;\n    };\n\n  public:\n    ExternalSharedMemoryManager() = default;\n    using Descriptor = std::unique_ptr<PartialSegmentDescriptor>;\n\n    Descriptor Acquire(size_t shm_id, size_t offset, size_t size)\n    {\n        const auto& segment = GetOrAttachToShmID(shm_id);\n        CHECK_LE(offset + size, segment->Size());\n        return std::make_unique<PartialSegmentDescriptor>(segment, offset, size);\n    }\n\n    void Release(size_t shm_id)\n    {\n        std::lock_guard<std::mutex> l(m_Mutex);\n        auto count = m_AttachedSegments.erase(shm_id);\n        DLOG_IF(WARNING, count == 0) << \"Attempting to Release an unmapped shm_id\";\n    }\n\n  protected:\n    std::shared_ptr<SystemV> GetOrAttachToShmID(size_t shm_id)\n    {\n        std::shared_ptr<SystemV> segment;\n        std::lock_guard<std::mutex> l(m_Mutex);\n        auto search = m_AttachedSegments.find(shm_id);\n        if(search == m_AttachedSegments.end())\n        {\n            DLOG(INFO) << \"SystemV Manager: attaching to shm_id: \" << shm_id;\n            segment = SystemV::Attach(shm_id);\n            m_AttachedSegments[shm_id] = segment;\n        }\n        else\n        {\n            segment = search->second;\n        }\n        return segment;\n    }\n\n  private:\n    std::map<size_t, std::shared_ptr<SystemV>> m_AttachedSegments;\n    std::mutex m_Mutex;\n};\n\nstruct SimpleResources : public Resources\n{\n    SimpleResources() = default;\n\n    ExternalSharedMemoryManager& GetExternalSharedMemoryManager()\n    {\n        return m_ExternalSharedMemoryManager;\n    }\n\n  private:\n    ExternalSharedMemoryManager m_ExternalSharedMemoryManager;\n};\n\nclass SimpleContext final : public Context<simple::Input, simple::Output, SimpleResources>\n{\n    void ExecuteRPC(RequestType& input, ResponseType& output) final override\n    {\n        ExternalSharedMemoryManager::Descriptor mdesc;\n        if(input.has_sysv())\n        {\n            mdesc = GetResources()->GetExternalSharedMemoryManager().Acquire(\n                input.sysv().shm_id(), input.sysv().offset(), input.sysv().size());\n        }\n        CHECK(mdesc);\n        auto array = mdesc->CastToArray<size_t>();\n        CHECK_EQ(array[0], input.batch_id());\n        CHECK_EQ(array[1], 0xDEADBEEF);\n        array[1] = input.batch_id();\n\n        output.set_batch_id(input.batch_id());\n        this->FinishResponse();\n    }\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // A server will bind an IP:PORT to listen on\n    Server server(\"0.0.0.0:50051\");\n\n    // A server can host multiple services\n    LOG(INFO) << \"Register Service (simple::Inference) with Server\";\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n\n    LOG(INFO) << \"Register RPC (simple::Inference::Compute) with Service (simple::Inference)\";\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestCompute);\n\n    LOG(INFO) << \"Initializing Resources for RPC (simple::Inference::Compute)\";\n    auto rpcResources = std::make_shared<SimpleResources>();\n\n    LOG(INFO) << \"Creating Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    LOG(INFO) << \"Creating Execution Contexts for RPC (simple::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {});\n}\n"
  },
  {
    "path": "examples/nvRPC/StreamingInOrderSendRecv/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(nvrpc-bidirectional-server.x\n    server.cc)\n\ntarget_link_libraries(nvrpc-bidirectional-server.x\n    nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(nvrpc-bidirectional-client.x\n    client.cc\n)\n\ntarget_link_libraries(nvrpc-bidirectional-client.x\n    nvrpc\n    nvrpc-client\n    echo-protos\n    gflags\n)"
  },
  {
    "path": "examples/nvRPC/StreamingInOrderSendRecv/README.md",
    "content": "# BidirectionalStream In-Order Send/Recv\n\n```\nrpc InOrderSendRecv (stream Request) returns (stream Response)\n```\n\nThe service will accept a stream or Requests, queue them for in-order execution\nvia the `ExecuteRPC` virtual method, and for each result of `ExecuteRPC` return\na Response on the stream.\n\nOnly one `ExecuteRPC` can be in-action at anytime which allows the RPC to\noptionally maintain a state.  In some regards, this lifecyle could be used to\nmodel an RNN as the collective history can be built into the resources.\n\n"
  },
  {
    "path": "examples/nvRPC/StreamingInOrderSendRecv/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"nvrpc/client/client_streaming.h\"\n#include \"nvrpc/client/executor.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\n\nusing nvrpc::client::ClientBidirectional;\nusing nvrpc::client::Executor;\n\n#include \"echo.grpc.pb.h\"\n\nusing simple::Inference;\nusing simple::Input;\nusing simple::Output;\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\nDEFINE_string(hostname, \"127.0.0.1:50051\", \"hostname and port\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    std::mutex mutex;\n    std::size_t count = 0;\n\n    auto executor = std::make_shared<Executor>(FLAGS_thread_count);\n\n    auto channel = grpc::CreateChannel(FLAGS_hostname, grpc::InsecureChannelCredentials());\n    auto stub = Inference::NewStub(channel);\n\n    auto infer_prepare_fn = [&stub](::grpc::ClientContext * context,\n                                    ::grpc::CompletionQueue * cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncBidirectional(context, cq));\n    };\n\n    auto stream = std::make_unique<ClientBidirectional<Input, Output>>(\n        infer_prepare_fn, executor,\n        [](Input&& request) {\n            LOG_FIRST_N(INFO, 10) << \"Sent Request with BatchID: \" << request.batch_id();\n            static size_t last = 0;\n            CHECK_EQ(last + 1, request.batch_id());\n            ++last;\n            // CHECK(request.batch_id());\n        },\n        [&mutex, &count](Output&& response) {\n            LOG_FIRST_N(INFO, 10) << \"Received Response with BatchID: \" << response.batch_id();\n            // CHECK(response.batch_id());\n            std::lock_guard<std::mutex> lock(mutex);\n            --count;\n        });\n\n    auto start = std::chrono::steady_clock::now();\n    auto elapsed = [start]() -> float {\n        return std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n    };\n\n    for(int i = 1; i < FLAGS_count + 1; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        stream->Send(std::move(input));\n    }\n    std::cout << FLAGS_count << \" queued in \" << elapsed() << \"seconds\" << std::endl;\n    auto future = stream->Done();\n    auto status = future.get();\n    executor->ShutdownAndJoin();\n    CHECK_EQ(count, 0UL);\n    std::cout << FLAGS_count << \" completed in \" << elapsed() << \"seconds\" << std::endl;\n    std::cout << \"gRPC Status: \" << (status.ok() ? \"OK\" : \"NOT OK\") << std::endl;\n    return 0;\n}"
  },
  {
    "path": "examples/nvRPC/StreamingInOrderSendRecv/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::BidirectionalContext;\nusing nvrpc::Executor;\nusing nvrpc::Server;\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\n// Define the resources your RPC will need to execute\n// ==================================================\n// In this case, all simple::Inference::Compute RPCs share a threadpool in which they will\n// queue up some work on.  This essentially means, after the message as been received and\n// processed, the actual work for the RPC is pushed to a worker pool outside the scope of\n// the transaction processing system (TPS).  This is essentially async computing, we have\n// decoupled the transaction from the workers executing the implementation.  The TPS can\n// continue to queue work, while the workers process the load.\nstruct SimpleResources : public Resources\n{\n    SimpleResources(int numThreadsInPool = 3) : m_ThreadPool(numThreadsInPool)\n    {\n        LOG(INFO) << \"Server ThreadCount: \" << numThreadsInPool;\n    }\n\n    ThreadPool& AcquireThreadPool() { return m_ThreadPool; }\n\n  private:\n    ThreadPool m_ThreadPool;\n};\n\n// Contexts hold the state and provide the definition of the work to be performed by the RPC.\n// This is where you define what gets executed for a given RPC.\n// Incoming Message = simple::Input (RequestType)\n// Outgoing Message = simple::Output (ResponseType)\nclass SimpleContext final\n    : public BidirectionalContext<simple::Input, simple::Output, SimpleResources>\n{\n    void ExecuteRPC(RequestType& input, ResponseType& output) final override\n    {\n        // We could do work here, but we'd block the TPS, i.e. the threads pulling messages\n        // off the incoming recieve queue.  Very quick responses are best done here; however,\n        // longer running workload should be offloaded so the TPS can avoid being blocked.\n        // GetResources()->AcquireThreadPool().enqueue([this, &input, &output]{\n        // Now running on a worker thread of the ThreadPool defined in SimpleResources.\n        // Here we are just echoing back the incoming // batch_id; however, in later\n        // examples, we'll show how to run an async cuda pipline.\n        LOG_FIRST_N(INFO, 10) << \"BatchID: \" << input.batch_id() << \" Tag = \" << Tag()\n                              << \" Thread = \" << std::this_thread::get_id();\n        output.set_batch_id(input.batch_id());\n        this->FinishResponse();\n        // });\n        // The TPS thread is now free to continue processing message - async ftw!\n    }\n};\n\nDEFINE_string(ip_port, \"0.0.0.0:50051\", \"IP/Port\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // A server will bind an IP:PORT to listen on\n    Server server(FLAGS_ip_port);\n\n    // A server can host multiple services\n    LOG(INFO) << \"Register Service (simple::Inference) with Server\";\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n\n    // An RPC has two components that need to be specified when registering with the service:\n    //  1) Type of Execution Context (SimpleContext).  The execution context defines the behavor\n    //     of the RPC, i.e. it contains the control logic for the execution of the RPC.\n    //  2) The Request function (RequestCompute) which was generated by gRPC when compiling the\n    //     protobuf which defined the service.  This function is responsible for queuing the\n    //     RPC's execution context to the\n    LOG(INFO) << \"Register RPC (simple::Inference::Compute) with Service (simple::Inference)\";\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestBidirectional);\n\n    LOG(INFO) << \"Initializing Resources for RPC (simple::Inference::Compute)\";\n    auto rpcResources = std::make_shared<SimpleResources>(FLAGS_thread_count);\n\n    // Create Executors - Executors provide the messaging processing resources for the RPCs\n    // Multiple Executors can be registered with a Server.  The executor is responsible\n    // for pulling incoming message off the receive queue and executing the associated\n    // context.  By default, an executor only uses a single thread.  A typical usecase is\n    // an Executor executes a context, which immediate pushes the work to a thread pool.\n    // However, for very low-latency messaging, you might want to use a multi-threaded\n    // Executor and a Blocking Context - meaning the Context performs the entire RPC function\n    // on the Executor's thread.\n    LOG(INFO) << \"Creating Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    // You can register RPC execution contexts from any registered RPC on any executor.\n    // The power of that will become clear in later examples. For now, we will register\n    // 10 instances of the simple::Inference::Compute RPC's SimpleContext execution context\n    // with the Executor.\n    LOG(INFO) << \"Creating Execution Contexts for RPC (simple::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {\n        // This is a timeout loop executed every 2seconds\n        // Run() with no arguments will run an empty timeout loop every 5 seconds.\n        // RunAsync() will return immediately, its your responsibility to ensure the\n        // server doesn't go out of scope or a Shutdown will be triggered on your services.\n    });\n}\n"
  },
  {
    "path": "examples/nvRPC/StreamingInOrderSendRecv/test.sh",
    "content": "#!/bin/bash \n\ncleanup() {\n  kill $(jobs -p) ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\n./nvrpc-bidirectional-server.x --ip_port=\"0.0.0.0:5555\" &\n\nf=$(mktmp)\ncat <<EOF > $f\nPS1='nvRPC Bidirectional: '\n\ngo() { ./nvrpc-bidirectional-client.x --hostname=\"localhost:5555\" --count=${1:-100} }\nEOF\n\nps aux\n\necho\necho 'Try ./nvrpc-bidirectional-client.x --hostname=\"localhost:5555\" --count=100'\nbash --rcfile <(echo \"PS1='nvRPC Bidirectional: '\")\n"
  },
  {
    "path": "examples/nvRPC/StreamingService/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nset(LIBS nvrpc echo-protos gflags)\n\nadd_executable(nvrpc-ping-pong-server.x ping-pong.cc)\nadd_executable(nvrpc-even-odds-server.x even-odds.cc)\n\ntarget_link_libraries(nvrpc-ping-pong-server.x ${LIBS})\ntarget_link_libraries(nvrpc-even-odds-server.x ${LIBS})\n\nadd_executable(nvrpc-streaming-client.x client.cc)\ntarget_link_libraries(nvrpc-streaming-client.x ${LIBS} nvrpc-client)"
  },
  {
    "path": "examples/nvRPC/StreamingService/README.md",
    "content": "# Streaming Examples\n\nAsync gRPC streaming can take on many forms. nvRPC provides a set of LifeCycles\nto accommodate a variety of common use-cases.\n\nFor all examples, the RPC that we will implement will have the same form:\n\n```protobuf\nrpc Bidirectional (stream Input) returns (stream Output) {}\n```\n\nTo implement a `StreamingContext`, you must implement the `ReceivedRequest` pure\nvirtual method.  This method is triggered once for each incoming request that is\nread from the stream.  The `ServerStream` object is used to write responses or \nclose the stream.  \n\n```c++\nclass SimpleContext final : public StreamingContext<Input, Output, ExternalResources>\n{\n    void RequestReceived(RequestType&& input, std::shared_ptr<ServerStream> stream) final override\n    {\n       // `input` incoming message of Input/RequestType\n       // `stream` allows you to:\n       //  ->StreamID()\n       //    - unique identifier for this stream; note, the ID will be reused when the context is\n       //      recycled.\n       //  ->WriteResponse(Output&&)\n       //    - writes a response on the stream; returns `true` if the stream is connected;\n       //      otherwise, `false`  if the stream is disconnected\n       //  ->IsConnected()\n       //    - bool - is the stream still connected to the client. `FinishStream` or `CancelStream`\n       //      will disconnect all `ServerStream`  objects that share the same StreamID.\n       //  ->FinishStream()\n       //    - Close the Stream from the server-side with status OK\n       //  ->CancelStream()\n       //    - Close the Stream with status CANCELLED\n       //\n       //  NOTE: The gRPC stream will stay open to the client until:\n       //        1) the client closes its half of the stream, and\n       //        2) all `ServerStream` objects are destroyed OR\n       //           the stream is explicitly closed by Cancel/FinishStream\n    }\n```\n\nThe final comment is worth further discussion.  The life of the `ServerStream` object does\nnot have to be tied to the life of the `ReceivedRequest` call.  You can pass the\n`ServerStream` object off to an external resource which can then write messages to on the\nstream has long as the stream remains connected.  \n\nThe stream will disconnect implicitly \n\n\n- `ping-pong.cc` - In-order send/recv stream. This client sends a Request and\n  the server Response with the same value for `batch_id`.  "
  },
  {
    "path": "examples/nvRPC/StreamingService/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"nvrpc/client/client_streaming.h\"\n#include \"nvrpc/client/executor.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\n\nusing nvrpc::client::ClientStreaming;\nusing nvrpc::client::Executor;\n\n#include \"echo.grpc.pb.h\"\n\nusing simple::Inference;\nusing simple::Input;\nusing simple::Output;\n\nstatic bool ValidateEven(const char* flagname, int value)\n{\n    LOG_IF(ERROR, value % 2) << \"Examples require an even number of messages\";\n    return (value % 2 == 0);\n}\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\nDEFINE_validator(count, &ValidateEven);\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\nDEFINE_string(hostname, \"127.0.0.1:50051\", \"hostname and port\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    std::mutex mutex;\n    std::size_t count = 0;\n\n    auto executor = std::make_shared<Executor>(FLAGS_thread_count);\n\n    auto channel = grpc::CreateChannel(FLAGS_hostname, grpc::InsecureChannelCredentials());\n    auto stub = Inference::NewStub(channel);\n\n    auto infer_prepare_fn = [&stub](::grpc::ClientContext * context,\n                                    ::grpc::CompletionQueue * cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncBidirectional(context, cq));\n    };\n\n    auto stream = std::make_unique<ClientStreaming<Input, Output>>(\n        infer_prepare_fn, executor,\n        [](Input&& request) {\n            LOG_FIRST_N(INFO, 10) << \"Sent Request with BatchID: \" << request.batch_id();\n        },\n        [&mutex, &count](Output&& response) {\n            static size_t last = 0;\n            LOG_FIRST_N(INFO, 10) << \"Received Response with BatchID: \" << response.batch_id();\n            CHECK_EQ(++last, response.batch_id());\n            std::lock_guard<std::mutex> lock(mutex);\n            --count;\n        });\n\n    auto start = std::chrono::steady_clock::now();\n    auto elapsed = [start]() -> float {\n        return std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n    };\n\n    for(int i = 1; i < FLAGS_count + 1; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        stream->Write(std::move(input));\n    }\n    std::cout << FLAGS_count << \" queued in \" << elapsed() << \"seconds\" << std::endl;\n    auto future = stream->Done();\n    // auto future = stream->Status();\n    auto status = future.get();\n    std::cout << FLAGS_count << \" completed in \" << elapsed() << \"seconds\" << std::endl;\n    std::cout << \"gRPC Status: \" << (status.ok() ? \"OK\" : \"NOT OK\") << std::endl;\n    executor->ShutdownAndJoin();\n    CHECK_EQ(count, 0UL);\n    return 0;\n}"
  },
  {
    "path": "examples/nvRPC/StreamingService/common.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Executor;\nusing nvrpc::Server;\nusing nvrpc::StreamingContext;\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n"
  },
  {
    "path": "examples/nvRPC/StreamingService/even-odds.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"common.h\"\n\n// clang-format off\nstruct SimpleResources : public Resources\n{\n    SimpleResources(int numThreadsInPool = 3) : m_ThreadPool(numThreadsInPool) {}\n    ThreadPool& AcquireThreadPool() { return m_ThreadPool; }\n  private:\n    ThreadPool m_ThreadPool;\n};\n// clang-format on\n\nclass SimpleContext final : public StreamingContext<simple::Input, simple::Output, SimpleResources>\n{\n    void RequestReceived(RequestType&& input, std::shared_ptr<ServerStream> stream) final override\n    {\n        LOG_FIRST_N(INFO, 10) << \"BatchID: \" << input.batch_id() << \" Tag = \" << Tag()\n                              << \" Thread = \" << std::this_thread::get_id();\n\n        // If even, send back two responses.\n        // If odd, do nothing\n        if(input.batch_id() % 2 == 0)\n        {\n            LOG_FIRST_N(INFO, 5) << \"Received Even an BatchID: Sending back two responses\";\n            for(int i = input.batch_id() - 1; i <= input.batch_id(); i++)\n            {\n                ResponseType output;\n                output.set_batch_id(i);\n                stream->WriteResponse(std::move(output));\n            }\n        }\n        else\n        {\n            LOG_FIRST_N(INFO, 5) << \"Received an Odd BatchID: No Response will be sent\";\n        }\n    }\n};\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\nDEFINE_string(ip_port, \"0.0.0.0:50051\", \"IP/Port\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    Server server(FLAGS_ip_port);\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestBidirectional);\n    auto rpcResources = std::make_shared<SimpleResources>(FLAGS_thread_count);\n    auto executor = server.RegisterExecutor(new Executor(1));\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n    server.Run(std::chrono::milliseconds(2000), [] {});\n}\n"
  },
  {
    "path": "examples/nvRPC/StreamingService/ping-pong.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"common.h\"\n\n// clang-format off\nstruct SimpleResources : public Resources\n{\n    SimpleResources(int numThreadsInPool = 3) : m_ThreadPool(numThreadsInPool) {}\n    ThreadPool& AcquireThreadPool() { return m_ThreadPool; }\n  private:\n    ThreadPool m_ThreadPool;\n};\n// clang-format on\n\nclass SimpleContext final : public StreamingContext<simple::Input, simple::Output, SimpleResources>\n{\n    void RequestReceived(RequestType&& input, std::shared_ptr<ServerStream> stream) final override\n    {\n        LOG_FIRST_N(INFO, 10) << \"BatchID: \" << input.batch_id() << \" Tag = \" << Tag()\n                              << \" Thread = \" << std::this_thread::get_id();\n        ResponseType output;\n        output.set_batch_id(input.batch_id());\n        stream->WriteResponse(std::move(output));\n        // TODO: add a test which the server closes the before the client does\n        // stream->FinishStream();\n    }\n};\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\nDEFINE_string(ip_port, \"0.0.0.0:50051\", \"IP/Port\");\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    Server server(FLAGS_ip_port);\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestBidirectional);\n    auto rpcResources = std::make_shared<SimpleResources>(FLAGS_thread_count);\n    auto executor = server.RegisterExecutor(new Executor(1));\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n    server.Run(std::chrono::milliseconds(2000), [] {});\n}\n"
  },
  {
    "path": "examples/nvRPC/StreamingService/test.sh",
    "content": "#!/bin/bash \n\ncleanup() {\n  kill $(jobs -p) ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\nexport PATH=\".:$PATH\"\n\nexe=${1:-\"./nvrpc-ping-pong-server.x\"}\n\n$exe --ip_port=\"0.0.0.0:5555\" &\n\nf=$(mktmp)\ncat <<EOF > $f\nPS1='nvRPC Bidirectional: '\n\ngo() { ./nvrpc-streaming-client.x --hostname=\"localhost:5555\" --count=${1:-100} }\nEOF\n\nps aux\n\necho\necho 'Try ./nvrpc-streaming-client.x --hostname=\"localhost:5555\" --count=100'\nbash --rcfile <(echo \"PS1='nvRPC StreamingService: '\")\n"
  },
  {
    "path": "examples/nvRPC/UnaryService/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_executable(nvrpc-unary-server.x\n    server.cc)\n\ntarget_link_libraries(nvrpc-unary-server.x\n    nvrpc\n    echo-protos\n    gflags\n)\n\nadd_executable(nvrpc-unary-client.x\n    client.cc)\n\ntarget_link_libraries(nvrpc-unary-client.x\n    nvrpc\n    nvrpc-client\n    echo-protos\n    gflags\n)"
  },
  {
    "path": "examples/nvRPC/UnaryService/client.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <grpcpp/grpcpp.h>\n\n#include \"nvrpc/client/client_unary.h\"\n#include \"nvrpc/client/executor.h\"\n\nusing grpc::Channel;\nusing grpc::ClientContext;\nusing grpc::Status;\n\nusing nvrpc::client::ClientUnary;\nusing nvrpc::client::Executor;\n\n#include \"echo.grpc.pb.h\"\n\nusing simple::Inference;\nusing simple::Input;\nusing simple::Output;\n\nDEFINE_int32(count, 100, \"number of grpc messages to send\");\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\nint main(int argc, char** argv)\n{\n    // Instantiate the client. It requires a channel, out of which the actual RPCs\n    // are created. This channel models a connection to an endpoint (in this case,\n    // localhost at port 50051). We indicate that the channel isn't authenticated\n    // (use of InsecureChannelCredentials()).\n    FLAGS_alsologtostderr = 1; // It will dump to console\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    auto executor = std::make_shared<Executor>(FLAGS_thread_count);\n\n    auto channel = grpc::CreateChannel(\"localhost:50051\", grpc::InsecureChannelCredentials());\n    auto stub = Inference::NewStub(channel);\n\n    auto infer_prepare_fn = [&stub](::grpc::ClientContext * context, const ::simple::Input& request,\n                                    ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncCompute(context, request, cq));\n    };\n\n    auto runner = std::make_unique<ClientUnary<Input, Output>>(infer_prepare_fn, executor);\n\n    auto start = std::chrono::steady_clock::now();\n    auto elapsed = [start]() -> float {\n        return std::chrono::duration<float>(std::chrono::steady_clock::now() - start).count();\n    };\n\n    for(int i = 0; i < FLAGS_count; i++)\n    {\n        Input input;\n        input.set_batch_id(i);\n        runner->Enqueue(std::move(input),\n                        [i](Input& input, Output& output, ::grpc::Status& status) -> bool {\n                            CHECK(output.batch_id() == i);\n                            LOG_FIRST_N(INFO, 20) << \"Check: \" << i;\n                            return (bool)(output.batch_id() == i);\n                        });\n    }\n    std::cout << FLAGS_count << \" queued in \" << elapsed() << \"seconds\" << std::endl;\n    executor->ShutdownAndJoin();\n    std::cout << FLAGS_count << \" completed in \" << elapsed() << \"seconds\" << std::endl;\n    return 0;\n}"
  },
  {
    "path": "examples/nvRPC/UnaryService/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n#include <thread>\n\n#include \"tensorrt/laboratory/core/pool.h\"\n#include \"tensorrt/laboratory/core/resources.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n\nusing trtlab::Resources;\nusing trtlab::ThreadPool;\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\nusing nvrpc::AsyncRPC;\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\n\n#include \"echo.grpc.pb.h\"\n#include \"echo.pb.h\"\n\n// CLI Options\nDEFINE_int32(thread_count, 1, \"Size of thread pool\");\n\n/**\n * Embedding a copy of the Protobuf specification for the gRPC service.\n *\n * Package Name: simple\n * Service Name: Inference\n *     RPC Name: Compute\n *\n * Incoming Message: Input\n * Outgoing Message: Ouput\n **\n\nsyntax = \"proto3\";\n\npackage simple;\n\nservice Inference {\n   rpc Compute (Input) returns (Output) {}\n}\n\nmessage Input {\n    uint64 batch_id = 1;\n}\n\nmessage Output {\n    uint64 batch_id = 1;\n}\n*/\n\n// Define the resources your RPC will need to execute\n// ==================================================\n// In this case, all simple::Inference::Compute RPCs share a threadpool in which they will\n// queue up some work on.  This essentially means, after the message as been received and\n// processed, the actual work for the RPC is pushed to a worker pool outside the scope of\n// the transaction processing system (TPS).  This is essentially async computing, we have\n// decoupled the transaction from the workers executing the implementation.  The TPS can\n// continue to queue work, while the workers process the load.\nstruct SimpleResources : public Resources\n{\n    SimpleResources(int numThreadsInPool = 3) : m_ThreadPool(numThreadsInPool)\n    {\n        LOG(INFO) << \"Server ThreadCount: \" << numThreadsInPool;\n    }\n\n    ThreadPool& AcquireThreadPool() { return m_ThreadPool; }\n\n  private:\n    ThreadPool m_ThreadPool;\n};\n\n// Contexts hold the state and provide the definition of the work to be performed by the RPC.\n// This is where you define what gets executed for a given RPC.\n// Incoming Message = simple::Input (RequestType)\n// Outgoing Message = simple::Output (ResponseType)\nclass SimpleContext final : public Context<simple::Input, simple::Output, SimpleResources>\n{\n    void ExecuteRPC(RequestType& input, ResponseType& output) final override\n    {\n        // We could do work here, but we'd block the TPS, i.e. the threads pulling messages\n        // off the incoming recieve queue.  Very quick responses are best done here; however,\n        // longer running workload should be offloaded so the TPS can avoid being blocked.\n        GetResources()->AcquireThreadPool().enqueue([this, &input, &output] {\n            // Now running on a worker thread of the ThreadPool defined in SimpleResources.\n            // Here we are just echoing back the incoming // batch_id; however, in later\n            // examples, we'll show how to run an async cuda pipline.\n            LOG_FIRST_N(INFO, 20) << \"Tag = \" << Tag()\n                                  << \" Thread = \" << std::this_thread::get_id();\n            output.set_batch_id(input.batch_id());\n            this->FinishResponse();\n        });\n        // The TPS thread is now free to continue processing message - async ftw!\n    }\n};\n\nint main(int argc, char* argv[])\n{\n    FLAGS_alsologtostderr = 1; // Log to console\n\n    ::google::InitGoogleLogging(\"simpleServer\");\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n\n    // A server will bind an IP:PORT to listen on\n    Server server(\"0.0.0.0:50051\");\n\n    // A server can host multiple services\n    LOG(INFO) << \"Register Service (simple::Inference) with Server\";\n    auto simpleInference = server.RegisterAsyncService<simple::Inference>();\n\n    // An RPC has two components that need to be specified when registering with the service:\n    //  1) Type of Execution Context (SimpleContext).  The execution context defines the behavor\n    //     of the RPC, i.e. it contains the control logic for the execution of the RPC.\n    //  2) The Request function (RequestCompute) which was generated by gRPC when compiling the\n    //     protobuf which defined the service.  This function is responsible for queuing the\n    //     RPC's execution context to the\n    LOG(INFO) << \"Register RPC (simple::Inference::Compute) with Service (simple::Inference)\";\n    auto rpcCompute = simpleInference->RegisterRPC<SimpleContext>(\n        &simple::Inference::AsyncService::RequestCompute);\n\n    LOG(INFO) << \"Initializing Resources for RPC (simple::Inference::Compute)\";\n    auto rpcResources = std::make_shared<SimpleResources>(FLAGS_thread_count);\n\n    // Create Executors - Executors provide the messaging processing resources for the RPCs\n    // Multiple Executors can be registered with a Server.  The executor is responsible\n    // for pulling incoming message off the receive queue and executing the associated\n    // context.  By default, an executor only uses a single thread.  A typical usecase is\n    // an Executor executes a context, which immediate pushes the work to a thread pool.\n    // However, for very low-latency messaging, you might want to use a multi-threaded\n    // Executor and a Blocking Context - meaning the Context performs the entire RPC function\n    // on the Executor's thread.\n    LOG(INFO) << \"Creating Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    // You can register RPC execution contexts from any registered RPC on any executor.\n    // The power of that will become clear in later examples. For now, we will register\n    // 10 instances of the simple::Inference::Compute RPC's SimpleContext execution context\n    // with the Executor.\n    LOG(INFO) << \"Creating Execution Contexts for RPC (simple::Inference::Compute) with Executor\";\n    executor->RegisterContexts(rpcCompute, rpcResources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(2000), [] {\n        // This is a timeout loop executed every 2seconds\n        // Run() with no arguments will run an empty timeout loop every 5 seconds.\n        // RunAsync() will return immediately, its your responsibility to ensure the\n        // server doesn't go out of scope or a Shutdown will be triggered on your services.\n    });\n}\n"
  },
  {
    "path": "jupyter_notebook_config.py",
    "content": "# Configuration file for jupyter-notebook.\n\n#------------------------------------------------------------------------------\n# Application(SingletonConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## This is an application.\n\n## The date format used by logging formatters for %(asctime)s\n#c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S'\n\n## The Logging format template\n#c.Application.log_format = '[%(name)s]%(highlevel)s %(message)s'\n\n## Set the log level by value or name.\n#c.Application.log_level = 30\n\n#------------------------------------------------------------------------------\n# JupyterApp(Application) configuration\n#------------------------------------------------------------------------------\n\n## Base class for Jupyter applications\n\n## Answer yes to any prompts.\n#c.JupyterApp.answer_yes = False\n\n## Full path of a config file.\n#c.JupyterApp.config_file = ''\n\n## Specify a config file to load.\n#c.JupyterApp.config_file_name = ''\n\n## Generate default config file.\n#c.JupyterApp.generate_config = False\n\n#------------------------------------------------------------------------------\n# NotebookApp(JupyterApp) configuration\n#------------------------------------------------------------------------------\n\n## Set the Access-Control-Allow-Credentials: true header\n#c.NotebookApp.allow_credentials = False\n\n## Set the Access-Control-Allow-Origin header\n#  \n#  Use '*' to allow any origin to access your server.\n#  \n#  Takes precedence over allow_origin_pat.\n#c.NotebookApp.allow_origin = ''\n\n## Use a regular expression for the Access-Control-Allow-Origin header\n#  \n#  Requests from an origin matching the expression will get replies with:\n#  \n#      Access-Control-Allow-Origin: origin\n#  \n#  where `origin` is the origin of the request.\n#  \n#  Ignored if allow_origin is set.\n#c.NotebookApp.allow_origin_pat = ''\n\n## Allow password to be changed at login for the notebook server.\n#  \n#  While loggin in with a token, the notebook server UI will give the opportunity\n#  to the user to enter a new password at the same time that will replace the\n#  token login mechanism.\n#  \n#  This can be set to false to prevent changing password from the UI/API.\n#c.NotebookApp.allow_password_change = True\n\n## Allow requests where the Host header doesn't point to a local server\n#  \n#  By default, requests get a 403 forbidden response if the 'Host' header shows\n#  that the browser thinks it's on a non-local domain. Setting this option to\n#  True disables this check.\n#  \n#  This protects against 'DNS rebinding' attacks, where a remote web server\n#  serves you a page and then changes its DNS to send later requests to a local\n#  IP, bypassing same-origin checks.\n#  \n#  Local IP addresses (such as 127.0.0.1 and ::1) are allowed as local, along\n#  with hostnames configured in local_hostnames.\nc.NotebookApp.allow_remote_access = True\n\n## Whether to allow the user to run the notebook as root.\nc.NotebookApp.allow_root = True\n\n## DEPRECATED use base_url\n#c.NotebookApp.base_project_url = '/'\n\n## The base URL for the notebook server.\n#  \n#  Leading and trailing slashes can be omitted, and will automatically be added.\n#c.NotebookApp.base_url = '/'\n\n## Specify what command to use to invoke a web browser when opening the notebook.\n#  If not specified, the default browser will be determined by the `webbrowser`\n#  standard library module, which allows setting of the BROWSER environment\n#  variable to override it.\n#c.NotebookApp.browser = ''\n\n## The full path to an SSL/TLS certificate file.\n#c.NotebookApp.certfile = ''\n\n## The full path to a certificate authority certificate for SSL/TLS client\n#  authentication.\n#c.NotebookApp.client_ca = ''\n\n## The config manager class to use\n#c.NotebookApp.config_manager_class = 'notebook.services.config.manager.ConfigManager'\n\n## The notebook manager class to use.\n#c.NotebookApp.contents_manager_class = 'notebook.services.contents.largefilemanager.LargeFileManager'\n\n## Extra keyword arguments to pass to `set_secure_cookie`. See tornado's\n#  set_secure_cookie docs for details.\n#c.NotebookApp.cookie_options = {}\n\n## The random bytes used to secure cookies. By default this is a new random\n#  number every time you start the Notebook. Set it to a value in a config file\n#  to enable logins to persist across server sessions.\n#  \n#  Note: Cookie secrets should be kept private, do not share config files with\n#  cookie_secret stored in plaintext (you can read the value from a file).\n#c.NotebookApp.cookie_secret = b''\n\n## The file where the cookie secret is stored.\n#c.NotebookApp.cookie_secret_file = ''\n\n## Override URL shown to users.\n#  \n#  Replace actual URL, including protocol, address, port and base URL, with the\n#  given value when displaying URL to the users. Do not change the actual\n#  connection URL. If authentication token is enabled, the token is added to the\n#  custom URL automatically.\n#  \n#  This option is intended to be used when the URL to display to the user cannot\n#  be determined reliably by the Jupyter notebook server (proxified or\n#  containerized setups for example).\n#c.NotebookApp.custom_display_url = ''\n\n## The default URL to redirect to from `/`\n#c.NotebookApp.default_url = '/tree'\n\n## Disable cross-site-request-forgery protection\n#  \n#  Jupyter notebook 4.3.1 introduces protection from cross-site request\n#  forgeries, requiring API requests to either:\n#  \n#  - originate from pages served by this server (validated with XSRF cookie and\n#  token), or - authenticate with a token\n#  \n#  Some anonymous compute resources still desire the ability to run code,\n#  completely without authentication. These services can disable all\n#  authentication and security checks, with the full knowledge of what that\n#  implies.\n#c.NotebookApp.disable_check_xsrf = False\n\n## Whether to enable MathJax for typesetting math/TeX\n#  \n#  MathJax is the javascript library Jupyter uses to render math/LaTeX. It is\n#  very large, so you may want to disable it if you have a slow internet\n#  connection, or for offline use of the notebook.\n#  \n#  When disabled, equations etc. will appear as their untransformed TeX source.\n#c.NotebookApp.enable_mathjax = True\n\n## extra paths to look for Javascript notebook extensions\n#c.NotebookApp.extra_nbextensions_path = []\n\n## handlers that should be loaded at higher priority than the default services\n#c.NotebookApp.extra_services = []\n\n## Extra paths to search for serving static files.\n#  \n#  This allows adding javascript/css to be available from the notebook server\n#  machine, or overriding individual files in the IPython\n#c.NotebookApp.extra_static_paths = []\n\n## Extra paths to search for serving jinja templates.\n#  \n#  Can be used to override templates from notebook.templates.\n#c.NotebookApp.extra_template_paths = []\n\n## \n#c.NotebookApp.file_to_run = ''\n\n## Extra keyword arguments to pass to `get_secure_cookie`. See tornado's\n#  get_secure_cookie docs for details.\n#c.NotebookApp.get_secure_cookie_kwargs = {}\n\n## Deprecated: Use minified JS file or not, mainly use during dev to avoid JS\n#  recompilation\n#c.NotebookApp.ignore_minified_js = False\n\n## (bytes/sec) Maximum rate at which stream output can be sent on iopub before\n#  they are limited.\n#c.NotebookApp.iopub_data_rate_limit = 1000000\n\n## (msgs/sec) Maximum rate at which messages can be sent on iopub before they are\n#  limited.\n#c.NotebookApp.iopub_msg_rate_limit = 1000\n\n## The IP address the notebook server will listen on.\nc.NotebookApp.ip = '0.0.0.0'\n\n## Supply extra arguments that will be passed to Jinja environment.\n#c.NotebookApp.jinja_environment_options = {}\n\n## Extra variables to supply to jinja templates when rendering.\n#c.NotebookApp.jinja_template_vars = {}\n\n## The kernel manager class to use.\n#c.NotebookApp.kernel_manager_class = 'notebook.services.kernels.kernelmanager.MappingKernelManager'\n\n## The kernel spec manager class to use. Should be a subclass of\n#  `jupyter_client.kernelspec.KernelSpecManager`.\n#  \n#  The Api of KernelSpecManager is provisional and might change without warning\n#  between this version of Jupyter and the next stable one.\n#c.NotebookApp.kernel_spec_manager_class = 'jupyter_client.kernelspec.KernelSpecManager'\n\n## The full path to a private key file for usage with SSL/TLS.\n#c.NotebookApp.keyfile = ''\n\n## Hostnames to allow as local when allow_remote_access is False.\n#  \n#  Local IP addresses (such as 127.0.0.1 and ::1) are automatically accepted as\n#  local as well.\n#c.NotebookApp.local_hostnames = ['localhost']\n\n## The login handler class to use.\n#c.NotebookApp.login_handler_class = 'notebook.auth.login.LoginHandler'\n\n## The logout handler class to use.\n#c.NotebookApp.logout_handler_class = 'notebook.auth.logout.LogoutHandler'\n\n## The MathJax.js configuration file that is to be used.\n#c.NotebookApp.mathjax_config = 'TeX-AMS-MML_HTMLorMML-full,Safe'\n\n## A custom url for MathJax.js. Should be in the form of a case-sensitive url to\n#  MathJax, for example:  /static/components/MathJax/MathJax.js\n#c.NotebookApp.mathjax_url = ''\n\n## Sets the maximum allowed size of the client request body, specified in  the\n#  Content-Length request header field. If the size in a request  exceeds the\n#  configured value, a malformed HTTP message is returned to the client.\n#  \n#  Note: max_body_size is applied even in streaming mode.\n#c.NotebookApp.max_body_size = 536870912\n\n## Gets or sets the maximum amount of memory, in bytes, that is allocated  for\n#  use by the buffer manager.\n#c.NotebookApp.max_buffer_size = 536870912\n\n## Dict of Python modules to load as notebook server extensions.Entry values can\n#  be used to enable and disable the loading ofthe extensions. The extensions\n#  will be loaded in alphabetical order.\n#c.NotebookApp.nbserver_extensions = {}\n\n## The directory to use for notebooks and kernels.\nc.NotebookApp.notebook_dir = '/work'\n\n## Whether to open in a browser after starting. The specific browser used is\n#  platform dependent and determined by the python standard library `webbrowser`\n#  module, unless it is overridden using the --browser (NotebookApp.browser)\n#  configuration option.\n#c.NotebookApp.open_browser = True\n\n## Hashed password to use for web authentication.\n#  \n#  To generate, type in a python/IPython shell:\n#  \n#    from notebook.auth import passwd; passwd()\n#  \n#  The string should be of the form type:salt:hashed-password.\n#c.NotebookApp.password = ''\n\n## Forces users to use a password for the Notebook server. This is useful in a\n#  multi user environment, for instance when everybody in the LAN can access each\n#  other's machine through ssh.\n#  \n#  In such a case, server the notebook server on localhost is not secure since\n#  any user can connect to the notebook server via ssh.\n#c.NotebookApp.password_required = False\n\n## The port the notebook server will listen on.\n#c.NotebookApp.port = 8888\n\n## The number of additional ports to try if the specified port is not available.\n#c.NotebookApp.port_retries = 50\n\n## DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.\n#c.NotebookApp.pylab = 'disabled'\n\n## If True, display a button in the dashboard to quit (shutdown the notebook\n#  server).\n#c.NotebookApp.quit_button = True\n\n## (sec) Time window used to  check the message and data rate limits.\n#c.NotebookApp.rate_limit_window = 3\n\n## Reraise exceptions encountered loading server extensions?\n#c.NotebookApp.reraise_server_extension_failures = False\n\n## DEPRECATED use the nbserver_extensions dict instead\n#c.NotebookApp.server_extensions = []\n\n## The session manager class to use.\n#c.NotebookApp.session_manager_class = 'notebook.services.sessions.sessionmanager.SessionManager'\n\n## Shut down the server after N seconds with no kernels or terminals running and\n#  no activity. This can be used together with culling idle kernels\n#  (MappingKernelManager.cull_idle_timeout) to shutdown the notebook server when\n#  it's not in use. This is not precisely timed: it may shut down up to a minute\n#  later. 0 (the default) disables this automatic shutdown.\n#c.NotebookApp.shutdown_no_activity_timeout = 0\n\n## Supply SSL options for the tornado HTTPServer. See the tornado docs for\n#  details.\n#c.NotebookApp.ssl_options = {}\n\n## Supply overrides for terminado. Currently only supports \"shell_command\".\n#c.NotebookApp.terminado_settings = {}\n\n## Set to False to disable terminals.\n#  \n#  This does *not* make the notebook server more secure by itself. Anything the\n#  user can in a terminal, they can also do in a notebook.\n#  \n#  Terminals may also be automatically disabled if the terminado package is not\n#  available.\n#c.NotebookApp.terminals_enabled = True\n\n## Token used for authenticating first-time connections to the server.\n#  \n#  When no password is enabled, the default is to generate a new, random token.\n#  \n#  Setting to an empty string disables authentication altogether, which is NOT\n#  RECOMMENDED.\n#c.NotebookApp.token = '<generated>'\n\n## Supply overrides for the tornado.web.Application that the Jupyter notebook\n#  uses.\n#c.NotebookApp.tornado_settings = {}\n\n## Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-\n#  For headerssent by the upstream reverse proxy. Necessary if the proxy handles\n#  SSL\n#c.NotebookApp.trust_xheaders = False\n\n## DEPRECATED, use tornado_settings\n#c.NotebookApp.webapp_settings = {}\n\n## Specify Where to open the notebook on startup. This is the `new` argument\n#  passed to the standard library method `webbrowser.open`. The behaviour is not\n#  guaranteed, but depends on browser support. Valid values are:\n#  \n#   - 2 opens a new tab,\n#   - 1 opens a new window,\n#   - 0 opens in an existing window.\n#  \n#  See the `webbrowser.open` documentation for details.\n#c.NotebookApp.webbrowser_open_new = 2\n\n## Set the tornado compression options for websocket connections.\n#  \n#  This value will be returned from\n#  :meth:`WebSocketHandler.get_compression_options`. None (default) will disable\n#  compression. A dict (even an empty one) will enable compression.\n#  \n#  See the tornado docs for WebSocketHandler.get_compression_options for details.\n#c.NotebookApp.websocket_compression_options = None\n\n## The base URL for websockets, if it differs from the HTTP server (hint: it\n#  almost certainly doesn't).\n#  \n#  Should be in the form of an HTTP origin: ws[s]://hostname[:port]\n#c.NotebookApp.websocket_url = ''\n\n#------------------------------------------------------------------------------\n# ConnectionFileMixin(LoggingConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## Mixin for configurable classes that work with connection files\n\n## JSON file in which to store connection info [default: kernel-<pid>.json]\n#  \n#  This file will contain the IP, ports, and authentication key needed to connect\n#  clients to this kernel. By default, this file will be created in the security\n#  dir of the current profile, but can be specified by absolute path.\n#c.ConnectionFileMixin.connection_file = ''\n\n## set the control (ROUTER) port [default: random]\n#c.ConnectionFileMixin.control_port = 0\n\n## set the heartbeat port [default: random]\n#c.ConnectionFileMixin.hb_port = 0\n\n## set the iopub (PUB) port [default: random]\n#c.ConnectionFileMixin.iopub_port = 0\n\n## Set the kernel's IP address [default localhost]. If the IP address is\n#  something other than localhost, then Consoles on other machines will be able\n#  to connect to the Kernel, so be careful!\n#c.ConnectionFileMixin.ip = ''\n\n## set the shell (ROUTER) port [default: random]\n#c.ConnectionFileMixin.shell_port = 0\n\n## set the stdin (ROUTER) port [default: random]\n#c.ConnectionFileMixin.stdin_port = 0\n\n## \n#c.ConnectionFileMixin.transport = 'tcp'\n\n#------------------------------------------------------------------------------\n# KernelManager(ConnectionFileMixin) configuration\n#------------------------------------------------------------------------------\n\n## Manages a single kernel in a subprocess on this host.\n#  \n#  This version starts kernels with Popen.\n\n## Should we autorestart the kernel if it dies.\n#c.KernelManager.autorestart = True\n\n## DEPRECATED: Use kernel_name instead.\n#  \n#  The Popen Command to launch the kernel. Override this if you have a custom\n#  kernel. If kernel_cmd is specified in a configuration file, Jupyter does not\n#  pass any arguments to the kernel, because it cannot make any assumptions about\n#  the arguments that the kernel understands. In particular, this means that the\n#  kernel does not receive the option --debug if it given on the Jupyter command\n#  line.\n#c.KernelManager.kernel_cmd = []\n\n## Time to wait for a kernel to terminate before killing it, in seconds.\n#c.KernelManager.shutdown_wait_time = 5.0\n\n#------------------------------------------------------------------------------\n# Session(Configurable) configuration\n#------------------------------------------------------------------------------\n\n## Object for handling serialization and sending of messages.\n#  \n#  The Session object handles building messages and sending them with ZMQ sockets\n#  or ZMQStream objects.  Objects can communicate with each other over the\n#  network via Session objects, and only need to work with the dict-based IPython\n#  message spec. The Session will handle serialization/deserialization, security,\n#  and metadata.\n#  \n#  Sessions support configurable serialization via packer/unpacker traits, and\n#  signing with HMAC digests via the key/keyfile traits.\n#  \n#  Parameters ----------\n#  \n#  debug : bool\n#      whether to trigger extra debugging statements\n#  packer/unpacker : str : 'json', 'pickle' or import_string\n#      importstrings for methods to serialize message parts.  If just\n#      'json' or 'pickle', predefined JSON and pickle packers will be used.\n#      Otherwise, the entire importstring must be used.\n#  \n#      The functions must accept at least valid JSON input, and output *bytes*.\n#  \n#      For example, to use msgpack:\n#      packer = 'msgpack.packb', unpacker='msgpack.unpackb'\n#  pack/unpack : callables\n#      You can also set the pack/unpack callables for serialization directly.\n#  session : bytes\n#      the ID of this Session object.  The default is to generate a new UUID.\n#  username : unicode\n#      username added to message headers.  The default is to ask the OS.\n#  key : bytes\n#      The key used to initialize an HMAC signature.  If unset, messages\n#      will not be signed or checked.\n#  keyfile : filepath\n#      The file containing a key.  If this is set, `key` will be initialized\n#      to the contents of the file.\n\n## Threshold (in bytes) beyond which an object's buffer should be extracted to\n#  avoid pickling.\n#c.Session.buffer_threshold = 1024\n\n## Whether to check PID to protect against calls after fork.\n#  \n#  This check can be disabled if fork-safety is handled elsewhere.\n#c.Session.check_pid = True\n\n## Threshold (in bytes) beyond which a buffer should be sent without copying.\n#c.Session.copy_threshold = 65536\n\n## Debug output in the Session\n#c.Session.debug = False\n\n## The maximum number of digests to remember.\n#  \n#  The digest history will be culled when it exceeds this value.\n#c.Session.digest_history_size = 65536\n\n## The maximum number of items for a container to be introspected for custom\n#  serialization. Containers larger than this are pickled outright.\n#c.Session.item_threshold = 64\n\n## execution key, for signing messages.\n#c.Session.key = b''\n\n## path to file containing execution key.\n#c.Session.keyfile = ''\n\n## Metadata dictionary, which serves as the default top-level metadata dict for\n#  each message.\n#c.Session.metadata = {}\n\n## The name of the packer for serializing messages. Should be one of 'json',\n#  'pickle', or an import name for a custom callable serializer.\n#c.Session.packer = 'json'\n\n## The UUID identifying this session.\n#c.Session.session = ''\n\n## The digest scheme used to construct the message signatures. Must have the form\n#  'hmac-HASH'.\n#c.Session.signature_scheme = 'hmac-sha256'\n\n## The name of the unpacker for unserializing messages. Only used with custom\n#  functions for `packer`.\n#c.Session.unpacker = 'json'\n\n## Username for the Session. Default is your system username.\n#c.Session.username = 'username'\n\n#------------------------------------------------------------------------------\n# MultiKernelManager(LoggingConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## A class for managing multiple kernels.\n\n## The name of the default kernel to start\n#c.MultiKernelManager.default_kernel_name = 'python3'\n\n## The kernel manager class.  This is configurable to allow subclassing of the\n#  KernelManager for customized behavior.\n#c.MultiKernelManager.kernel_manager_class = 'jupyter_client.ioloop.IOLoopKernelManager'\n\n#------------------------------------------------------------------------------\n# MappingKernelManager(MultiKernelManager) configuration\n#------------------------------------------------------------------------------\n\n## A KernelManager that handles notebook mapping and HTTP error handling\n\n## Whether messages from kernels whose frontends have disconnected should be\n#  buffered in-memory.\n#  \n#  When True (default), messages are buffered and replayed on reconnect, avoiding\n#  lost messages due to interrupted connectivity.\n#  \n#  Disable if long-running kernels will produce too much output while no\n#  frontends are connected.\n#c.MappingKernelManager.buffer_offline_messages = True\n\n## Whether to consider culling kernels which are busy. Only effective if\n#  cull_idle_timeout > 0.\n#c.MappingKernelManager.cull_busy = False\n\n## Whether to consider culling kernels which have one or more connections. Only\n#  effective if cull_idle_timeout > 0.\n#c.MappingKernelManager.cull_connected = False\n\n## Timeout (in seconds) after which a kernel is considered idle and ready to be\n#  culled. Values of 0 or lower disable culling. Very short timeouts may result\n#  in kernels being culled for users with poor network connections.\n#c.MappingKernelManager.cull_idle_timeout = 0\n\n## The interval (in seconds) on which to check for idle kernels exceeding the\n#  cull timeout value.\n#c.MappingKernelManager.cull_interval = 300\n\n## Timeout for giving up on a kernel (in seconds).\n#  \n#  On starting and restarting kernels, we check whether the kernel is running and\n#  responsive by sending kernel_info_requests. This sets the timeout in seconds\n#  for how long the kernel can take before being presumed dead.  This affects the\n#  MappingKernelManager (which handles kernel restarts)  and the\n#  ZMQChannelsHandler (which handles the startup).\n#c.MappingKernelManager.kernel_info_timeout = 60\n\n## \n#c.MappingKernelManager.root_dir = ''\n\n#------------------------------------------------------------------------------\n# ContentsManager(LoggingConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## Base class for serving files and directories.\n#  \n#  This serves any text or binary file, as well as directories, with special\n#  handling for JSON notebook documents.\n#  \n#  Most APIs take a path argument, which is always an API-style unicode path, and\n#  always refers to a directory.\n#  \n#  - unicode, not url-escaped\n#  - '/'-separated\n#  - leading and trailing '/' will be stripped\n#  - if unspecified, path defaults to '',\n#    indicating the root path.\n\n## Allow access to hidden files\n#c.ContentsManager.allow_hidden = False\n\n## \n#c.ContentsManager.checkpoints = None\n\n## \n#c.ContentsManager.checkpoints_class = 'notebook.services.contents.checkpoints.Checkpoints'\n\n## \n#c.ContentsManager.checkpoints_kwargs = {}\n\n## handler class to use when serving raw file requests.\n#  \n#  Default is a fallback that talks to the ContentsManager API, which may be\n#  inefficient, especially for large files.\n#  \n#  Local files-based ContentsManagers can use a StaticFileHandler subclass, which\n#  will be much more efficient.\n#  \n#  Access to these files should be Authenticated.\n#c.ContentsManager.files_handler_class = 'notebook.files.handlers.FilesHandler'\n\n## Extra parameters to pass to files_handler_class.\n#  \n#  For example, StaticFileHandlers generally expect a `path` argument specifying\n#  the root directory from which to serve files.\n#c.ContentsManager.files_handler_params = {}\n\n## Glob patterns to hide in file and directory listings.\n#c.ContentsManager.hide_globs = ['__pycache__', '*.pyc', '*.pyo', '.DS_Store', '*.so', '*.dylib', '*~']\n\n## Python callable or importstring thereof\n#  \n#  To be called on a contents model prior to save.\n#  \n#  This can be used to process the structure, such as removing notebook outputs\n#  or other side effects that should not be saved.\n#  \n#  It will be called as (all arguments passed by keyword)::\n#  \n#      hook(path=path, model=model, contents_manager=self)\n#  \n#  - model: the model to be saved. Includes file contents.\n#    Modifying this dict will affect the file that is stored.\n#  - path: the API path of the save destination\n#  - contents_manager: this ContentsManager instance\n#c.ContentsManager.pre_save_hook = None\n\n## \n#c.ContentsManager.root_dir = '/'\n\n## The base name used when creating untitled directories.\n#c.ContentsManager.untitled_directory = 'Untitled Folder'\n\n## The base name used when creating untitled files.\n#c.ContentsManager.untitled_file = 'untitled'\n\n## The base name used when creating untitled notebooks.\n#c.ContentsManager.untitled_notebook = 'Untitled'\n\n#------------------------------------------------------------------------------\n# FileManagerMixin(Configurable) configuration\n#------------------------------------------------------------------------------\n\n## Mixin for ContentsAPI classes that interact with the filesystem.\n#  \n#  Provides facilities for reading, writing, and copying both notebooks and\n#  generic files.\n#  \n#  Shared by FileContentsManager and FileCheckpoints.\n#  \n#  Note ---- Classes using this mixin must provide the following attributes:\n#  \n#  root_dir : unicode\n#      A directory against against which API-style paths are to be resolved.\n#  \n#  log : logging.Logger\n\n## By default notebooks are saved on disk on a temporary file and then if\n#  succefully written, it replaces the old ones. This procedure, namely\n#  'atomic_writing', causes some bugs on file system whitout operation order\n#  enforcement (like some networked fs). If set to False, the new notebook is\n#  written directly on the old one which could fail (eg: full filesystem or quota\n#  )\n#c.FileManagerMixin.use_atomic_writing = True\n\n#------------------------------------------------------------------------------\n# FileContentsManager(FileManagerMixin,ContentsManager) configuration\n#------------------------------------------------------------------------------\n\n## If True (default), deleting files will send them to the platform's\n#  trash/recycle bin, where they can be recovered. If False, deleting files\n#  really deletes them.\n#c.FileContentsManager.delete_to_trash = True\n\n## Python callable or importstring thereof\n#  \n#  to be called on the path of a file just saved.\n#  \n#  This can be used to process the file on disk, such as converting the notebook\n#  to a script or HTML via nbconvert.\n#  \n#  It will be called as (all arguments passed by keyword)::\n#  \n#      hook(os_path=os_path, model=model, contents_manager=instance)\n#  \n#  - path: the filesystem path to the file just written - model: the model\n#  representing the file - contents_manager: this ContentsManager instance\n#c.FileContentsManager.post_save_hook = None\n\n## \n#c.FileContentsManager.root_dir = ''\n\n## DEPRECATED, use post_save_hook. Will be removed in Notebook 5.0\n#c.FileContentsManager.save_script = False\n\n#------------------------------------------------------------------------------\n# NotebookNotary(LoggingConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## A class for computing and verifying notebook signatures.\n\n## The hashing algorithm used to sign notebooks.\n#c.NotebookNotary.algorithm = 'sha256'\n\n## The sqlite file in which to store notebook signatures. By default, this will\n#  be in your Jupyter data directory. You can set it to ':memory:' to disable\n#  sqlite writing to the filesystem.\n#c.NotebookNotary.db_file = ''\n\n## The secret key with which notebooks are signed.\n#c.NotebookNotary.secret = b''\n\n## The file where the secret key is stored.\n#c.NotebookNotary.secret_file = ''\n\n## A callable returning the storage backend for notebook signatures. The default\n#  uses an SQLite database.\n#c.NotebookNotary.store_factory = traitlets.Undefined\n\n#------------------------------------------------------------------------------\n# KernelSpecManager(LoggingConfigurable) configuration\n#------------------------------------------------------------------------------\n\n## If there is no Python kernelspec registered and the IPython kernel is\n#  available, ensure it is added to the spec list.\n#c.KernelSpecManager.ensure_native_kernel = True\n\n## The kernel spec class.  This is configurable to allow subclassing of the\n#  KernelSpecManager for customized behavior.\n#c.KernelSpecManager.kernel_spec_class = 'jupyter_client.kernelspec.KernelSpec'\n\n## Whitelist of allowed kernel names.\n#  \n#  By default, all installed kernels are allowed.\n#c.KernelSpecManager.whitelist = set()\n"
  },
  {
    "path": "models/README.md",
    "content": "## Sample Models\n\nIncluded in this folder are a collection of open source models and\nsome scripts to build TensorRT engines from these models.\n\nCurrently, the samples provided only generate TensorRT engines\nwith random weights and are only good for synthetic tests.\n\nTODO: update scripts to pull open sourced weights for fully functional\nmodels.\n\n\n## Credits\n\nCaffe ResNet-50 and ResNet-152 models from [KaimingHe/deep-residual-networks]\n(https://github.com/KaimingHe/deep-residual-networks) are included without modification.\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2016 Shaoqing Ren\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n"
  },
  {
    "path": "models/ResNet-152-deploy.prototxt",
    "content": "name: \"ResNet-152\"\ninput: \"data\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 224\ninput_dim: 224\n\nlayer {\n\tbottom: \"data\"\n\ttop: \"conv1\"\n\tname: \"conv1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 7\n\t\tpad: 3\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"conv1\"\n\tname: \"bn_conv1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"conv1\"\n\tname: \"scale_conv1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"conv1\"\n\tbottom: \"conv1\"\n\tname: \"conv1_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"pool1\"\n\tname: \"pool1\"\n\ttype: \"Pooling\"\n\tpooling_param {\n\t\tkernel_size: 3\n\t\tstride: 2\n\t\tpool: MAX\n\t}\n}\n\nlayer {\n\tbottom: \"pool1\"\n\ttop: \"res2a_branch1\"\n\tname: \"res2a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\ttop: \"res2a_branch1\"\n\tname: \"bn2a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\ttop: \"res2a_branch1\"\n\tname: \"scale2a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"pool1\"\n\ttop: \"res2a_branch2a\"\n\tname: \"res2a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2a\"\n\tname: \"bn2a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2a\"\n\tname: \"scale2a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2a_branch2a\"\n\tbottom: \"res2a_branch2a\"\n\tname: \"res2a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2b\"\n\tname: \"res2a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2b\"\n\tname: \"bn2a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2b\"\n\tname: \"scale2a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2a_branch2b\"\n\tbottom: \"res2a_branch2b\"\n\tname: \"res2a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2c\"\n\tname: \"res2a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a_branch2c\"\n\tname: \"bn2a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a_branch2c\"\n\tname: \"scale2a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a\"\n\tname: \"res2a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2a\"\n\ttop: \"res2a\"\n\tname: \"res2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"res2b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"bn2b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"scale2b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2b_branch2a\"\n\tbottom: \"res2b_branch2a\"\n\tname: \"res2b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2b\"\n\tname: \"res2b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2b\"\n\tname: \"bn2b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2b\"\n\tname: \"scale2b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2b_branch2b\"\n\tbottom: \"res2b_branch2b\"\n\tname: \"res2b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2c\"\n\tname: \"res2b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b_branch2c\"\n\tname: \"bn2b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b_branch2c\"\n\tname: \"scale2b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a\"\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b\"\n\tname: \"res2b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2b\"\n\ttop: \"res2b\"\n\tname: \"res2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b\"\n\ttop: \"res2c_branch2a\"\n\tname: \"res2c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2a\"\n\tname: \"bn2c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2a\"\n\tname: \"scale2c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2c_branch2a\"\n\tbottom: \"res2c_branch2a\"\n\tname: \"res2c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2b\"\n\tname: \"res2c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2b\"\n\tname: \"bn2c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2b\"\n\tname: \"scale2c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res2c_branch2b\"\n\tbottom: \"res2c_branch2b\"\n\tname: \"res2c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2c\"\n\tname: \"res2c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c_branch2c\"\n\tname: \"bn2c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c_branch2c\"\n\tname: \"scale2c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b\"\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c\"\n\tname: \"res2c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res2c\"\n\tname: \"res2c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res3a_branch1\"\n\tname: \"res3a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\ttop: \"res3a_branch1\"\n\tname: \"bn3a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\ttop: \"res3a_branch1\"\n\tname: \"scale3a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res3a_branch2a\"\n\tname: \"res3a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2a\"\n\tname: \"bn3a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2a\"\n\tname: \"scale3a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3a_branch2a\"\n\tbottom: \"res3a_branch2a\"\n\tname: \"res3a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2b\"\n\tname: \"res3a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2b\"\n\tname: \"bn3a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2b\"\n\tname: \"scale3a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3a_branch2b\"\n\tbottom: \"res3a_branch2b\"\n\tname: \"res3a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2c\"\n\tname: \"res3a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a_branch2c\"\n\tname: \"bn3a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a_branch2c\"\n\tname: \"scale3a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a\"\n\tname: \"res3a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3a\"\n\ttop: \"res3a\"\n\tname: \"res3a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a\"\n\ttop: \"res3b1_branch2a\"\n\tname: \"res3b1_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2a\"\n\ttop: \"res3b1_branch2a\"\n\tname: \"bn3b1_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2a\"\n\ttop: \"res3b1_branch2a\"\n\tname: \"scale3b1_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b1_branch2a\"\n\tbottom: \"res3b1_branch2a\"\n\tname: \"res3b1_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b1_branch2a\"\n\ttop: \"res3b1_branch2b\"\n\tname: \"res3b1_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2b\"\n\ttop: \"res3b1_branch2b\"\n\tname: \"bn3b1_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2b\"\n\ttop: \"res3b1_branch2b\"\n\tname: \"scale3b1_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b1_branch2b\"\n\tbottom: \"res3b1_branch2b\"\n\tname: \"res3b1_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b1_branch2b\"\n\ttop: \"res3b1_branch2c\"\n\tname: \"res3b1_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2c\"\n\ttop: \"res3b1_branch2c\"\n\tname: \"bn3b1_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1_branch2c\"\n\ttop: \"res3b1_branch2c\"\n\tname: \"scale3b1_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a\"\n\tbottom: \"res3b1_branch2c\"\n\ttop: \"res3b1\"\n\tname: \"res3b1\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b1\"\n\ttop: \"res3b1\"\n\tname: \"res3b1_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b1\"\n\ttop: \"res3b2_branch2a\"\n\tname: \"res3b2_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2a\"\n\ttop: \"res3b2_branch2a\"\n\tname: \"bn3b2_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2a\"\n\ttop: \"res3b2_branch2a\"\n\tname: \"scale3b2_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b2_branch2a\"\n\tbottom: \"res3b2_branch2a\"\n\tname: \"res3b2_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b2_branch2a\"\n\ttop: \"res3b2_branch2b\"\n\tname: \"res3b2_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2b\"\n\ttop: \"res3b2_branch2b\"\n\tname: \"bn3b2_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2b\"\n\ttop: \"res3b2_branch2b\"\n\tname: \"scale3b2_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b2_branch2b\"\n\tbottom: \"res3b2_branch2b\"\n\tname: \"res3b2_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b2_branch2b\"\n\ttop: \"res3b2_branch2c\"\n\tname: \"res3b2_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2c\"\n\ttop: \"res3b2_branch2c\"\n\tname: \"bn3b2_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2_branch2c\"\n\ttop: \"res3b2_branch2c\"\n\tname: \"scale3b2_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b1\"\n\tbottom: \"res3b2_branch2c\"\n\ttop: \"res3b2\"\n\tname: \"res3b2\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b2\"\n\ttop: \"res3b2\"\n\tname: \"res3b2_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b2\"\n\ttop: \"res3b3_branch2a\"\n\tname: \"res3b3_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2a\"\n\ttop: \"res3b3_branch2a\"\n\tname: \"bn3b3_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2a\"\n\ttop: \"res3b3_branch2a\"\n\tname: \"scale3b3_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b3_branch2a\"\n\tbottom: \"res3b3_branch2a\"\n\tname: \"res3b3_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b3_branch2a\"\n\ttop: \"res3b3_branch2b\"\n\tname: \"res3b3_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2b\"\n\ttop: \"res3b3_branch2b\"\n\tname: \"bn3b3_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2b\"\n\ttop: \"res3b3_branch2b\"\n\tname: \"scale3b3_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b3_branch2b\"\n\tbottom: \"res3b3_branch2b\"\n\tname: \"res3b3_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b3_branch2b\"\n\ttop: \"res3b3_branch2c\"\n\tname: \"res3b3_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2c\"\n\ttop: \"res3b3_branch2c\"\n\tname: \"bn3b3_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3_branch2c\"\n\ttop: \"res3b3_branch2c\"\n\tname: \"scale3b3_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b2\"\n\tbottom: \"res3b3_branch2c\"\n\ttop: \"res3b3\"\n\tname: \"res3b3\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b3\"\n\ttop: \"res3b3\"\n\tname: \"res3b3_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b3\"\n\ttop: \"res3b4_branch2a\"\n\tname: \"res3b4_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2a\"\n\ttop: \"res3b4_branch2a\"\n\tname: \"bn3b4_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2a\"\n\ttop: \"res3b4_branch2a\"\n\tname: \"scale3b4_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b4_branch2a\"\n\tbottom: \"res3b4_branch2a\"\n\tname: \"res3b4_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b4_branch2a\"\n\ttop: \"res3b4_branch2b\"\n\tname: \"res3b4_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2b\"\n\ttop: \"res3b4_branch2b\"\n\tname: \"bn3b4_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2b\"\n\ttop: \"res3b4_branch2b\"\n\tname: \"scale3b4_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b4_branch2b\"\n\tbottom: \"res3b4_branch2b\"\n\tname: \"res3b4_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b4_branch2b\"\n\ttop: \"res3b4_branch2c\"\n\tname: \"res3b4_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2c\"\n\ttop: \"res3b4_branch2c\"\n\tname: \"bn3b4_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4_branch2c\"\n\ttop: \"res3b4_branch2c\"\n\tname: \"scale3b4_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b3\"\n\tbottom: \"res3b4_branch2c\"\n\ttop: \"res3b4\"\n\tname: \"res3b4\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b4\"\n\ttop: \"res3b4\"\n\tname: \"res3b4_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b4\"\n\ttop: \"res3b5_branch2a\"\n\tname: \"res3b5_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2a\"\n\ttop: \"res3b5_branch2a\"\n\tname: \"bn3b5_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2a\"\n\ttop: \"res3b5_branch2a\"\n\tname: \"scale3b5_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b5_branch2a\"\n\tbottom: \"res3b5_branch2a\"\n\tname: \"res3b5_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b5_branch2a\"\n\ttop: \"res3b5_branch2b\"\n\tname: \"res3b5_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2b\"\n\ttop: \"res3b5_branch2b\"\n\tname: \"bn3b5_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2b\"\n\ttop: \"res3b5_branch2b\"\n\tname: \"scale3b5_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b5_branch2b\"\n\tbottom: \"res3b5_branch2b\"\n\tname: \"res3b5_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b5_branch2b\"\n\ttop: \"res3b5_branch2c\"\n\tname: \"res3b5_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2c\"\n\ttop: \"res3b5_branch2c\"\n\tname: \"bn3b5_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5_branch2c\"\n\ttop: \"res3b5_branch2c\"\n\tname: \"scale3b5_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b4\"\n\tbottom: \"res3b5_branch2c\"\n\ttop: \"res3b5\"\n\tname: \"res3b5\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b5\"\n\ttop: \"res3b5\"\n\tname: \"res3b5_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b5\"\n\ttop: \"res3b6_branch2a\"\n\tname: \"res3b6_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2a\"\n\ttop: \"res3b6_branch2a\"\n\tname: \"bn3b6_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2a\"\n\ttop: \"res3b6_branch2a\"\n\tname: \"scale3b6_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b6_branch2a\"\n\tbottom: \"res3b6_branch2a\"\n\tname: \"res3b6_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b6_branch2a\"\n\ttop: \"res3b6_branch2b\"\n\tname: \"res3b6_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2b\"\n\ttop: \"res3b6_branch2b\"\n\tname: \"bn3b6_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2b\"\n\ttop: \"res3b6_branch2b\"\n\tname: \"scale3b6_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b6_branch2b\"\n\tbottom: \"res3b6_branch2b\"\n\tname: \"res3b6_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b6_branch2b\"\n\ttop: \"res3b6_branch2c\"\n\tname: \"res3b6_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2c\"\n\ttop: \"res3b6_branch2c\"\n\tname: \"bn3b6_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6_branch2c\"\n\ttop: \"res3b6_branch2c\"\n\tname: \"scale3b6_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b5\"\n\tbottom: \"res3b6_branch2c\"\n\ttop: \"res3b6\"\n\tname: \"res3b6\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b6\"\n\ttop: \"res3b6\"\n\tname: \"res3b6_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b6\"\n\ttop: \"res3b7_branch2a\"\n\tname: \"res3b7_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2a\"\n\ttop: \"res3b7_branch2a\"\n\tname: \"bn3b7_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2a\"\n\ttop: \"res3b7_branch2a\"\n\tname: \"scale3b7_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b7_branch2a\"\n\tbottom: \"res3b7_branch2a\"\n\tname: \"res3b7_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b7_branch2a\"\n\ttop: \"res3b7_branch2b\"\n\tname: \"res3b7_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2b\"\n\ttop: \"res3b7_branch2b\"\n\tname: \"bn3b7_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2b\"\n\ttop: \"res3b7_branch2b\"\n\tname: \"scale3b7_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res3b7_branch2b\"\n\tbottom: \"res3b7_branch2b\"\n\tname: \"res3b7_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b7_branch2b\"\n\ttop: \"res3b7_branch2c\"\n\tname: \"res3b7_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2c\"\n\ttop: \"res3b7_branch2c\"\n\tname: \"bn3b7_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7_branch2c\"\n\ttop: \"res3b7_branch2c\"\n\tname: \"scale3b7_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b6\"\n\tbottom: \"res3b7_branch2c\"\n\ttop: \"res3b7\"\n\tname: \"res3b7\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b7\"\n\ttop: \"res3b7\"\n\tname: \"res3b7_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b7\"\n\ttop: \"res4a_branch1\"\n\tname: \"res4a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\ttop: \"res4a_branch1\"\n\tname: \"bn4a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\ttop: \"res4a_branch1\"\n\tname: \"scale4a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b7\"\n\ttop: \"res4a_branch2a\"\n\tname: \"res4a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2a\"\n\tname: \"bn4a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2a\"\n\tname: \"scale4a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4a_branch2a\"\n\tbottom: \"res4a_branch2a\"\n\tname: \"res4a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2b\"\n\tname: \"res4a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2b\"\n\tname: \"bn4a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2b\"\n\tname: \"scale4a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4a_branch2b\"\n\tbottom: \"res4a_branch2b\"\n\tname: \"res4a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2c\"\n\tname: \"res4a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a_branch2c\"\n\tname: \"bn4a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a_branch2c\"\n\tname: \"scale4a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a\"\n\tname: \"res4a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4a\"\n\ttop: \"res4a\"\n\tname: \"res4a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a\"\n\ttop: \"res4b1_branch2a\"\n\tname: \"res4b1_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2a\"\n\ttop: \"res4b1_branch2a\"\n\tname: \"bn4b1_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2a\"\n\ttop: \"res4b1_branch2a\"\n\tname: \"scale4b1_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b1_branch2a\"\n\tbottom: \"res4b1_branch2a\"\n\tname: \"res4b1_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b1_branch2a\"\n\ttop: \"res4b1_branch2b\"\n\tname: \"res4b1_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2b\"\n\ttop: \"res4b1_branch2b\"\n\tname: \"bn4b1_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2b\"\n\ttop: \"res4b1_branch2b\"\n\tname: \"scale4b1_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b1_branch2b\"\n\tbottom: \"res4b1_branch2b\"\n\tname: \"res4b1_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b1_branch2b\"\n\ttop: \"res4b1_branch2c\"\n\tname: \"res4b1_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2c\"\n\ttop: \"res4b1_branch2c\"\n\tname: \"bn4b1_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1_branch2c\"\n\ttop: \"res4b1_branch2c\"\n\tname: \"scale4b1_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a\"\n\tbottom: \"res4b1_branch2c\"\n\ttop: \"res4b1\"\n\tname: \"res4b1\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b1\"\n\ttop: \"res4b1\"\n\tname: \"res4b1_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b1\"\n\ttop: \"res4b2_branch2a\"\n\tname: \"res4b2_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2a\"\n\ttop: \"res4b2_branch2a\"\n\tname: \"bn4b2_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2a\"\n\ttop: \"res4b2_branch2a\"\n\tname: \"scale4b2_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b2_branch2a\"\n\tbottom: \"res4b2_branch2a\"\n\tname: \"res4b2_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b2_branch2a\"\n\ttop: \"res4b2_branch2b\"\n\tname: \"res4b2_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2b\"\n\ttop: \"res4b2_branch2b\"\n\tname: \"bn4b2_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2b\"\n\ttop: \"res4b2_branch2b\"\n\tname: \"scale4b2_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b2_branch2b\"\n\tbottom: \"res4b2_branch2b\"\n\tname: \"res4b2_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b2_branch2b\"\n\ttop: \"res4b2_branch2c\"\n\tname: \"res4b2_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2c\"\n\ttop: \"res4b2_branch2c\"\n\tname: \"bn4b2_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2_branch2c\"\n\ttop: \"res4b2_branch2c\"\n\tname: \"scale4b2_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b1\"\n\tbottom: \"res4b2_branch2c\"\n\ttop: \"res4b2\"\n\tname: \"res4b2\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b2\"\n\ttop: \"res4b2\"\n\tname: \"res4b2_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b2\"\n\ttop: \"res4b3_branch2a\"\n\tname: \"res4b3_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2a\"\n\ttop: \"res4b3_branch2a\"\n\tname: \"bn4b3_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2a\"\n\ttop: \"res4b3_branch2a\"\n\tname: \"scale4b3_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b3_branch2a\"\n\tbottom: \"res4b3_branch2a\"\n\tname: \"res4b3_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b3_branch2a\"\n\ttop: \"res4b3_branch2b\"\n\tname: \"res4b3_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2b\"\n\ttop: \"res4b3_branch2b\"\n\tname: \"bn4b3_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2b\"\n\ttop: \"res4b3_branch2b\"\n\tname: \"scale4b3_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b3_branch2b\"\n\tbottom: \"res4b3_branch2b\"\n\tname: \"res4b3_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b3_branch2b\"\n\ttop: \"res4b3_branch2c\"\n\tname: \"res4b3_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2c\"\n\ttop: \"res4b3_branch2c\"\n\tname: \"bn4b3_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3_branch2c\"\n\ttop: \"res4b3_branch2c\"\n\tname: \"scale4b3_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b2\"\n\tbottom: \"res4b3_branch2c\"\n\ttop: \"res4b3\"\n\tname: \"res4b3\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b3\"\n\ttop: \"res4b3\"\n\tname: \"res4b3_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b3\"\n\ttop: \"res4b4_branch2a\"\n\tname: \"res4b4_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2a\"\n\ttop: \"res4b4_branch2a\"\n\tname: \"bn4b4_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2a\"\n\ttop: \"res4b4_branch2a\"\n\tname: \"scale4b4_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b4_branch2a\"\n\tbottom: \"res4b4_branch2a\"\n\tname: \"res4b4_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b4_branch2a\"\n\ttop: \"res4b4_branch2b\"\n\tname: \"res4b4_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2b\"\n\ttop: \"res4b4_branch2b\"\n\tname: \"bn4b4_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2b\"\n\ttop: \"res4b4_branch2b\"\n\tname: \"scale4b4_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b4_branch2b\"\n\tbottom: \"res4b4_branch2b\"\n\tname: \"res4b4_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b4_branch2b\"\n\ttop: \"res4b4_branch2c\"\n\tname: \"res4b4_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2c\"\n\ttop: \"res4b4_branch2c\"\n\tname: \"bn4b4_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4_branch2c\"\n\ttop: \"res4b4_branch2c\"\n\tname: \"scale4b4_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b3\"\n\tbottom: \"res4b4_branch2c\"\n\ttop: \"res4b4\"\n\tname: \"res4b4\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b4\"\n\ttop: \"res4b4\"\n\tname: \"res4b4_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b4\"\n\ttop: \"res4b5_branch2a\"\n\tname: \"res4b5_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2a\"\n\ttop: \"res4b5_branch2a\"\n\tname: \"bn4b5_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2a\"\n\ttop: \"res4b5_branch2a\"\n\tname: \"scale4b5_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b5_branch2a\"\n\tbottom: \"res4b5_branch2a\"\n\tname: \"res4b5_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b5_branch2a\"\n\ttop: \"res4b5_branch2b\"\n\tname: \"res4b5_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2b\"\n\ttop: \"res4b5_branch2b\"\n\tname: \"bn4b5_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2b\"\n\ttop: \"res4b5_branch2b\"\n\tname: \"scale4b5_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b5_branch2b\"\n\tbottom: \"res4b5_branch2b\"\n\tname: \"res4b5_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b5_branch2b\"\n\ttop: \"res4b5_branch2c\"\n\tname: \"res4b5_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2c\"\n\ttop: \"res4b5_branch2c\"\n\tname: \"bn4b5_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5_branch2c\"\n\ttop: \"res4b5_branch2c\"\n\tname: \"scale4b5_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b4\"\n\tbottom: \"res4b5_branch2c\"\n\ttop: \"res4b5\"\n\tname: \"res4b5\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b5\"\n\ttop: \"res4b5\"\n\tname: \"res4b5_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b5\"\n\ttop: \"res4b6_branch2a\"\n\tname: \"res4b6_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2a\"\n\ttop: \"res4b6_branch2a\"\n\tname: \"bn4b6_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2a\"\n\ttop: \"res4b6_branch2a\"\n\tname: \"scale4b6_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b6_branch2a\"\n\tbottom: \"res4b6_branch2a\"\n\tname: \"res4b6_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b6_branch2a\"\n\ttop: \"res4b6_branch2b\"\n\tname: \"res4b6_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2b\"\n\ttop: \"res4b6_branch2b\"\n\tname: \"bn4b6_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2b\"\n\ttop: \"res4b6_branch2b\"\n\tname: \"scale4b6_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b6_branch2b\"\n\tbottom: \"res4b6_branch2b\"\n\tname: \"res4b6_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b6_branch2b\"\n\ttop: \"res4b6_branch2c\"\n\tname: \"res4b6_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2c\"\n\ttop: \"res4b6_branch2c\"\n\tname: \"bn4b6_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6_branch2c\"\n\ttop: \"res4b6_branch2c\"\n\tname: \"scale4b6_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b5\"\n\tbottom: \"res4b6_branch2c\"\n\ttop: \"res4b6\"\n\tname: \"res4b6\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b6\"\n\ttop: \"res4b6\"\n\tname: \"res4b6_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b6\"\n\ttop: \"res4b7_branch2a\"\n\tname: \"res4b7_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2a\"\n\ttop: \"res4b7_branch2a\"\n\tname: \"bn4b7_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2a\"\n\ttop: \"res4b7_branch2a\"\n\tname: \"scale4b7_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b7_branch2a\"\n\tbottom: \"res4b7_branch2a\"\n\tname: \"res4b7_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b7_branch2a\"\n\ttop: \"res4b7_branch2b\"\n\tname: \"res4b7_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2b\"\n\ttop: \"res4b7_branch2b\"\n\tname: \"bn4b7_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2b\"\n\ttop: \"res4b7_branch2b\"\n\tname: \"scale4b7_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b7_branch2b\"\n\tbottom: \"res4b7_branch2b\"\n\tname: \"res4b7_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b7_branch2b\"\n\ttop: \"res4b7_branch2c\"\n\tname: \"res4b7_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2c\"\n\ttop: \"res4b7_branch2c\"\n\tname: \"bn4b7_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7_branch2c\"\n\ttop: \"res4b7_branch2c\"\n\tname: \"scale4b7_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b6\"\n\tbottom: \"res4b7_branch2c\"\n\ttop: \"res4b7\"\n\tname: \"res4b7\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b7\"\n\ttop: \"res4b7\"\n\tname: \"res4b7_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b7\"\n\ttop: \"res4b8_branch2a\"\n\tname: \"res4b8_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2a\"\n\ttop: \"res4b8_branch2a\"\n\tname: \"bn4b8_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2a\"\n\ttop: \"res4b8_branch2a\"\n\tname: \"scale4b8_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b8_branch2a\"\n\tbottom: \"res4b8_branch2a\"\n\tname: \"res4b8_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b8_branch2a\"\n\ttop: \"res4b8_branch2b\"\n\tname: \"res4b8_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2b\"\n\ttop: \"res4b8_branch2b\"\n\tname: \"bn4b8_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2b\"\n\ttop: \"res4b8_branch2b\"\n\tname: \"scale4b8_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b8_branch2b\"\n\tbottom: \"res4b8_branch2b\"\n\tname: \"res4b8_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b8_branch2b\"\n\ttop: \"res4b8_branch2c\"\n\tname: \"res4b8_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2c\"\n\ttop: \"res4b8_branch2c\"\n\tname: \"bn4b8_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8_branch2c\"\n\ttop: \"res4b8_branch2c\"\n\tname: \"scale4b8_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b7\"\n\tbottom: \"res4b8_branch2c\"\n\ttop: \"res4b8\"\n\tname: \"res4b8\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b8\"\n\ttop: \"res4b8\"\n\tname: \"res4b8_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b8\"\n\ttop: \"res4b9_branch2a\"\n\tname: \"res4b9_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2a\"\n\ttop: \"res4b9_branch2a\"\n\tname: \"bn4b9_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2a\"\n\ttop: \"res4b9_branch2a\"\n\tname: \"scale4b9_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b9_branch2a\"\n\tbottom: \"res4b9_branch2a\"\n\tname: \"res4b9_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b9_branch2a\"\n\ttop: \"res4b9_branch2b\"\n\tname: \"res4b9_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2b\"\n\ttop: \"res4b9_branch2b\"\n\tname: \"bn4b9_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2b\"\n\ttop: \"res4b9_branch2b\"\n\tname: \"scale4b9_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b9_branch2b\"\n\tbottom: \"res4b9_branch2b\"\n\tname: \"res4b9_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b9_branch2b\"\n\ttop: \"res4b9_branch2c\"\n\tname: \"res4b9_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2c\"\n\ttop: \"res4b9_branch2c\"\n\tname: \"bn4b9_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9_branch2c\"\n\ttop: \"res4b9_branch2c\"\n\tname: \"scale4b9_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b8\"\n\tbottom: \"res4b9_branch2c\"\n\ttop: \"res4b9\"\n\tname: \"res4b9\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b9\"\n\ttop: \"res4b9\"\n\tname: \"res4b9_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b9\"\n\ttop: \"res4b10_branch2a\"\n\tname: \"res4b10_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2a\"\n\ttop: \"res4b10_branch2a\"\n\tname: \"bn4b10_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2a\"\n\ttop: \"res4b10_branch2a\"\n\tname: \"scale4b10_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b10_branch2a\"\n\tbottom: \"res4b10_branch2a\"\n\tname: \"res4b10_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b10_branch2a\"\n\ttop: \"res4b10_branch2b\"\n\tname: \"res4b10_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2b\"\n\ttop: \"res4b10_branch2b\"\n\tname: \"bn4b10_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2b\"\n\ttop: \"res4b10_branch2b\"\n\tname: \"scale4b10_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b10_branch2b\"\n\tbottom: \"res4b10_branch2b\"\n\tname: \"res4b10_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b10_branch2b\"\n\ttop: \"res4b10_branch2c\"\n\tname: \"res4b10_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2c\"\n\ttop: \"res4b10_branch2c\"\n\tname: \"bn4b10_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10_branch2c\"\n\ttop: \"res4b10_branch2c\"\n\tname: \"scale4b10_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b9\"\n\tbottom: \"res4b10_branch2c\"\n\ttop: \"res4b10\"\n\tname: \"res4b10\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b10\"\n\ttop: \"res4b10\"\n\tname: \"res4b10_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b10\"\n\ttop: \"res4b11_branch2a\"\n\tname: \"res4b11_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2a\"\n\ttop: \"res4b11_branch2a\"\n\tname: \"bn4b11_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2a\"\n\ttop: \"res4b11_branch2a\"\n\tname: \"scale4b11_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b11_branch2a\"\n\tbottom: \"res4b11_branch2a\"\n\tname: \"res4b11_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b11_branch2a\"\n\ttop: \"res4b11_branch2b\"\n\tname: \"res4b11_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2b\"\n\ttop: \"res4b11_branch2b\"\n\tname: \"bn4b11_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2b\"\n\ttop: \"res4b11_branch2b\"\n\tname: \"scale4b11_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b11_branch2b\"\n\tbottom: \"res4b11_branch2b\"\n\tname: \"res4b11_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b11_branch2b\"\n\ttop: \"res4b11_branch2c\"\n\tname: \"res4b11_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2c\"\n\ttop: \"res4b11_branch2c\"\n\tname: \"bn4b11_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11_branch2c\"\n\ttop: \"res4b11_branch2c\"\n\tname: \"scale4b11_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b10\"\n\tbottom: \"res4b11_branch2c\"\n\ttop: \"res4b11\"\n\tname: \"res4b11\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b11\"\n\ttop: \"res4b11\"\n\tname: \"res4b11_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b11\"\n\ttop: \"res4b12_branch2a\"\n\tname: \"res4b12_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2a\"\n\ttop: \"res4b12_branch2a\"\n\tname: \"bn4b12_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2a\"\n\ttop: \"res4b12_branch2a\"\n\tname: \"scale4b12_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b12_branch2a\"\n\tbottom: \"res4b12_branch2a\"\n\tname: \"res4b12_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b12_branch2a\"\n\ttop: \"res4b12_branch2b\"\n\tname: \"res4b12_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2b\"\n\ttop: \"res4b12_branch2b\"\n\tname: \"bn4b12_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2b\"\n\ttop: \"res4b12_branch2b\"\n\tname: \"scale4b12_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b12_branch2b\"\n\tbottom: \"res4b12_branch2b\"\n\tname: \"res4b12_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b12_branch2b\"\n\ttop: \"res4b12_branch2c\"\n\tname: \"res4b12_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2c\"\n\ttop: \"res4b12_branch2c\"\n\tname: \"bn4b12_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12_branch2c\"\n\ttop: \"res4b12_branch2c\"\n\tname: \"scale4b12_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b11\"\n\tbottom: \"res4b12_branch2c\"\n\ttop: \"res4b12\"\n\tname: \"res4b12\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b12\"\n\ttop: \"res4b12\"\n\tname: \"res4b12_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b12\"\n\ttop: \"res4b13_branch2a\"\n\tname: \"res4b13_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2a\"\n\ttop: \"res4b13_branch2a\"\n\tname: \"bn4b13_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2a\"\n\ttop: \"res4b13_branch2a\"\n\tname: \"scale4b13_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b13_branch2a\"\n\tbottom: \"res4b13_branch2a\"\n\tname: \"res4b13_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b13_branch2a\"\n\ttop: \"res4b13_branch2b\"\n\tname: \"res4b13_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2b\"\n\ttop: \"res4b13_branch2b\"\n\tname: \"bn4b13_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2b\"\n\ttop: \"res4b13_branch2b\"\n\tname: \"scale4b13_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b13_branch2b\"\n\tbottom: \"res4b13_branch2b\"\n\tname: \"res4b13_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b13_branch2b\"\n\ttop: \"res4b13_branch2c\"\n\tname: \"res4b13_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2c\"\n\ttop: \"res4b13_branch2c\"\n\tname: \"bn4b13_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13_branch2c\"\n\ttop: \"res4b13_branch2c\"\n\tname: \"scale4b13_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b12\"\n\tbottom: \"res4b13_branch2c\"\n\ttop: \"res4b13\"\n\tname: \"res4b13\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b13\"\n\ttop: \"res4b13\"\n\tname: \"res4b13_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b13\"\n\ttop: \"res4b14_branch2a\"\n\tname: \"res4b14_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2a\"\n\ttop: \"res4b14_branch2a\"\n\tname: \"bn4b14_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2a\"\n\ttop: \"res4b14_branch2a\"\n\tname: \"scale4b14_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b14_branch2a\"\n\tbottom: \"res4b14_branch2a\"\n\tname: \"res4b14_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b14_branch2a\"\n\ttop: \"res4b14_branch2b\"\n\tname: \"res4b14_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2b\"\n\ttop: \"res4b14_branch2b\"\n\tname: \"bn4b14_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2b\"\n\ttop: \"res4b14_branch2b\"\n\tname: \"scale4b14_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b14_branch2b\"\n\tbottom: \"res4b14_branch2b\"\n\tname: \"res4b14_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b14_branch2b\"\n\ttop: \"res4b14_branch2c\"\n\tname: \"res4b14_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2c\"\n\ttop: \"res4b14_branch2c\"\n\tname: \"bn4b14_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14_branch2c\"\n\ttop: \"res4b14_branch2c\"\n\tname: \"scale4b14_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b13\"\n\tbottom: \"res4b14_branch2c\"\n\ttop: \"res4b14\"\n\tname: \"res4b14\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b14\"\n\ttop: \"res4b14\"\n\tname: \"res4b14_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b14\"\n\ttop: \"res4b15_branch2a\"\n\tname: \"res4b15_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2a\"\n\ttop: \"res4b15_branch2a\"\n\tname: \"bn4b15_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2a\"\n\ttop: \"res4b15_branch2a\"\n\tname: \"scale4b15_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b15_branch2a\"\n\tbottom: \"res4b15_branch2a\"\n\tname: \"res4b15_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b15_branch2a\"\n\ttop: \"res4b15_branch2b\"\n\tname: \"res4b15_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2b\"\n\ttop: \"res4b15_branch2b\"\n\tname: \"bn4b15_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2b\"\n\ttop: \"res4b15_branch2b\"\n\tname: \"scale4b15_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b15_branch2b\"\n\tbottom: \"res4b15_branch2b\"\n\tname: \"res4b15_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b15_branch2b\"\n\ttop: \"res4b15_branch2c\"\n\tname: \"res4b15_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2c\"\n\ttop: \"res4b15_branch2c\"\n\tname: \"bn4b15_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15_branch2c\"\n\ttop: \"res4b15_branch2c\"\n\tname: \"scale4b15_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b14\"\n\tbottom: \"res4b15_branch2c\"\n\ttop: \"res4b15\"\n\tname: \"res4b15\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b15\"\n\ttop: \"res4b15\"\n\tname: \"res4b15_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b15\"\n\ttop: \"res4b16_branch2a\"\n\tname: \"res4b16_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2a\"\n\ttop: \"res4b16_branch2a\"\n\tname: \"bn4b16_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2a\"\n\ttop: \"res4b16_branch2a\"\n\tname: \"scale4b16_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b16_branch2a\"\n\tbottom: \"res4b16_branch2a\"\n\tname: \"res4b16_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b16_branch2a\"\n\ttop: \"res4b16_branch2b\"\n\tname: \"res4b16_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2b\"\n\ttop: \"res4b16_branch2b\"\n\tname: \"bn4b16_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2b\"\n\ttop: \"res4b16_branch2b\"\n\tname: \"scale4b16_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b16_branch2b\"\n\tbottom: \"res4b16_branch2b\"\n\tname: \"res4b16_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b16_branch2b\"\n\ttop: \"res4b16_branch2c\"\n\tname: \"res4b16_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2c\"\n\ttop: \"res4b16_branch2c\"\n\tname: \"bn4b16_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16_branch2c\"\n\ttop: \"res4b16_branch2c\"\n\tname: \"scale4b16_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b15\"\n\tbottom: \"res4b16_branch2c\"\n\ttop: \"res4b16\"\n\tname: \"res4b16\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b16\"\n\ttop: \"res4b16\"\n\tname: \"res4b16_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b16\"\n\ttop: \"res4b17_branch2a\"\n\tname: \"res4b17_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2a\"\n\ttop: \"res4b17_branch2a\"\n\tname: \"bn4b17_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2a\"\n\ttop: \"res4b17_branch2a\"\n\tname: \"scale4b17_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b17_branch2a\"\n\tbottom: \"res4b17_branch2a\"\n\tname: \"res4b17_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b17_branch2a\"\n\ttop: \"res4b17_branch2b\"\n\tname: \"res4b17_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2b\"\n\ttop: \"res4b17_branch2b\"\n\tname: \"bn4b17_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2b\"\n\ttop: \"res4b17_branch2b\"\n\tname: \"scale4b17_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b17_branch2b\"\n\tbottom: \"res4b17_branch2b\"\n\tname: \"res4b17_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b17_branch2b\"\n\ttop: \"res4b17_branch2c\"\n\tname: \"res4b17_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2c\"\n\ttop: \"res4b17_branch2c\"\n\tname: \"bn4b17_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17_branch2c\"\n\ttop: \"res4b17_branch2c\"\n\tname: \"scale4b17_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b16\"\n\tbottom: \"res4b17_branch2c\"\n\ttop: \"res4b17\"\n\tname: \"res4b17\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b17\"\n\ttop: \"res4b17\"\n\tname: \"res4b17_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b17\"\n\ttop: \"res4b18_branch2a\"\n\tname: \"res4b18_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2a\"\n\ttop: \"res4b18_branch2a\"\n\tname: \"bn4b18_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2a\"\n\ttop: \"res4b18_branch2a\"\n\tname: \"scale4b18_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b18_branch2a\"\n\tbottom: \"res4b18_branch2a\"\n\tname: \"res4b18_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b18_branch2a\"\n\ttop: \"res4b18_branch2b\"\n\tname: \"res4b18_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2b\"\n\ttop: \"res4b18_branch2b\"\n\tname: \"bn4b18_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2b\"\n\ttop: \"res4b18_branch2b\"\n\tname: \"scale4b18_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b18_branch2b\"\n\tbottom: \"res4b18_branch2b\"\n\tname: \"res4b18_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b18_branch2b\"\n\ttop: \"res4b18_branch2c\"\n\tname: \"res4b18_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2c\"\n\ttop: \"res4b18_branch2c\"\n\tname: \"bn4b18_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18_branch2c\"\n\ttop: \"res4b18_branch2c\"\n\tname: \"scale4b18_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b17\"\n\tbottom: \"res4b18_branch2c\"\n\ttop: \"res4b18\"\n\tname: \"res4b18\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b18\"\n\ttop: \"res4b18\"\n\tname: \"res4b18_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b18\"\n\ttop: \"res4b19_branch2a\"\n\tname: \"res4b19_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2a\"\n\ttop: \"res4b19_branch2a\"\n\tname: \"bn4b19_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2a\"\n\ttop: \"res4b19_branch2a\"\n\tname: \"scale4b19_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b19_branch2a\"\n\tbottom: \"res4b19_branch2a\"\n\tname: \"res4b19_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b19_branch2a\"\n\ttop: \"res4b19_branch2b\"\n\tname: \"res4b19_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2b\"\n\ttop: \"res4b19_branch2b\"\n\tname: \"bn4b19_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2b\"\n\ttop: \"res4b19_branch2b\"\n\tname: \"scale4b19_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b19_branch2b\"\n\tbottom: \"res4b19_branch2b\"\n\tname: \"res4b19_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b19_branch2b\"\n\ttop: \"res4b19_branch2c\"\n\tname: \"res4b19_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2c\"\n\ttop: \"res4b19_branch2c\"\n\tname: \"bn4b19_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19_branch2c\"\n\ttop: \"res4b19_branch2c\"\n\tname: \"scale4b19_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b18\"\n\tbottom: \"res4b19_branch2c\"\n\ttop: \"res4b19\"\n\tname: \"res4b19\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b19\"\n\ttop: \"res4b19\"\n\tname: \"res4b19_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b19\"\n\ttop: \"res4b20_branch2a\"\n\tname: \"res4b20_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2a\"\n\ttop: \"res4b20_branch2a\"\n\tname: \"bn4b20_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2a\"\n\ttop: \"res4b20_branch2a\"\n\tname: \"scale4b20_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b20_branch2a\"\n\tbottom: \"res4b20_branch2a\"\n\tname: \"res4b20_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b20_branch2a\"\n\ttop: \"res4b20_branch2b\"\n\tname: \"res4b20_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2b\"\n\ttop: \"res4b20_branch2b\"\n\tname: \"bn4b20_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2b\"\n\ttop: \"res4b20_branch2b\"\n\tname: \"scale4b20_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b20_branch2b\"\n\tbottom: \"res4b20_branch2b\"\n\tname: \"res4b20_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b20_branch2b\"\n\ttop: \"res4b20_branch2c\"\n\tname: \"res4b20_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2c\"\n\ttop: \"res4b20_branch2c\"\n\tname: \"bn4b20_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20_branch2c\"\n\ttop: \"res4b20_branch2c\"\n\tname: \"scale4b20_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b19\"\n\tbottom: \"res4b20_branch2c\"\n\ttop: \"res4b20\"\n\tname: \"res4b20\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b20\"\n\ttop: \"res4b20\"\n\tname: \"res4b20_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b20\"\n\ttop: \"res4b21_branch2a\"\n\tname: \"res4b21_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2a\"\n\ttop: \"res4b21_branch2a\"\n\tname: \"bn4b21_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2a\"\n\ttop: \"res4b21_branch2a\"\n\tname: \"scale4b21_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b21_branch2a\"\n\tbottom: \"res4b21_branch2a\"\n\tname: \"res4b21_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b21_branch2a\"\n\ttop: \"res4b21_branch2b\"\n\tname: \"res4b21_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2b\"\n\ttop: \"res4b21_branch2b\"\n\tname: \"bn4b21_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2b\"\n\ttop: \"res4b21_branch2b\"\n\tname: \"scale4b21_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b21_branch2b\"\n\tbottom: \"res4b21_branch2b\"\n\tname: \"res4b21_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b21_branch2b\"\n\ttop: \"res4b21_branch2c\"\n\tname: \"res4b21_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2c\"\n\ttop: \"res4b21_branch2c\"\n\tname: \"bn4b21_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21_branch2c\"\n\ttop: \"res4b21_branch2c\"\n\tname: \"scale4b21_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b20\"\n\tbottom: \"res4b21_branch2c\"\n\ttop: \"res4b21\"\n\tname: \"res4b21\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b21\"\n\ttop: \"res4b21\"\n\tname: \"res4b21_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b21\"\n\ttop: \"res4b22_branch2a\"\n\tname: \"res4b22_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2a\"\n\ttop: \"res4b22_branch2a\"\n\tname: \"bn4b22_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2a\"\n\ttop: \"res4b22_branch2a\"\n\tname: \"scale4b22_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b22_branch2a\"\n\tbottom: \"res4b22_branch2a\"\n\tname: \"res4b22_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b22_branch2a\"\n\ttop: \"res4b22_branch2b\"\n\tname: \"res4b22_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2b\"\n\ttop: \"res4b22_branch2b\"\n\tname: \"bn4b22_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2b\"\n\ttop: \"res4b22_branch2b\"\n\tname: \"scale4b22_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b22_branch2b\"\n\tbottom: \"res4b22_branch2b\"\n\tname: \"res4b22_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b22_branch2b\"\n\ttop: \"res4b22_branch2c\"\n\tname: \"res4b22_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2c\"\n\ttop: \"res4b22_branch2c\"\n\tname: \"bn4b22_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22_branch2c\"\n\ttop: \"res4b22_branch2c\"\n\tname: \"scale4b22_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b21\"\n\tbottom: \"res4b22_branch2c\"\n\ttop: \"res4b22\"\n\tname: \"res4b22\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b22\"\n\ttop: \"res4b22\"\n\tname: \"res4b22_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b22\"\n\ttop: \"res4b23_branch2a\"\n\tname: \"res4b23_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2a\"\n\ttop: \"res4b23_branch2a\"\n\tname: \"bn4b23_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2a\"\n\ttop: \"res4b23_branch2a\"\n\tname: \"scale4b23_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b23_branch2a\"\n\tbottom: \"res4b23_branch2a\"\n\tname: \"res4b23_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b23_branch2a\"\n\ttop: \"res4b23_branch2b\"\n\tname: \"res4b23_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2b\"\n\ttop: \"res4b23_branch2b\"\n\tname: \"bn4b23_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2b\"\n\ttop: \"res4b23_branch2b\"\n\tname: \"scale4b23_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b23_branch2b\"\n\tbottom: \"res4b23_branch2b\"\n\tname: \"res4b23_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b23_branch2b\"\n\ttop: \"res4b23_branch2c\"\n\tname: \"res4b23_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2c\"\n\ttop: \"res4b23_branch2c\"\n\tname: \"bn4b23_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23_branch2c\"\n\ttop: \"res4b23_branch2c\"\n\tname: \"scale4b23_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b22\"\n\tbottom: \"res4b23_branch2c\"\n\ttop: \"res4b23\"\n\tname: \"res4b23\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b23\"\n\ttop: \"res4b23\"\n\tname: \"res4b23_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b23\"\n\ttop: \"res4b24_branch2a\"\n\tname: \"res4b24_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2a\"\n\ttop: \"res4b24_branch2a\"\n\tname: \"bn4b24_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2a\"\n\ttop: \"res4b24_branch2a\"\n\tname: \"scale4b24_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b24_branch2a\"\n\tbottom: \"res4b24_branch2a\"\n\tname: \"res4b24_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b24_branch2a\"\n\ttop: \"res4b24_branch2b\"\n\tname: \"res4b24_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2b\"\n\ttop: \"res4b24_branch2b\"\n\tname: \"bn4b24_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2b\"\n\ttop: \"res4b24_branch2b\"\n\tname: \"scale4b24_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b24_branch2b\"\n\tbottom: \"res4b24_branch2b\"\n\tname: \"res4b24_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b24_branch2b\"\n\ttop: \"res4b24_branch2c\"\n\tname: \"res4b24_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2c\"\n\ttop: \"res4b24_branch2c\"\n\tname: \"bn4b24_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24_branch2c\"\n\ttop: \"res4b24_branch2c\"\n\tname: \"scale4b24_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b23\"\n\tbottom: \"res4b24_branch2c\"\n\ttop: \"res4b24\"\n\tname: \"res4b24\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b24\"\n\ttop: \"res4b24\"\n\tname: \"res4b24_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b24\"\n\ttop: \"res4b25_branch2a\"\n\tname: \"res4b25_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2a\"\n\ttop: \"res4b25_branch2a\"\n\tname: \"bn4b25_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2a\"\n\ttop: \"res4b25_branch2a\"\n\tname: \"scale4b25_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b25_branch2a\"\n\tbottom: \"res4b25_branch2a\"\n\tname: \"res4b25_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b25_branch2a\"\n\ttop: \"res4b25_branch2b\"\n\tname: \"res4b25_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2b\"\n\ttop: \"res4b25_branch2b\"\n\tname: \"bn4b25_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2b\"\n\ttop: \"res4b25_branch2b\"\n\tname: \"scale4b25_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b25_branch2b\"\n\tbottom: \"res4b25_branch2b\"\n\tname: \"res4b25_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b25_branch2b\"\n\ttop: \"res4b25_branch2c\"\n\tname: \"res4b25_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2c\"\n\ttop: \"res4b25_branch2c\"\n\tname: \"bn4b25_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25_branch2c\"\n\ttop: \"res4b25_branch2c\"\n\tname: \"scale4b25_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b24\"\n\tbottom: \"res4b25_branch2c\"\n\ttop: \"res4b25\"\n\tname: \"res4b25\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b25\"\n\ttop: \"res4b25\"\n\tname: \"res4b25_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b25\"\n\ttop: \"res4b26_branch2a\"\n\tname: \"res4b26_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2a\"\n\ttop: \"res4b26_branch2a\"\n\tname: \"bn4b26_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2a\"\n\ttop: \"res4b26_branch2a\"\n\tname: \"scale4b26_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b26_branch2a\"\n\tbottom: \"res4b26_branch2a\"\n\tname: \"res4b26_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b26_branch2a\"\n\ttop: \"res4b26_branch2b\"\n\tname: \"res4b26_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2b\"\n\ttop: \"res4b26_branch2b\"\n\tname: \"bn4b26_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2b\"\n\ttop: \"res4b26_branch2b\"\n\tname: \"scale4b26_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b26_branch2b\"\n\tbottom: \"res4b26_branch2b\"\n\tname: \"res4b26_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b26_branch2b\"\n\ttop: \"res4b26_branch2c\"\n\tname: \"res4b26_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2c\"\n\ttop: \"res4b26_branch2c\"\n\tname: \"bn4b26_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26_branch2c\"\n\ttop: \"res4b26_branch2c\"\n\tname: \"scale4b26_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b25\"\n\tbottom: \"res4b26_branch2c\"\n\ttop: \"res4b26\"\n\tname: \"res4b26\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b26\"\n\ttop: \"res4b26\"\n\tname: \"res4b26_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b26\"\n\ttop: \"res4b27_branch2a\"\n\tname: \"res4b27_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2a\"\n\ttop: \"res4b27_branch2a\"\n\tname: \"bn4b27_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2a\"\n\ttop: \"res4b27_branch2a\"\n\tname: \"scale4b27_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b27_branch2a\"\n\tbottom: \"res4b27_branch2a\"\n\tname: \"res4b27_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b27_branch2a\"\n\ttop: \"res4b27_branch2b\"\n\tname: \"res4b27_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2b\"\n\ttop: \"res4b27_branch2b\"\n\tname: \"bn4b27_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2b\"\n\ttop: \"res4b27_branch2b\"\n\tname: \"scale4b27_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b27_branch2b\"\n\tbottom: \"res4b27_branch2b\"\n\tname: \"res4b27_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b27_branch2b\"\n\ttop: \"res4b27_branch2c\"\n\tname: \"res4b27_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2c\"\n\ttop: \"res4b27_branch2c\"\n\tname: \"bn4b27_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27_branch2c\"\n\ttop: \"res4b27_branch2c\"\n\tname: \"scale4b27_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b26\"\n\tbottom: \"res4b27_branch2c\"\n\ttop: \"res4b27\"\n\tname: \"res4b27\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b27\"\n\ttop: \"res4b27\"\n\tname: \"res4b27_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b27\"\n\ttop: \"res4b28_branch2a\"\n\tname: \"res4b28_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2a\"\n\ttop: \"res4b28_branch2a\"\n\tname: \"bn4b28_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2a\"\n\ttop: \"res4b28_branch2a\"\n\tname: \"scale4b28_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b28_branch2a\"\n\tbottom: \"res4b28_branch2a\"\n\tname: \"res4b28_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b28_branch2a\"\n\ttop: \"res4b28_branch2b\"\n\tname: \"res4b28_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2b\"\n\ttop: \"res4b28_branch2b\"\n\tname: \"bn4b28_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2b\"\n\ttop: \"res4b28_branch2b\"\n\tname: \"scale4b28_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b28_branch2b\"\n\tbottom: \"res4b28_branch2b\"\n\tname: \"res4b28_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b28_branch2b\"\n\ttop: \"res4b28_branch2c\"\n\tname: \"res4b28_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2c\"\n\ttop: \"res4b28_branch2c\"\n\tname: \"bn4b28_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28_branch2c\"\n\ttop: \"res4b28_branch2c\"\n\tname: \"scale4b28_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b27\"\n\tbottom: \"res4b28_branch2c\"\n\ttop: \"res4b28\"\n\tname: \"res4b28\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b28\"\n\ttop: \"res4b28\"\n\tname: \"res4b28_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b28\"\n\ttop: \"res4b29_branch2a\"\n\tname: \"res4b29_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2a\"\n\ttop: \"res4b29_branch2a\"\n\tname: \"bn4b29_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2a\"\n\ttop: \"res4b29_branch2a\"\n\tname: \"scale4b29_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b29_branch2a\"\n\tbottom: \"res4b29_branch2a\"\n\tname: \"res4b29_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b29_branch2a\"\n\ttop: \"res4b29_branch2b\"\n\tname: \"res4b29_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2b\"\n\ttop: \"res4b29_branch2b\"\n\tname: \"bn4b29_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2b\"\n\ttop: \"res4b29_branch2b\"\n\tname: \"scale4b29_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b29_branch2b\"\n\tbottom: \"res4b29_branch2b\"\n\tname: \"res4b29_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b29_branch2b\"\n\ttop: \"res4b29_branch2c\"\n\tname: \"res4b29_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2c\"\n\ttop: \"res4b29_branch2c\"\n\tname: \"bn4b29_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29_branch2c\"\n\ttop: \"res4b29_branch2c\"\n\tname: \"scale4b29_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b28\"\n\tbottom: \"res4b29_branch2c\"\n\ttop: \"res4b29\"\n\tname: \"res4b29\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b29\"\n\ttop: \"res4b29\"\n\tname: \"res4b29_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b29\"\n\ttop: \"res4b30_branch2a\"\n\tname: \"res4b30_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2a\"\n\ttop: \"res4b30_branch2a\"\n\tname: \"bn4b30_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2a\"\n\ttop: \"res4b30_branch2a\"\n\tname: \"scale4b30_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b30_branch2a\"\n\tbottom: \"res4b30_branch2a\"\n\tname: \"res4b30_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b30_branch2a\"\n\ttop: \"res4b30_branch2b\"\n\tname: \"res4b30_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2b\"\n\ttop: \"res4b30_branch2b\"\n\tname: \"bn4b30_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2b\"\n\ttop: \"res4b30_branch2b\"\n\tname: \"scale4b30_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b30_branch2b\"\n\tbottom: \"res4b30_branch2b\"\n\tname: \"res4b30_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b30_branch2b\"\n\ttop: \"res4b30_branch2c\"\n\tname: \"res4b30_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2c\"\n\ttop: \"res4b30_branch2c\"\n\tname: \"bn4b30_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30_branch2c\"\n\ttop: \"res4b30_branch2c\"\n\tname: \"scale4b30_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b29\"\n\tbottom: \"res4b30_branch2c\"\n\ttop: \"res4b30\"\n\tname: \"res4b30\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b30\"\n\ttop: \"res4b30\"\n\tname: \"res4b30_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b30\"\n\ttop: \"res4b31_branch2a\"\n\tname: \"res4b31_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2a\"\n\ttop: \"res4b31_branch2a\"\n\tname: \"bn4b31_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2a\"\n\ttop: \"res4b31_branch2a\"\n\tname: \"scale4b31_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b31_branch2a\"\n\tbottom: \"res4b31_branch2a\"\n\tname: \"res4b31_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b31_branch2a\"\n\ttop: \"res4b31_branch2b\"\n\tname: \"res4b31_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2b\"\n\ttop: \"res4b31_branch2b\"\n\tname: \"bn4b31_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2b\"\n\ttop: \"res4b31_branch2b\"\n\tname: \"scale4b31_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b31_branch2b\"\n\tbottom: \"res4b31_branch2b\"\n\tname: \"res4b31_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b31_branch2b\"\n\ttop: \"res4b31_branch2c\"\n\tname: \"res4b31_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2c\"\n\ttop: \"res4b31_branch2c\"\n\tname: \"bn4b31_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31_branch2c\"\n\ttop: \"res4b31_branch2c\"\n\tname: \"scale4b31_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b30\"\n\tbottom: \"res4b31_branch2c\"\n\ttop: \"res4b31\"\n\tname: \"res4b31\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b31\"\n\ttop: \"res4b31\"\n\tname: \"res4b31_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b31\"\n\ttop: \"res4b32_branch2a\"\n\tname: \"res4b32_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2a\"\n\ttop: \"res4b32_branch2a\"\n\tname: \"bn4b32_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2a\"\n\ttop: \"res4b32_branch2a\"\n\tname: \"scale4b32_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b32_branch2a\"\n\tbottom: \"res4b32_branch2a\"\n\tname: \"res4b32_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b32_branch2a\"\n\ttop: \"res4b32_branch2b\"\n\tname: \"res4b32_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2b\"\n\ttop: \"res4b32_branch2b\"\n\tname: \"bn4b32_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2b\"\n\ttop: \"res4b32_branch2b\"\n\tname: \"scale4b32_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b32_branch2b\"\n\tbottom: \"res4b32_branch2b\"\n\tname: \"res4b32_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b32_branch2b\"\n\ttop: \"res4b32_branch2c\"\n\tname: \"res4b32_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2c\"\n\ttop: \"res4b32_branch2c\"\n\tname: \"bn4b32_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32_branch2c\"\n\ttop: \"res4b32_branch2c\"\n\tname: \"scale4b32_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b31\"\n\tbottom: \"res4b32_branch2c\"\n\ttop: \"res4b32\"\n\tname: \"res4b32\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b32\"\n\ttop: \"res4b32\"\n\tname: \"res4b32_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b32\"\n\ttop: \"res4b33_branch2a\"\n\tname: \"res4b33_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2a\"\n\ttop: \"res4b33_branch2a\"\n\tname: \"bn4b33_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2a\"\n\ttop: \"res4b33_branch2a\"\n\tname: \"scale4b33_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b33_branch2a\"\n\tbottom: \"res4b33_branch2a\"\n\tname: \"res4b33_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b33_branch2a\"\n\ttop: \"res4b33_branch2b\"\n\tname: \"res4b33_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2b\"\n\ttop: \"res4b33_branch2b\"\n\tname: \"bn4b33_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2b\"\n\ttop: \"res4b33_branch2b\"\n\tname: \"scale4b33_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b33_branch2b\"\n\tbottom: \"res4b33_branch2b\"\n\tname: \"res4b33_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b33_branch2b\"\n\ttop: \"res4b33_branch2c\"\n\tname: \"res4b33_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2c\"\n\ttop: \"res4b33_branch2c\"\n\tname: \"bn4b33_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33_branch2c\"\n\ttop: \"res4b33_branch2c\"\n\tname: \"scale4b33_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b32\"\n\tbottom: \"res4b33_branch2c\"\n\ttop: \"res4b33\"\n\tname: \"res4b33\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b33\"\n\ttop: \"res4b33\"\n\tname: \"res4b33_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b33\"\n\ttop: \"res4b34_branch2a\"\n\tname: \"res4b34_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2a\"\n\ttop: \"res4b34_branch2a\"\n\tname: \"bn4b34_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2a\"\n\ttop: \"res4b34_branch2a\"\n\tname: \"scale4b34_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b34_branch2a\"\n\tbottom: \"res4b34_branch2a\"\n\tname: \"res4b34_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b34_branch2a\"\n\ttop: \"res4b34_branch2b\"\n\tname: \"res4b34_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2b\"\n\ttop: \"res4b34_branch2b\"\n\tname: \"bn4b34_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2b\"\n\ttop: \"res4b34_branch2b\"\n\tname: \"scale4b34_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b34_branch2b\"\n\tbottom: \"res4b34_branch2b\"\n\tname: \"res4b34_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b34_branch2b\"\n\ttop: \"res4b34_branch2c\"\n\tname: \"res4b34_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2c\"\n\ttop: \"res4b34_branch2c\"\n\tname: \"bn4b34_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34_branch2c\"\n\ttop: \"res4b34_branch2c\"\n\tname: \"scale4b34_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b33\"\n\tbottom: \"res4b34_branch2c\"\n\ttop: \"res4b34\"\n\tname: \"res4b34\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b34\"\n\ttop: \"res4b34\"\n\tname: \"res4b34_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b34\"\n\ttop: \"res4b35_branch2a\"\n\tname: \"res4b35_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2a\"\n\ttop: \"res4b35_branch2a\"\n\tname: \"bn4b35_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2a\"\n\ttop: \"res4b35_branch2a\"\n\tname: \"scale4b35_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b35_branch2a\"\n\tbottom: \"res4b35_branch2a\"\n\tname: \"res4b35_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b35_branch2a\"\n\ttop: \"res4b35_branch2b\"\n\tname: \"res4b35_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2b\"\n\ttop: \"res4b35_branch2b\"\n\tname: \"bn4b35_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2b\"\n\ttop: \"res4b35_branch2b\"\n\tname: \"scale4b35_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res4b35_branch2b\"\n\tbottom: \"res4b35_branch2b\"\n\tname: \"res4b35_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b35_branch2b\"\n\ttop: \"res4b35_branch2c\"\n\tname: \"res4b35_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2c\"\n\ttop: \"res4b35_branch2c\"\n\tname: \"bn4b35_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35_branch2c\"\n\ttop: \"res4b35_branch2c\"\n\tname: \"scale4b35_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b34\"\n\tbottom: \"res4b35_branch2c\"\n\ttop: \"res4b35\"\n\tname: \"res4b35\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b35\"\n\ttop: \"res4b35\"\n\tname: \"res4b35_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b35\"\n\ttop: \"res5a_branch1\"\n\tname: \"res5a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\ttop: \"res5a_branch1\"\n\tname: \"bn5a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\ttop: \"res5a_branch1\"\n\tname: \"scale5a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b35\"\n\ttop: \"res5a_branch2a\"\n\tname: \"res5a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2a\"\n\tname: \"bn5a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2a\"\n\tname: \"scale5a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5a_branch2a\"\n\tbottom: \"res5a_branch2a\"\n\tname: \"res5a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2b\"\n\tname: \"res5a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2b\"\n\tname: \"bn5a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2b\"\n\tname: \"scale5a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5a_branch2b\"\n\tbottom: \"res5a_branch2b\"\n\tname: \"res5a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2c\"\n\tname: \"res5a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a_branch2c\"\n\tname: \"bn5a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a_branch2c\"\n\tname: \"scale5a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a\"\n\tname: \"res5a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5a\"\n\ttop: \"res5a\"\n\tname: \"res5a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"res5b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"bn5b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"scale5b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5b_branch2a\"\n\tbottom: \"res5b_branch2a\"\n\tname: \"res5b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2b\"\n\tname: \"res5b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2b\"\n\tname: \"bn5b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2b\"\n\tname: \"scale5b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5b_branch2b\"\n\tbottom: \"res5b_branch2b\"\n\tname: \"res5b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2c\"\n\tname: \"res5b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b_branch2c\"\n\tname: \"bn5b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b_branch2c\"\n\tname: \"scale5b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a\"\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b\"\n\tname: \"res5b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5b\"\n\ttop: \"res5b\"\n\tname: \"res5b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b\"\n\ttop: \"res5c_branch2a\"\n\tname: \"res5c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2a\"\n\tname: \"bn5c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2a\"\n\tname: \"scale5c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5c_branch2a\"\n\tbottom: \"res5c_branch2a\"\n\tname: \"res5c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2b\"\n\tname: \"res5c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2b\"\n\tname: \"bn5c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2b\"\n\tname: \"scale5c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\ttop: \"res5c_branch2b\"\n\tbottom: \"res5c_branch2b\"\n\tname: \"res5c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2c\"\n\tname: \"res5c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c_branch2c\"\n\tname: \"bn5c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c_branch2c\"\n\tname: \"scale5c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b\"\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c\"\n\tname: \"res5c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5c\"\n\ttop: \"res5c\"\n\tname: \"res5c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c\"\n\ttop: \"pool5\"\n\tname: \"pool5\"\n\ttype: \"Pooling\"\n\tpooling_param {\n\t\tkernel_size: 7\n\t\tstride: 1\n\t\tpool: AVE\n\t}\n}\n\nlayer {\n\tbottom: \"pool5\"\n\ttop: \"fc1000\"\n\tname: \"fc1000\"\n\ttype: \"InnerProduct\"\n\tinner_product_param {\n\t\tnum_output: 1000\n\t}\n}\n\nlayer {\n\tbottom: \"fc1000\"\n\ttop: \"prob\"\n\tname: \"prob\"\n\ttype: \"Softmax\"\n}\n\n"
  },
  {
    "path": "models/ResNet-50-deploy.prototxt",
    "content": "name: \"ResNet-50\"\ninput: \"data\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 224\ninput_dim: 224\n\nlayer {\n\tbottom: \"data\"\n\ttop: \"conv1\"\n\tname: \"conv1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 7\n\t\tpad: 3\n\t\tstride: 2\n\t}\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"conv1\"\n\tname: \"bn_conv1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"conv1\"\n\tname: \"scale_conv1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"conv1\"\n\tname: \"conv1_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"conv1\"\n\ttop: \"pool1\"\n\tname: \"pool1\"\n\ttype: \"Pooling\"\n\tpooling_param {\n\t\tkernel_size: 3\n\t\tstride: 2\n\t\tpool: MAX\n\t}\n}\n\nlayer {\n\tbottom: \"pool1\"\n\ttop: \"res2a_branch1\"\n\tname: \"res2a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\ttop: \"res2a_branch1\"\n\tname: \"bn2a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\ttop: \"res2a_branch1\"\n\tname: \"scale2a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"pool1\"\n\ttop: \"res2a_branch2a\"\n\tname: \"res2a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2a\"\n\tname: \"bn2a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2a\"\n\tname: \"scale2a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2a\"\n\tname: \"res2a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a_branch2a\"\n\ttop: \"res2a_branch2b\"\n\tname: \"res2a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2b\"\n\tname: \"bn2a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2b\"\n\tname: \"scale2a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2b\"\n\tname: \"res2a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a_branch2b\"\n\ttop: \"res2a_branch2c\"\n\tname: \"res2a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a_branch2c\"\n\tname: \"bn2a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a_branch2c\"\n\tname: \"scale2a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a_branch1\"\n\tbottom: \"res2a_branch2c\"\n\ttop: \"res2a\"\n\tname: \"res2a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2a\"\n\ttop: \"res2a\"\n\tname: \"res2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"res2b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"bn2b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"scale2b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2a\"\n\tname: \"res2b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b_branch2a\"\n\ttop: \"res2b_branch2b\"\n\tname: \"res2b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2b\"\n\tname: \"bn2b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2b\"\n\tname: \"scale2b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2b\"\n\tname: \"res2b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b_branch2b\"\n\ttop: \"res2b_branch2c\"\n\tname: \"res2b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b_branch2c\"\n\tname: \"bn2b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b_branch2c\"\n\tname: \"scale2b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2a\"\n\tbottom: \"res2b_branch2c\"\n\ttop: \"res2b\"\n\tname: \"res2b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2b\"\n\ttop: \"res2b\"\n\tname: \"res2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2b\"\n\ttop: \"res2c_branch2a\"\n\tname: \"res2c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2a\"\n\tname: \"bn2c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2a\"\n\tname: \"scale2c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2a\"\n\tname: \"res2c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c_branch2a\"\n\ttop: \"res2c_branch2b\"\n\tname: \"res2c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 64\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2b\"\n\tname: \"bn2c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2b\"\n\tname: \"scale2c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2b\"\n\tname: \"res2c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c_branch2b\"\n\ttop: \"res2c_branch2c\"\n\tname: \"res2c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c_branch2c\"\n\tname: \"bn2c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c_branch2c\"\n\tname: \"scale2c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2b\"\n\tbottom: \"res2c_branch2c\"\n\ttop: \"res2c\"\n\tname: \"res2c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res2c\"\n\tname: \"res2c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res3a_branch1\"\n\tname: \"res3a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\ttop: \"res3a_branch1\"\n\tname: \"bn3a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\ttop: \"res3a_branch1\"\n\tname: \"scale3a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res2c\"\n\ttop: \"res3a_branch2a\"\n\tname: \"res3a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2a\"\n\tname: \"bn3a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2a\"\n\tname: \"scale3a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2a\"\n\tname: \"res3a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a_branch2a\"\n\ttop: \"res3a_branch2b\"\n\tname: \"res3a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2b\"\n\tname: \"bn3a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2b\"\n\tname: \"scale3a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2b\"\n\tname: \"res3a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a_branch2b\"\n\ttop: \"res3a_branch2c\"\n\tname: \"res3a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a_branch2c\"\n\tname: \"bn3a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a_branch2c\"\n\tname: \"scale3a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a_branch1\"\n\tbottom: \"res3a_branch2c\"\n\ttop: \"res3a\"\n\tname: \"res3a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3a\"\n\ttop: \"res3a\"\n\tname: \"res3a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3a\"\n\ttop: \"res3b_branch2a\"\n\tname: \"res3b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2a\"\n\ttop: \"res3b_branch2a\"\n\tname: \"bn3b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2a\"\n\ttop: \"res3b_branch2a\"\n\tname: \"scale3b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2a\"\n\ttop: \"res3b_branch2a\"\n\tname: \"res3b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b_branch2a\"\n\ttop: \"res3b_branch2b\"\n\tname: \"res3b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2b\"\n\ttop: \"res3b_branch2b\"\n\tname: \"bn3b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2b\"\n\ttop: \"res3b_branch2b\"\n\tname: \"scale3b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2b\"\n\ttop: \"res3b_branch2b\"\n\tname: \"res3b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b_branch2b\"\n\ttop: \"res3b_branch2c\"\n\tname: \"res3b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2c\"\n\ttop: \"res3b_branch2c\"\n\tname: \"bn3b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b_branch2c\"\n\ttop: \"res3b_branch2c\"\n\tname: \"scale3b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3a\"\n\tbottom: \"res3b_branch2c\"\n\ttop: \"res3b\"\n\tname: \"res3b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3b\"\n\ttop: \"res3b\"\n\tname: \"res3b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3b\"\n\ttop: \"res3c_branch2a\"\n\tname: \"res3c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2a\"\n\ttop: \"res3c_branch2a\"\n\tname: \"bn3c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2a\"\n\ttop: \"res3c_branch2a\"\n\tname: \"scale3c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2a\"\n\ttop: \"res3c_branch2a\"\n\tname: \"res3c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3c_branch2a\"\n\ttop: \"res3c_branch2b\"\n\tname: \"res3c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2b\"\n\ttop: \"res3c_branch2b\"\n\tname: \"bn3c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2b\"\n\ttop: \"res3c_branch2b\"\n\tname: \"scale3c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2b\"\n\ttop: \"res3c_branch2b\"\n\tname: \"res3c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3c_branch2b\"\n\ttop: \"res3c_branch2c\"\n\tname: \"res3c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2c\"\n\ttop: \"res3c_branch2c\"\n\tname: \"bn3c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c_branch2c\"\n\ttop: \"res3c_branch2c\"\n\tname: \"scale3c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3b\"\n\tbottom: \"res3c_branch2c\"\n\ttop: \"res3c\"\n\tname: \"res3c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3c\"\n\ttop: \"res3c\"\n\tname: \"res3c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3c\"\n\ttop: \"res3d_branch2a\"\n\tname: \"res3d_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2a\"\n\ttop: \"res3d_branch2a\"\n\tname: \"bn3d_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2a\"\n\ttop: \"res3d_branch2a\"\n\tname: \"scale3d_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2a\"\n\ttop: \"res3d_branch2a\"\n\tname: \"res3d_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3d_branch2a\"\n\ttop: \"res3d_branch2b\"\n\tname: \"res3d_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 128\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2b\"\n\ttop: \"res3d_branch2b\"\n\tname: \"bn3d_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2b\"\n\ttop: \"res3d_branch2b\"\n\tname: \"scale3d_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2b\"\n\ttop: \"res3d_branch2b\"\n\tname: \"res3d_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3d_branch2b\"\n\ttop: \"res3d_branch2c\"\n\tname: \"res3d_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2c\"\n\ttop: \"res3d_branch2c\"\n\tname: \"bn3d_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d_branch2c\"\n\ttop: \"res3d_branch2c\"\n\tname: \"scale3d_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3c\"\n\tbottom: \"res3d_branch2c\"\n\ttop: \"res3d\"\n\tname: \"res3d\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res3d\"\n\ttop: \"res3d\"\n\tname: \"res3d_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res3d\"\n\ttop: \"res4a_branch1\"\n\tname: \"res4a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\ttop: \"res4a_branch1\"\n\tname: \"bn4a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\ttop: \"res4a_branch1\"\n\tname: \"scale4a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res3d\"\n\ttop: \"res4a_branch2a\"\n\tname: \"res4a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2a\"\n\tname: \"bn4a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2a\"\n\tname: \"scale4a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2a\"\n\tname: \"res4a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a_branch2a\"\n\ttop: \"res4a_branch2b\"\n\tname: \"res4a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2b\"\n\tname: \"bn4a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2b\"\n\tname: \"scale4a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2b\"\n\tname: \"res4a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a_branch2b\"\n\ttop: \"res4a_branch2c\"\n\tname: \"res4a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a_branch2c\"\n\tname: \"bn4a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a_branch2c\"\n\tname: \"scale4a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a_branch1\"\n\tbottom: \"res4a_branch2c\"\n\ttop: \"res4a\"\n\tname: \"res4a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4a\"\n\ttop: \"res4a\"\n\tname: \"res4a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4a\"\n\ttop: \"res4b_branch2a\"\n\tname: \"res4b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2a\"\n\ttop: \"res4b_branch2a\"\n\tname: \"bn4b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2a\"\n\ttop: \"res4b_branch2a\"\n\tname: \"scale4b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2a\"\n\ttop: \"res4b_branch2a\"\n\tname: \"res4b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b_branch2a\"\n\ttop: \"res4b_branch2b\"\n\tname: \"res4b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2b\"\n\ttop: \"res4b_branch2b\"\n\tname: \"bn4b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2b\"\n\ttop: \"res4b_branch2b\"\n\tname: \"scale4b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2b\"\n\ttop: \"res4b_branch2b\"\n\tname: \"res4b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b_branch2b\"\n\ttop: \"res4b_branch2c\"\n\tname: \"res4b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2c\"\n\ttop: \"res4b_branch2c\"\n\tname: \"bn4b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b_branch2c\"\n\ttop: \"res4b_branch2c\"\n\tname: \"scale4b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4a\"\n\tbottom: \"res4b_branch2c\"\n\ttop: \"res4b\"\n\tname: \"res4b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4b\"\n\ttop: \"res4b\"\n\tname: \"res4b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4b\"\n\ttop: \"res4c_branch2a\"\n\tname: \"res4c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2a\"\n\ttop: \"res4c_branch2a\"\n\tname: \"bn4c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2a\"\n\ttop: \"res4c_branch2a\"\n\tname: \"scale4c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2a\"\n\ttop: \"res4c_branch2a\"\n\tname: \"res4c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4c_branch2a\"\n\ttop: \"res4c_branch2b\"\n\tname: \"res4c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2b\"\n\ttop: \"res4c_branch2b\"\n\tname: \"bn4c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2b\"\n\ttop: \"res4c_branch2b\"\n\tname: \"scale4c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2b\"\n\ttop: \"res4c_branch2b\"\n\tname: \"res4c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4c_branch2b\"\n\ttop: \"res4c_branch2c\"\n\tname: \"res4c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2c\"\n\ttop: \"res4c_branch2c\"\n\tname: \"bn4c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c_branch2c\"\n\ttop: \"res4c_branch2c\"\n\tname: \"scale4c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4b\"\n\tbottom: \"res4c_branch2c\"\n\ttop: \"res4c\"\n\tname: \"res4c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4c\"\n\ttop: \"res4c\"\n\tname: \"res4c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4c\"\n\ttop: \"res4d_branch2a\"\n\tname: \"res4d_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2a\"\n\ttop: \"res4d_branch2a\"\n\tname: \"bn4d_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2a\"\n\ttop: \"res4d_branch2a\"\n\tname: \"scale4d_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2a\"\n\ttop: \"res4d_branch2a\"\n\tname: \"res4d_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4d_branch2a\"\n\ttop: \"res4d_branch2b\"\n\tname: \"res4d_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2b\"\n\ttop: \"res4d_branch2b\"\n\tname: \"bn4d_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2b\"\n\ttop: \"res4d_branch2b\"\n\tname: \"scale4d_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2b\"\n\ttop: \"res4d_branch2b\"\n\tname: \"res4d_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4d_branch2b\"\n\ttop: \"res4d_branch2c\"\n\tname: \"res4d_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2c\"\n\ttop: \"res4d_branch2c\"\n\tname: \"bn4d_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d_branch2c\"\n\ttop: \"res4d_branch2c\"\n\tname: \"scale4d_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4c\"\n\tbottom: \"res4d_branch2c\"\n\ttop: \"res4d\"\n\tname: \"res4d\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4d\"\n\ttop: \"res4d\"\n\tname: \"res4d_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4d\"\n\ttop: \"res4e_branch2a\"\n\tname: \"res4e_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2a\"\n\ttop: \"res4e_branch2a\"\n\tname: \"bn4e_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2a\"\n\ttop: \"res4e_branch2a\"\n\tname: \"scale4e_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2a\"\n\ttop: \"res4e_branch2a\"\n\tname: \"res4e_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4e_branch2a\"\n\ttop: \"res4e_branch2b\"\n\tname: \"res4e_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2b\"\n\ttop: \"res4e_branch2b\"\n\tname: \"bn4e_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2b\"\n\ttop: \"res4e_branch2b\"\n\tname: \"scale4e_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2b\"\n\ttop: \"res4e_branch2b\"\n\tname: \"res4e_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4e_branch2b\"\n\ttop: \"res4e_branch2c\"\n\tname: \"res4e_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2c\"\n\ttop: \"res4e_branch2c\"\n\tname: \"bn4e_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e_branch2c\"\n\ttop: \"res4e_branch2c\"\n\tname: \"scale4e_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4d\"\n\tbottom: \"res4e_branch2c\"\n\ttop: \"res4e\"\n\tname: \"res4e\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4e\"\n\ttop: \"res4e\"\n\tname: \"res4e_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4e\"\n\ttop: \"res4f_branch2a\"\n\tname: \"res4f_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2a\"\n\ttop: \"res4f_branch2a\"\n\tname: \"bn4f_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2a\"\n\ttop: \"res4f_branch2a\"\n\tname: \"scale4f_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2a\"\n\ttop: \"res4f_branch2a\"\n\tname: \"res4f_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4f_branch2a\"\n\ttop: \"res4f_branch2b\"\n\tname: \"res4f_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 256\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2b\"\n\ttop: \"res4f_branch2b\"\n\tname: \"bn4f_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2b\"\n\ttop: \"res4f_branch2b\"\n\tname: \"scale4f_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2b\"\n\ttop: \"res4f_branch2b\"\n\tname: \"res4f_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4f_branch2b\"\n\ttop: \"res4f_branch2c\"\n\tname: \"res4f_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 1024\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2c\"\n\ttop: \"res4f_branch2c\"\n\tname: \"bn4f_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f_branch2c\"\n\ttop: \"res4f_branch2c\"\n\tname: \"scale4f_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4e\"\n\tbottom: \"res4f_branch2c\"\n\ttop: \"res4f\"\n\tname: \"res4f\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res4f\"\n\ttop: \"res4f\"\n\tname: \"res4f_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res4f\"\n\ttop: \"res5a_branch1\"\n\tname: \"res5a_branch1\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\ttop: \"res5a_branch1\"\n\tname: \"bn5a_branch1\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\ttop: \"res5a_branch1\"\n\tname: \"scale5a_branch1\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res4f\"\n\ttop: \"res5a_branch2a\"\n\tname: \"res5a_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 2\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2a\"\n\tname: \"bn5a_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2a\"\n\tname: \"scale5a_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2a\"\n\tname: \"res5a_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a_branch2a\"\n\ttop: \"res5a_branch2b\"\n\tname: \"res5a_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2b\"\n\tname: \"bn5a_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2b\"\n\tname: \"scale5a_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2b\"\n\tname: \"res5a_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a_branch2b\"\n\ttop: \"res5a_branch2c\"\n\tname: \"res5a_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a_branch2c\"\n\tname: \"bn5a_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a_branch2c\"\n\tname: \"scale5a_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a_branch1\"\n\tbottom: \"res5a_branch2c\"\n\ttop: \"res5a\"\n\tname: \"res5a\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5a\"\n\ttop: \"res5a\"\n\tname: \"res5a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"res5b_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"bn5b_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"scale5b_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2a\"\n\tname: \"res5b_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b_branch2a\"\n\ttop: \"res5b_branch2b\"\n\tname: \"res5b_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2b\"\n\tname: \"bn5b_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2b\"\n\tname: \"scale5b_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2b\"\n\tname: \"res5b_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b_branch2b\"\n\ttop: \"res5b_branch2c\"\n\tname: \"res5b_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b_branch2c\"\n\tname: \"bn5b_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b_branch2c\"\n\tname: \"scale5b_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5a\"\n\tbottom: \"res5b_branch2c\"\n\ttop: \"res5b\"\n\tname: \"res5b\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5b\"\n\ttop: \"res5b\"\n\tname: \"res5b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5b\"\n\ttop: \"res5c_branch2a\"\n\tname: \"res5c_branch2a\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2a\"\n\tname: \"bn5c_branch2a\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2a\"\n\tname: \"scale5c_branch2a\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2a\"\n\tname: \"res5c_branch2a_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c_branch2a\"\n\ttop: \"res5c_branch2b\"\n\tname: \"res5c_branch2b\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 512\n\t\tkernel_size: 3\n\t\tpad: 1\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2b\"\n\tname: \"bn5c_branch2b\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2b\"\n\tname: \"scale5c_branch2b\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2b\"\n\tname: \"res5c_branch2b_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c_branch2b\"\n\ttop: \"res5c_branch2c\"\n\tname: \"res5c_branch2c\"\n\ttype: \"Convolution\"\n\tconvolution_param {\n\t\tnum_output: 2048\n\t\tkernel_size: 1\n\t\tpad: 0\n\t\tstride: 1\n\t\tbias_term: false\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c_branch2c\"\n\tname: \"bn5c_branch2c\"\n\ttype: \"BatchNorm\"\n\tbatch_norm_param {\n\t\tuse_global_stats: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c_branch2c\"\n\tname: \"scale5c_branch2c\"\n\ttype: \"Scale\"\n\tscale_param {\n\t\tbias_term: true\n\t}\n}\n\nlayer {\n\tbottom: \"res5b\"\n\tbottom: \"res5c_branch2c\"\n\ttop: \"res5c\"\n\tname: \"res5c\"\n\ttype: \"Eltwise\"\n}\n\nlayer {\n\tbottom: \"res5c\"\n\ttop: \"res5c\"\n\tname: \"res5c_relu\"\n\ttype: \"ReLU\"\n}\n\nlayer {\n\tbottom: \"res5c\"\n\ttop: \"pool5\"\n\tname: \"pool5\"\n\ttype: \"Pooling\"\n\tpooling_param {\n\t\tkernel_size: 7\n\t\tstride: 1\n\t\tpool: AVE\n\t}\n}\n\nlayer {\n\tbottom: \"pool5\"\n\ttop: \"fc1000\"\n\tname: \"fc1000\"\n\ttype: \"InnerProduct\"\n\tinner_product_param {\n\t\tnum_output: 1000\n\t}\n}\n\nlayer {\n\tbottom: \"fc1000\"\n\ttop: \"prob\"\n\tname: \"prob\"\n\ttype: \"Softmax\"\n}\n\n"
  },
  {
    "path": "models/mps_builder",
    "content": "#!/bin/bash -e\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\ncleanup() {\n  kill $(jobs -p) ||:\n  echo quit | nvidia-cuda-mps-control > /dev/null 2>&1 ||:\n}\ntrap \"cleanup\" EXIT SIGINT SIGTERM\n\nactive_sms=${1:-100}\necho \"Setting Active SM Percentage: ${active_sms}\"\nexport CUDA_MPS_ACTIVE_THREAD_PERCENTAGE=${active_sms}\n\nnvidia-cuda-mps-control -d ||:\n\nsleep 1\n\necho\necho \"Starting a new shell with MPS running...\"\nbash --rcfile <(echo \"PS1='MPS Subshell: '\")\n"
  },
  {
    "path": "models/onnx/common.py",
    "content": "import os\nimport argparse\nimport numpy as np\nimport pycuda.driver as cuda\nimport tensorrt as trt\n\ntry:\n    # Sometimes python2 does not understand FileNotFoundError\n    FileNotFoundError\nexcept NameError:\n    FileNotFoundError = IOError\n\ndef GiB(val):\n    return val * 1 << 30\n\ndef find_sample_data(description=\"Runs a TensorRT Python sample\", subfolder=\"\", find_files=[]):\n    '''\n    Parses sample arguments.\n    Args:\n        description (str): Description of the sample.\n        subfolder (str): The subfolder containing data relevant to this sample\n        find_files (str): A list of filenames to find. Each filename will be replaced with an absolute path.\n    Returns:\n        str: Path of data directory.\n    Raises:\n        FileNotFoundError\n    '''\n    kDEFAULT_DATA_ROOT = os.path.abspath(\"/usr/src/tensorrt/data\")\n    parser = argparse.ArgumentParser(description=description)\n    # Standard command-line arguments for all samples.\n    parser.add_argument(\"-d\", \"--datadir\", help=\"Location of the TensorRT sample data directory.\")\n    args, unknown_args = parser.parse_known_args()\n    # If data directory is not specified, use the default.\n    data_root = args.datadir if args.datadir else kDEFAULT_DATA_ROOT\n    data_path = os.path.join(data_root, subfolder) if subfolder else data_root\n    # Make sure data directory exists.\n    if not (os.path.exists(data_path)):\n        raise FileNotFoundError(data_path + \" does not exist. Please provide the correct data path with the -d option.\")\n    # Find all requested files.\n    for index, f in enumerate(find_files):\n        find_files[index] = os.path.abspath(os.path.join(data_path, f))\n        if not os.path.exists(find_files[index]):\n            raise FileNotFoundError(find_files[index] + \" does not exist. Please provide the correct data path with the -d option.\")\n    if find_files:\n        return data_path, find_files\n    else:\n        return data_path\n\n# Simple helper data class that's a little nicer to use than a 2-tuple.\nclass HostDeviceMem(object):\n    def __init__(self, host_mem, device_mem):\n        self.host = host_mem\n        self.device = device_mem\n\n    def __str__(self):\n        return \"Host:\\n\" + str(self.host) + \"\\nDevice:\\n\" + str(self.device)\n\n    def __repr__(self):\n        return self.__str__()\n\n# Allocates all buffers required for an engine, i.e. host/device inputs/outputs.\ndef allocate_buffers(engine):\n    inputs = []\n    outputs = []\n    bindings = []\n    stream = cuda.Stream()\n    for binding in engine:\n        size = trt.volume(engine.get_binding_shape(binding))\n        dtype = trt.nptype(engine.get_binding_dtype(binding))\n        # Allocate host and device buffers\n        host_mem = cuda.pagelocked_empty(size, dtype)\n        device_mem = cuda.mem_alloc(host_mem.nbytes)\n        # Append the device buffer to device bindings.\n        bindings.append(int(device_mem))\n        # Append to the appropriate list.\n        if engine.binding_is_input(binding):\n            inputs.append(HostDeviceMem(host_mem, device_mem))\n        else:\n            outputs.append(HostDeviceMem(host_mem, device_mem))\n    return inputs, outputs, bindings, stream\n\n# This function is generalized for multiple inputs/outputs.\n# inputs and outputs are expected to be lists of HostDeviceMem objects.\ndef do_inference(context, bindings, inputs, outputs, stream):\n    # Transfer input data to the GPU.\n    [cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs]\n    # Run inference.\n    context.execute_async(bindings=bindings, stream_handle=stream.handle)\n    # Transfer predictions back from the GPU.\n    [cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs]\n    # Synchronize the stream\n    stream.synchronize()\n    # Return only the host outputs.\n    return [out.host for out in outputs]\n"
  },
  {
    "path": "models/onnx/mnist-v1.3/test_data_set_0/output_0.pb",
    "content": "\b\u0001\b\n\u0010\u0001J(sDU\u001aČtE\u0001'DWQeYQ\u0018\u00123vNKB\u0003"
  },
  {
    "path": "models/onnx/mnist-v1.3/test_data_set_1/output_0.pb",
    "content": "\b\u0001\b\n\u0010\u0001J(\u001cE\f\u000e_\u0001;ÁXy\u0019Ą*_DHԺÓ!9Z"
  },
  {
    "path": "models/onnx/mnist-v1.3/test_data_set_2/output_0.pb",
    "content": "\b\u0001\b\n\u0010\u0001J(l\u0011\u00034ĐDM\u000fW\u001fD\u001b˿>'\u0002a¤&B\u00156hE"
  },
  {
    "path": "models/onnx/onnx_builder.py",
    "content": "# This sample uses an ONNX ResNet50 Model to create a TensorRT Inference Engine\nimport random\nfrom PIL import Image\nimport numpy as np\nimport ctypes\n\nimport pycuda.driver as cuda\n# This import causes pycuda to automatically manage CUDA context creation and cleanup.\nimport pycuda.autoinit\n\nimport tensorrt as trt\n\nimport sys, os\nsys.path.insert(1, os.path.join(sys.path[0], \".\"))\nimport common\n\ndef softmax(X, theta = 1.0, axis = None):\n    \"\"\"\n    Compute the softmax of each element along an axis of X.\n\n    Parameters\n    ----------\n    X: ND-Array. Probably should be floats. \n    theta (optional): float parameter, used as a multiplier\n        prior to exponentiation. Default = 1.0\n    axis (optional): axis to compute values along. Default is the \n        first non-singleton axis.\n\n    Returns an array the same size as X. The result will sum to 1\n    along the specified axis.\n    \"\"\"\n\n    # make X at least 2d\n    y = np.atleast_2d(X)\n\n    # find axis\n    if axis is None:\n        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)\n\n    # multiply y against the theta parameter, \n    y = y * float(theta)\n\n    # subtract the max for numerical stability\n    y = y - np.expand_dims(np.max(y, axis = axis), axis)\n    \n    # exponentiate y\n    y = np.exp(y)\n\n    # take the sum along the specified axis\n    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)\n\n    # finally: divide elementwise\n    p = y / ax_sum\n\n    # flatten if X was 1D\n    if len(X.shape) == 1: p = p.flatten()\n\n    return p\n\nclass ModelData(object):\n    MODEL_PATH = \"/work/models/flowers-152.onnx\"\n    INPUT_SHAPE = (3, 224, 224)\n    # We can convert TensorRT data types to numpy types with trt.nptype()\n    DTYPE = trt.float32\n\n# You can set the logger severity higher to suppress messages (or lower to display more messages).\nTRT_LOGGER = trt.Logger(trt.Logger.WARNING)\n\n# Allocate host and device buffers, and create a stream.\ndef allocate_buffers(engine):\n    # Determine dimensions and create page-locked memory buffers (i.e. won't be swapped to disk) to hold host inputs/outputs.\n    h_input = cuda.pagelocked_empty(trt.volume(engine.get_binding_shape(0)), dtype=trt.nptype(ModelData.DTYPE))\n    h_output = cuda.pagelocked_empty(trt.volume(engine.get_binding_shape(1)), dtype=trt.nptype(ModelData.DTYPE))\n    # Allocate device memory for inputs and outputs.\n    d_input = cuda.mem_alloc(h_input.nbytes)\n    d_output = cuda.mem_alloc(h_output.nbytes)\n    # Create a stream in which to copy inputs/outputs and run inference.\n    stream = cuda.Stream()\n    return h_input, d_input, h_output, d_output, stream\n\ndef do_inference(context, h_input, d_input, h_output, d_output, stream):\n    # Transfer input data to the GPU.\n    cuda.memcpy_htod_async(d_input, h_input, stream)\n    # Run inference.\n    context.execute_async(bindings=[int(d_input), int(d_output)], stream_handle=stream.handle)\n    # Transfer predictions back from the GPU.\n    cuda.memcpy_dtoh_async(h_output, d_output, stream)\n    # Synchronize the stream\n    stream.synchronize()\n\n# The Onnx path is used for Onnx models.\ndef build_engine_onnx(model_file, calibrator=None):\n    with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.OnnxParser(network, TRT_LOGGER) as parser:\n        builder.max_workspace_size = common.GiB(1)\n        builder.max_batch_size = 8\n        precision = \"fp32\"\n        if calibrator:\n            builder.int8_mode = True\n            builder.int8_calibrator = calibrator\n            precision = \"int8\"\n        else:\n            builder.fp16_mode = True\n            precision = \"fp16\"\n        # Load the Onnx model and parse it in order to populate the TensorRT network.\n        with open(model_file, 'rb') as model:\n            parser.parse(model.read())\n        engine = builder.build_cuda_engine(network)\n        serialized = engine.serialize()\n        with open(\"/work/models/flowers-152-b{}-{}.engine\".format(builder.max_batch_size, precision), \"wb\") as file:\n            file.write(serialized)\n        return engine\n\ndef normalize_image(image_name):\n    image = Image.open(image_name)\n    # Resize, antialias and transpose the image to CHW.\n    c, h, w = ModelData.INPUT_SHAPE\n    image_arr = np.asarray(image.resize((w, h), Image.ANTIALIAS)).transpose([2, 0, 1]).astype(trt.nptype(ModelData.DTYPE)).ravel()\n    # This particular ResNet50 model requires some preprocessing, specifically, mean normalization.\n    return ((image_arr / 255.0) - 0.5) * 2.0\n\ndef load_normalized_test_case(test_image, pagelocked_buffer):\n    # Normalize the image and copy to pagelocked memory.\n    np.copyto(pagelocked_buffer, normalize_image(test_image))\n    return test_image\n\ndef create_calibration_dataset():\n    jpegs = []\n    for dirpath, subdirs, files in os.walk(\"/work/models/flowers-data/flowers\"):\n        for f in files:\n            if f.endswith(\"jpg\"):\n                jpegs.append(os.path.join(dirpath, f))\n    random.shuffle(jpegs)\n    return jpegs[:200]\n\nclass ImageBatchStream:\n    def __init__(self, batch_size, calibration_files):\n        c, h, w = ModelData.INPUT_SHAPE\n        self.batch_size = batch_size\n        self.files = calibration_files\n        self.batch = 0\n        self.max_batches = (len(calibration_files) // batch_size) + \\\n                           (1 if (len(calibration_files) % batch_size) else 0)\n        self.calibration_data = np.zeros((batch_size, c, h, w), dtype=np.float32)\n\n    def reset(self):\n        self.batch = 0\n     \n    def next_batch(self):\n        c, h, w = ModelData.INPUT_SHAPE\n        if self.batch < self.max_batches:\n            imgs = []\n            files_for_batch = self.files[self.batch_size * self.batch : \\\n                                  self.batch_size * (self.batch + 1)]\n            for f in files_for_batch:\n                print(\"[ImageBatchStream] Processing \", f)\n                img = normalize_image(f)\n                imgs.append(img.reshape((c, h, w)))\n            for i in range(len(imgs)):\n                self.calibration_data[i] = imgs[i]\n            self.batch += 1\n            return np.ascontiguousarray(self.calibration_data, dtype=np.float32)\n        else:\n            return np.array([])\n\n\nclass MyEntropyCalibrator(trt.IInt8EntropyCalibrator):\n    def __init__(self, stream):\n        trt.IInt8EntropyCalibrator.__init__(self)\n        self.batchstream = stream\n        self.d_input = cuda.mem_alloc(self.batchstream.calibration_data.nbytes)\n        stream.reset()\n\n    def get_batch_size(self):\n        return self.batchstream.batch_size\n\n    def get_batch(self, bindings, names):\n        batch = self.batchstream.next_batch()\n        if not batch.size:\n            return None\n        cuda.memcpy_htod(self.d_input, batch)\n        bindings[0] = int(self.d_input)\n        return bindings\n\n    def read_calibration_cache(self, length):\n        return None\n\n    def write_calibration_cache(self, ptr, size):\n#       cache = ctypes.c_char_p(int(ptr))\n#       with open('calibration_cache.bin', 'wb') as f:\n#           f.write(cache.value)\n        return None\n\n\n\ndef main():\n    calibration_files = create_calibration_dataset()\n    batch_stream = ImageBatchStream(8, calibration_files)\n    int8_calibrator = None\n    int8_calibrator = MyEntropyCalibrator(batch_stream)\n    engine = build_engine_onnx(\"/work/models/flowers-152.onnx\", calibrator=int8_calibrator)\n#   serialized = engine.serialize()\n#   with open(\"/work/models/flowers-152-b8-int8.engine\", \"wb\") as file:\n#       file.write(serialized)\n#   h_input, d_input, h_output, d_output, stream = allocate_buffers(engine)\n#   with engine.create_execution_context() as context:\n#       for test_image in [\"/work/models/flowers-data/test/image_07927.jpg\",\n#                          \"/work/models/flowers-data/test/image_06969.jpg\",]:\n#           #test_image = \"/work/models/flowers-data/test/image_07927.jpg\" # 13 - blanket flower\n#           #test_image = \"/work/models/flowers-data/test/image_06969.jpg\"  # 0 - alpine sea holly\n#           test_case = load_normalized_test_case(test_image, h_input)\n#           do_inference(context, h_input, d_input, h_output, d_output, stream)\n#           # We use the highest probability as our prediction. Its index corresponds to the predicted label.\n#           pred = np.argmax(h_output)\n#           score = softmax(h_output)[pred]\n#           print(\"Recognized \" + test_case + \" as \" + str(pred) + \" score: \" + str(score))\n\ndef old_main():\n    # Set the data path to the directory that contains the trained models and test images for inference.\n    data_path, data_files = common.find_sample_data(description=\"Runs a ResNet50 network with a TensorRT inference engine.\", subfolder=\"resnet50\", find_files=[\"binoculars.jpeg\", \"reflex_camera.jpeg\", \"tabby_tiger_cat.jpg\", ModelData.MODEL_PATH, \"class_labels.txt\"])\n    # Get test images, models and labels.\n    test_images = data_files[0:3]\n    onnx_model_file, labels_file = data_files[3:]\n    labels = open(labels_file, 'r').read().split('\\n')\n\n    # Build a TensorRT engine.\n    with build_engine_onnx(onnx_model_file) as engine:\n        # Inference is the same regardless of which parser is used to build the engine, since the model architecture is the same.\n        # Allocate buffers and create a CUDA stream.\n        h_input, d_input, h_output, d_output, stream = allocate_buffers(engine)\n        # Contexts are used to perform inference.\n        with engine.create_execution_context() as context:\n            # Load a normalized test case into the host input page-locked buffer.\n            test_image = random.choice(test_images)\n            test_case = load_normalized_test_case(test_image, h_input)\n            # Run the engine. The output will be a 1D tensor of length 1000, where each value represents the\n            # probability that the image corresponds to that label\n            do_inference(context, h_input, d_input, h_output, d_output, stream)\n            # We use the highest probability as our prediction. Its index corresponds to the predicted label.\n            pred = np.argmax(h_output)\n            print(\"Recognized \" + test_case + \" as \" + pred)\n\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "models/setup.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\nimport os\nimport subprocess\n\nmodels = [\n    (\"ResNet-50-deploy.prototxt\", \"prob\"),\n#   (\"ResNet-152-deploy.prototxt\", \"prob\"),\n]\n\nprecisions = [\n#   (\"fp32\", \"\"),\n    (\"fp16\", \"--fp16\"),\n#   (\"int8\", \"--int8\")\n]\n\ndef main():\n    for model, o in models:\n        for name, p in precisions:\n            for b in [1, 8]: #, 2, 4, 8]:\n                n = \"b{}-{}\".format(b, name)\n                e = model.replace(\"prototxt\", \"engine\")\n                e = e.replace(\"deploy\", n)\n                m = os.path.join(\"/work/models\", model)\n                if os.path.isfile(e):\n                    continue\n                subprocess.call(\"trtexec --deploy={} --batch={} --output={} {} --engine={}\".format(\n                    m, b, o, p, e\n                ), shell=True)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "notebooks/Demo Day 1.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import time\\n\",\n    \"import numpy as np\\n\",\n    \"import wurlitzer\\n\",\n    \"\\n\",\n    \"import trtlab\\n\",\n    \"import infer_test_utils as utils\\n\",\n    \"\\n\",\n    \"# this allows us to capture stdout and stderr from the backend c++ infer-runtime\\n\",\n    \"display_output = wurlitzer.sys_pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"inputs = utils.load_inputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\\n\",\n    \"expected = utils.load_outputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!trtexec --onnx=/work/models/onnx/mnist-v1.3/model.onnx --saveEngine=/tmp/mnist-v1.3.engine\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Local Inference Setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager = trtlab.InferenceManager(max_exec_concurrency=2)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.register_tensorrt_engine(\\\"mnist\\\", \\\"/tmp/mnist-v1.3.engine\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.update_resources()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Local Inference Properties\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist = manager.infer_runner(\\\"mnist\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.input_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.output_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Local Inference Compute\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"futures = [mnist.infer(Input3=input) for input in inputs]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# free to do other work while inference is being computed\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"results = [f.get() for f in futures]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"for r, e in zip(results, expected):\\n\",\n    \"    for key, val in r.items():\\n\",\n    \"        r = val.reshape((1,10))\\n\",\n    \"        np.testing.assert_almost_equal(r, e, decimal=3)\\n\",\n    \"        print(\\\"Test Passed\\\")\\n\",\n    \"        print(\\\"Result: {}\\\".format(np.argmax(utils.softmax(r))))\\n\",\n    \"\\n\",\n    \"utils.mnist_image(inputs[0]).show()\\n\",\n    \"expected[0]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "notebooks/Demo Day 2.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import time\\n\",\n    \"import numpy as np\\n\",\n    \"import wurlitzer\\n\",\n    \"\\n\",\n    \"import trtlab\\n\",\n    \"import infer_test_utils as utils\\n\",\n    \"\\n\",\n    \"# this allows us to capture stdout and stderr from the backend c++ infer-runtime\\n\",\n    \"display_output = wurlitzer.sys_pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"inputs = utils.load_inputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\\n\",\n    \"expected = utils.load_outputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Remote Inference Setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager = trtlab.RemoteInferenceManager(hostname=\\\"localhost:50052\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    models = manager.get_models()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    print(models)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Remote Inference Properties\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist = manager.infer_runner(\\\"mnist\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.input_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.output_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Remote Inference Compute\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"futures = [mnist.infer(Input3=input) for input in inputs]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# free to do other work while inference is being computed\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"results = [f.get() for f in futures]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"for r, e in zip(results, expected):\\n\",\n    \"    for key, val in r.items():\\n\",\n    \"        r = val.reshape((1,10))\\n\",\n    \"        np.testing.assert_almost_equal(r, e, decimal=3)\\n\",\n    \"        print(\\\"Test Passed\\\")\\n\",\n    \"        print(\\\"Output Binding Name: {}; shape: {}\\\".format(key, val.shape))\\n\",\n    \"        print(\\\"Result: {}\\\".format(np.argmax(utils.softmax(r))))\\n\",\n    \"        \\n\",\n    \"utils.mnist_image(inputs[0]).show()\\n\",\n    \"expected[0]\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "notebooks/Demo Day 3.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import time\\n\",\n    \"import numpy as np\\n\",\n    \"import wurlitzer\\n\",\n    \"\\n\",\n    \"import trtlab\\n\",\n    \"import infer_test_utils as utils\\n\",\n    \"\\n\",\n    \"# this allows us to capture stdout and stderr from the backend c++ infer-runtime\\n\",\n    \"display_output = wurlitzer.sys_pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!trtexec --onnx=/work/models/onnx/mnist-v1.3/model.onnx --saveEngine=/tmp/mnist-v1.3.engine\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Remote Inference Setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager = trtlab.InferenceManager(max_exec_concurrency=2)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.register_tensorrt_engine(\\\"mnist\\\", \\\"/tmp/mnist-v1.3.engine\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.update_resources()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Remote Inference Server\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.serve()\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "notebooks/Multiple Models.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import time\\n\",\n    \"import numpy as np\\n\",\n    \"import wurlitzer\\n\",\n    \"\\n\",\n    \"import trtlab\\n\",\n    \"\\n\",\n    \"# this allows us to capture stdout and stderr from the backend c++ infer-runtime\\n\",\n    \"display_output = wurlitzer.sys_pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!/work/models/setup.py\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Local Inference Setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"WARNING: Logging before InitGoogleLogging() is written to STDERR\\n\",\n      \"I0204 22:01:27.543411   925 inference_manager.cc:64] -- Initialzing TensorRT Resource Manager --\\n\",\n      \"I0204 22:01:27.543426   925 inference_manager.cc:65] Maximum Execution Concurrency: 4\\n\",\n      \"I0204 22:01:27.543429   925 inference_manager.cc:66] Maximum Copy Concurrency: 8\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager = trtlab.InferenceManager(max_exec_concurrency=4)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"I0204 22:01:30.164453   925 model.cc:91] Binding: data; isInput: true; dtype size: 4; bytes per batch item: 602112\\n\",\n      \"I0204 22:01:30.164479   925 model.cc:91] Binding: prob; isInput: false; dtype size: 4; bytes per batch item: 4000\\n\",\n      \"I0204 22:01:30.169529   925 inference_manager.cc:149] -- Registering Model: rn50-b1 --\\n\",\n      \"I0204 22:01:30.169546   925 inference_manager.cc:150] Input/Output Tensors require 591.9 KiB\\n\",\n      \"I0204 22:01:30.169550   925 inference_manager.cc:151] Execution Activations require 5.7 MiB\\n\",\n      \"I0204 22:01:30.169554   925 inference_manager.cc:155] Weights require 75.8 MiB\\n\",\n      \"I0204 22:01:30.223752   925 model.cc:91] Binding: data; isInput: true; dtype size: 4; bytes per batch item: 602112\\n\",\n      \"I0204 22:01:30.223776   925 model.cc:91] Binding: prob; isInput: false; dtype size: 4; bytes per batch item: 4000\\n\",\n      \"I0204 22:01:30.227011   925 inference_manager.cc:149] -- Registering Model: rn50-b8 --\\n\",\n      \"I0204 22:01:30.227035   925 inference_manager.cc:150] Input/Output Tensors require 4.6 MiB\\n\",\n      \"I0204 22:01:30.227041   925 inference_manager.cc:151] Execution Activations require 39.8 MiB\\n\",\n      \"I0204 22:01:30.227046   925 inference_manager.cc:155] Weights require 49.0 MiB\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.register_tensorrt_engine(\\\"rn50-b1\\\", \\\"/work/models/ResNet-50-b1-fp16.engine\\\")\\n\",\n    \"    manager.register_tensorrt_engine(\\\"rn50-b8\\\", \\\"/work/models/ResNet-50-b8-fp16.engine\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stderr\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"I0204 22:01:31.025523   925 inference_manager.cc:194] -- Allocating TensorRT Resources --\\n\",\n      \"I0204 22:01:31.025539   925 inference_manager.cc:195] Creating 4 TensorRT execution tokens.\\n\",\n      \"I0204 22:01:31.025542   925 inference_manager.cc:196] Creating a Pool of 8 Host/Device Memory Stacks\\n\",\n      \"I0204 22:01:31.025550   925 inference_manager.cc:197] Each Host Stack contains 4.7 MiB\\n\",\n      \"I0204 22:01:31.025554   925 inference_manager.cc:198] Each Device Stack contains 4.8 MiB\\n\",\n      \"I0204 22:01:31.025559   925 inference_manager.cc:199] Total GPU Memory: 197.5 MiB\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    manager.update_resources()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Local Inference Properties\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"b1 = manager.infer_runner(\\\"rn50-b1\\\")\\n\",\n    \"b8 = manager.infer_runner(\\\"rn50-b8\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"{'data': {'dtype': dtype('float32'), 'shape': [3, 224, 224]}}\"\n      ]\n     },\n     \"execution_count\": 6,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"b1.input_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"b1.max_batch_size()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"{'data': {'dtype': dtype('float32'), 'shape': [3, 224, 224]}}\"\n      ]\n     },\n     \"execution_count\": 8,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"b8.input_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"8\"\n      ]\n     },\n     \"execution_count\": 9,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"b8.max_batch_size()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def max_batch_size_shape(x, input='data'):\\n\",\n    \"    batch = [x.max_batch_size()]\\n\",\n    \"    batch.extend(x.input_bindings()[input]['shape'])\\n\",\n    \"    return batch\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[8, 3, 224, 224]\"\n      ]\n     },\n     \"execution_count\": 12,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"max_batch_size_shape(b8)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Compute\\n\",\n    \"\\n\",\n    \"Here we launch two async inferences with two different TensorRT engines, one built for batch1, the other for batch8.  While these are the same ResNet-50 models, they could be any two unique TensorRT engines.\\n\",\n    \"\\n\",\n    \"Note: for this example the weights of the model and the input tensors are all random values.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"futures = [model.infer(data=np.random.random_sample(max_batch_size_shape(model))) for model in [b1, b8]]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 19,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# free to do other work while inference is being computed\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 20,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"results = [f.get() for f in futures]\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"prob binding has shape: (1, 1000, 1, 1)\\n\",\n      \"prob binding has shape: (8, 1000, 1, 1)\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"for result in results:\\n\",\n    \"    for output, tensor in result.items():\\n\",\n    \"        print(\\\"{} binding has shape: {}\\\".format(output, tensor.shape))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "notebooks/Quickstart.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# TensorRT Runtime\\n\",\n    \"\\n\",\n    \"This example walks through the basic usecase of:\\n\",\n    \"  1. initialization the infer-runtime\\n\",\n    \"  2. loading a model\\n\",\n    \"  3. allocating resources\\n\",\n    \"  4. inspecting the input/output bindings of the model\\n\",\n    \"  5. evaluating the model using async futures\\n\",\n    \"  6. testing for correctness\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"import os\\n\",\n    \"import time\\n\",\n    \"import numpy as np\\n\",\n    \"import wurlitzer\\n\",\n    \"\\n\",\n    \"import trtlab\\n\",\n    \"import infer_test_utils as utils\\n\",\n    \"\\n\",\n    \"# this allows us to capture stdout and stderr from the backend c++ infer-runtime\\n\",\n    \"display_output = wurlitzer.sys_pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"!trtexec --onnx=/work/models/onnx/mnist-v1.3/model.onnx --saveEngine=/work/models/onnx/mnist-v1.3/mnist-v1.3.engine\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1. Initialize infer-runtime\\n\",\n    \"\\n\",\n    \"The most important option when initializing the infer-runtime is to set the maximum number of conncurrent executions that can be executed at any given time.  This value is tunable for your application.  Lower setting reduce latency; higher-settings increase throughput.  Evaluate how your model performs using ...TODO-this-notebook...\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    models = infer.InferenceManager(max_executions=2)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2. Register a Model\\n\",\n    \"\\n\",\n    \"To register a model, simply associate a `model_name` with a path to a TensorRT engine file. The returned object is an `InferRunner` object.  Use an `InferRunner` to submit work to the backend inference queue.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    mnist = models.register_tensorrt_engine(\\\"mnist\\\", \\\"/work/models/onnx/mnist-v1.3/mnist-v1.3.engine\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 3. Allocate Resources\\n\",\n    \"\\n\",\n    \"Before you can submit inference requests, you need to allocate some internal resources.  This should be done anytime new models are registered.  There maybe a runtime performance interruption if you update the resources while the queue is full.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    models.update_resources()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 4. Inspect Model\\n\",\n    \"\\n\",\n    \"Query the `InferenceRunner` to see what it expects for inputs and what it will return for outputs.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.input_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"mnist.output_bindings()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5. Submit Infer Requests\\n\",\n    \"\\n\",\n    \"`InferenceRunner.infer` accecpts a dict of numpy arrays that match the input description, submits this inference request to the backend compute engine and returns a future to a dict of numpy arrays.  \\n\",\n    \"\\n\",\n    \"That means, this method should returns almost immediately; however, that does not mean the inference is complete.  Use `get()` to wait for the result.  This is a blocking call.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"result = mnist.infer(Input3=np.random.random_sample([1,28,28]))\\n\",\n    \"result # result is a future\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"result = result.get()\\n\",\n    \"result # result is the value of the future - dict of np arrays\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"with display_output():\\n\",\n    \"    start = time.process_time()\\n\",\n    \"    result = mnist.infer(**{k: np.random.random_sample(v['shape']) for k,v in mnist.input_bindings().items()})\\n\",\n    \"    print(\\\"Queue Time: {}\\\".format(time.process_time() - start))\\n\",\n    \"    result = result.get()\\n\",\n    \"    print(\\\"Compute Time: {}\\\".format(time.process_time() - start))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6. Test for Correctness\\n\",\n    \"\\n\",\n    \"Load test image and results.  [Thanks to the ONNX Model Zoo](https://github.com/onnx/models/tree/master/mnist) for this example.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"inputs = utils.load_inputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\\n\",\n    \"expected = utils.load_outputs(\\\"/work/models/onnx/mnist-v1.3/test_data_set_0\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"utils.mnist_image(inputs[0]).show()\\n\",\n    \"expected[0]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"\\n\",\n    \"Submit the images to the inference queue, then wait for each result to be returned.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"results = [mnist.infer(Input3=input) for input in inputs]\\n\",\n    \"results = [r.get() for r in results]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Check results.\\n\",\n    \"TODO - update the utils to return dictionaries instead of arrays\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"for r, e in zip(results, expected):\\n\",\n    \"    for key, val in r.items():\\n\",\n    \"        r = val.reshape((1,10))\\n\",\n    \"        np.testing.assert_almost_equal(r, e, decimal=3)\\n\",\n    \"        print(\\\"Test Passed\\\")\\n\",\n    \"        print(\\\"Output Binding Name: {}; shape: {}\\\".format(key, val.shape))\\n\",\n    \"        print(\\\"Result: {}\\\".format(np.argmax(utils.softmax(r))))\\n\",\n    \"        # r # show the raw tensor\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "notebooks/README.md",
    "content": "# Jupyter Notebooks\n\nNote: Many of the ONNX examples will fail until TensorRT 5.1 is available in the container.\n\nThis includes:\n  - Demo Day 1\n  - Demo Day 2\n  - Demo Day 3"
  },
  {
    "path": "requirements.txt",
    "content": "appdirs==1.4.3\natomicwrites==1.2.1\nattrs==18.2.0\nbackcall==0.1.0\nbleach>=3.1.1\nboto3==1.9.109\nbotocore==1.12.109\nclick==6.7\ncmake==3.11.0\ncycler==0.10.0\ndecorator==4.3.0\ndefusedxml==0.5.0\ndocutils==0.14\nentrypoints==0.3\ngrpcio==1.16.1\nipykernel==5.1.0\nipython==7.3.0\nipython-genutils==0.2.0\njedi==0.13.3\nJinja2==2.10.1\njmespath==0.9.4\njsonschema==3.0.1\njupyter-client==5.2.4\njupyter-core==4.4.0\njupyterlab==0.35.4\njupyterlab-server==0.2.0\nkiwisolver==1.0.1\nMako==1.0.7\nMarkupSafe==1.0\nmatplotlib==3.0.2\nmistune==0.8.4\nmore-itertools==4.3.0\nmxnet==1.4.0.post0\nnbconvert==5.4.1\nnbformat==4.4.0\nnotebook==5.7.8\nnumpy==1.15.4\nonnx==1.3.0\npandocfilters==1.4.2\nparso==0.5.0\npathlib2==2.3.3\npexpect==4.6.0\npickleshare==0.7.5\nPillow>=6.2.2\npluggy==0.8.0\nprometheus-client==0.6.0\nprompt-toolkit==2.0.9\nprotobuf==3.7.0\nptyprocess==0.6.0\npy==1.7.0\npycuda==2018.1.1\nPygments==2.3.1\npyparsing==2.3.1\npyrsistent==0.14.11\npytest==4.0.2\npython-dateutil==2.8.0\npytools==2018.5.2\npyzmq==18.0.0\ns3transfer==0.2.0\nSend2Trash==1.5.0\nsix==1.12.0\nterminado==0.8.1\ntestpath==0.4.2\ntornado==5.1\ntraitlets==4.3.2\ntyping==3.6.6\ntyping-extensions==3.7.2\nurllib3==1.24.2\nwcwidth==0.1.7\nwebencodings==0.5.1\nwurlitzer==1.0.2\n"
  },
  {
    "path": "trtlab/BUILD.bazel",
    "content": "exports_files([\n    \"core\",\n    \"cuda\",\n    \"nvrpc\",\n    \"tensorrt\",\n    ],\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "trtlab/CMakeLists.txt",
    "content": "#cmake_minimum_required(VERSION 3.9 FATAL_ERROR)\n\n#project(trtlab)\n\n#include(GNUInstallDirs)\n\n#option(ENABLE_TESTING \"Build tests\" ON)\n\n#set(CMAKE_CXX_STANDARD 17)\n#set(CMAKE_CXX_EXTENSIONS ON)\n\n#set(CMAKE_DEBUG_POSTFIX \"-d\")\nset(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\n#set(default_build_type \"Release\")\n\n#set(CMAKE_THREAD_PREFER_PTHREAD TRUE)\n#find_package(Threads)\n\n#if(ENABLE_TESTING)\n#  message(STATUS \"Building Tests\")\n#  find_package(GTest) #1.8.1 CONFIG REQUIRED)\n#  find_package(benchmark)\n#  enable_testing()\n#endif()\n\n# suppress warnings\n\n#add_compile_options(\n#  $<$<AND:$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>,$<CXX_COMPILER_ID:AppleClang>>:-Wno-deprecated-declarations>\n#)\n\nif(BUILD_MEMORY)\n  add_subdirectory(memory)\nendif()\n\nif(BUILD_CORE)\n  add_subdirectory(core)\nendif()\n\nif(BUILD_CUDA)\n  add_subdirectory(cuda)\nendif()\n\nif(BUILD_NVRPC)\n  add_subdirectory(nvrpc)\nendif()\n\nif(BUILD_TENSORRT)\n   add_subdirectory(tensorrt)\nendif()\n\nif(BUILD_PYTHON)\n  add_subdirectory(pybind)\nendif()\n\n\n# install\n\n# include(CMakePackageConfigHelpers)\n#\n# install(\n#   EXPORT ${PROJECT_NAME}-targets\n#   NAMESPACE ${PROJECT_NAME}::\n#   FILE ${PROJECT_NAME}-targets.cmake\n#   DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n# )\n#\n# configure_package_config_file(\n#   \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in\"\n#   ${PROJECT_NAME}-config.cmake\n#   INSTALL_DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n#   NO_CHECK_REQUIRED_COMPONENTS_MACRO\n#   PATH_VARS CMAKE_INSTALL_INCLUDEDIR\n# )\n#\n# install(\n# # FILES \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake\"\n#   DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n# )\n"
  },
  {
    "path": "trtlab/core/BUILD.bazel",
    "content": "cc_library(\n    name = \"core\",\n    srcs = glob([\n        \"src/**/*.cc\",\n        \"src/**/*.h\",\n    ]),\n    hdrs = glob(\n        [\"include/**/*.h\"],\n    ),\n    deps = [\n        \"@com_google_glog//:glog\",\n    ],\n    strip_include_prefix = \"include\",\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "trtlab/core/CMakeLists.txt",
    "content": "include(GNUInstallDirs)\nset(CMAKE_THREAD_PREFER_PTHREAD TRUE)\nfind_package(Threads)\nfind_package(cpuaff)\nfind_package(glog 0.3.5 REQUIRED)\nfind_package(dlpack)\nfind_package(Boost REQUIRED COMPONENTS fiber_numa fiber context)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nset(CMAKE_CXX_EXTENSIONS ON)\n\n# when linking against static glog one also needs to link against gflags\n# which version of gflags is depended on build type\nfind_package(gflags REQUIRED)\nif( CMAKE_BUILD_TYPE STREQUAL \"Debug\" )\n  find_package(gflags COMPONENTS nothreads_shared)\n  set(trtlab_gflags \"gflags_nothreads_shared\")\n  message(STATUS \"gflags: ${trtlab_gflags}\")\n  message(STATUS \"build_type: ${CMAKE_BUILD_TYPE}\")\nelse()\n  find_package(gflags COMPONENTS nothreads_static)\n  set(trtlab_gflags \"gflags_nothreads_static\")\n  message(STATUS \"gflags: ${trtlab_gflags}\")\n  message(STATUS \"build_type: ${CMAKE_BUILD_TYPE}\")\nendif()\n\nset(header_path ${CMAKE_CURRENT_SOURCE_DIR}/include/trtlab/core)\n\nadd_library(core\n# src/types.cc\n  src/affinity.cc\n  src/utils.cc\n  src/cyclic_buffer.cc\n  src/cyclic_windowed_buffer.cc\n)\n\nadd_library(${PROJECT_NAME}::core ALIAS core)\n\nmessage(STATUS \"jemalloc: ${JEMALLOC_STATIC_LIBRARIES}\")\n\ntarget_link_libraries(core\n  PUBLIC\n    trtlab_memory\n\n    dlpack::dlpack\n    Threads::Threads\n    $<$<AND:$<BOOL:UNIX>,$<NOT:$<BOOL:APPLE>>>:rt>\n    glog::glog\n    ${trtlab_gflags}\n    Boost::fiber\n    Boost::fiber_numa\n    Boost::context\n    ${JEMALLOC_STATIC_LIBRARIES}\n    dl\n)\n\ntarget_include_directories(core\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n  PRIVATE\n    ${header_path}\n)\n\nset_target_properties(core PROPERTIES OUTPUT_NAME ${PROJECT_NAME}_core)\n\ninstall(\n  TARGETS core\n  EXPORT ${PROJECT_NAME}-targets\n  RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\ninstall(\n  DIRECTORY include/\n  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\n#if(ENABLE_TESTING)\n  add_subdirectory(tests)\n#endif()\n\n#if(benchmark_FOUND)\n  add_subdirectory(benchmarks)\n#endif()\n\n"
  },
  {
    "path": "trtlab/core/benchmarks/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(benchmark)\n\nadd_executable(bench_core\n  main.cc\n  bench_pool.cc\n  bench_thread_pool.cc\n  bench_batcher.cc\n# bench_memory.cc\n# bench_memory_stack.cc\n)\n\ntarget_link_libraries(bench_core \n  PRIVATE \n    ${PROJECT_NAME}::core\n    benchmark::benchmark\n)\n\nadd_test(NAME bench_core COMMAND $<TARGET_FILE:bench_core>)\n"
  },
  {
    "path": "trtlab/core/benchmarks/bench_batcher.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include <trtlab/core/standard_threads.h>\n\n#include <trtlab/core/batcher.h>\n#include <trtlab/core/dispatcher.h>\n\nusing namespace trtlab;\n\nstatic void batcher_standard_batcher_int(benchmark::State& state)\n{\n    StandardBatcher<int, standard_threads> batcher(state.range(0));\n    std::size_t                            counter = 0;\n\n    for (auto _ : state)\n    {\n        auto future = batcher.enqueue(++counter);\n        auto batch  = batcher.update();\n\n        if (batch)\n        {\n            batch->promise.set_value();\n            future.wait();\n        }\n    }\n    state.SetItemsProcessed(static_cast<int64_t>(state.iterations()));\n}\n\nstruct audio_state\n{\n    const std::uint16_t*  data;\n    std::size_t           size;\n    std::shared_ptr<long> state;\n};\n\nstatic void batcher_standard_batcher_audio(benchmark::State& state)\n{\n    StandardBatcher<audio_state, standard_threads> batcher(state.range(0));\n    std::size_t                                    counter = 0;\n\n    for (auto _ : state)\n    {\n        auto future = batcher.enqueue({nullptr, 0ul, nullptr});\n        auto batch  = batcher.update();\n\n        if (batch)\n        {\n            batch->promise.set_value();\n            future.wait();\n        }\n    }\n    state.SetItemsProcessed(static_cast<int64_t>(state.iterations()));\n}\n\nstatic void batcher_engine(benchmark::State& state)\n{\n    const std::size_t batch_size = state.range(0);\n\n    auto execute_on_batch = [](const std::vector<int>& batch, std::function<void()> free_inputs) { free_inputs(); };\n\n    auto                                   thread_pool = std::make_shared<ThreadPool>(1);\n    auto                                   task_pool   = std::make_shared<DeferredShortTaskPool>();\n    StandardBatcher<int, standard_threads> batcher(batch_size);\n    Dispatcher<decltype(batcher)> dispatcher(std::move(batcher), std::chrono::milliseconds(15), thread_pool, task_pool, execute_on_batch);\n\n    std::queue<std::shared_future<void>> f;\n\n    int pre_load = 3;\n\n    for (int i = 0; i < pre_load; i++)\n    {\n        f.push(dispatcher.enqueue(0));\n    }\n    for (int i = 0; i < (batch_size - 1) * pre_load; i++)\n    {\n        dispatcher.enqueue(i);\n    }\n\n    for (auto _ : state)\n    {\n        f.push(dispatcher.enqueue(0));\n        for (int i = 0; i < batch_size - 1; i++)\n        {\n            dispatcher.enqueue(i);\n        }\n        f.front().wait();\n        f.pop();\n    }\n\n    while (!f.empty())\n    {\n        f.front().wait();\n        f.pop();\n    }\n\n    state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * state.range(0));\n}\n\nBENCHMARK(batcher_standard_batcher_int)->RangeMultiplier(2)->Range(1, 1 << 7);\nBENCHMARK(batcher_standard_batcher_audio)->RangeMultiplier(2)->Range(1 << 6, 1 << 7);\nBENCHMARK(batcher_engine)->RangeMultiplier(2)->Range(4, 1 << 6)->UseRealTime()->MinTime(3.0);\n;"
  },
  {
    "path": "trtlab/core/benchmarks/bench_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/sysv_allocator.h\"\n\nusing namespace trtlab;\nusing namespace trtlab;\n\n\nstatic void BM_Memory_SystemMalloc(benchmark::State& state)\n{\n    for(auto _ : state)\n    {\n        //auto unique = std::make_unique<Allocator<Malloc>>(1024 * 1024);\n        //auto shared = std::make_shared<Allocator<Malloc>>(1024 * 1024);\n        Allocator<Malloc> memory1(1024 * 1024);\n        Allocator<Malloc> memory2(1024 * 1024);\n        Allocator<Malloc> memory3(1024 * 1024);\n    }\n}\n\nstatic void BM_Memory_SystemV_descriptor(benchmark::State& state)\n{\n    auto master = std::make_unique<Allocator<SystemV>>(1024 * 1024);\n    for(auto _ : state)\n    {\n        auto mdesc = SystemV::Attach(master->ShmID());\n    }\n}\n\n/*\nstatic void BM_Memory_HostDescriptor(benchmark::State& state)\n{\n    void *ptr = (void*)0xDEADBEEF;\n    mem_size_t size = 1337;\n\n    for(auto _ : state)\n    {\n        nextgen::HostDescriptor hdesc(ptr, size, []{});\n    }\n}\n*/\n\n/*\nstatic void BM_Memory_SharedHostDescriptor(benchmark::State& state)\n{\n    void *ptr = (void*)0xDEADBEEF;\n    mem_size_t size = 1337;\n\n    for(auto _ : state)\n    {\n        nextgen::Descriptor<HostMemory> hdesc(ptr, size, []{});\n        auto shared = std::make_shared<nextgen::SharedDescriptor<HostMemory>>(std::move(hdesc));\n    }\n}\n*/\n\n/*\nstatic void BM_Memory_NextGenMalloc(benchmark::State& state)\n{\n    static mem_size_t one_mb = 1024*1024;\n\n    for(auto _ : state)\n    {\n        auto hdesc0 = nextgen::Malloc::Allocate(one_mb);\n        auto hdesc1 = nextgen::Malloc::Allocate(one_mb);\n    }\n}\n*/\n\nBENCHMARK(BM_Memory_SystemMalloc);\nBENCHMARK(BM_Memory_SystemV_descriptor);\n// BENCHMARK(BM_Memory_HostDescriptor);\n// BENCHMARK(BM_Memory_SharedHostDescriptor);\n// BENCHMARK(BM_Memory_NextGenMalloc);"
  },
  {
    "path": "trtlab/core/benchmarks/bench_memory_stack.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include \"trtlab/core/hybrid_mutex.h\"\n\n#include \"trtlab/core/memory.h\"\n\n#include <foonathan/memory/namespace_alias.hpp>\n\nusing namespace trtlab;\nusing namespace trtlab;\n\nstatic void allocators_transactional_raw(benchmark::State& state)\n{\n    using namespace memory::literals;\n\n    auto alloc = memory::make_allocator_adapter(memory::malloc_allocator());\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 4u, std::move(alloc));\n    auto trans_alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    trans_alloc.reserve_blocks(4u);\n\n    for(auto _ : state)\n    {\n        for(int i=0; i < state.range(0); i++)\n        {\n            auto ptr = trans_alloc.allocate_node(1024, 64);\n            trans_alloc.deallocate_node(ptr, 0u, 0u);\n        }\n    }\n}\n\nstatic void allocators_transactional_std(benchmark::State& state)\n{\n    using namespace memory::literals;\n\n    auto alloc = memory::make_allocator_adapter(memory::malloc_allocator());\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 4u, std::move(alloc));\n    auto trans_alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    trans_alloc.reserve_blocks(4u);\n\n    auto smart = memory::trtlab::make_allocator(std::move(trans_alloc));\n\n    for(auto _ : state)\n    {\n        for(int i=0; i < state.range(0); i++)\n        {\n            auto ptr = smart.allocate_node(1024, 64);\n            smart.deallocate_node(ptr, 0u, 0u);\n        }\n    }\n}\n\nstatic void allocators_transactional_md(benchmark::State& state)\n{\n    using namespace memory::literals;\n\n    auto alloc = memory::make_allocator_adapter(memory::malloc_allocator());\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 4u, std::move(alloc));\n    auto trans_alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    trans_alloc.reserve_blocks(4u);\n\n    auto smart = memory::trtlab::make_allocator(std::move(trans_alloc));\n\n    for(auto _ : state)\n    {\n        for(int i=0; i < state.range(0); i++)\n        {\n            auto md = smart.allocate_descriptor(1024, 64);\n        }\n    }\n}\n\n#if 0\ntemplate<typename T>\nusing custom_vector = std::vector<T, stl::temporary_allocator<T, Malloc>>;\n\ntemplate<typename T, typename RawAllocator>\nauto make_vector(RawAllocator& alloc)\n{\n    using std_allocator = memory::std_allocator<T, RawAllocator>;\n    return std::vector<T, std_allocator>(std_allocator(alloc));\n}\n\n\nstatic void BM_vector_transactional(benchmark::State& state)\n{\n    using namespace memory::literals;\n\n    auto malloc = memory::make_allocator_reference(memory::MallocAllocator());\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(128_MiB, 8, std::move(malloc));\n    auto trans_alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    trans_alloc.reserve_blocks(8);\n\n    for(auto _ : state)\n    {\n        auto vec = make_vector<int>(trans_alloc);\n        vec.reserve(1024*1024*8);\n    }\n}\n\nstatic void BM_vector_smart_transactional(benchmark::State& state)\n{\n    using namespace memory::literals;\n\n    auto malloc = memory::make_allocator_reference(memory::MallocAllocator());\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(128_MiB, 8, std::move(malloc));\n    auto trans_alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    trans_alloc.reserve_blocks(8);\n\n    auto smart = memory::trtlab::make_allocator<std::mutex>(std::move(trans_alloc));\n    \n    for(auto _ : state)\n    {\n        auto vec = memory::trtlab::make_vector<int>(smart);\n        vec.reserve(1024*1024*8);\n    }\n}\n\n\nstatic void BM_CyclicAllocator_stl_allocator(benchmark::State& state)\n{\n    {\n        auto v0 = custom_vector<int>(1024);\n    }\n    for(auto _ : state)\n    {\n        custom_vector<int> vector;\n        vector.reserve(1024*1024*8);\n    }\n}\n\nstatic void BM_CyclicAllocator_stl_allocator2(benchmark::State& state)\n{\n    size_t ctr = 1024;\n    for(auto _ : state)\n    {\n        custom_vector<int> v3;\n        v3.reserve(ctr*ctr*8);\n    }\n}\n\nstatic void BM_vector_default(benchmark::State& state)\n{\n    size_t ctr = 1024;\n    for(auto _ : state)\n    {\n        std::vector<int> vec;\n        vec.reserve(1024*1024*8);\n    }\n}\n\nstatic void BM_stl_allocator_ctor(benchmark::State& state)\n{\n    for(auto _ : state)\n    {\n        auto a = stl::temporary_allocator<int, Malloc>();\n    }\n}\n\nstatic void BM_stl_allocator_allocate_lifecycle(benchmark::State& state)\n{\n    for(auto _ : state)\n    {\n        auto a = stl::temporary_allocator<int, Malloc>();\n        auto i = a.allocate(1024);\n        a.deallocate(i, 1024);\n    }\n}\n#endif\n\nBENCHMARK(allocators_transactional_raw)->RangeMultiplier(2)->Range(1, 1 << 2);\nBENCHMARK(allocators_transactional_std)->RangeMultiplier(2)->Range(1, 1 << 0);\nBENCHMARK(allocators_transactional_md)->RangeMultiplier(2)->Range(1, 1 << 0);\n"
  },
  {
    "path": "trtlab/core/benchmarks/bench_pool.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/pool.h\"\n#include \"trtlab/core/userspace_threads.h\"\n#include <benchmark/benchmark.h>\n\nstatic void BM_Pool_v1_Pop(benchmark::State& state)\n{\n    using trtlab::v1::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object>::Create();\n    pool->EmplacePush(new Object);\n\n    for(auto _ : state)\n    {\n        auto obj = pool->Pop();\n    }\n}\n\nstatic void BM_Pool_v2_Pop(benchmark::State& state)\n{\n    using trtlab::v2::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object>::Create();\n    pool->EmplacePush();\n\n    for(auto _ : state)\n    {\n        auto obj = pool->Pop();\n    }\n}\n\nstatic void BM_Pool_v3_Pop(benchmark::State& state)\n{\n    using trtlab::v3::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object>::Create();\n    pool->emplace_push();\n\n    for(auto _ : state)\n    {\n        auto obj = std::move(pool->pop());\n    }\n}\n\nstatic void BM_Pool_v4_Pop(benchmark::State& state)\n{\n    using trtlab::v4::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object>::Create();\n    pool->EmplacePush();\n\n    for(auto _ : state)\n    {\n        auto obj = std::move(pool->pop_unique());\n    }\n}\n\nstatic void BM_Pool_v4_Pop_Shared(benchmark::State& state)\n{\n    using trtlab::v4::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object>::Create();\n    pool->emplace_push();\n\n    for(auto _ : state)\n    {\n        auto obj = std::move(pool->pop_shared());\n    }\n}\n\nstatic void BM_Pool_v3_Pop_Userspace(benchmark::State& state)\n{\n    using trtlab::v3::Pool;\n    struct Object\n    {\n    };\n    auto pool = Pool<Object, trtlab::userspace_threads>::Create();\n    pool->emplace_push();\n\n    for(auto _ : state)\n    {\n        auto obj = std::move(pool->pop());\n    }\n}\n\nBENCHMARK(BM_Pool_v1_Pop);\nBENCHMARK(BM_Pool_v2_Pop);\nBENCHMARK(BM_Pool_v3_Pop);\nBENCHMARK(BM_Pool_v4_Pop);\nBENCHMARK(BM_Pool_v4_Pop_Shared);\nBENCHMARK(BM_Pool_v3_Pop_Userspace);\n"
  },
  {
    "path": "trtlab/core/benchmarks/bench_thread_pool.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/hybrid_condition.h\"\n#include \"trtlab/core/hybrid_mutex.h\"\n#include \"trtlab/core/thread_pool.h\"\n#include <benchmark/benchmark.h>\n\nstatic void BM_ThreadPool_Enqueue(benchmark::State& state)\n{\n    using trtlab::ThreadPool;\n    auto pool = std::make_unique<ThreadPool>(1);\n\n    for(auto _ : state)\n    {\n        CHECK(pool);\n        // enqueue only\n        auto future = pool->enqueue([] {});\n        //future.get();\n    }\n}\nBENCHMARK(BM_ThreadPool_Enqueue)->UseRealTime();\n\nstatic void BM_HybridThreadPool_Enqueue(benchmark::State& state)\n{\n    using trtlab::BaseThreadPool;\n    auto pool = std::make_unique<BaseThreadPool<hybrid_mutex, hybrid_condition>>(1);\n\n    for(auto _ : state)\n    {\n        auto future = pool->enqueue([] {});\n    }\n}\nBENCHMARK(BM_HybridThreadPool_Enqueue)->UseRealTime();"
  },
  {
    "path": "trtlab/core/benchmarks/main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\nBENCHMARK_MAIN();"
  },
  {
    "path": "trtlab/core/include/trtlab/core/affinity.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <vector>\n\n#include \"cpuaff/cpuaff.hpp\"\n\nnamespace trtlab\n{\n    struct affinity;\n\n    class cpu_set final : public cpuaff::cpu_set\n    {\n    public:\n        using cpuaff::cpu_set::cpu_set;\n\n        cpu_set get_intersection(const cpu_set& other) const;\n        cpu_set get_union(const cpu_set& other) const;\n        cpu_set get_difference(const cpu_set& other) const;\n\n        static cpu_set from_string(std::string);\n\n        std::string cpus_string() const;\n        std::string cores_string() const;\n        std::string sockets_string() const;\n\n        auto get_allocator() const -> cpuaff::round_robin_allocator\n        {\n            return cpuaff::round_robin_allocator(*this);\n        };\n\n        friend std::ostream& operator<<(std::ostream& s, const cpu_set& cpus);\n    };\n\n    std::ostream& operator<<(std::ostream& s, const cpu_set& cpus);\n\n    class affinity_guard final\n    {\n        // hold the original affinity of the calling thread\n        // the original affinity will be restored on destruction\n        cpu_set m_original_cpus;\n\n    public:\n        affinity_guard();\n        explicit affinity_guard(const cpu_set&);\n        ~affinity_guard();\n\n        affinity_guard(const affinity_guard&) = delete;\n        affinity_guard& operator=(const affinity_guard&) = delete;\n\n        affinity_guard(affinity_guard&&) noexcept = delete;\n        affinity_guard& operator=(affinity_guard&&) noexcept = delete;\n    };\n\n    struct numa_node\n    {\n        unsigned              id;\n        cpu_set               cpus;\n        std::vector<unsigned> distances;\n\n        friend std::ostream& operator<<(std::ostream& s, const numa_node& cpus);\n    };\n\n    std::ostream& operator<<(std::ostream& s, const numa_node& cpus);\n\n    struct affinity final\n    {\n        struct this_thread final\n        {\n            static cpu_set get_affinity();\n            static void    set_affinity(const cpu_set&);\n        };\n\n        struct system final\n        {\n            // static cpu_set cpus_by_numa(int numa_id);\n            // static cpu_set cpus_by_socket(int socket_id);\n            // static cpu_set cpus_by_core(int core_id);\n            // static cpu_set cpus_by_hyperthread(int thread_id);\n\n            static cpuaff::cpu cpu_from_logical_id(int id);\n\n            static std::vector<numa_node> topology();\n        };\n    };\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/async_compute.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <future>\n#include <memory>\n\nnamespace trtlab\n{\n    namespace async\n    {\n        namespace detail\n        {\n            template <template <typename> class Promise, template <typename> class Future, typename CompleterFn>\n            struct shared_packaged_task;\n\n            template <template <typename> class Promise, template <typename> class Future, typename... Args>\n            struct shared_packaged_task<Promise, Future, void(Args...)>\n            {\n                using CallingFn = std::function<void(Args...)>;\n                using WrappedFn = std::function<void(Args...)>;\n\n                shared_packaged_task(CallingFn calling_fn)\n                {\n                    m_WrappedFn = [this, calling_fn](Args&&... args) {\n                        calling_fn(args...);\n                        m_Promise.set_value();\n                    };\n                }\n\n                Future<void> get_future()\n                {\n                    return m_Promise.get_future();\n                }\n\n                void operator()(Args&&... args)\n                {\n                    m_WrappedFn(args...);\n                }\n\n            private:\n                WrappedFn     m_WrappedFn;\n                Promise<void> m_Promise;\n            };\n\n            template <template <typename> class Promise, template <typename> class Future, typename ResultType, typename... Args>\n            struct shared_packaged_task<Promise, Future, ResultType(Args...)>\n            {\n                using CallingFn = std::function<ResultType(Args...)>;\n                using WrappedFn = std::function<void(Args...)>;\n\n                shared_packaged_task(CallingFn calling_fn)\n                {\n                    m_WrappedFn = [this, calling_fn](Args&&... args) { m_Promise.set_value(std::move(calling_fn(args...))); };\n                }\n\n                std::future<ResultType> get_future()\n                {\n                    return m_Promise.get_future();\n                }\n\n                void operator()(Args&&... args)\n                {\n                    m_WrappedFn(args...);\n                }\n\n            private:\n                WrappedFn                m_WrappedFn;\n                std::promise<ResultType> m_Promise;\n            };\n\n        } // namespace detail\n\n    } // namespace async\n\n    template <typename CompleterFn>\n    struct async_compute;\n\n    template <typename... Args>\n    struct async_compute<void(Args...)>\n    {\n        // create a shared object that holds both the promise and the user function\n        // to call with some pre-defined arguments.\n        // upon calling the () method on the created object, the value of the promise\n        // is set by the return value of the wrapped  user function\n        template <typename F>\n        static auto wrap(F&& f)\n        {\n            using ResultType = typename std::result_of<F(Args...)>::type;\n            using UserFn     = ResultType(Args...);\n            //return std::make_shared<detail::async_compute_impl<UserFn>>(f);\n            return std::make_shared<async::detail::shared_packaged_task<std::promise, std::future, UserFn>>(f);\n        }\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/batcher.h",
    "content": "#pragma once\n\n#include <chrono>\n#include <future>\n#include <memory>\n#include <optional>\n#include <queue>\n#include <vector>\n\n#include <glog/logging.h>\n\nnamespace trtlab\n{\n    // Defines the batching logic used by the Batcher class.\n    // This class only provides the core logic for batching,\n    // managed the state, and provides the synchronization\n    // future-promise mapping.\n    // There are no public methods besides the constructor\n    // and deconstructor.  There is also no internal mutex\n    // for synchronization.  This class is designed to be\n    // privately inherited by the Batcher which will provide\n    // the necessary threads, mutexes, etc. for use.\n    template <typename T, typename ThreadType>\n    class StandardBatcher\n    {\n        using promise_t       = typename ThreadType::template promise<void>;\n        using shared_future_t = typename ThreadType::template shared_future<void>;\n\n    public:\n        StandardBatcher(std::size_t max_batch_size) : m_MaxBatchSize(max_batch_size), m_BatchCounter(0)\n        {\n        }\n        virtual ~StandardBatcher(){};\n\n        StandardBatcher(StandardBatcher&&) = default;\n\n    public:\n        using thread_type = ThreadType;\n        using clock_type  = std::chrono::high_resolution_clock;\n\n        struct Batch\n        {\n            std::vector<T>    items;\n            mutable promise_t promise;\n            std::size_t       batch_id;\n        };\n\n        using batch_item  = T;\n        using batch_type  = std::optional<Batch>;\n        using future_type = shared_future_t;\n        using release_fn  = std::function<void(void)>;\n\n        // Enqueue a batch item\n        // This is the data-in interface to the batcher.\n        // This method is intended to collect together multiple BatchItems.\n        // For each BatchItem a shared_future (unique to the batch) is returned\n        // to the caller.  The shared_future is not unique to the BatchItem.\n        // This future is the caller portion of the Batcher's promise to\n        // use the data and to fulfill the promise by setting some value\n        // of ReturnType at a later time.  Until the batcher fulfills the\n        // promise, the caller should not modify or delete any of the data\n        // passed to the batcher.  This is a performance optimization to avoid\n        // data copies.\n        future_type enqueue(T);\n\n        // Updates the state of the batcher and tests to determine if the\n        // conditions for closing the batching window have been met.\n        // If the batch is complete, the optional to the batch is fulfilled;\n        // otherwise, the optional is empty or std::nullopt;\n        batch_type update();\n\n        // Closes the current batch and returns an optional batch_type\n        batch_type close_batch();\n\n        bool empty()\n        {\n            return !m_State.has_value();\n        }\n\n        clock_type::time_point start_time()\n        {\n            return (m_State ? m_State->start_time : clock_type::time_point{});\n        }\n\n    private:\n        struct State\n        {\n            Batch                  batch;\n            shared_future_t        future;\n            clock_type::time_point start_time;\n        };\n\n        State create_state();\n\n        std::size_t          m_MaxBatchSize;\n        std::optional<State> m_State;\n        std::size_t          m_BatchCounter;\n    };\n\n    template <typename T, typename ThreadType>\n    typename StandardBatcher<T, ThreadType>::future_type StandardBatcher<T, ThreadType>::enqueue(T new_item)\n    {\n        // no state is ok - simiply create a state to start the timing window\n        if (!m_State)\n        {\n            m_State = create_state();\n        }\n\n        // perform some checks\n        DCHECK_LT(m_State->batch.items.size(), m_MaxBatchSize);\n\n        // push back new item (memory has been reserved)\n        m_State->batch.items.push_back(std::move(new_item));\n\n        return m_State->future;\n    }\n\n    template <typename T, typename ThreadType>\n    typename StandardBatcher<T, ThreadType>::batch_type StandardBatcher<T, ThreadType>::update()\n    {\n        if (m_State)\n        {\n            if (m_State->batch.items.size() == m_MaxBatchSize) /* || clock_type::now() > m_State->deadline)*/\n            {\n                batch_type batch(std::move(m_State->batch));\n                m_State = std::nullopt;\n                return batch;\n            }\n        }\n        return std::nullopt;\n    }\n\n    template <typename T, typename ThreadType>\n    typename StandardBatcher<T, ThreadType>::batch_type StandardBatcher<T, ThreadType>::close_batch()\n    {\n        if (m_State)\n        {\n            batch_type batch(std::move(m_State->batch));\n            m_State = std::nullopt;\n            return batch;\n        }\n        return std::nullopt;\n    }\n\n    template <typename T, typename ThreadType>\n    typename StandardBatcher<T, ThreadType>::State StandardBatcher<T, ThreadType>::create_state()\n    {\n        State state;\n        state.batch.items.reserve(m_MaxBatchSize);\n        state.batch.batch_id = m_BatchCounter++;\n        state.future         = state.batch.promise.get_future().share();\n        state.start_time     = clock_type::now();\n        return state;\n    }\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/cyclic_buffer.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <functional>\n#include <memory>\n#include <experimental/propagate_const>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/descriptor.h>\n\nnamespace trtlab\n{\n    class CyclicBuffer\n    {\n    public:\n        using SyncFn     = std::function<bool(bool)>;\n        using CallbackFn = std::function<SyncFn(std::size_t, const void*, std::size_t)>;\n\n        CyclicBuffer(memory::descriptor&&, std::size_t window_size, std::size_t overlap_size, CallbackFn);\n        virtual ~CyclicBuffer();\n\n        // returns the number of bytes needed for count windows of size overlapping by overlap bytes\n        static std::size_t SizeFor(std::size_t count, std::size_t size, std::size_t overlap)\n        {\n            CHECK_GT(count, 0);\n            CHECK_GT(size, overlap);\n            return size + (count - 1) * (size - overlap);\n        }\n\n        // as data is appended, the callback will be triggered when a window is completed.\n        // after a window is completed, the window is shifted by ShiftSize. if the\n        // subsequent window is also complete, callbacks will be triggered.\n        // AppendData will block until all data the buffer has allocated memory for all the data.\n        // AppendData could issue async copies.  The only guarantee is that all memory copies have\n        // been issued, but may not have finished when AppendData returns.  This means that the\n        // memory passed to the AppendData method is volatile and should not be changed until the\n        // SyncFn has returns true. AppendData will use the thread to drive forward progress\n        // of the buffers internal state.  before new data is appended, a window must be available\n        // for use.  Under the worst case scenario, no windows are free, so we must wait on the\n        // next window in the ring to become available.  data is copied into available windows.\n        // when a window fills, the callback method is applied to that data region and the state\n        // of the copy and callback are tracked by the manager.  this continues until all data\n        // has been consumed.\n\n        // blocks until all copies are in-flight\n        // one must wait on the CopyStatus method to check for completeness\n        // when CopyStatus() returns true, then the data buffer passed to AppendData can be reused\n        SyncFn AppendData(void*, std::size_t);\n\n        // tell the buffer to shutdown, this will attempt to push all windows into a \"running\"\n        // state.  the final window may not be data complete, but a method in the manager\n        // will handle that case.\n        void Shutdown(std::function<void(std::size_t, const void* data, std::size_t)> fill);\n\n        // waits for all windows to become available\n        void Sync();\n\n        void PreferFullWindows(bool);\n\n    protected:\n        std::size_t Size() const\n        {\n            return m_Size;\n        }\n        std::size_t WindowSize() const\n        {\n            return m_WindowSize;\n        }\n        std::size_t ShiftSize() const\n        {\n            return m_ShiftSize;\n        }\n\n        std::size_t Offset(const void* addr) const\n        {\n            auto mem = reinterpret_cast<std::uintptr_t>(addr);\n            DCHECK_GE(mem, m_Data);\n            return mem - m_Data;\n        }\n\n        std::size_t Offset(std::uintptr_t addr) const\n        {\n            DCHECK_GE(addr, m_Data);\n            return addr - m_Data;\n        }\n\n    private:\n        enum class WindowStatus\n        {\n            Ready,\n            Running,\n            Finished\n        };\n\n        struct WindowState\n        {\n            WindowStatus status;\n            SyncFn       syncfn;\n        };\n\n        // used to copy data from AppendData into the buffer\n        virtual void Copy(void* dst, const void* src, std::size_t size) = 0;\n\n        // used to copy data to be replicated data internally within the buffer\n        virtual void Replicate(void* dst, const void* src, std::size_t size) = 0;\n\n        // if data can be async copied into the buffer, then AppendData\n        // may return before the entirely the data in its source buffers\n        // has be copied to the buffer; however, all copies are in-flight\n        // the return value of SyncFn signifies when the source data can be reused\n        virtual SyncFn FinishedAppendingData() = 0;\n\n        // wrapper to set state and capture the sync function of the callback\n        void RunCallback(const void* data, std::size_t size);\n\n        // determine the amount of free bytes availabe in the current window\n        std::size_t Free();\n\n        // repllicate overlapping data from end of the buffer to the start\n        // this method is called automatically by Free when the buffer resets\n        void ReplicateData();\n\n        // wrapper to copy external data to the buffer and shift internal pointers\n        void CopyToHead(std::uintptr_t data, std::size_t size);\n\n        // wrapper to copy/move internal data within the buffer\n        void ReplicateToHead(std::uintptr_t data, std::size_t size);\n\n        // called to launch callback on all available windows\n        void ExecuteWindows();\n\n        // wrapper to set state and capture the sync function of a callback\n        void RunCallbackOnWindow(std::uintptr_t data, std::size_t size);\n\n        // returns true of the window is ready for use; false if not\n        bool SyncWindow(std::size_t window, bool wait);\n\n        // resets the state of a window\n        void ResetWindow(std::size_t window);\n\n        // the following are directly set by constructor calling arguments\n        memory::descriptor m_Descriptor;\n        std::uintptr_t     m_Data;\n        std::size_t        m_Size;\n        std::size_t        m_WindowSize;\n        std::size_t        m_ShiftSize;\n        std::uintptr_t     m_CurrentLocation; // location of next data append\n        std::uintptr_t     m_WindowStart;     // start of current window\n        std::size_t        m_CurrentWindow;\n        bool               m_PreferFullWindows;\n        CallbackFn         m_Callback;\n\n        // the remaining variables are set in the constructor's body\n        std::uintptr_t           m_ReplicationStart; // location of data which will be copied to head\n        std::uintptr_t           m_NextPassStart;    // location of first new data after replicated data\n        std::uintptr_t           m_SyncLocation;     // location of the last byte of sync'ed memory\n        std::size_t              m_SyncWindow;       // window number of\n        std::size_t              m_WindowCount;\n        std::vector<WindowState> m_State;\n    };\n\n    class HostCyclicBuffer : public CyclicBuffer\n    {\n    public:\n        using CyclicBuffer::CyclicBuffer;\n\n    private:\n        void Copy(void* dst, const void* src, std::size_t size) final override\n        {\n            std::memcpy(dst, src, size);\n        }\n\n        void Replicate(void* dst, const void* src, std::size_t size) final override\n        {\n            std::memcpy(dst, src, size);\n        }\n\n        SyncFn FinishedAppendingData() final override\n        {\n            return [](bool) { return true; };\n        }\n    };\n\n    template <typename T, typename WindowedBuffer>\n    class TypedWindowedBuffer : private WindowedBuffer\n    {\n    public:\n        using SyncFn     = std::function<bool(bool)>;\n        using CallbackFn = std::function<SyncFn(const T*, std::size_t)>;\n\n        TypedWindowedBuffer(std::size_t window_size, std::size_t shift_size, memory::descriptor&& md, CallbackFn callback)\n        : WindowedBuffer(window_size * sizeof(T), shift_size * sizeof(T), std::move(md),\n                         [callback](const void* data, std::size_t size) -> SyncFn {\n                             DCHECK_EQ(size % sizeof(T), 0);\n                             return callback(static_cast<const T*>(data), size / sizeof(T));\n                         })\n        {\n        }\n\n        virtual ~TypedWindowedBuffer() {}\n\n        SyncFn AppendData(const T* data, std::size_t count)\n        {\n            return WindowedBuffer::AppendData(static_cast<void*>(data), count * sizeof(T));\n        }\n\n        void Sync()\n        {\n            WindowedBuffer::Sync();\n        }\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/cyclic_windowed_buffer.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <functional>\n#include <future>\n#include <memory>\n\n#include <trtlab/memory/align.h>\n#include <trtlab/memory/descriptor.h>\n#include <trtlab/memory/memory_type.h>\n\nnamespace trtlab\n{\n    // forward declare the classes in this header\n    // buffer hold the data and core properties\n    class cyclic_windowed_buffer;\n\n    // stack manages window lifecycle and syncing\n    //template<typename MemoryType = memory::host_memory>\n    //class cyclic_windowed_stack;\n\n    // launches a task as each window is filled\n    template <typename MemoryType, typename ThreadType>\n    class cyclic_windowed_task_executor;\n\n    // provides a reserved window with the requested amount of overlap\n    // only one window can be reserved at a time\n    class cyclic_windowed_reservation;\n\n    // cyclic windowed buffer\n\n    class cyclic_windowed_buffer\n    {\n    public:\n        cyclic_windowed_buffer();\n\n        cyclic_windowed_buffer(memory::descriptor md, std::size_t window_size, std::size_t overlap_size);\n\n        virtual ~cyclic_windowed_buffer() {}\n\n        cyclic_windowed_buffer(cyclic_windowed_buffer&&) noexcept;\n        cyclic_windowed_buffer& operator=(cyclic_windowed_buffer&&) noexcept;\n\n        cyclic_windowed_buffer(const cyclic_windowed_buffer&) = delete;\n        cyclic_windowed_buffer& operator=(const cyclic_windowed_buffer&) = delete;\n\n        // returns the number of bytes needed for count windows of size overlapping by overlap bytes\n        static std::size_t min_allocation_size(std::size_t window_count, std::size_t window_size, std::size_t overlap);\n\n        // number of windows in the buffer\n        std::size_t window_count() const noexcept\n        {\n            return m_window_count;\n        }\n\n        // size of each window in bytes\n        std::size_t window_size() const noexcept\n        {\n            return m_window_size;\n        }\n\n        // the stride of the shift in bytes\n        std::size_t shift_size() const noexcept\n        {\n            return m_shift_size;\n        }\n\n        // amount of overlap between windows in bytes\n        std::size_t overlap_size() const noexcept\n        {\n            return m_window_size - m_shift_size;\n        }\n\n        // effective number of the allocated bytes used to back the windows\n        std::size_t capacity() const noexcept\n        {\n            return m_capacity;\n        };\n\n        DLContext device_context() const noexcept\n        {\n            return m_descriptor.device_context();\n        }\n\n    protected:\n        memory::addr_t data() const noexcept\n        {\n            return static_cast<memory::addr_t>(const_cast<void*>(m_descriptor.data()));\n        }\n\n        std::ptrdiff_t offset(memory::addr_t p) const noexcept\n        {\n            return p - data();\n        }\n\n    private:\n        // initializer list\n        memory::descriptor m_descriptor; /* move-only */\n        std::size_t        m_window_size;\n\n        // computed in constructor\n        std::size_t m_window_count;\n        std::size_t m_shift_size;\n        std::size_t m_capacity;\n    };\n\n    namespace detail\n    {\n        class cyclic_windowed_stack_impl : private cyclic_windowed_buffer\n        {\n        public:\n            cyclic_windowed_stack_impl();\n            cyclic_windowed_stack_impl(memory::descriptor md, std::size_t window_size, std::size_t overlap_size);\n\n            cyclic_windowed_stack_impl(cyclic_windowed_stack_impl&&) noexcept;\n            cyclic_windowed_stack_impl& operator=(cyclic_windowed_stack_impl&&) noexcept;\n\n            cyclic_windowed_stack_impl(const cyclic_windowed_stack_impl&) = delete;\n            cyclic_windowed_stack_impl& operator=(const cyclic_windowed_stack_impl&) = delete;\n\n            ~cyclic_windowed_stack_impl() override\n            {\n                reset();\n            }\n\n            // access the cyclic buffer\n            const cyclic_windowed_buffer& buffer() const\n            {\n                return *this;\n            }\n\n        protected:\n            virtual void on_window_complete_event(std::size_t, const void*, std::size_t) {}\n\n            // bytes available in current window\n            std::size_t available() const noexcept;\n\n            // push the data pointer forward\n            // cannot advance past the end of the current window\n            std::size_t push_data(const void*, std::size_t);\n\n            // shift to the next window, recording a sync function for the current window\n            // this method will block if the next window is not available\n            // if the buffer wraps, the last overlap_size bytes of data is replicated to the\n            // front of the stack.\n            void push_window(std::function<void()>);\n\n            // sync all outstanding windows and resets the stack to the start of the buffer\n            void reset();\n\n            // access the top of the data stack\n            void* data_top()\n            {\n                return m_data_top;\n            }\n\n            // access the start of the current window\n            void* window_start()\n            {\n                return m_win_top;\n            }\n\n            // convenience function\n            using cyclic_windowed_buffer::window_size;\n\n        private:\n            // todo: figure out a way to relax the constrain of blocking copy and replicate\n\n            // function used to copy external data to the buffer\n            // required to be a blocking call\n            virtual void copy(void*, const void*, size_t) = 0;\n\n            // internal buffer copy function: defaults to std::memcpy; override for cuda\n            // required to be a blocking call\n            virtual void replicate(void*, const void*, std::size_t) = 0;\n\n            // access the top of the stack\n            memory::addr_t top()\n            {\n                return m_data_top;\n            }\n\n            // return the unique window id for the current window\n            // this is monotonically increasing even though the buffer wraps\n            std::size_t window_id() const noexcept\n            {\n                return m_win_counter;\n            }\n\n            // recycle buffer - reset, sync and replicate\n            void recycle_buffer();\n\n            // sync the next window and push the sync stack\n            void sync_and_shift();\n\n            // end of the buffer\n            memory::addr_t m_end;\n\n            // location of first free byte in the stack\n            // allowed range [m_win_top, m_win_top + window_size_in_bytes()]\n            memory::addr_t m_data_top;\n\n            // location of first byte that needs synchronization\n            // allowed range [data() + shift_size(), data() + capacity() , shift_size()]\n            memory::addr_t m_sync_top;\n\n            // start of the current window\n            // allowed range [data(), data() + capacity_in_bytes() - window_size_in_bytes(), shift_size()]\n            memory::addr_t m_win_top;\n\n            // count the number of windows that have been triggered\n            // effectively a unqiue id for a window\n            std::size_t m_win_counter;\n\n            // synchronization functions\n            std::queue<std::pair<memory::addr_t, std::function<void()>>> m_sync;\n        };\n\n    } // namespace detail\n\n    template <typename MemoryType, typename ThreadType>\n    class cyclic_windowed_stack;\n\n    template <typename ThreadType>\n    class cyclic_windowed_stack<memory::host_memory, ThreadType> : public detail::cyclic_windowed_stack_impl\n    {\n    public:\n        using memory_type = memory::host_memory;\n\n        cyclic_windowed_stack(memory::descriptor md, std::size_t window_size, std::size_t overlap_size)\n        : cyclic_windowed_stack_impl(std::move(md), window_size, overlap_size)\n        {\n        }\n\n        cyclic_windowed_stack(cyclic_windowed_stack&& other) noexcept\n        : cyclic_windowed_stack_impl(std::move(other)) {}\n        cyclic_windowed_stack& operator=(cyclic_windowed_stack&& other) noexcept\n        {\n            cyclic_windowed_stack_impl::operator=(std::move(other));\n            return *this;\n        }\n\n        ~cyclic_windowed_stack() override {}\n\n        using cyclic_windowed_stack_impl::buffer;\n\n    private:\n        void copy(void* dst, const void* src, std::size_t size) final override\n        {\n            std::memcpy(dst, src, size);\n        }\n\n        void replicate(void* dst, const void* src, std::size_t size) final override\n        {\n            std::memcpy(dst, src, size);\n        }\n    };\n\n    template <typename MemoryType, typename ThreadType>\n    class cyclic_windowed_reserved_stack : private cyclic_windowed_stack<MemoryType, ThreadType>\n    {\n        using stack = cyclic_windowed_stack<MemoryType, ThreadType>;\n\n        using promise_t = typename ThreadType::template promise<void>;\n        using future_t  = typename ThreadType::template future<void>;\n\n    public:\n        cyclic_windowed_reserved_stack() {}\n\n        cyclic_windowed_reserved_stack(stack&& s) : stack(std::move(s)) {}\n\n        ~cyclic_windowed_reserved_stack() override {}\n\n        // allow access back to the underlying buffer\n        using stack::buffer;\n\n        struct reservation;\n\n        const reservation reserve_window()\n        {\n            CHECK(stack::window_size());\n            if (m_future.valid())\n            {\n                m_future.get();\n                stack::push_window([] {} /* empty sync fn */);\n            }\n\n            // prepare promise/future combo\n            promise_t promise;\n            m_future = promise.get_future();\n\n            // build reservation\n            reservation r(stack::window_start(), stack::window_size(), stack::data_top(), stack::available(), std::move(promise));\n\n            return r;\n        }\n\n        void reset()\n        {\n            if(m_future.valid())\n            {\n                m_future.get();\n            }\n            stack::reset();\n        }\n\n        struct reservation\n        {\n            reservation() {}\n            reservation(void* wstart, std::size_t wsize, void* dstart, std::size_t dsize, promise_t&& promise)\n            : window_start(wstart), window_size(wsize), data_start(dstart), data_size(dsize), m_promise(std::move(promise))\n            {\n            }\n\n            virtual ~reservation() {}\n\n            reservation(reservation&&) noexcept = default;\n            reservation& operator=(reservation&&) noexcept = default;\n\n            void*       window_start;\n            std::size_t window_size;\n            void*       data_start;\n            std::size_t data_size;\n\n            void release() const\n            {\n                DCHECK(window_start);\n                m_promise.set_value();\n                // nullify pointers and zero out sizes?\n            }\n\n        private:\n            mutable promise_t m_promise;\n        };\n\n    private:\n        future_t m_future;\n    };\n\n    // task executor\n\n    template <typename MemoryType, typename ThreadType>\n    class cyclic_windowed_task_executor : private cyclic_windowed_stack<MemoryType, ThreadType>\n    {\n        using stack           = cyclic_windowed_stack<MemoryType, ThreadType>;\n        using shared_future_t = typename ThreadType::template shared_future<void>;\n\n    public:\n        //cyclic_windowed_task_executor();\n        cyclic_windowed_task_executor(stack&& s) : stack(std::move(s)) {}\n\n        cyclic_windowed_task_executor(const cyclic_windowed_task_executor&) = delete;\n        cyclic_windowed_task_executor& operator=(const cyclic_windowed_task_executor&) = delete;\n\n        cyclic_windowed_task_executor(cyclic_windowed_task_executor&& other) noexcept : stack(std::move(other)) {}\n        cyclic_windowed_task_executor& operator=(cyclic_windowed_task_executor&& other) noexcept\n        {\n            stack::operator=(std::move(other));\n            return *this;\n        }\n\n        ~cyclic_windowed_task_executor() override {}\n\n        // allow access back to the underlying buffer\n        using stack::buffer;\n\n        // write data to the buffer\n        // as windows are filled the task function is run on the window data\n        // the task function must return a shared_future that be used to sync the window\n        // the completion of the future signifies that the data in the window can be reused\n        void append_data(const void* data, std::size_t size);\n\n        // TODO: requires some memory_utilities<MemoryType>\n        // writes val the the remaining entries in the current window\n        // and triggers a task execution\n        // void flush(T val) {}\n\n        // TODO: requires some memory_utilities<MemoryType>\n        // pre populate some portion the first window\n        // only allowed before data is pushed/appended\n        // count must be less than the size of the first window\n        // void pre_populate(T val, std::size_t count) {}\n\n        // sync and reset the stack\n        void reset()\n        {\n            stack::reset();\n        }\n\n    private:\n        virtual shared_future_t on_compute_window(std::size_t, const void*, std::size_t) = 0;\n        void                    on_window_complete_event(std::size_t, const void*, std::size_t) final override;\n    };\n\n    template <typename MemoryType, typename ThreadType>\n    void cyclic_windowed_task_executor<MemoryType, ThreadType>::append_data(const void* data, std::size_t size)\n    {\n        memory::addr_t src = reinterpret_cast<memory::addr_t>(const_cast<void*>(data));\n\n        while (size)\n        {\n            auto bytes = std::min(size, stack::available());\n            size -= stack::push_data(src, bytes);\n            src += bytes;\n        }\n    }\n\n    template <typename MemoryType, typename ThreadType>\n    void cyclic_windowed_task_executor<MemoryType, ThreadType>::on_window_complete_event(std::size_t id, const void* data, std::size_t size)\n    {\n        auto f = on_compute_window(id, data, size);\n        stack::push_window([f] { f.get(); });\n    }\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/dispatcher.h",
    "content": "\n\n#pragma once\n\n#include <chrono>\n#include <future>\n#include <memory>\n#include <optional>\n#include <queue>\n\n#include <boost/container/static_vector.hpp>\n#include <boost/smart_ptr/detail/spinlock.hpp>\n\n#include <glog/logging.h>\n\n#include \"hybrid_condition.h\"\n#include \"hybrid_mutex.h\"\n#include \"thread_pool.h\"\n#include \"task_pool.h\"\n\n#include \"standard_threads.h\"\n#include \"userspace_threads.h\"\n\nnamespace trtlab\n{\n    template <typename Batcher>\n    class Dispatcher;\n\n    template <template <class, class> class Batcher, typename T>\n    class Dispatcher<Batcher<T, standard_threads>> : private Batcher<T, standard_threads>\n    {\n        using batcher_type = Batcher<T, standard_threads>;\n        using thread_type  = typename batcher_type::thread_type;\n        using clock_type   = typename batcher_type::clock_type;\n\n        using mutex_type   = std::mutex;\n        using cv_type      = std::condition_variable;\n        using thread_pool  = std::shared_ptr<ThreadPool>;\n        using task_pool    = std::shared_ptr<DeferredShortTaskPool>;\n\n        // extra performance can be achieved using hybrid mutex/condition variables\n        // using thread_pool = BaseThreadPool<hybrid_mutex, hybrid_condition>;\n\n    public:\n        using future_type = typename batcher_type::future_type;\n        using execute_fn  = std::function<void(const std::vector<typename batcher_type::batch_item>&, std::function<void()>)>;\n\n        //template <typename... Args>\n        Dispatcher(batcher_type&& batcher, std::chrono::nanoseconds batching_window, thread_pool workers, task_pool progress, execute_fn exec_fn)\n        : batcher_type(std::move(batcher)),\n          m_Workers(workers),\n          m_Progress(progress),\n          m_UserFn(exec_fn),\n          m_ProgressTaskEnqueued(false),\n          m_DispatchID(0),\n          m_BatchingWindow(batching_window),\n          m_Shutdown(false)\n        {\n        }\n\n        virtual ~Dispatcher()\n        {\n            shutdown();\n        }\n\n        // can be moveable, but only if we inherit from std::enable_shared_from_this\n        // and all thread/task offsets refer to this object via a shared_ptr and not this.\n        Dispatcher(Dispatcher&&) = delete;\n        Dispatcher& operator=(Dispatcher&&) = delete;\n\n        // not copyable\n        Dispatcher(const Dispatcher&) = delete;\n        Dispatcher& operator=(const Dispatcher&) = delete;\n\n        // enqueue will add the item to the current batch\n        // the batcher controls all the in-process logic of batching\n        // the dispatcher controls the out-of-process logic, like timeouts\n        // access control is via the dispatcher\n        future_type enqueue(T item)\n        {\n            std::lock_guard<mutex_type> lock(m_EnqueueMutex);\n            if (m_Shutdown)\n            {\n                throw std::runtime_error(\"dispatcher shutting down; no new enqueues can be accepted\");\n            }\n\n            // should we launch a deferred async task to ensure forward progress\n            bool enqueue_progress_task = !m_ProgressTaskEnqueued && batcher_type::empty();\n\n            // push current items, then query the batcher for a batch\n            auto future = batcher_type::enqueue(std::move(item));\n            if (auto batch = batcher_type::update())\n            {\n                QueueBatch(*batch);\n                enqueue_progress_task = false;\n            }\n\n            if (enqueue_progress_task)\n            {\n                QueueProgressTask();\n            }\n\n            return future;\n        }\n\n        void shutdown()\n        {\n            std::condition_variable      cv;\n            std::unique_lock<mutex_type> lock(m_EnqueueMutex);\n            m_Shutdown = true;\n            while (m_ProgressTaskEnqueued)\n            {\n                cv.wait_until(lock, clock_type::now() + m_BatchingWindow);\n            }\n        }\n\n    private:\n        // requires mutex\n        void QueueBatch(typename batcher_type::Batch& batch)\n        {\n            DCHECK_GT(batch.items.size(), 0);\n            auto work = [batch = std::move(batch), user_fn = m_UserFn]() {\n                auto completer = [&batch]() mutable { batch.promise.set_value(); };\n                user_fn(batch.items, completer);\n            };\n            m_Workers->enqueue(std::move(work));\n            m_DispatchID++;\n        }\n\n        // requires mutex\n        void QueueProgressTask()\n        {\n            DCHECK(!batcher_type::empty());\n            auto deadline = batcher_type::start_time() + m_BatchingWindow;\n            auto task     = [this, id = m_DispatchID]() { ProgressTask(id); };\n            m_Progress->enqueue_deferred(deadline, std::move(task));\n            m_ProgressTaskEnqueued = true;\n        }\n\n        void ProgressTask(std::size_t id)\n        {\n            std::lock_guard<mutex_type> lock(m_EnqueueMutex);\n            m_ProgressTaskEnqueued = false;\n\n            // if the ids match, then close and queue the current batch - it timed out!\n            if (m_DispatchID == id)\n            {\n                DCHECK(!batcher_type::empty());\n                if (auto batch = batcher_type::close_batch())\n                {\n                    QueueBatch(*batch);\n                }\n            }\n            else\n            {\n                // if there is potential work, re-queue the progress task to ensure\n                // that work will complete at some future time\n                if (!batcher_type::empty())\n                {\n                    if (auto batch = batcher_type::update())\n                    {\n                        QueueBatch(*batch);\n                    }\n                    else\n                    {\n                        QueueProgressTask();\n                    }\n                }\n            }\n        }\n\n        execute_fn                m_UserFn;\n        thread_pool              m_Workers;\n        task_pool                m_Progress;\n        mutex_type               m_EnqueueMutex;\n        bool                     m_ProgressTaskEnqueued;\n        std::size_t              m_DispatchID;\n        std::chrono::nanoseconds m_BatchingWindow;\n        bool                     m_Shutdown;\n    };\n\n    // userspace_threads\n\n    template <template <class, class> class Batcher, typename T>\n    class Dispatcher<Batcher<T, userspace_threads>> : private Batcher<T, userspace_threads>\n    {\n        using batcher_type = Batcher<T, userspace_threads>;\n        using thread_type  = typename batcher_type::thread_type;\n        using clock_type   = typename batcher_type::clock_type;\n\n        using mutex_type   = typename thread_type::mutex;\n        using cv_type      = typename thread_type::cv;\n\n    public:\n        using batch_t     = std::vector<typename batcher_type::batch_item>;\n        using future_type = typename batcher_type::future_type;\n\n        //template <typename... Args>\n        Dispatcher(batcher_type&& batcher, std::chrono::nanoseconds batching_window)\n        : batcher_type(std::move(batcher)),\n          m_ProgressTaskEnqueued(false),\n          m_DispatchID(0),\n          m_BatchingWindow(batching_window),\n          m_Shutdown(false)\n        {\n        }\n\n        virtual ~Dispatcher()\n        {\n            shutdown();\n        }\n\n        // can be moveable, but only if we inherit from std::enable_shared_from_this\n        // and all thread/task offsets refer to this object via a shared_ptr and not this.\n        Dispatcher(Dispatcher&&) = delete;\n        Dispatcher& operator=(Dispatcher&&) = delete;\n\n        // not copyable\n        Dispatcher(const Dispatcher&) = delete;\n        Dispatcher& operator=(const Dispatcher&) = delete;\n\n        // enqueue will add the item to the current batch\n        // the batcher controls all the in-process logic of batching\n        // the dispatcher controls the out-of-process logic, like timeouts\n        // access control is via the dispatcher\n        future_type enqueue(T item)\n        {\n            std::lock_guard<mutex_type> lock(m_EnqueueMutex);\n            if (m_Shutdown)\n            {\n                throw std::runtime_error(\"dispatcher shutting down; no new enqueues can be accepted\");\n            }\n\n            // should we launch a deferred async task to ensure forward progress\n            bool enqueue_progress_task = !m_ProgressTaskEnqueued && batcher_type::empty();\n\n            // push current items, then query the batcher for a batch\n            auto future = batcher_type::enqueue(std::move(item));\n            if (auto batch = batcher_type::update())\n            {\n                DVLOG(2) << \"got batch from batcher - queuing execution\";\n                QueueBatch(std::move(*batch));\n                enqueue_progress_task = false;\n                DVLOG(2) << \"batch queued\";\n            }\n\n            if (enqueue_progress_task)\n            {\n                DVLOG(2) << \"queuing progress task to close window on timeout\";\n                QueueProgressTask();\n            }\n\n            return future;\n        }\n\n        void shutdown()\n        {\n            cv_type                      cv;\n            std::unique_lock<mutex_type> lock(m_EnqueueMutex);\n            m_Shutdown = true;\n            while (m_ProgressTaskEnqueued)\n            {\n                cv.wait_until(lock, clock_type::now() + m_BatchingWindow);\n            }\n        }\n\n    private:\n        virtual void compute_batch_fn(const batch_t&, std::function<void()>) {}\n\n        // requires mutex\n        void QueueBatch(typename batcher_type::Batch&& batch)\n        {\n            DCHECK_GT(batch.items.size(), 0);\n\n            DVLOG(3) << \"QueueBatch\";\n            boost::fibers::fiber(boost::fibers::launch::dispatch, [this, batch = std::move(batch)] {\n                auto completer = [&batch]() mutable { batch.promise.set_value(); };\n                compute_batch_fn(batch.items, completer);\n            }).detach();\n\n            m_DispatchID++;\n        }\n\n        // requires mutex\n        void QueueProgressTask()\n        {\n            DCHECK(!batcher_type::empty());\n            auto deadline = batcher_type::start_time() + m_BatchingWindow;\n            boost::fibers::fiber(boost::fibers::launch::dispatch, [this, id = m_DispatchID, deadline]() { \n                thread_type::sleep_until(deadline);\n                ProgressTask(id); \n            }).detach();\n            m_ProgressTaskEnqueued = true;\n        }\n\n        void ProgressTask(std::size_t id)\n        {\n            std::lock_guard<mutex_type> lock(m_EnqueueMutex);\n            m_ProgressTaskEnqueued = false;\n\n            // if the ids match, then close and queue the current batch - it timed out!\n            if (m_DispatchID == id)\n            {\n                DCHECK(!batcher_type::empty());\n                if (auto batch = batcher_type::close_batch())\n                {\n                    QueueBatch(std::move(*batch));\n                }\n            }\n            else\n            {\n                // if there is potential work, re-queue the progress task to ensure\n                // that work will complete at some future time\n                if (!batcher_type::empty())\n                {\n                    if (auto batch = batcher_type::update())\n                    {\n                        QueueBatch(std::move(*batch));\n                    }\n                    else\n                    {\n                        QueueProgressTask();\n                    }\n                }\n            }\n        }\n\n        mutex_type               m_EnqueueMutex;\n        bool                     m_ProgressTaskEnqueued;\n        std::size_t              m_DispatchID;\n        std::chrono::nanoseconds m_BatchingWindow;\n        bool                     m_Shutdown;\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/fiber_group.h",
    "content": "#pragma once\n#include <mutex>\n#include <vector>\n#include <boost/fiber/all.hpp>\n#include <glog/logging.h>\n\nnamespace trtlab\n{\n    template <typename SchedulerType = boost::fibers::algo::shared_work, typename... Args>\n    class FiberGroup\n    {\n    public:\n        FiberGroup(std::size_t thread_count, Args&&... args) : m_thread_count(thread_count), m_running(true), m_thread_barrier(thread_count)\n        {\n            auto scheduler_init = std::bind(boost::fibers::use_scheduling_algorithm<SchedulerType>, std::forward<Args>(args)...);\n            for (int i = 1; i < thread_count; i++)\n            {\n                m_threads.emplace_back([this, thread_count, scheduler_init] {\n                    scheduler_init();\n                    m_thread_barrier.wait();\n                    std::unique_lock<std::mutex> lock(m_thread_mutex);\n                    m_thread_cond.wait(lock, [this] { return !m_running; });\n                });\n            }\n            boost::fibers::use_scheduling_algorithm<SchedulerType>(std::forward<Args>(args)...);\n            m_thread_barrier.wait();\n            // VLOG(1) << \"thread and fiber scheduler initialized on \" << thread_count << \" threads\";\n        }\n\n        ~FiberGroup()\n        {\n            {\n                std::lock_guard<decltype(m_thread_mutex)> lock(m_thread_mutex);\n                m_running = false;\n            }\n            m_thread_cond.notify_all();\n\n            for (auto& t : m_threads)\n            {\n                t.join();\n            }\n        }\n\n    private:\n        bool                                  m_running;\n        const std::size_t                     m_thread_count;\n        boost::fibers::barrier                m_thread_barrier;\n        std::vector<std::thread>              m_threads;\n        std::mutex                            m_thread_mutex;\n        boost::fibers::condition_variable_any m_thread_cond;\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/hybrid_condition.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <atomic>\n#include <cassert>\n#include <chrono>\n#include <condition_variable>\n#include <cstdint>\n#include <limits>\n#include <mutex>\n\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#include <sys/time.h>\n#include <unistd.h>\n\n#include <x86intrin.h>\n\n#include \"trtlab/core/hybrid_mutex.h\"\n\n/**\n *\n */\nclass alignas(16) hybrid_condition final\n{\n    hybrid_condition(const hybrid_condition&) = delete;\n    hybrid_condition& operator=(const hybrid_condition&) = delete;\n\n  public:\n    /**\n     */\n    constexpr hybrid_condition() noexcept : m_mutex(nullptr), m_sequence(0) {}\n\n    /**\n     */\n    ~hybrid_condition() noexcept {}\n\n    /** Wait for mutex to signal */\n    void wait(std::unique_lock<hybrid_mutex>& lock) noexcept\n    {\n        (void)wait_for_impl(lock.mutex(), std::chrono::seconds(0), std::chrono::nanoseconds(0));\n    }\n\n    /**\n     */\n    template<typename TPredicate>\n    void wait(std::unique_lock<hybrid_mutex>& lock, const TPredicate& pred)\n    {\n        while(!pred())\n        {\n            wait(lock);\n        }\n    }\n\n    /**\n     */\n    template<typename TRep, typename TPeriod>\n    std::cv_status wait_for(std::unique_lock<hybrid_mutex>& lock,\n                            const std::chrono::duration<TRep, TPeriod>& rel_time)\n    {\n        auto rtime = rel_time;\n        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(rtime);\n        rtime -= std::chrono::duration_cast<std::chrono::duration<TRep, TPeriod>>(seconds);\n        auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(rtime);\n        return wait_for_impl(lock.mutex(), seconds, nanos);\n    }\n\n    /**\n     */\n    template<typename TRep, typename TPeriod, typename TPredicate>\n    bool wait_for(std::unique_lock<hybrid_mutex>& lock,\n                  const std::chrono::duration<TRep, TPeriod>& rel_time, TPredicate pred)\n    {\n        while(!pred())\n        {\n            if(wait_for(lock, rel_time) == std::cv_status::timeout)\n            {\n                return pred();\n            }\n        }\n\n        return true;\n    }\n\n    /** Notify one waiting thread to wake */\n    void notify_one() noexcept\n    {\n        // if no waiters, just return\n        if(m_mutex == nullptr)\n        {\n            return;\n        }\n\n        // increment sequence for wakeup\n        __atomic_fetch_add(&m_sequence, 1, __ATOMIC_ACQ_REL);\n\n        // wake up one thread\n        (void)sys_futex(&m_sequence, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);\n    }\n\n    /** Notify all waiting threads to wake */\n    void notify_all() noexcept\n    {\n        hybrid_mutex* mutex = m_mutex;\n\n        // if no waiters, just return\n        if(mutex == nullptr)\n        {\n            return;\n        }\n\n        // increment sequence for wakeup\n        __atomic_fetch_add(&m_sequence, 1, __ATOMIC_ACQ_REL);\n\n        // wake one thread, requeue the rest, avoids thundering herd\n        // wakes up one thread, requeues all remaining threads on mutex's queue\n        (void)sys_futex(&m_sequence, FUTEX_CMP_REQUEUE_PRIVATE, 1,\n                        reinterpret_cast<struct timespec*>(std::numeric_limits<int32_t>::max()),\n                        &mutex->m_lock, m_sequence);\n    }\n\n  private:\n    hybrid_mutex* m_mutex;\n    int32_t m_sequence;\n\n    /// wait for implementation\n    std::cv_status wait_for_impl(hybrid_mutex* mutex, const std::chrono::seconds& seconds,\n                                 const std::chrono::nanoseconds& nanoseconds) noexcept\n    {\n        // expected sequence number\n        int sequence = m_sequence;\n\n        if(m_mutex != mutex)\n        {\n            hybrid_mutex* expected = nullptr;\n\n            // atomically set mutex ptr\n            __atomic_compare_exchange_n(&m_mutex, &expected, mutex, false, __ATOMIC_ACQ_REL,\n                                        __ATOMIC_ACQUIRE);\n\n            // make sure this condition variable is not\n            // used by more than one mutex\n            assert(m_mutex == mutex);\n        }\n\n        // unlock the calling mutex\n        mutex->unlock();\n\n        // setup timeout (outside of lock)\n        struct timespec* timeoutptr = nullptr;\n        struct timespec timeout;\n\n        // if any timeout is set, setup time struct\n        if(seconds.count() > 0 || nanoseconds.count() > 0)\n        {\n            timeout.tv_sec = seconds.count();\n            timeout.tv_nsec = nanoseconds.count();\n            timeoutptr = &timeout;\n        }\n\n        // put thread to sleep on the sequence address,\n        // iff mSequence is still equal to sequence (value while lock was held)\n        int ret = -1;\n        std::cv_status status = std::cv_status::no_timeout;\n\n        // if interrupted.. continue.. and try again..\n        while((ret = sys_futex(&m_sequence, FUTEX_WAIT_PRIVATE, sequence, timeoutptr, nullptr,\n                               0)) == -1 &&\n              errno == EINTR)\n        {\n            continue;\n        }\n\n        // return false if we had timeout waiting to be notified\n        if(ret == -1 && errno == ETIMEDOUT)\n        {\n            status = std::cv_status::timeout;\n        }\n\n        // awoke, we need to aquire then lock before we exit\n        // slight bit of code duplication here with regard to hybrid_mutex::lock()\n        while(__atomic_exchange_n(&mutex->m_lock.u, 0x101, __ATOMIC_ACQUIRE) & 0x1)\n        {\n            (void)sys_futex(&mutex->m_lock.u, FUTEX_WAIT_PRIVATE, 0x101, nullptr, nullptr, 0);\n        }\n\n        return status;\n    }\n};\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/hybrid_mutex.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#include <sys/time.h>\n#include <unistd.h>\n\n#include <x86intrin.h>\n\n/**\n *\n */\ninline int sys_futex(void* addr1, int op, int val1, const struct timespec* timeout, void* addr2,\n                     int val3) noexcept\n{\n    return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);\n}\n\n/**\n *\n */\nclass alignas(16) hybrid_mutex final\n{\n    hybrid_mutex(const hybrid_mutex&) = delete;\n    hybrid_mutex& operator=(const hybrid_mutex&) = delete;\n\n    friend class hybrid_condition;\n\n  public:\n    /**\n     */\n    constexpr hybrid_mutex() noexcept : m_spins(1U), m_lock(0x0) {}\n\n    /**\n     */\n    constexpr hybrid_mutex(uint32_t spins) noexcept : m_spins(spins), m_lock(0x0) {}\n\n    /**\n     */\n    ~hybrid_mutex() noexcept { assert(m_lock.u == 0x0); }\n\n    /**\n     */\n    void lock() noexcept\n    {\n        // try and spin first\n        for(uint32_t i = 0U; i < m_spins; i++)\n        {\n            // do atomic exchange, returns previous value. if the previous\n            // value was 0, i.e. unlocked, we acquired the lock.\n            if(!__atomic_exchange_n(&m_lock.locked, 0x1, __ATOMIC_ACQUIRE))\n            {\n                return;\n            }\n\n            // be nice, tell the cpu we are spinning\n            __pause();\n        }\n\n        // didn't get lock, we may need to sleep.\n        // exchange with both the locked and contended bits set.\n        // if the previous value is still locked, i.e. 0x1,\n        // we need to go into the kernel and sleep\n        while(__atomic_exchange_n(&m_lock.u, 0x101, __ATOMIC_ACQUIRE) & 0x1)\n        {\n            (void)sys_futex(&m_lock.u, FUTEX_WAIT_PRIVATE, 0x101, nullptr, nullptr, 0);\n        }\n    }\n\n    /**\n     */\n    bool try_lock() noexcept\n    {\n        if(!__atomic_exchange_n(&m_lock.locked, 0x1, __ATOMIC_ACQUIRE))\n        {\n            return true;\n        }\n        else\n        {\n            return false;\n        }\n    }\n\n    /**\n     */\n    void unlock() noexcept\n    {\n        // locked and not contended\n        // if we are locked without contention, i.e. only the locked flag is set,\n        // attempt to atomically compare and swap to unlock\n        if(m_lock.u == 0x1)\n        {\n            uint32_t locked = 0x1;\n\n            if(__atomic_compare_exchange_n(&m_lock.u, &locked, 0x0, false, __ATOMIC_ACQ_REL,\n                                           __ATOMIC_ACQUIRE))\n            {\n                return;\n            }\n        }\n\n        // unlock, setting locked = 0, using release memory barrier\n        __atomic_exchange_n(&m_lock.locked, 0x0, __ATOMIC_RELEASE);\n\n        // spin, hoping someone takes the lock\n        // if someone takes the lock under the spin\n        // we can avoid going to the kernel\n        // note: if m_spins * 2 overflows, there is no check here... though that many spins is\n        // dumb...\n        for(uint32_t i = 0U; i < m_spins * 2U; i++)\n        {\n            if(m_lock.locked)\n            {\n                return;\n            }\n\n            // be nice, tell the cpu we are spinning\n            __pause();\n        }\n\n        // we need to wake someone up, go into the kernel\n        // reset the contended flag. anyone actively waiting\n        // on it, will set it again; otherwise, the kernel\n        // will have no one to wake and the mutex will remain\n        // in the unlocked, non-contended state (i.e. mLock.u == 0)\n        m_lock.contended = 0x0;\n\n        // tell the kernel to wake up 1 thread waiting on mLock address\n        (void)sys_futex(&m_lock.u, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);\n    }\n\n  private:\n    uint32_t m_spins; ///< number of spins before going to OS\n\n    /*\n     * lock data structure.\n     *\n     * The mutex in unlocked when the entire structure\n     * has a value of 0. (i.e. mLock.u == 0)\n     *\n     * locked is the userland byte that is used for the\n     * spinlock portion of the mutex.\n     */\n    union lock\n    {\n        constexpr lock(uint32_t _u) : u(_u) {}\n\n        uint32_t u;\n        struct\n        {\n            uint8_t locked;\n            uint8_t contended;\n            uint16_t pad;\n        };\n    } m_lock;\n};\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/memory/first_touch_allocator.h",
    "content": "#pragma once\n#include <cstring>\n#include <set>\n#include <utility>\n\n#include <trtlab/memory/allocator_traits.h>\n\n#include \"../affinity.h\"\n\n#if HAS_LIBNUMA\n#include <numaif.h>\n#endif\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace traits_detail\n        {\n            //=== page_size() ===//\n            // first try Allocator::page_size()\n            // then return maximum value\n            template <class Allocator>\n            auto page_size(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.page_size(), std::size_t)\n/*\n                template <class Allocator>\n                std::size_t page_size(min_concept, const Allocator&)\n            {\n                return std::size_t(0);\n            }\n*/\n        } // namespace traits_detail\n\n        template <typename RawAllocator, char Fill = 0x42>\n        class first_touch_allocator : TRTLAB_EBO(allocator_traits<RawAllocator>::allocator_type)\n        {\n            using traits            = allocator_traits<RawAllocator>;\n            using composable_traits = composable_allocator_traits<RawAllocator>;\n            using composable        = is_composable_allocator<typename traits::allocator_type>;\n\n        public:\n            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;\n            using memory_type    = typename allocator_traits<RawAllocator>::memory_type;\n            using is_stateful    = std::true_type;\n\n            static_assert(is_host_memory<memory_type>::value, \"currently only implemented for host_memory\");\n\n            explicit first_touch_allocator(int numa_node_id, RawAllocator&& alloc = {}) : allocator_type(std::move(alloc))\n            {\n                auto topology = affinity::system::topology();\n                CHECK_LE(numa_node_id, topology.size());\n                m_numa_node = topology[numa_node_id];\n            }\n\n            first_touch_allocator(first_touch_allocator&& other) noexcept\n            : allocator_type(std::move(other)), m_numa_node(std::move(other.m_numa_node))\n            {\n            }\n\n            first_touch_allocator& operator=(first_touch_allocator&& other) noexcept\n            {\n                allocator_type::operator=(std::move(other));\n                m_numa_node             = std::move(other.m_numa_node);\n                return *this;\n            }\n\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                \n                affinity_guard scoped_affinity(m_numa_node.cpus);\n                auto           ptr = traits::allocate_node(get_allocator(), size, alignment);\n                return first_touch(ptr, size);\n            }\n\n            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                affinity_guard scoped_affinity(m_numa_node.cpus);\n                auto           ptr = traits::allocate_array(get_allocator(), count, size, alignment);\n                return first_touch(ptr, count * size);\n            }\n\n            // TODO: turn all the default implemenations into macros\n            // DEFAULT_TRAITS_DEALLOCATE_NODE\n            // DEFAULT_TRAITS_DEALLOCATE_ARRAY\n            // etc\n\n            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                traits::deallocate_node(get_allocator(), ptr, size, alignment);\n            }\n\n            void deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                traits::deallocate_array(get_allocator(), ptr, count, size, alignment);\n            }\n\n            std::size_t max_node_size() const\n            {\n                return traits::max_node_size(get_allocator());\n            }\n\n            std::size_t max_array_size() const\n            {\n                return traits::max_array_size(get_allocator());\n            }\n\n            std::size_t max_alignment() const\n            {\n                return traits::max_alignment(get_allocator());\n            }\n\n            std::size_t min_alignment() const\n            {\n                return traits::min_alignment(get_allocator());\n            }\n\n            /// @{\n            /// \\returns A reference to the underlying allocator.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n\n        private:\n            void* first_touch(void* ptr, std::size_t size)\n            {\n                auto page_size = traits_detail::page_size(traits_detail::full_concept{}, get_allocator());\n                if (page_size && is_aligned(ptr, page_size))\n                {\n                    DVLOG(2) << \"allocator provides memory aligned to page_size: \" << page_size;\n                    first_touch_aligned_pages(ptr, size, page_size);\n                }\n                else\n                {\n                    DVLOG(2) << \"allocator did not provide page_size or is not aligned on a page boundry\";\n                    std::memset(ptr, Fill, size);\n                }\n                return ptr;\n            }\n\n            void first_touch_aligned_pages(void* ptr, std::size_t size, std::size_t page_size)\n            {\n                auto page_count = size / page_size + (size % page_size ? 1 : 0);\n                auto nodes      = 1;\n#if HAS_LIBNUMA\n                void* pages[page_count];\n                int   nodes[page_count];\n                int   status[page_count];\n#endif\n                auto pages_per_node  = page_count / nodes;\n                auto pages_remaining = page_count % nodes;\n\n                for (std::size_t n = 0; n < nodes; n++)\n                {\n                    auto pages = pages_per_node + (n < pages_remaining ? 1 : 0);\n                    DVLOG(1) << \"assign \" << pages << \" to numa_ndoe \" << n;\n\n                    affinity_guard scoped_affinity(m_numa_node.cpus);\n                    for (std::size_t p = n; p < pages; p += nodes)\n                    {\n                        char* page = static_cast<char*>(ptr);\n                        page += p * page_size;\n                        *page = Fill; // touch the first byte of the page\n#if HAS_LIBNUMA\n                        pages[p] = static_cast<void*>(page);\n                        nodes[p] = n; // the node the page should be on\n#endif\n                    }\n                }\n#if HAS_NUMA\n                // get status of pages\n                auto rc = move_pages(0 /*self memory */, page_count, &pages, NULL, status, 0);\n                if (rc)\n                {\n                    LOG(WARNING) << \"page_check: move_pages returned :\" << std::strerror(errno);\n                }\n\n                std::vector<int> move;\n                for (std::size_t p = 0; p < page_count; p++)\n                {\n                    LOG_IF(WARNING, status[p] < 0) << \"page \" << p << \": \" << std::strerror(std::abs(errno));\n                    if (status[p] >= 0 && status[p] != nodes[p])\n                    {\n                        move.push_back(p);\n                        LOG(WARNING) << \"page \" << p << \": expected on node \" << node[p] \"; found on \" << status[p];\n                    }\n                }\n\n                // move any misaligned pages\n                if (move.size())\n                {\n                    // overwrite pages/nodes with pages o be moved\n                    for (std::size_t p = 0; p < move.size; p++)\n                    {\n                        page_id  = move[p];\n                        pages[p] = pages[page_id];\n                        nodes[p] = nodes[page_id];\n                    }\n                    rc = move_pages(0, move.size(), &pages, nodes, status, MPOL_MF_MOVE);\n                }\n#endif\n            }\n\n            numa_node m_numa_node;\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/pool.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <condition_variable>\n#include <functional>\n#include <memory>\n#include <mutex>\n#include <queue>\n\n#include \"standard_threads.h\"\n#include \"utils.h\"\n\n#include \"glog/logging.h\"\n\nnamespace trtlab\n{\n    /**\n * @brief Templated Thread-safe Queue\n *\n * A simple thread-safe queue using a mutex and a condition variable.  This\n * class is derived from `std::enabled_shared_from_this` which requires it\n * to be create using `std::make_shared`.\n *\n * @tparam T\n */\n    template <typename T>\n    class Queue : public std::enable_shared_from_this<Queue<T>>\n    {\n    protected:\n        Queue() = default;\n\n    public:\n        /**\n     * @brief Factory function to properly create a Queue.\n     *\n     * @return std::shared_ptr<Queue<T>>\n     */\n        static std::shared_ptr<Queue<T>> Create()\n        {\n            return std::shared_ptr<Queue<T>>(new Queue<T>());\n        }\n\n        Queue(Queue&& other)\n        {\n            std::lock_guard<std::mutex> lock(other.mutex_);\n            queue_ = std::move(other.queue_);\n        }\n\n        virtual ~Queue() {}\n\n        /**\n     * @brief Push a new value of T to the Queue\n     *\n     * @param value\n     */\n        void Push(T value)\n        {\n            {\n                std::lock_guard<std::mutex> lock(mutex_);\n                queue_.push(std::move(value));\n            }\n            cond_.notify_one();\n        }\n\n        /**\n     * @brief Pop the Front object from the Queue and return.\n     *\n     * @return T\n     */\n        T Pop()\n        {\n            std::unique_lock<std::mutex> lock(mutex_);\n            cond_.wait(lock, [this] { return !queue_.empty(); });\n            T value = std::move(queue_.front());\n            queue_.pop();\n            return value;\n        }\n\n        /**\n     * @brief Numbe of items in the Queue\n     *\n     * @return std::size_t\n     */\n        std::size_t Size()\n        {\n            std::lock_guard<std::mutex> lock(mutex_);\n            return queue_.size();\n        }\n\n    private:\n        mutable std::mutex      mutex_;\n        std::queue<T>           queue_;\n        std::condition_variable cond_;\n    };\n\n    /**\n * @brief Pool of ResourceType\n *\n * Pool of ResourceTypes implemented as a Queue.\n *\n * A unique aspect of this Pool object is the return type of the Pop method.  While the\n * Pool consists of shared_ptr's to objects of ResourceType typically created with the\n * the std::default_deleter.  The Pop method of this Pool clsss returned a different\n * type of shared_ptr<ResourceType> than the object pushed to the Pool.  The difference\n * is that the returned shared_ptr uses a custom deleter thereby creating a new logic\n * block for tracking this shared_ptr.  Rather than freeing the object in question,\n * the custom deleter captures both the original shared_ptr from the pool and the\n * shared_ptr of the Pool (shared_from_this), and uses those captured values to return\n * the original shared_ptr (with the default_deleter) to the Pool.\n *\n * By holding a reference to the pool in the custom deleter of the returned shared_ptr,\n * we ensure that the pool can not be deallocated while resources have been checked out.\n *\n * The custom shared_ptr also helps ensure resources are returned to the pool even if the\n * thread using the resources throws an exception.\n *\n * @tparam T\n */\n\n    namespace v1\n    {\n        template <typename ResourceType>\n        class Pool : public Queue<std::shared_ptr<ResourceType>>\n        {\n        protected:\n            using Queue<std::shared_ptr<ResourceType>>::Queue;\n\n        public:\n            /**\n     * @brief Factory function for creating a Pool.\n     *\n     * @return std::shared_ptr<Pool<ResourceType>>\n     */\n\n            static std::shared_ptr<Pool<ResourceType>> Create()\n            {\n                return std::shared_ptr<Pool<ResourceType>>(new Pool<ResourceType>());\n            }\n\n            /**\n     * @brief Acquire a shared pointer to a ResourceType held by the Pool.\n     *\n     * Returns a shared_ptr<ResourceType> with a custom deleter that return the\n     * Resource object by to the pool when the reference count of the shared_ptr\n     * goes to zero.\n     *\n     * @return std::shared_ptr<ResourceType>\n     */\n            std::shared_ptr<ResourceType> Pop()\n            {\n                return Pop([](ResourceType&) {});\n            }\n\n            /**\n     * @brief Acquire a shared pointer to a ResourceType held by the Pool.\n     *\n     * Returns a shared_ptr<ResourceType> with a custom deleter that return the\n     * Resource object by to the pool when the reference count of the shared_ptr\n     * goes to zero.\n     *\n     * onReturn will be executed prior to the object being returned to the pool.\n     * onReturn is passed the raw pointer to the ResourceType.\n     *\n     * @param onReturn\n     * @return std::shared_ptr<ResourceType>\n     */\n            std::shared_ptr<ResourceType> Pop(std::function<void(ResourceType&)> onReturn)\n            {\n                // auto pool_ptr = this->shared_from_this();\n                auto                          from_pool = Queue<std::shared_ptr<ResourceType>>::Pop();\n                auto                          raw       = from_pool.get();\n                std::shared_ptr<ResourceType> ptr(raw, [from_pool = std::move(from_pool), pool_ptr = std::move(this->shared_from_this()),\n                                                        onReturn](auto p) mutable {\n                    onReturn(*p);\n                    pool_ptr->Push(std::move(from_pool));\n                    pool_ptr.reset();\n                });\n                return ptr;\n            }\n\n            /**\n     * @brief Instantiates and Pushes a new Resource object.\n     *\n     * @param newObj Raw pointer to an object of ResourceType\n     */\n            void EmplacePush(ResourceType* newObj)\n            {\n                this->Push(std::shared_ptr<ResourceType>(newObj));\n            }\n\n            /**\n     * @brief Instantiates and Pushes a new Resource object.\n     *\n     * Forwards the arguments passed to this method to the ResourceType constructor.\n     *\n     * @tparam Args\n     * @param args\n     */\n            template <typename... Args>\n            void EmplacePush(Args&&... args)\n            {\n                EmplacePush(new ResourceType(std::forward<Args>(args)...));\n            }\n\n            /**\n     * @brief Pop/Dequeue a shared pointer to a ResourceType object.\n     *\n     * Unlike the Pop() that provides a shared_ptr whose Deleter returns the object\n     * to the Pool; this method permanently removes the object from the Pool.\n     *\n     * @return std::shared_ptr<ResourceType>\n     * @see Pop()\n     */\n            std::shared_ptr<ResourceType> PopWithoutReturn()\n            {\n                return Queue<std::shared_ptr<ResourceType>>::Pop();\n            }\n        };\n\n    } // namespace v1\n\n    namespace v2\n    {\n        template <typename ResourceType, typename ThreadType = standard_threads>\n        class Pool final : public std::enable_shared_from_this<Pool<ResourceType, ThreadType>>\n        {\n            struct internal_key\n            {\n            };\n            using mutex_t = typename ThreadType::mutex;\n            using cv_t    = typename ThreadType::cv;\n            mutable mutex_t          m_Mutex;\n            cv_t                     m_Condition;\n            std::queue<ResourceType> m_Queue;\n\n        public:\n            using PoolItem   = std::shared_ptr<ResourceType>;\n            using PoolType   = std::shared_ptr<Pool<ResourceType, ThreadType>>;\n            using OnReturnFn = std::function<void(ResourceType&)>;\n\n            Pool(internal_key) {}\n            ~Pool() {}\n\n            static PoolType Create()\n            {\n                return std::make_shared<Pool<ResourceType, ThreadType>>(internal_key());\n            }\n\n            void Push(ResourceType&& obj)\n            {\n                {\n                    std::lock_guard<mutex_t> lock(m_Mutex);\n                    m_Queue.push(std::move(obj));\n                }\n                m_Condition.notify_one();\n            }\n\n            template <typename... Args>\n            void EmplacePush(Args&&... args)\n            {\n                ResourceType obj(std::forward<Args>(args)...);\n                Push(std::move(obj));\n            }\n\n            PoolItem Pop(OnReturnFn onReturn)\n            {\n                std::unique_lock<mutex_t> lock(m_Mutex);\n                m_Condition.wait(lock, [this] { return !m_Queue.empty(); });\n                std::shared_ptr<ResourceType> ptr(new ResourceType(std::move(m_Queue.front())),\n                                                  [pool = this->shared_from_this(), onReturn](ResourceType* p) {\n                                                      onReturn(*p);\n                                                      pool->Push(std::move(*p));\n                                                      delete p;\n                                                  });\n                m_Queue.pop();\n                return ptr;\n            }\n\n            PoolItem Pop()\n            {\n                return Pop([](ResourceType&) {});\n            }\n\n            PoolItem PopWithoutReturn()\n            {\n                std::unique_lock<mutex_t> lock(m_Mutex);\n                m_Condition.wait(lock, [this] { return !m_Queue.empty(); });\n                auto ptr = std::make_shared<ResourceType>(std::move(m_Queue.front()));\n                m_Queue.pop();\n                return ptr;\n            }\n\n            std::size_t Size() const\n            {\n                std::lock_guard<mutex_t> lock(m_Mutex);\n                return m_Queue.size();\n            }\n        };\n\n    } // namespace v2\n\n    namespace v3\n    {\n        template <typename ResourceType, typename ThreadType = standard_threads>\n        class Pool final : public std::enable_shared_from_this<Pool<ResourceType, ThreadType>>\n        {\n            struct key\n            {\n            };\n            class Resource;\n\n            using pool_t = std::shared_ptr<Pool<ResourceType, ThreadType>>;\n            using item_t = std::unique_ptr<ResourceType>;\n\n        public:\n            using resource_type = ResourceType;\n            using on_return_fn  = std::function<void(ResourceType&)>;\n\n            Pool(key) {}\n            virtual ~Pool() {}\n\n            DELETE_COPYABILITY(Pool);\n            DELETE_MOVEABILITY(Pool);\n\n            static pool_t Create()\n            {\n                return std::make_shared<Pool<ResourceType, ThreadType>>(key());\n            }\n\n            void push(ResourceType&& resource)\n            {\n                internal_push(std::make_unique<ResourceType>(std::move(resource)));\n            }\n\n            void push(std::unique_ptr<ResourceType> resource)\n            {\n                internal_push(std::move(resource));\n            }\n\n            template <typename... Args>\n            void emplace_push(Args&&... args)\n            {\n                push(std::make_unique<ResourceType>(std::forward<Args>(args)...));\n            }\n\n            Resource pop(on_return_fn on_return)\n            {\n                return Resource(internal_pop(), this->shared_from_this(), on_return);\n            }\n\n            Resource pop()\n            {\n                return pop([](ResourceType&) {});\n            }\n\n            Resource pop_without_return()\n            {\n                return Resource(internal_pop(), nullptr, [](ResourceType&) {});\n            }\n\n        private:\n            void internal_push(item_t ptr)\n            {\n                {\n                    std::lock_guard<mutex_t> lock(m_Mutex);\n                    m_Queue.push(std::move(ptr));\n                }\n                m_Condition.notify_one();\n            }\n\n            item_t internal_pop()\n            {\n                std::unique_lock<mutex_t> lock(m_Mutex);\n                m_Condition.wait(lock, [this] { return !m_Queue.empty(); });\n                auto ptr = std::move(m_Queue.front());\n                m_Queue.pop();\n                return ptr;\n            }\n\n            class Resource\n            {\n            public:\n                Resource(item_t resource, pool_t pool, on_return_fn on_return)\n                : m_Resource(std::move(resource)), m_Pool(pool), m_OnReturnFn(on_return)\n                {\n                }\n\n                virtual ~Resource()\n                {\n                    if (m_Resource)\n                    {\n                        m_OnReturnFn(*m_Resource);\n                        if (m_Pool)\n                        {\n                            m_Pool->push(std::move(m_Resource));\n                        }\n                    }\n                }\n\n                DELETE_COPYABILITY(Resource);\n\n                Resource(Resource&&) noexcept = default;\n                Resource& operator=(Resource&&) noexcept = default;\n\n                ResourceType* operator->()\n                {\n                    return m_Resource.get();\n                }\n                const ResourceType* operator->() const\n                {\n                    return m_Resource.get();\n                }\n\n            private:\n                pool_t       m_Pool;\n                item_t       m_Resource;\n                on_return_fn m_OnReturnFn;\n            };\n\n            using mutex_t = typename ThreadType::mutex;\n            using cv_t    = typename ThreadType::cv;\n            mutable mutex_t    m_Mutex;\n            cv_t               m_Condition;\n            std::queue<item_t> m_Queue;\n        };\n\n    } // namespace v3\n\n    inline namespace v4\n    {\n        template <typename ResourceType, typename ThreadType = standard_threads>\n        class Pool final : public std::enable_shared_from_this<Pool<ResourceType, ThreadType>>\n        {\n            struct key\n            {\n            };\n            class UniqueItem;\n            using SharedItem = std::shared_ptr<ResourceType>;\n\n            using pool_t = std::shared_ptr<Pool<ResourceType, ThreadType>>;\n            using item_t = ResourceType;\n\n        public:\n            using resource_type = ResourceType;\n            using on_return_fn  = std::function<void(ResourceType&)>;\n\n            Pool(key) {}\n            virtual ~Pool() {}\n\n            DELETE_COPYABILITY(Pool);\n            DELETE_MOVEABILITY(Pool);\n\n            static pool_t Create()\n            {\n                return std::make_shared<Pool<ResourceType, ThreadType>>(key());\n            }\n\n            void Push(ResourceType&& resource)\n            {\n                internal_push(std::move(resource));\n            }\n\n            void push(ResourceType&& resource)\n            {\n                internal_push(std::move(resource));\n            }\n\n            template <typename... Args>\n            void emplace_push(Args&&... args)\n            {\n                push(ResourceType(std::forward<Args>(args)...));\n            }\n\n            template <typename... Args>\n            void EmplacePush(Args&&... args)\n            {\n                push(ResourceType(std::forward<Args>(args)...));\n            }\n\n            SharedItem Pop(on_return_fn on_return)\n            {\n                return pop_shared(on_return);\n            }\n\n            SharedItem Pop()\n            {\n                return pop_shared();\n            }\n\n            SharedItem PopWithoutReturn()\n            {\n                return pop_shared_without_return();\n            }\n\n            UniqueItem pop_unique(on_return_fn on_return)\n            {\n                return UniqueItem(internal_pop(), this->shared_from_this(), on_return);\n            }\n\n            UniqueItem pop_unique()\n            {\n                return pop_unique([](ResourceType&) {});\n            }\n\n            UniqueItem pop_unique_without_return()\n            {\n                return UniqueItem(internal_pop(), nullptr, [](ResourceType&) {});\n            }\n\n            SharedItem pop_shared(on_return_fn on_return)\n            {\n                return std::shared_ptr<item_t>(new item_t(std::move(internal_pop())), [pool = this->shared_from_this(), on_return](item_t* ptr) mutable {\n                    on_return(*ptr);\n                    pool->push(std::move(*ptr));\n                    delete ptr;\n                });\n            }\n\n            SharedItem pop_shared()\n            {\n                return pop_shared([](ResourceType&) {});\n            }\n\n            SharedItem pop_shared_without_return()\n            {\n                return std::make_shared<item_t>(std::move(internal_pop()));\n            }\n\n            std::size_t Size() const\n            {\n                std::lock_guard<mutex_t> lock(m_Mutex);\n                return m_Queue.size();\n            }\n\n            std::size_t size() const\n            {\n                std::lock_guard<mutex_t> lock(m_Mutex);\n                return m_Queue.size();\n            }\n\n        private:\n            void internal_push(item_t&& ptr)\n            {\n                {\n                    std::lock_guard<mutex_t> lock(m_Mutex);\n                    m_Queue.push(std::move(ptr));\n                }\n                m_Condition.notify_one();\n            }\n\n            item_t internal_pop()\n            {\n                std::unique_lock<mutex_t> lock(m_Mutex);\n                m_Condition.wait(lock, [this] { return !m_Queue.empty(); });\n                auto ptr = std::move(m_Queue.front());\n                m_Queue.pop();\n                return std::move(ptr);\n            }\n\n            class UniqueItem\n            {\n            public:\n                UniqueItem(item_t resource, pool_t pool, on_return_fn on_return)\n                : m_Resource(std::move(resource)), m_Pool(pool), m_OnReturnFn(on_return)\n                {\n                }\n\n                virtual ~UniqueItem()\n                {\n                    if (m_Pool)\n                    {\n                        m_OnReturnFn(m_Resource);\n                        m_Pool->push(std::move(m_Resource));\n                    }\n                }\n\n                DELETE_COPYABILITY(UniqueItem);\n                //DELETE_MOVEABILITY(UniqueItem);\n\n                UniqueItem(UniqueItem&& other) noexcept\n                : m_Resource(std::move(other.m_Resource)), m_Pool(std::exchange(other.m_Pool, nullptr)), m_OnReturnFn(std::move(other.m_OnReturnFn))\n                {\n                }\n                UniqueItem& operator=(UniqueItem&& other) noexcept\n                {\n                    m_Resource   = std::move(other.m_Resource);\n                    m_Pool       = std::exchange(other.m_Pool, nullptr);\n                    m_OnReturnFn = std::exchange(other.m_OnReturnFn, nullptr);\n                    return *this;\n                }\n\n                ResourceType* operator->()\n                {\n                    return &m_Resource;\n                }\n                const ResourceType* operator->() const\n                {\n                    return &m_Resource;\n                }\n\n            private:\n                item_t       m_Resource;\n                pool_t       m_Pool;\n                on_return_fn m_OnReturnFn;\n            };\n\n\n            using mutex_t = typename ThreadType::mutex;\n            using cv_t    = typename ThreadType::cv;\n            mutable mutex_t    m_Mutex;\n            cv_t               m_Condition;\n            std::queue<item_t> m_Queue;\n        };\n\n        template <typename ResourceType, typename ThreadType = standard_threads>\n        class UniquePool final : public std::enable_shared_from_this<UniquePool<ResourceType, ThreadType>>\n        {\n            struct key\n            {\n            };\n\n            using pool_t = std::shared_ptr<UniquePool<ResourceType, ThreadType>>;\n\n        public:\n            using item_t = std::unique_ptr<ResourceType>;\n            using resource_type = ResourceType;\n            using on_return_fn  = std::function<void(ResourceType&)>;\n\n            class UniqueItem;\n            \n            UniquePool(key) {}\n            virtual ~UniquePool() {}\n\n            DELETE_COPYABILITY(UniquePool);\n            DELETE_MOVEABILITY(UniquePool);\n\n            static pool_t Create()\n            {\n                return std::make_shared<UniquePool<ResourceType, ThreadType>>(key());\n            }\n\n            void push(item_t item)\n            {\n                internal_push(std::move(item));\n            }\n\n            template <typename... Args>\n            void emplace_push(Args&&... args)\n            {\n                internal_push(std::make_unique<ResourceType>(std::forward<Args>(args)...));\n            }\n\n            UniqueItem pop_unique(on_return_fn on_return)\n            {\n                return UniqueItem(internal_pop(), this->shared_from_this(), on_return);\n            }\n\n            UniqueItem pop_unique()\n            {\n                return pop_unique([](ResourceType&) {});\n            }\n\n            UniqueItem pop_unique_without_return()\n            {\n                return UniqueItem(internal_pop(), nullptr, [](ResourceType&) {});\n            }\n\n            std::size_t size() const\n            {\n                std::lock_guard<mutex_t> lock(m_Mutex);\n                return m_Queue.size();\n            }\n\n        private:\n            void internal_push(item_t&& ptr)\n            {\n                {\n                    std::lock_guard<mutex_t> lock(m_Mutex);\n                    m_Queue.push(std::move(ptr));\n                }\n                m_Condition.notify_one();\n            }\n\n            item_t internal_pop()\n            {\n                std::unique_lock<mutex_t> lock(m_Mutex);\n                m_Condition.wait(lock, [this] { return !m_Queue.empty(); });\n                auto ptr = std::move(m_Queue.front());\n                m_Queue.pop();\n                return std::move(ptr);\n            }\n\n        public:\n            class UniqueItem\n            {\n            public:\n                UniqueItem(item_t resource, pool_t pool, on_return_fn on_return)\n                : m_Resource(std::move(resource)), m_Pool(pool), m_OnReturnFn(on_return)\n                {\n                }\n\n                virtual ~UniqueItem()\n                {\n                    if (m_Pool)\n                    {\n                        m_OnReturnFn(*m_Resource);\n                        m_Pool->push(std::move(m_Resource));\n                    }\n                }\n\n                DELETE_COPYABILITY(UniqueItem);\n                //DELETE_MOVEABILITY(UniqueItem);\n\n                UniqueItem(UniqueItem&& other) noexcept\n                : m_Resource(std::move(other.m_Resource)), m_Pool(std::exchange(other.m_Pool, nullptr)), m_OnReturnFn(std::move(other.m_OnReturnFn))\n                {\n                }\n                UniqueItem& operator=(UniqueItem&& other) noexcept\n                {\n                    m_Resource   = std::move(other.m_Resource);\n                    m_Pool       = std::exchange(other.m_Pool, nullptr);\n                    m_OnReturnFn = std::exchange(other.m_OnReturnFn, nullptr);\n                    return *this;\n                }\n\n                ResourceType* operator->()\n                {\n                    return m_Resource.get();\n                }\n                const ResourceType* operator->() const\n                {\n                    return m_Resource.get();\n                }\n\n            private:\n                item_t       m_Resource;\n                pool_t       m_Pool;\n                on_return_fn m_OnReturnFn;\n            };\n\n\n            using mutex_t = typename ThreadType::mutex;\n            using cv_t    = typename ThreadType::cv;\n            mutable mutex_t    m_Mutex;\n            cv_t               m_Condition;\n            std::queue<item_t> m_Queue;\n\n        };\n\n    } // namespace v4\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/ranges.h",
    "content": "#pragma once\n#include <numeric>\n#include <vector>\n#include <utility>\n#include <type_traits>\n\nnamespace trtlab\n{\n    template <typename T>\n    std::vector<std::pair<T, T>> find_ranges(const std::vector<T>& values)\n    {\n        static_assert(std::is_integral<T>::value, \"only integral types allowed\");\n\n        auto copy = values;\n        sort(copy.begin(), copy.end());\n\n        std::vector<std::pair<T, T>> ranges;\n\n        auto it  = copy.cbegin();\n        auto end = copy.cend();\n\n        while (it != end)\n        {\n            auto low  = *it;\n            auto high = *it;\n            for (T i = 0; it != end && low + i == *it; it++, i++)\n            {\n                high = *it;\n            }\n            ranges.push_back(std::make_pair(low, high));\n        }\n\n        return ranges;\n    }\n\n    template <typename T>\n    std::string print_ranges(const std::vector<std::pair<T, T>>& ranges)\n    {\n        return std::accumulate(std::begin(ranges), std::end(ranges), std::string(), [](std::string r, std::pair<T, T> p) {\n            if (p.first == p.second)\n            {\n                return r + (r.empty() ? \"\" : \",\") + std::to_string(p.first);\n            }\n            else\n            {\n                return r + (r.empty() ? \"\" : \",\") + std::to_string(p.first) + \"-\" + std::to_string(p.second);\n            }\n        });\n    }\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/resources.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <memory>\n\nnamespace trtlab {\n\nstruct Resources : public std::enable_shared_from_this<Resources>\n{\n    virtual ~Resources() {}\n\n    template<class Target>\n    std::shared_ptr<Target> casted_shared_from_this()\n    {\n        return std::dynamic_pointer_cast<Target>(Resources::shared_from_this());\n    }\n};\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/standard_threads.h",
    "content": "#pragma once\n#include <future>\n\nnamespace trtlab\n{\n    struct standard_threads\n    {\n\n        using mutex = std::mutex;\n\n        using cv = std::condition_variable;\n        \n        template <typename T>\n        using promise = std::promise<T>;\n\n        template <typename T>\n        using future = std::future<T>;\n\n        template <typename T>\n        using shared_future = std::shared_future<T>;\n\n        template <class Function, class... Args>\n        static auto async(Function&& f, Args&&... args)\n        {\n            return std::async(f, std::forward<Args>(args)...);\n        }\n\n        template <typename Rep, typename Period>\n        static void sleep_for(std::chrono::duration<Rep, Period> const& timeout_duration)\n        {\n            std::this_thread::sleep_for(timeout_duration);\n        }\n\n        template <typename Clock, typename Duration>\n        static void sleep_until(std::chrono::time_point<Clock, Duration> const& sleep_time_point)\n        {\n            std::this_thread::sleep_until(sleep_time_point);\n        }\n    };\n}"
  },
  {
    "path": "trtlab/core/include/trtlab/core/task_pool.h",
    "content": "/* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <chrono>\n#include <map>\n#include <mutex>\n#include <thread>\n\nnamespace trtlab\n{\n    class DeferredShortTaskPool\n    {\n    public:\n        using clock_type = std::chrono::high_resolution_clock;\n        using time_point = clock_type::time_point;\n\n        DeferredShortTaskPool() : m_Thread(std::make_unique<std::thread>([this]() { ProgressThread(); })), m_Stop(false) {}\n\n        virtual ~DeferredShortTaskPool()\n        {\n            shutdown();\n            m_Thread->join();\n        }\n\n        DELETE_COPYABILITY(DeferredShortTaskPool);\n        DELETE_MOVEABILITY(DeferredShortTaskPool);\n\n        void enqueue_deferred(time_point deadline, std::function<void()> task)\n        {\n            {\n                std::lock_guard<std::mutex> lock(m_Mutex);\n                if(m_Stop) { throw std::runtime_error(\"shutting down task pool; new submission not allowed\"); }\n                m_Tasks[deadline] = std::move(task);\n            }\n            m_Condition.notify_one();\n        }\n\n        void shutdown()\n        {\n            {\n                std::lock_guard<std::mutex> lock(m_Mutex);\n                m_Stop = true;\n            }\n            m_Condition.notify_all();\n        }\n\n    private:\n        void ProgressThread()\n        {\n            for (;;)\n            {\n                std::function<void()>  task;\n                clock_type::time_point deadline;\n                {\n                    std::unique_lock<std::mutex> lock(m_Mutex);\n                    if (m_Tasks.empty())\n                    {\n                        m_Condition.wait(lock, [this]() { return m_Stop || !m_Tasks.empty(); });\n                    }\n                    else\n                    {\n                        auto keyval = m_Tasks.cbegin();\n                        m_Condition.wait_until(lock, keyval->first, [this]() { return m_Stop; });\n                    }\n\n                    if (m_Stop && m_Tasks.empty()) { return; }\n                    if (m_Tasks.empty()) { continue; }\n\n                    auto it = m_Tasks.begin();\n                    if(clock_type::now() < it->first) { continue; }\n                    task    = std::move(it->second);\n                    m_Tasks.erase(it->first);\n                }\n                //auto start = clock_type::now();\n                task();\n                //auto end = clock_type::now();\n                //auto wall = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();\n                //LOG_IF(WARNING, wall >= 5) << \"task exceeded short duration limit (max 5us): \" << wall << \"us\";\n            }\n        }\n\n        std::unique_ptr<std::thread> m_Thread;\n        bool                         m_Stop;\n\n        std::map<time_point, std::function<void()>> m_Tasks;\n        std::mutex                                  m_Mutex;\n        std::condition_variable                     m_Condition;\n    };\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/thread_pool.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n//\n// Original Source: https://github.com/progschj/BaseThreadPool\n//\n// Original License:\n//\n// Copyright (c) 2012 Jakob Progsch, Václav Zeman\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n//   1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n//\n//   2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n//\n//   3. This notice may not be removed or altered from any source\n//   distribution.\n//\n// Modifications:\n//   * Header-only file was split into .h/.cc files\n//   * Added an extra safety check (lines 30-31) in the construction (.cc file).\n//   * Added CPU affinity options to the constructor\n//   * Added Size() method to get thread count\n//   * Implemented transwarp::executor protocol\n//\n#pragma once\n\n#include \"trtlab/core/affinity.h\"\n#include \"trtlab/core/utils.h\"\n\n#include <functional>\n#include <future>\n#include <queue>\n\n#include <glog/logging.h>\n\nnamespace trtlab\n{\n    template <typename MutexType, typename ConditionType>\n    class BaseThreadPool;\n\n    using ThreadPool = BaseThreadPool<std::mutex, std::condition_variable>;\n\n    /**\n * @brief Manages a Pool of Threads that consume a shared work Queue\n *\n * BaseThreadPool is the primary resoruce class for handling threads used throughout\n * the YAIS examples and tests.  The library is entirely a BYO-resources;\n * however, this implemenation is provided as a convenience class.  Many thanks\n * to the original authors for a beautifully designed class.\n */\n    template <typename MutexType, typename ConditionType>\n    class BaseThreadPool\n    {\n    public:\n        /**\n     * @brief Construct a new Thread Pool\n     * @param nThreads Number of Worker Threads\n     */\n        BaseThreadPool(size_t nThreads);\n\n        /**\n     * @brief Construct a new Thread Pool with Shared CPU Affinity\n     *\n     * Creates a BaseThreadPool with nThreads where each thread sets its CPU affinity\n     * to affinity_mask.\n     *\n     * @param nThreads\n     * @param affinity_mask\n     */\n        BaseThreadPool(size_t nThreads, const cpu_set& affinity_mask);\n\n        /**\n     * @brief Construct a new Thread Pool with Exclusive CPU Affinity\n     *\n     * Creates a BaseThreadPool using a cpu_set such a for each CPU in the cpu_set a\n     * thread is created and the affnity of that thread is dedicted to the\n     * respective CPU from the cpu_set.\n     *\n     * @param cpu_set\n     */\n        BaseThreadPool(const cpu_set& cpu_set);\n        virtual ~BaseThreadPool();\n\n        DELETE_COPYABILITY(BaseThreadPool);\n        DELETE_MOVEABILITY(BaseThreadPool);\n\n        /**\n     * @brief Enqueue Work to the BaseThreadPool by passing a Lambda Function\n     *\n     * Variadic template allows for an arbituary number of arguments to be passed\n     * the captured lambda function.  Captures are still allowed and used\n     * throughout the examples.\n     *\n     * The queue can grow larger than the number of threads.  A single worker\n     * thread executues pulls a lambda function off the queue and executes it to\n     * completion.  These are synchronous executions in an async messaging\n     * library.  These synchronous pools can be swapped for truely async workers\n     * using libevent or asio.  Happy to accept PRs to improve the async\n     * abilities.\n     *\n     * @tparam F\n     * @tparam Args\n     * @param f\n     * @param args\n     * @return std::future<typename std::result_of<F(Args...)>::type>\n     */\n        template <class F, class... Args>\n        auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>;\n\n        void enqueue(std::function<void()> task);\n\n        /**\n     * @brief Number of Threads in the Pool\n     */\n        int Size();\n\n#ifdef USE_TRANSWARP\n        // transwarp interface: get_name, execute\n\n        // The name of the executor\n        std::string get_name() const final override\n        {\n            return \"trtlab::BaseThreadPool\";\n        }\n\n        // Only ever called on the thread of the caller to schedule()\n        void execute(const std::function<void()>& functor, const std::shared_ptr<tw::node>& node) final override\n        {\n            {\n                std::unique_lock<MutexType> lock(m_QueueMutex);\n                tasks.push(functor);\n            }\n            m_Condition.notify_one();\n        }\n#endif\n\n    private:\n        void CreateThread(const cpu_set& affinity_mask);\n\n        // need to keep track of threads so we can join them\n        std::vector<std::thread> workers;\n        // the task queue\n        //std::queue<std::function<void()>> tasks;\n        std::queue<std::packaged_task<void()>> tasks;\n\n        // synchronization\n        MutexType     m_QueueMutex;\n        ConditionType m_Condition;\n        bool          stop;\n    };\n\n    // add new work item to the pool\n    template <typename MutexType, typename ConditionType>\n    template <class F, class... Args>\n    auto BaseThreadPool<MutexType, ConditionType>::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>\n    {\n        using return_type = typename std::result_of<F(Args...)>::type;\n\n        std::packaged_task<return_type()> task(\n            std::bind(std::forward<F>(f), std::forward<Args>(args)...)\n        );\n\n        std::future<return_type> res = task.get_future();\n        {\n            std::lock_guard<MutexType> lock(m_QueueMutex);\n\n            // don't allow enqueueing after stopping the pool\n            if (stop)\n                throw std::runtime_error(\"enqueue on stopped BaseThreadPool\");\n\n            tasks.emplace(std::move(task));\n        }\n        m_Condition.notify_one();\n        return res;\n    }\n/*\n    template <typename MutexType, typename ConditionType>\n    void BaseThreadPool<MutexType, ConditionType>::enqueue(std::function<void()> task)\n    {\n        {\n            std::lock_guard<MutexType> lock(m_QueueMutex);\n\n            // don't allow enqueueing after stopping the pool\n            if (stop)\n                throw std::runtime_error(\"enqueue on stopped BaseThreadPool\");\n\n            std::packaged_task\n            tasks.push(task);\n        }\n        m_Condition.notify_one();\n    }\n*/\n    template <typename MutexType, typename ConditionType>\n    BaseThreadPool<MutexType, ConditionType>::BaseThreadPool(size_t nThreads)\n    : BaseThreadPool(nThreads, affinity::this_thread::get_affinity())\n    {\n    }\n\n    template <typename MutexType, typename ConditionType>\n    BaseThreadPool<MutexType, ConditionType>::BaseThreadPool(size_t nThreads, const cpu_set& affinity_mask) : stop(false)\n    {\n        for (size_t i = 0; i < nThreads; ++i)\n        {\n            CreateThread(affinity_mask);\n        }\n    }\n\n    template <typename MutexType, typename ConditionType>\n    BaseThreadPool<MutexType, ConditionType>::BaseThreadPool(const cpu_set& cpus) : stop(false)\n    {\n        auto exclusive = cpus.get_allocator();\n        for (size_t i = 0; i < exclusive.size(); i++)\n        {\n            cpu_set affinity_mask;\n            CHECK(exclusive.allocate(affinity_mask, 1)) << \"Affinity Allocator failed on pass: \" << i;\n            CreateThread(affinity_mask);\n        }\n    }\n\n    template <typename MutexType, typename ConditionType>\n    void BaseThreadPool<MutexType, ConditionType>::CreateThread(const cpu_set& affinity_mask)\n    {\n        workers.emplace_back([this, affinity_mask]() {\n            affinity::this_thread::set_affinity(affinity_mask);\n            for (;;)\n            {\n                std::packaged_task<void()> task;\n                {\n                    std::unique_lock<MutexType> lock(this->m_QueueMutex);\n                    this->m_Condition.wait(lock, [this]() { return this->stop || !this->tasks.empty(); });\n                    if (this->stop && this->tasks.empty())\n                        return;\n                    task = move(this->tasks.front());\n                    this->tasks.pop();\n                }\n                task();\n            }\n        });\n    }\n\n    // the destructor joins all threads\n    template <typename MutexType, typename ConditionType>\n    BaseThreadPool<MutexType, ConditionType>::~BaseThreadPool()\n    {\n        {\n            std::lock_guard<MutexType> lock(m_QueueMutex);\n            stop = true;\n        }\n        m_Condition.notify_all();\n\n        for (std::thread& worker : workers)\n        {\n            worker.join();\n        }\n    }\n\n    template <typename MutexType, typename ConditionType>\n    int BaseThreadPool<MutexType, ConditionType>::Size()\n    {\n        return workers.size();\n    }\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/include/trtlab/core/types.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <cstdint> // for int64_t etc\n#include <functional> // for std::multiplies\n#include <memory>\n#include <numeric>\n#include <vector>\n#include <ostream>\n\nnamespace trtlab {\nnamespace types {\n\ntemplate<typename T>\nstruct ArrayType final\n{\n    using NativeType = T;\n    static uint64_t ItemSize();\n    static DLDataType DataTypeInfo();\n\n  protected:\n    ArrayType() = default;\n};\n\ntemplate<typename T>\nDLDataType ArrayType<T>::DataTypeInfo()\n{\n    DLDataType dtype;\n    // clang-format off\n    if(std::is_floating_point<T>::value) { dtype.code = kDLFloat; }\n    else if(std::is_integral<T>::value)\n    {\n        dtype.code = kDLUInt;\n        if(std::is_signed<unsigned int>::value) { dtype.code = kDLInt; }\n    }\n    else { throw std::runtime_error(\"Only integer or floating point types accepted\"); }\n    // clang-format on\n\n    dtype.bits = 8 * ItemSize();\n    dtype.lanes = 1;\n\n    return dtype;\n}\n\ntemplate<typename T>\nuint64_t ArrayType<T>::ItemSize()\n{\n    return sizeof(T);\n}\n\ntemplate<>\ninline DLDataType ArrayType<void>::DataTypeInfo()\n{\n    return ArrayType<uint8_t>::DataTypeInfo();\n}\n\ntemplate<>\ninline uint64_t ArrayType<void>::ItemSize()\n{\n    return 1;\n}\n\nstruct dtype final\n{\n    dtype(const DLDataType&);\n    dtype(uint8_t code, uint8_t bits, uint16_t lanes);\n\n    template<typename T>\n    static dtype from() { return dtype(ArrayType<T>::DataTypeInfo()); }\n\n    template<typename T>\n    bool is_compatible() const;\n\n    dtype(dtype&&) noexcept;\n    dtype& operator=(dtype&&) noexcept;\n\n    dtype(const dtype&);\n    dtype& operator=(const dtype&);\n\n    virtual ~dtype() {}\n\n    bool operator==(const dtype&) const;\n    bool operator!=(const dtype& other) const { return !(*this == other); }\n\n    int64_t bytes() const;\n    int64_t itemsize() const { return bytes(); };\n    const DLDataType& to_dlpack() const;\n\n    std::string Description() const;\n\n  protected:\n    uint32_t code() const { return m_DLPackType.code; }\n    uint32_t bits() const { return m_DLPackType.bits; }\n    uint32_t lanes() const { return m_DLPackType.lanes; }\n\n  private:\n    dtype();\n    DLDataType m_DLPackType;\n    int64_t m_Bytes;\n\n    friend std::ostream& operator<<(std::ostream& os, const dtype& dt);\n};\n\ntemplate<typename T>\nbool dtype::is_compatible() const\n{\n    if(lanes() != 1) { return false; }\n    if(bits() != sizeof(T) * 8) { return false; }\n    if(std::is_integral<T>::value)\n    {\n        if(std::is_signed<T>::value) { if(code() != kDLInt) { return false; } }\n        else{ if(code() != kDLUInt) { return false; }}\n    }\n    else if(std::is_floating_point<T>::value)\n    {\n        if(code() != kDLFloat) { return false; }\n    }\n    return true;\n}\n\ntemplate<>\ninline bool dtype::is_compatible<void>() const\n{\n    return true;\n}\n\n\nstatic const auto nil = dtype(kDLInt, 0U, 0U);\nstatic const auto bytes = dtype(kDLUInt, 8U, 1U);\n\nstatic const auto int8 = dtype(kDLInt, 8U, 1U);\nstatic const auto int16 = dtype(kDLInt, 16U, 1U);\nstatic const auto int32 = dtype(kDLInt, 32U, 1U);\nstatic const auto int64 = dtype(kDLInt, 64U, 1U);\nstatic const auto uint8 = dtype(kDLUInt, 8U, 1U);\nstatic const auto uint16 = dtype(kDLUInt, 16U, 1U);\nstatic const auto uint32 = dtype(kDLUInt, 32U, 1U);\nstatic const auto uint64 = dtype(kDLUInt, 64U, 1U);\nstatic const auto fp16 = dtype(kDLFloat, 16U, 1U);\nstatic const auto fp32 = dtype(kDLFloat, 32U, 1U);\nstatic const auto fp64 = dtype(kDLFloat, 64U, 1U);\n\nstatic const dtype All[] = {int8, int16, int32, int64, uint8, uint16, uint32, uint64, fp16, fp32, fp64};\n\n} // namespace types\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/userspace_threads.h",
    "content": "#pragma once\n#include <boost/fiber/all.hpp>\n\nnamespace trtlab\n{\n    struct userspace_threads\n    {\n        using mutex = boost::fibers::mutex;\n\n        using cv = boost::fibers::condition_variable;\n\n        template <typename T>\n        using promise = boost::fibers::promise<T>;\n\n        template <typename T>\n        using future = boost::fibers::future<T>;\n\n        template <typename T>\n        using shared_future = boost::fibers::shared_future<T>;\n\n        template <class R, class... Args>\n        using packaged_task = boost::fibers::packaged_task<R(Args...)>;\n\n        template <class Function, class... Args>\n        static auto async(Function&& f, Args&&... args)\n        {\n            return boost::fibers::async(f, std::forward<Args>(args)...);\n        }\n\n        template <typename Rep, typename Period>\n        static void sleep_for(std::chrono::duration<Rep, Period> const& timeout_duration)\n        {\n            boost::this_fiber::sleep_for(timeout_duration);\n        }\n\n        template <typename Clock, typename Duration>\n        static void sleep_until(std::chrono::time_point<Clock, Duration> const& sleep_time_point)\n        {\n            boost::this_fiber::sleep_until(sleep_time_point);\n        }\n    };\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/include/trtlab/core/utils.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <string>\n\n#define DELETE_COPYABILITY(foo) \\\n    foo(const foo&) = delete;   \\\n    foo& operator=(const foo& other) = delete;\n\n#define DELETE_MOVEABILITY(foo)   \\\n    foo(foo&&) noexcept = delete; \\\n    foo& operator=(foo&& other) noexcept = delete;\n\nnamespace trtlab {\n\nstd::string BytesToString(std::size_t bytes);\nstd::size_t StringToBytes(const std::string);\n\ntemplate<typename T>\nT round_up(T val, T multiple) \n{\n    static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, \"\");\n    DCHECK(multiple);\n    return ((val + multiple - 1) / multiple) * multiple;\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/src/affinity.cc",
    "content": "/* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"affinity.h\"\n\n#include <algorithm>\n#include <functional>\n\n#include <glog/logging.h>\n#include <boost/fiber/numa/topology.hpp>\n\n#include \"ranges.h\"\n\n#define test_bit(_n, _p) (_n & (1UL << _p))\n\nusing namespace trtlab;\n\nstatic cpuaff::affinity_manager s_manager;\nstatic std::string              cpu_int_string(const cpu_set& cpus, std::function<int(const cpuaff::cpu&)> extract);\nstatic std::vector<int>         parse_ints(const std::string data);\n\ncpu_set cpu_set::get_intersection(const cpu_set& other) const\n{\n    cpu_set cpus;\n    set_intersection(begin(), end(), other.begin(), other.end(), std::inserter(cpus, cpus.begin()));\n    return cpus;\n}\n\ncpu_set cpu_set::get_union(const cpu_set& other) const\n{\n    cpu_set cpus;\n    set_union(begin(), end(), other.begin(), other.end(), std::inserter(cpus, cpus.begin()));\n    return cpus;\n}\n\ncpu_set cpu_set::get_difference(const cpu_set& other) const\n{\n    cpu_set cpus;\n    set_difference(begin(), end(), other.begin(), other.end(), std::inserter(cpus, cpus.begin()));\n    return cpus;\n}\n\ncpu_set cpu_set::from_string(std::string ids)\n{\n    cpu_set cpus;\n    auto    ints = parse_ints(ids);\n    for (const auto id : ints)\n    {\n        cpus.insert(affinity::system::cpu_from_logical_id(id));\n    }\n    return cpus;\n}\n\nstd::string cpu_set::cpus_string() const\n{\n    auto extract = [](const cpuaff::cpu& cpu) { return int(cpu.id().get()); };\n    return cpu_int_string(*this, extract);\n}\n\nstd::string cpu_set::cores_string() const\n{\n    auto extract = [](const cpuaff::cpu& cpu) { return int(cpu.core()); };\n    return cpu_int_string(*this, extract);\n}\n\nstd::string cpu_set::sockets_string() const\n{\n    auto extract = [](const cpuaff::cpu& cpu) { return int(cpu.socket()); };\n    return cpu_int_string(*this, extract);\n}\n\nstd::ostream& trtlab::operator<<(std::ostream& s, const cpu_set& cpus)\n{\n    s << \"[cpu_set: cpus=\" << cpus.cpus_string() << \"; cores=\" << cpus.cores_string() << \"; sockets=\" << cpus.sockets_string() << \"]\";\n    return s;\n}\n\nstd::ostream& trtlab::operator<<(std::ostream& s, const numa_node& node)\n{\n    s << \"[numa_node: \" << node.id << \"; logical_cpus=\" << node.cpus.cpus_string()\n      << \"; distances=(\";\n    for(const auto& d : node.distances)\n    {\n        s << \" \" << d;\n    }\n    s << \" )]\";\n    return s;\n}\n\nstd::vector<numa_node> affinity::system::topology()\n{\n    auto                   topo = boost::fibers::numa::topology();\n    std::vector<numa_node> nodes;\n\n    for (const auto& n : topo)\n    {\n        nodes.emplace_back();\n        auto& node = nodes.back();\n\n        // numa node id\n        node.id = n.id;\n\n        // logical cpus\n        for (auto cpu : n.logical_cpus)\n        {\n            node.cpus.insert(affinity::system::cpu_from_logical_id(cpu));\n        }\n\n        // distance\n        for (auto d : n.distance)\n        {\n            node.distances.push_back(d);\n        }\n    }\n    return nodes;\n}\n\nvoid affinity::this_thread::set_affinity(const cpu_set& cpus)\n{\n    //DVLOG(1) << \"Affinity: set thread affinity to: \" << cpus;\n    CHECK(s_manager.set_affinity(cpus)) << \"SetAffinity failed for cpu_set: \" << cpus;\n}\n\ncpu_set affinity::this_thread::get_affinity()\n{\n    cpu_set cpus;\n    CHECK(s_manager.get_affinity(cpus)) << \"GetAffinity failed\";\n    //DVLOG(1) << \"Affinity: cpu affinity of calling thread: \" << cpus;\n    return cpus;\n}\n\n/*\ncpu_set Affinity::GetCpusByNuma(int numa_id)\n{\n    cpuaff::cpu_set cpus;\n    CHECK(s_manager.get_cpus_by_numa(cpus, numa_id)) << \"GetCpusByNuma failed for numa_id: \" << numa_id;\n    return cpu_set(cpus);\n}\n\ncpu_set Affinity::GetCpusBySocket(int socket_id)\n{\n    cpuaff::cpu_set cpus;\n    CHECK(s_manager.get_cpus_by_socket(cpus, socket_id)) << \"GetCpusBySocket failed for socket_id: \" << socket_id;\n    return cpu_set(cpus);\n}\n\ncpu_set Affinity::GetCpusByCore(int core_id)\n{\n    cpuaff::cpu_set cpus;\n    CHECK(s_manager.get_cpus_by_core(cpus, core_id)) << \"GetCpusByCore failed for core_id: \" << core_id;\n    return cpu_set(cpus);\n}\n\ncpu_set Affinity::GetCpusByProcessingUnit(int thread_id)\n{\n    cpuaff::cpu_set cpus;\n    CHECK(s_manager.get_cpus_by_processing_unit(cpus, thread_id)) << \"GetCpusByProcessingUnit failed for thread_id: \" << thread_id;\n    return cpu_set(cpus);\n}\n*/\n\naffinity_guard::affinity_guard()\n{\n    m_original_cpus = affinity::this_thread::get_affinity();\n}\naffinity_guard::affinity_guard(const cpu_set& cpus) : affinity_guard()\n{\n    CHECK(!cpus.empty());\n    affinity::this_thread::set_affinity(cpus);\n}\n\naffinity_guard::~affinity_guard()\n{\n    affinity::this_thread::set_affinity(m_original_cpus);\n}\n\n// static implementations\n\ncpuaff::cpu affinity::system::cpu_from_logical_id(int id)\n{\n    cpuaff::cpu cpu;\n    CHECK(s_manager.get_cpu_from_id(cpu, id)) << \"GetCpuById failed for cpu_id: \" << id;\n    return cpu;\n}\n\nint ConvertString2Int(const std::string& str)\n{\n    int               x;\n    std::stringstream ss(str);\n    CHECK(ss >> x) << \"Error converting \" << str << \" to integer\";\n    return x;\n}\n\nstd::vector<std::string> SplitStringToArray(const std::string& str, char splitter)\n{\n    std::vector<std::string> tokens;\n    std::stringstream        ss(str);\n    std::string              temp;\n    while (getline(ss, temp, splitter)) // split into new \"lines\" based on character\n    {\n        tokens.push_back(temp);\n    }\n    return tokens;\n}\n\nstd::vector<int> parse_ints(const std::string data)\n{\n    std::vector<int>         result;\n    std::vector<std::string> tokens = SplitStringToArray(data, ',');\n    for (std::vector<std::string>::const_iterator it = tokens.begin(), end_it = tokens.end(); it != end_it; ++it)\n    {\n        const std::string&       token = *it;\n        std::vector<std::string> range = SplitStringToArray(token, '-');\n        if (range.size() == 1)\n        {\n            result.push_back(ConvertString2Int(range[0]));\n        }\n        else if (range.size() == 2)\n        {\n            int start = ConvertString2Int(range[0]);\n            int stop  = ConvertString2Int(range[1]);\n            for (int i = start; i <= stop; i++)\n            {\n                result.push_back(i);\n            }\n        }\n        else\n        {\n            LOG(FATAL) << \"Error parsing token \" << token;\n        }\n    }\n    return result;\n}\n\nstd::string cpu_int_string(const cpu_set& cpus, std::function<int(const cpuaff::cpu&)> extract)\n{\n    std::set<int> uniques;\n\n    for (const auto& cpu : cpus)\n    {\n        uniques.insert(extract(cpu));\n    }\n\n    auto ranges = find_ranges(std::vector<int>(uniques.begin(), uniques.end()));\n    return print_ranges(ranges);\n}\n\n"
  },
  {
    "path": "trtlab/core/src/cyclic_buffer.cc",
    "content": "\n/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"trtlab/core/cyclic_buffer.h\"\n\n#include <cstring>\n#include <glog/logging.h>\n\nusing namespace trtlab;\n\nCyclicBuffer::CyclicBuffer(memory::descriptor&& md, std::size_t window_size, std::size_t overlap_size, CallbackFn callback)\n: m_Descriptor(std::move(md)),\n  m_Data(reinterpret_cast<std::uintptr_t>(m_Descriptor.data())),\n  m_Size(m_Descriptor.size()),\n  m_WindowSize(window_size),\n  m_ShiftSize(window_size - overlap_size),\n  m_CurrentLocation(m_Data),\n  m_WindowStart(m_Data),\n  m_Callback(callback),\n  m_CurrentWindow(0),\n  m_PreferFullWindows(false)\n{\n    CHECK_LE(m_WindowSize, m_Size) << \"Allocated memory must be >= the window_size\";\n    CHECK_LE(m_ShiftSize, m_WindowSize) << \"CyclicBuffer shift_size must be <= window_size\";\n\n    m_WindowCount = (m_Size - m_WindowSize) / m_ShiftSize + 1;\n    CHECK_GT(m_WindowCount, 1) << \"CyclicBuffer data segment must be at least 2x the window size\";\n    VLOG(1) << \"Allocation of \" << m_Size << \" bytes allows for \" << m_WindowCount << \" cyclic buffer windows\";\n\n    m_Size = m_WindowSize + (m_WindowCount - 1) * m_ShiftSize;\n    VLOG(2) << \"Effective allocation size \" << m_Size << \" bytes\";\n\n    // determine the location in the contiguous buffer where we need to replicate any bits\n    // past that point to the head of the buffer\n    auto replication_size = m_WindowSize - m_ShiftSize;\n    m_NextPassStart       = m_Data;\n    m_ReplicationStart    = m_Data + m_Size - replication_size;\n    VLOG(2) << \"Replication window begins at \" << Offset(m_ReplicationStart);\n\n    // set sync location to be the end of the buffer\n    // no sync is needed on the first pass, when we reset the pointers to the head,\n    // then the sync pointers move to the head and must shift forward before current\n    // position is allowed to move forward\n    m_SyncWindow   = m_WindowCount;\n    m_SyncLocation = m_Data + m_Size;\n\n    // initialze state trackers\n    // note: if we shift by the shift size, then there is always one sync location\n    // m_ShiftSize away from the end of the buffer that requires syncing.  this\n    // sync location is tied to the last window and has the same state as the prior\n    // sync location; however to make tracking simplier, we initialize this last\n    // window state as always ready\n    m_State.resize(m_WindowCount + 1);\n    for (std::size_t i = 0; i < m_WindowCount + 1; i++)\n    {\n        ResetWindow(i);\n    }\n}\n\nCyclicBuffer::~CyclicBuffer()\n{\n    Sync();\n}\n\nCyclicBuffer::SyncFn CyclicBuffer::AppendData(void* ptr, std::size_t size)\n{\n    // copy incoming data to the buffer\n    // data will be copied in chunks upto the size of each window\n    // windows will be computed when completed\n    // this maps well to a cuda architecture of where the copy/compute\n    // of one window can be overlapped with the copy of the next window\n    // this call blocks until all the data has been copied to the buffer\n    // the Free() method drives forward progress to reclaim buffer space\n    // from windows that have completed their callbacks\n    VLOG(1) << \"AppendData: \" << size << \" bytes to buffer at offset \" << Offset(m_CurrentLocation);\n    std::uintptr_t data      = reinterpret_cast<std::uintptr_t>(ptr);\n    auto           remaining = size;\n    while (remaining)\n    {\n        auto chunk_size = std::min(remaining, Free());\n        CopyToHead(data, chunk_size);\n        data += chunk_size;\n        remaining -= chunk_size;\n    }\n    return FinishedAppendingData();\n}\n\nstd::size_t CyclicBuffer::Free()\n{\n    // compute the available free space remainining in the current window\n    DCHECK_LE(m_WindowStart, m_CurrentLocation);\n    DCHECK_LE(m_CurrentLocation, m_SyncLocation);\n\n    if (m_CurrentLocation == m_SyncLocation)\n    {\n        SyncWindow(m_SyncWindow, true);\n        m_SyncLocation += m_ShiftSize;\n        m_SyncWindow++;\n    }\n\n    if (m_PreferFullWindows) // prefer full windows\n    {\n        auto next_window_start = m_WindowStart + m_WindowSize;\n        while (m_SyncLocation < next_window_start)\n        {\n            SyncWindow(m_SyncWindow, true);\n            m_SyncLocation += m_ShiftSize;\n            m_SyncWindow++;\n        }\n    }\n\n    auto free_current_window = m_WindowSize - (m_CurrentLocation - m_WindowStart);\n    auto free_synced         = m_SyncLocation - m_CurrentLocation;\n    auto free                = std::min(free_current_window, free_synced);\n    VLOG(2) << free << \" free bytes available in current window; \" << free_current_window - free << \" bytes require syncing\";\n    return free;\n}\n\nvoid CyclicBuffer::ReplicateData()\n{\n    VLOG(2) << \"Replicating data from offset \" << Offset(m_ReplicationStart) << \"-\" << Offset(m_Data + m_Size) << \" to head\";\n    DCHECK_EQ(m_CurrentLocation, m_Data); // ensure we are at the start\n    std::uintptr_t data      = m_ReplicationStart;\n    auto           remaining = m_WindowSize - m_ShiftSize;\n    while (remaining)\n    {\n        auto chunk_size = std::min(remaining, Free());\n        ReplicateToHead(data, chunk_size);\n        data += chunk_size;\n        remaining -= chunk_size;\n    }\n    DCHECK_EQ(m_CurrentLocation, m_NextPassStart);\n}\n\nvoid CyclicBuffer::ReplicateToHead(std::uintptr_t data, std::size_t size)\n{\n    auto dst = reinterpret_cast<void*>(m_CurrentLocation);\n    auto src = reinterpret_cast<void*>(data);\n    VLOG(3) << \"Replicating \" << size << \" bytes from \" << Offset(data) << \" to cyclic buffer @ \" << Offset(m_CurrentLocation);\n    Replicate(dst, src, size);\n    m_CurrentLocation += size;\n    DCHECK_LE(m_CurrentLocation, m_SyncLocation);\n}\n\nvoid CyclicBuffer::CopyToHead(std::uintptr_t data, std::size_t size)\n{\n    // copy bytes to current location\n    // if a window is complete, kick off the execution callback\n    auto dst = reinterpret_cast<void*>(m_CurrentLocation);\n    auto src = reinterpret_cast<void*>(data);\n    VLOG(2) << \"Copying \" << size << \" bytes to offset \" << Offset(m_CurrentLocation);\n    Copy(dst, src, size);\n    m_CurrentLocation += size;\n    DCHECK_LE(m_CurrentLocation, m_SyncLocation);\n\n    ExecuteWindows();\n}\n\nvoid CyclicBuffer::ExecuteWindows()\n{\n    while (m_CurrentLocation - m_WindowStart >= m_WindowSize)\n    {\n        VLOG(1) << \"Run Callback on Window \" << m_CurrentWindow << \"; offset: \" << Offset(m_WindowStart);\n        auto data = reinterpret_cast<void*>(m_WindowStart);\n        RunCallback(data, m_WindowSize);\n        m_WindowStart += m_ShiftSize;\n    }\n\n    if (m_CurrentLocation - m_Data == m_Size)\n    {\n        VLOG(2) << \"CyclicBuffer hit end of stack; resetting stack\";\n        m_CurrentLocation = m_Data;\n        m_WindowStart     = m_Data;\n        m_SyncLocation    = m_Data;\n        m_SyncWindow      = 0;\n        m_NextPassStart   = m_Data + (m_WindowSize - m_ShiftSize);\n        // we haven't actually replicated the data from the last window\n        // the first time we append data to window0, we first must sync on it\n        // that ensures we can overwrite the data in window0 with the replicated\n        // data first, then the new data to append\n\n        // before we can reuse the buffer, we must replicate the last bits to the head\n        if (m_CurrentLocation < m_NextPassStart)\n        {\n            DCHECK_EQ(m_ReplicationStart + m_ShiftSize, m_Data + m_Size);\n            ReplicateData();\n        }\n    }\n}\n\nvoid CyclicBuffer::RunCallback(const void* data, std::size_t size)\n{\n    auto window            = m_CurrentWindow % m_WindowCount;\n    m_State[window].status = WindowStatus::Running;\n    m_State[window].syncfn = m_Callback(m_CurrentWindow, data, size);\n    DCHECK(m_State[window].syncfn);\n    m_CurrentWindow++;\n}\n\nbool CyclicBuffer::SyncWindow(std::size_t window, bool wait)\n{\n    VLOG(3) << \"SyncWindow: \" << window << \"; wait=\" << (wait ? \"TRUE\" : \"FALSE\");\n    const auto& state = m_State[window];\n    switch (state.status)\n    {\n    case WindowStatus::Ready:\n    case WindowStatus::Finished:\n        VLOG(2) << \"SyncWindow \" << window << \" Completed: Synced == TRUE\";\n        return true;\n    case WindowStatus::Running:\n        bool finished = m_State[window].syncfn(wait);\n        VLOG(2) << \"SyncWindow \" << window << \" Completed: Synced == \" << (finished ? \"TRUE\" : \"FALSE\");\n        if (finished)\n        {\n            ResetWindow(window);\n        }\n        return finished;\n    };\n\n    LOG(FATAL) << \"should not be reachable \" << window;\n    return false;\n}\n\nvoid CyclicBuffer::ResetWindow(std::size_t window)\n{\n    auto& state  = m_State[window];\n    state.status = WindowStatus::Finished;\n    state.syncfn = nullptr;\n}\n\nvoid CyclicBuffer::Sync()\n{\n    for (std::size_t i = 0; i < m_State.size(); i++)\n    {\n        SyncWindow(i, true);\n    }\n}\n\nvoid CyclicBuffer::PreferFullWindows(bool val)\n{\n    m_PreferFullWindows = val;\n}"
  },
  {
    "path": "trtlab/core/src/cyclic_windowed_buffer.cc",
    "content": "\n#include <algorithm>\n#include <queue>\n\n#include \"cyclic_windowed_buffer.h\"\n\n#include <glog/logging.h>\n\nusing namespace trtlab;\nusing namespace detail;\n\ncyclic_windowed_buffer::cyclic_windowed_buffer() : m_window_size(0), m_window_count(0), m_shift_size(0), m_capacity(0) {}\n\ncyclic_windowed_buffer::cyclic_windowed_buffer(memory::descriptor md, std::size_t window_size, std::size_t overlap)\n: m_descriptor(std::move(md)), m_window_size(window_size), m_shift_size(window_size - overlap)\n{\n    CHECK_LE(window_size, m_descriptor.size()) << \"allocated memory must be >= the window_size\";\n    CHECK_LT(overlap, window_size) << \"requested overlap=\" << overlap << \"; must be [0 <= overlap < \" << window_size << \")\";\n\n    m_window_count = (m_descriptor.size() - m_window_size) / m_shift_size + 1;\n    DVLOG(1) << \"Allocation of \" << m_descriptor.size() << \" bytes allows for \" << m_window_count << \" cyclic buffer windows\";\n\n    m_capacity = m_window_size + (m_window_count - 1) * m_shift_size;\n    DVLOG(2) << \"Effective allocation size \" << m_capacity << \" usable bytes\";\n\n    DVLOG(2) << \"window_size: \" << m_window_size << \"; shift_size: \" << m_shift_size;\n}\n\ncyclic_windowed_buffer::cyclic_windowed_buffer(cyclic_windowed_buffer&& other) noexcept\n: m_descriptor(std::move(other.m_descriptor)),\n  m_window_size(std::exchange(other.m_window_size, 0UL)),\n  m_shift_size(std::exchange(other.m_shift_size, 0UL)),\n  m_window_count(std::exchange(other.m_window_count, 0UL)),\n  m_capacity(std::exchange(other.m_capacity, 0UL))\n{\n}\n\ncyclic_windowed_buffer& cyclic_windowed_buffer::operator=(cyclic_windowed_buffer&& other) noexcept\n{\n    m_descriptor   = std::move(other.m_descriptor);\n    m_window_size  = std::exchange(other.m_window_size, 0UL);\n    m_shift_size   = std::exchange(other.m_shift_size, 0UL);\n    m_window_count = std::exchange(other.m_window_count, 0UL);\n    m_capacity     = std::exchange(other.m_capacity, 0UL);\n    return *this;\n}\n\n\nstd::size_t cyclic_windowed_buffer::min_allocation_size(std::size_t window_count, std::size_t window_size, std::size_t overlap)\n{\n    CHECK_GT(window_count, 0);\n    CHECK_GT(window_size, overlap);\n    return window_size + (window_count - 1) * (window_size - overlap);\n}\n\n// stack impl\n\ncyclic_windowed_stack_impl::cyclic_windowed_stack_impl() : m_end(nullptr), m_data_top(nullptr), m_sync_top(nullptr), m_win_top(nullptr), m_win_counter(0) {}\n\ncyclic_windowed_stack_impl::cyclic_windowed_stack_impl(memory::descriptor md, std::size_t window_size, std::size_t overlap)\n: cyclic_windowed_buffer(std::move(md), window_size, overlap),\n  m_end(data() + capacity()),\n  m_data_top(data()),\n  m_sync_top(m_end),\n  m_win_top(data()),\n  m_win_counter(0)\n{\n}\n\n/*\ncyclic_windowed_stack_impl::cyclic_windowed_stack_impl(cyclic_windowed_buffer&& buffer)\n: cyclic_windowed_buffer(std::move(buffer)),\n  m_end(data() + capacity()),\n  m_data_top(data()),\n  m_sync_top(m_end),\n  m_win_top(data()),\n  m_win_counter(0)\n{\n}\n*/\n\n\ncyclic_windowed_stack_impl::cyclic_windowed_stack_impl(cyclic_windowed_stack_impl&& other) noexcept\n: cyclic_windowed_buffer(std::move(other)),\n  m_end(std::exchange(other.m_end, nullptr)),\n  m_data_top(std::exchange(other.m_data_top, nullptr)),\n  m_sync_top(std::exchange(other.m_sync_top, nullptr)),\n  m_win_top(std::exchange(other.m_win_top, nullptr)),\n  m_win_counter(std::exchange(other.m_win_counter, 0UL))\n{\n}\n\ncyclic_windowed_stack_impl& cyclic_windowed_stack_impl::operator=(cyclic_windowed_stack_impl&& other) noexcept\n{\n    cyclic_windowed_buffer::operator=(std::move(other));\n    m_end                           = std::exchange(other.m_end, nullptr);\n    m_data_top                      = std::exchange(other.m_data_top, nullptr);\n    m_sync_top                      = std::exchange(other.m_sync_top, nullptr);\n    m_win_top                       = std::exchange(other.m_win_top, nullptr);\n    m_win_counter                   = std::exchange(other.m_win_counter, 0UL);\n    return *this;\n}\n\n\nstd::size_t cyclic_windowed_stack_impl::available() const noexcept\n{\n    DCHECK_GE(offset(m_data_top), 0);\n    DCHECK_LE(offset(m_data_top), capacity());\n    DCHECK_GE(offset(m_sync_top), shift_size());\n    DCHECK_LE(offset(m_sync_top), capacity());\n    //DCHECK_EQ(offset(m_sync_top) % overlap_size(), 0);\n    DCHECK_GE(offset(m_win_top), 0);\n    DCHECK_LE(offset(m_win_top), capacity() - window_size());\n    //DCHECK_EQ(offset(m_win_top) % overlap_size(), 0);\n\n    DCHECK_LE(offset(m_data_top), offset(m_sync_top));\n\n    std::ptrdiff_t avail     = m_sync_top - m_data_top;\n    std::ptrdiff_t in_use    = m_data_top - m_win_top;\n    std::ptrdiff_t remaining = window_size() - in_use;\n\n    return std::min(avail, remaining);\n}\n\nvoid cyclic_windowed_stack_impl::push_window(std::function<void()> sync)\n{\n    DVLOG(1) << \"push window: \" << window_id() << \" - start offset = \" << offset(m_win_top);\n    DCHECK_GE(offset(m_data_top), 0);\n    DCHECK_LE(offset(m_data_top), capacity());\n    DCHECK_GE(offset(m_sync_top), shift_size());\n    DCHECK_LE(offset(m_sync_top), capacity());\n    //DCHECK_EQ(offset(m_sync_top) % overlap_size(), 0);\n    DCHECK_GE(offset(m_win_top), 0);\n    DCHECK_LE(offset(m_win_top), capacity() - window_size());\n    //DCHECK_EQ(offset(m_win_top) % overlap_size(), 0);\n\n    DVLOG(1) << \"push window: \" << window_id() << \" - start offset = \" << offset(m_win_top);\n\n    // record win_start and sync function for the current window\n    m_sync.push(std::make_pair(m_win_top, sync));\n\n    // move data pointer to end of current window\n    m_data_top = m_win_top + window_size();\n\n    // push window pointer\n    m_win_top += shift_size();\n\n    // if we are at the end, then recycle\n    if (m_data_top == m_end)\n    {\n        recycle_buffer();\n    }\n\n    // ensure the next window is free\n    while (m_sync_top < m_win_top + window_size())\n    {\n        sync_and_shift();\n    }\n\n    DVLOG(3) << \"push window complete\";\n\n    // increrement win_count;\n    m_win_counter++;\n}\n\nstd::size_t cyclic_windowed_stack_impl::push_data(const void* src, std::size_t bytes)\n{\n    DCHECK_LE(m_data_top + bytes, m_sync_top);\n    DCHECK_LE(m_data_top + bytes, m_win_top + window_size());\n\n    // copy data to buffer\n    copy(m_data_top, src, bytes);\n\n    // push data stack\n    m_data_top += bytes;\n\n    // if we completed a window, trigger an event\n    if (m_data_top == m_win_top + window_size())\n    {\n        on_window_complete_event(window_id(), m_win_top, window_size());\n    }\n\n    return bytes;\n}\n\nvoid cyclic_windowed_stack_impl::sync_and_shift()\n{\n    DCHECK_GE(offset(m_sync_top), 0);\n    DCHECK_LE(offset(m_sync_top), capacity());\n    //DCHECK_EQ(offset(m_sync_top) % shift_size(), 0);\n\n    auto [start, syncfn] = m_sync.front();\n    m_sync.pop();\n\n    DCHECK_EQ(offset(start), offset(m_sync_top));\n    DVLOG(2) << \"sync next window - starting window offset = \" << offset(start);\n\n    // call sync function\n    if (syncfn)\n    {\n        syncfn();\n    }\n\n    // push sync stack\n    m_sync_top += shift_size();\n\n    // the replication window does not need to be sync'd\n    // no window starts at end - shift_size\n    // that winwdow would overflow the buffer\n    if (m_sync_top == m_end - overlap_size())\n    {\n        m_sync_top = m_end;\n    }\n}\n\nvoid cyclic_windowed_stack_impl::recycle_buffer()\n{\n    DVLOG(2) << \"end of buffer - recycle\";\n    DCHECK_EQ(m_data_top, m_end);\n\n    // to keep the logic clean, we are going to push a no-op sync\n\n    // reset stack pointers\n    m_data_top = m_sync_top = m_win_top = data();\n\n    if (overlap_size())\n    {\n        DVLOG(2) << \"replicating \" << overlap_size() << \" bytes from the end to the beginning\";\n\n        // make space for the replicated data by syncing on windows from the last pass\n        while (m_sync_top <= data() + overlap_size())\n        {\n            sync_and_shift();\n        }\n\n        // copy overlap_size bytes from the end to the beginning\n        replicate(m_data_top, m_end - overlap_size(), overlap_size());\n\n        // move data top to after the replicated data\n        m_data_top += overlap_size();\n    }\n    DVLOG(3) << \"recycle complete\";\n}\n\nvoid cyclic_windowed_stack_impl::reset()\n{\n    while (!m_sync.empty())\n    {\n        auto [start, syncfn] = m_sync.front();\n        if (syncfn)\n        {\n            syncfn();\n        }\n        m_sync.pop();\n    }\n\n    m_data_top    = data();\n    m_sync_top    = m_end;\n    m_win_top     = data();\n    m_win_counter = 0;\n}\n\n// reservation\n"
  },
  {
    "path": "trtlab/core/src/memory/copy.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/copy.h\"\n\n#include <cstring>\n#include <glog/logging.h>\n\nnamespace trtlab {\n\nvoid Copy(HostMemory& dst, size_t dst_offset, const HostMemory& src, size_t src_offset, size_t size)\n{\n    CHECK_LE(size, dst.Size() - dst_offset) << \"Copy: dst range is invalid\";\n    CHECK_LE(size, src.Size() - src_offset) << \"Copy: src range is invalid\";\n    std::memcpy(dst[dst_offset], src[src_offset], size);\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/src/memory/host_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/host_memory.h\"\n\n#include <cstring>\n\n#include <glog/logging.h>\n\nnamespace trtlab {\n\n// HostMemory\n\nsize_t HostMemory::DefaultAlignment() { return 64; }\n\nDLContext HostMemory::DeviceContext()\n{\n    DLContext ctx;\n    ctx.device_type = kDLCPU;\n    ctx.device_id = 0;\n    return ctx;\n}\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/core/src/memory/malloc.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/malloc.h\"\n\n#include <foonathan/memory/namespace_alias.hpp>\n#include <foonathan/memory/error.hpp>\n\n\n#include <glog/logging.h>\n\nnamespace trtlab {\n\nvoid* Malloc::Allocate(size_t size)\n{\n    void* ptr = std::malloc(size);\n    CHECK(ptr) << \"malloc(\" << size << \") failed\";\n    return ptr;\n}\n\nstd::function<void()> Malloc::Free()\n{\n    CHECK(Data());\n    CHECK(Size());\n    return [ptr = Data(), size = Size()] {\n        DLOG(INFO) << \"Malloc: free \" << ptr << \"; size: \" << size;\n        free(ptr);\n    };\n}\n\nconst char* Malloc::TypeName() const\n{\n    return \"Malloc\";\n}\n\n} // namespace trtlab\n\nnamespace foonathan { namespace memory { \n\nmemory::allocator_info detail::MallocAllocatorImpl::info() noexcept\n{\n        return {\"trtlab::MallocAllocator\", nullptr};\n}\n\ntemplate class memory::detail::lowlevel_allocator<detail::MallocAllocatorImpl>;\ntemplate class memory::allocator_traits<MallocAllocator>;\n\n}}\n"
  },
  {
    "path": "trtlab/core/src/memory/memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/memory.h\"\n#include \"trtlab/core/utils.h\"\n\n#include <cstring>\n#include <glog/logging.h>\n\nnamespace trtlab {\n\nCoreMemory::CoreMemory() : m_Size(0), m_Capacity(0), m_Stride1(1)\n{\n    m_Handle.data = nullptr;\n    m_Handle.ndim = 0;\n    m_Handle.shape = &m_Size;\n    m_Handle.strides = &m_Stride1;\n    m_Handle.dtype.code = kDLUInt;\n    m_Handle.dtype.bits = 8U;\n    m_Handle.dtype.lanes = 1U;\n    m_Handle.ctx.device_type = kDLCPU;\n    m_Handle.ctx.device_id = 0;\n    m_Handle.byte_offset = 0;\n}\n\nCoreMemory::CoreMemory(void* ptr, mem_size_t size) : CoreMemory() { SetDataAndSize(ptr, size); }\n\nvoid CoreMemory::SetDataAndSize(void* ptr, mem_size_t size)\n{\n    m_Handle.data = ptr;\n    m_Handle.ndim = 1U;\n    m_Size = size;\n    m_Capacity = size;\n}\n\nCoreMemory::CoreMemory(void* ptr, mem_size_t size, const CoreMemory& mem) : CoreMemory(ptr, size)\n{\n    if(!mem.ContiguousBytes())\n    {\n        throw std::runtime_error(\n            \"CoreMemory ctor required the reference to be a contiguous bytearray\");\n    }\n    m_Handle.ctx = mem.m_Handle.ctx;\n}\n\nCoreMemory::CoreMemory(const DLTensor& handle) : CoreMemory() { SetHandle(handle); }\n\nCoreMemory::CoreMemory(CoreMemory&& other) noexcept\n    : m_Deleter(std::exchange(other.m_Deleter, nullptr))\n{\n    SetHandle(other.m_Handle);\n    other.m_Handle = DLTensor();\n    other.m_Size = 0;\n    other.m_Capacity = 0;\n}\n\nCoreMemory::CoreMemory(void* ptr, std::vector<int64_t> shape, const types::dtype& dt)\n{\n    DCHECK(ptr);\n    DCHECK(shape.size());\n\n    m_Handle.data = ptr;\n    m_Handle.ndim = shape.size();\n    m_Handle.dtype = dt.to_dlpack();\n\n    if(m_Handle.ndim == 1)\n    {\n        m_Size = m_Capacity = shape[0];\n        m_Handle.shape = &m_Size;\n    }\n    else\n    {\n        m_Size = m_Capacity = SizeFromShape(shape, dt.bytes());\n        m_Shape = shape;\n        m_Handle.shape = &m_Shape[0];\n    }\n}\n\nCoreMemory::~CoreMemory()\n{\n    if(m_Deleter)\n    {\n        DLOG(INFO) << \"Deallocating ptr: \" << m_Handle.data;\n        m_Deleter();\n    }\n}\n\ntypes::dtype CoreMemory::DataType() const { return types::dtype(m_Handle.dtype); }\n\nstd::vector<int64_t> CoreMemory::Shape() const\n{\n    if(m_Handle.ndim == 1)\n    {\n        std::vector<int64_t> shape = {m_Size};\n        return shape;\n    }\n    return m_Shape;\n}\n\nstd::vector<int64_t> CoreMemory::Strides() const\n{\n    if(m_Handle.ndim == 1)\n    {\n        std::vector<int64_t> strides = {m_Handle.strides[0]};\n        return strides;\n    }\n    return m_Strides;\n}\n\nvoid CoreMemory::Reshape(const std::vector<int64_t>& shape) { Reshape(shape, DataType()); }\n\nvoid CoreMemory::Reshape(const std::vector<int64_t>& shape, const types::dtype& dt)\n{\n    SetShape(shape, dt, true);\n}\n\nvoid CoreMemory::SetShape(const std::vector<int64_t>& shape, const types::dtype& dt,\n                          bool check_size)\n{\n    DCHECK(shape.size());\n    DCHECK(dt.bytes());\n\n    auto size = SizeFromShape(shape, dt.bytes());\n    if(check_size && size > m_Capacity)\n    {\n        throw std::length_error(\"Reshape exceeds capacity\");\n    }\n\n    m_Handle.ndim = shape.size();\n    m_Handle.dtype = dt.to_dlpack();\n    m_Handle.shape = nullptr;\n    m_Size = size;\n\n    if(shape.size() == 1)\n    {\n        m_Handle.shape = &m_Size;\n    }\n    else\n    {\n        m_Shape = shape;\n        m_Handle.shape = &m_Shape[0];\n    }\n\n    // set strides for fortran column major\n    m_Strides.resize(m_Handle.ndim);\n    m_Handle.strides = &m_Strides[0];\n    int64_t offset = 1;\n    for(int i=1; i<=m_Handle.ndim; i++)\n    {\n        m_Strides[m_Handle.ndim - i] = offset;\n        offset *= shape[m_Handle.ndim - i];\n    }\n}\n\nvoid CoreMemory::ReshapeToBytes() { Reshape({Capacity()}, types::bytes); }\n\nvoid* CoreMemory::operator[](size_t offset)\n{\n    CHECK_LE(offset, Size());\n    return static_cast<void*>(static_cast<char*>(Data()) + offset);\n}\n\nconst void* CoreMemory::operator[](size_t offset) const\n{\n    CHECK_LE(offset, Size());\n    return static_cast<const void*>(static_cast<const char*>(Data()) + offset);\n}\n\nvoid CoreMemory::SetHandle(const DLTensor& handle)\n{\n    m_Handle = handle;\n    if(handle.ndim == 1)\n    {\n        m_Capacity = m_Size = handle.shape[0] * SizeOfDataType();\n        m_Handle.shape = &m_Size;\n    }\n    else\n    {\n        m_Shape.resize(handle.ndim);\n        m_Handle.shape = &m_Shape[0];\n        std::memcpy(m_Handle.shape, handle.shape, handle.ndim * sizeof(int64_t));\n        m_Size = SizeFromShape(m_Shape, SizeOfDataType());\n        m_Capacity = m_Size;\n    }\n    if(handle.strides)\n    {\n        m_Strides.resize(handle.ndim);\n        m_Handle.strides = &m_Strides[0];\n        std::memcpy(m_Handle.strides, handle.strides, handle.ndim * sizeof(int64_t));\n        // compute capacity from strides\n        mem_size_t itemsize = DataType().bytes();\n        mem_size_t offset_to_end = itemsize;\n        const auto& shape = Shape();\n        for(int i = 0; i < m_Handle.ndim; i++)\n        {\n            offset_to_end += m_Strides[i] * (shape[i] - 1) * itemsize;\n        }\n        m_Capacity = offset_to_end;\n    }\n}\n\nmem_size_t CoreMemory::SizeOfDataType() const\n{\n    return ((mem_size_t)m_Handle.dtype.bits * (mem_size_t)m_Handle.dtype.lanes + 7) / 8;\n}\n\nbool CoreMemory::ContiguousBytes() const\n{\n    return ((m_Handle.ndim == 1) && (m_Size == m_Capacity) && (DataType() == types::bytes));\n}\n\nmem_size_t CoreMemory::SizeFromShape(const std::vector<mem_size_t>& shape, mem_size_t sizeof_dtype)\n{\n    mem_size_t size = std::accumulate(std::begin(shape), std::end(shape), mem_size_t(1),\n                                      std::multiplies<mem_size_t>());\n    size *= sizeof_dtype;\n    return size;\n}\n\nstd::string CoreMemory::Description() const\n{\n    std::ostringstream os;\n    // clang-format off\n    os << \"[\" << TypeName();\n    if(m_Handle.ctx.device_type == kDLGPU) { os << \" gpu:\" << m_Handle.ctx.device_id; }\n    os << \" \" << m_Handle.data << \"; shape: (\";\n    for(int i=0; i< m_Handle.ndim; i++) { os << (i ? \",\" : \"\") << m_Handle.shape[i]; }\n    os << \"); strides: (\";\n    for(int i=0; i< m_Handle.ndim; i++) { os << (i ? \",\" : \"\") << m_Handle.strides[i]; }\n    os << \"); dtype: \" << DataType() << \"; size: \" << BytesToString(Size());\n    if(Size() != Capacity()) { os << \"; capacity: \" << BytesToString(Capacity()); }\n    os << \"]\";\n    // clang-format on\n    return os.str();\n}\n\nstd::ostream& operator<<(std::ostream& os, const CoreMemory& core)\n{\n    // clang-format off\n    os << core.Description();\n    return os;\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/src/memory/sysv_allocator.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/sysv_allocator.h\"\n\n#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <sys/types.h>\n\n#include <map>\n#include <mutex>\n\n#include <glog/logging.h>\n\n#include \"trtlab/core/memory/block_arena.h\"\n#include \"trtlab/core/memory/block_manager.h\"\n\nnamespace foonathan {\nnamespace memory {\nnamespace trtlab {\nnamespace sysv_detail {\n\n    struct sysv_allocation final : memory_block\n    {\n        sysv_allocation() : memory_block(), shm_id(-1), release(true) {}\n        sysv_allocation(int id, void* mem, size_t size, bool rel = true)\n            : shm_id(id), memory_block(mem, size), release(rel) {}\n\n        sysv_allocation(const sysv_allocation&) = default;\n        sysv_allocation& operator=(const sysv_allocation&) = default;\n\n        sysv_allocation(sysv_allocation&& other)\n            : shm_id(std::exchange(other.shm_id, -1)),\n              release(other.shm_id),\n              memory_block(std::move(other)) {}\n\n        sysv_allocation& operator=(sysv_allocation&& other)\n        {\n            shm_id = std::exchange(other.shm_id, -1);\n            release = other.release;\n            memory_block::operator=(std::move(other));\n            return *this;\n        }\n\n        int shm_id;\n        bool release;\n    };\n\n    class sysv_manager final\n    {\n      public:\n        ~sysv_manager()\n        {\n            // warn or remove registered sysv segments depending on settings\n            DVLOG(1) << \"sysv_manager shutting down\";\n            if(m_manager.size())\n            {\n                LOG(WARNING) << \"Detected SysV allocations that were not deallocated\";\n                m_manager.for_each_block([](sysv_allocation& block) {\n                    DVLOG(3) << \"detaching block - ptr: \" << block.memory << \"; shm_id: \" << block.shm_id;\n                    sysv_manager::detach(block.memory);\n                });\n            }\n        }\n\n        static const sysv_allocation& allocate(std::size_t size)\n        {\n            auto shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0666);\n            DVLOG(2) << \"creating shmid: \" << shm_id << \"; size=\" << size;\n            if(shm_id == -1) { throw std::bad_alloc(); }\n            return sysv_manager::attach_impl(shm_id, true);\n        }\n\n        static const sysv_allocation& attach(int shm_id)\n        {\n            return sysv_manager::attach_impl(shm_id, false);\n        }\n\n        static int detach(void* addr)\n        {\n            auto& manager = sysv_manager::global_manager();\n            auto shm_id = manager.drop_allocation(addr);\n\n            if(shm_id > 0)\n            {\n                auto stats = sysv_manager::get_stats(shm_id);\n                if(!(stats.shm_perm.mode & SHM_DEST)) { sysv_manager::release(shm_id); }\n            }\n\n            auto rc = shmdt(addr);\n            DCHECK_EQ(rc, 0) << \"errno: \"  << errno;\n            if(rc != 0) { throw std::runtime_error(\"shmdt failed\"); }\n        }\n\n        static void release(int shm_id)\n        {\n            // check if the segment has been marked for release/destruction\n            auto stats = sysv_manager::get_stats(shm_id); \n            if(stats.shm_perm.mode & SHM_DEST) \n            {\n                DVLOG(3) << \"shm_id: \" << shm_id << \" already marked for removal\";\n                return; \n            }\n\n            // otherwise mark it for release/destruction\n            auto rc = shmctl(shm_id, IPC_RMID, &stats);\n            DCHECK_EQ(rc, 0) << \"shmctl failed; errno: \" << errno;\n            if(rc != 0) { throw std::runtime_error(\"unable to release shm_id\"); }\n            DVLOG(3) << \"shm_id: \" << shm_id << \" marked as removed\";\n        }\n\n        static std::size_t size(int shm_id)\n        {\n            auto stats = sysv_manager::get_stats(shm_id);\n            return stats.shm_segsz;\n        }\n\n        static bool release_on_deallocate()\n        {\n            auto& manager = sysv_manager::global_manager();\n            std::lock_guard<std::mutex> lock(manager.m_mutex);\n            return manager.m_release_on_deallocate;\n        }\n\n        static bool release_on_deallocate(bool val)\n        {\n            auto& manager = sysv_manager::global_manager();\n            std::lock_guard<std::mutex> lock(manager.m_mutex);\n            manager.m_release_on_deallocate = val;\n            return manager.m_release_on_deallocate;\n        }\n\n        static sysv_info sysv_info_for_pointer(void* ptr)\n        {\n            auto& manager = sysv_manager::global_manager();\n            std::lock_guard<std::mutex> lock(manager.m_mutex);\n            auto block = manager.m_manager.find_block(ptr);\n            if(block && block->contains(ptr))\n            {\n                DCHECK_NE(block->shm_id, -1);\n                auto stats = sysv_manager::get_stats(block->shm_id);\n                bool released = stats.shm_perm.mode & SHM_DEST;\n                return {block->shm_id, block->size, block->distance(ptr), stats.shm_nattch, !released};\n            }\n            throw std::runtime_error(\"no sysv info found for pointer\");\n        }\n\n     private:\n        sysv_manager() : m_release_on_deallocate(true) {}\n\n        sysv_manager(const sysv_manager&) = delete;\n        sysv_manager& operator=(const sysv_manager&) = delete;\n\n        sysv_manager(sysv_manager&&) = delete;\n        sysv_manager& operator=(sysv_manager&&) = delete;\n\n        static sysv_manager& global_manager()\n        {\n            static sysv_manager manager;\n            return manager;\n        }\n\n        static const sysv_allocation& attach_impl(int shm_id, bool has_ownership)\n        {\n            DVLOG(2) << \"attaching to shm_id: \" << shm_id;\n            auto stats = sysv_manager::get_stats(shm_id);\n            if(stats.shm_perm.mode & SHM_DEST) { throw std::bad_alloc(); }\n            auto ptr = shmat(shm_id, nullptr, 0);\n            if(ptr == (void*)-1) { throw std::bad_alloc(); }\n            auto& manager = sysv_manager::global_manager();\n            return manager.register_allocation(shm_id, ptr, sysv_manager::size(shm_id), has_ownership);\n        }\n\n        static struct shmid_ds  get_stats(int shm_id)\n        {\n            struct shmid_ds stats;\n            auto rc = shmctl(shm_id, IPC_STAT, &stats);\n            DCHECK_EQ(rc, 0);\n            if(rc != 0) throw std::runtime_error(\"no sysv info found for pointer\");\n            return stats;\n        }\n\n        const sysv_allocation& register_allocation(int shm_id, void* addr, std::size_t size, bool has_ownership)\n        {\n            // ownership and release on deallocate need to be true for a sysv segment to be removed\n            // allocate -> has_ownership == true\n            // attach   -> has_ownership == false\n            std::lock_guard<std::mutex> lock(m_mutex);\n            DVLOG(3) << this << \": registering shmd_id: \" << shm_id << \"; addr: \" << addr << \"; size: \" << size;\n            return m_manager.add_block({shm_id, addr, size, m_release_on_deallocate && has_ownership});\n        }\n\n        int drop_allocation(void* addr)\n        {\n            std::lock_guard<std::mutex> lock(m_mutex);\n            int shm_id = -1;\n            auto block = m_manager.find_block(addr);\n            DCHECK(block);\n            if(block)\n            {\n                DVLOG(3) << this << \": dropping sysv allocation containing \" << addr;\n                m_manager.drop_block(addr);\n                if(block->release) { shm_id = block->shm_id; }\n            }\n            DVLOG(3) << this << \": \" << addr << \" maps to shm_id \" << shm_id;\n            return shm_id;\n        }\n\n        std::mutex m_mutex;\n        block_manager<sysv_allocation> m_manager;\n        bool m_release_on_deallocate;\n    };\n\n} // namesapce sysv_detail\n\n    void* sysv_allocator::allocate_node(std::size_t size, std::size_t)\n    {\n        DVLOG(1) << \"sysv::allocate_node - \" << size;\n        const auto& allocation = sysv_detail::sysv_manager::allocate(size);\n        return allocation.memory;\n    }\n\n    void sysv_allocator::deallocate_node(void* ptr, std::size_t, std::size_t)\n    {\n        DVLOG(1) << \"sysv::deallocate_node - \" << ptr;\n        sysv_detail::sysv_manager::detach(ptr);\n    }\n\n    void* sysv_allocator::attach(int shm_id)\n    {\n        DVLOG(1) << \"sysv::attach - \" << shm_id;\n        const auto& allocation = sysv_detail::sysv_manager::attach(shm_id);\n        return allocation.memory;\n    }\n\n    void sysv_allocator::release(int shm_id)\n    {\n        DVLOG(1) << \"sysv::release - \" << shm_id;\n        sysv_detail::sysv_manager::release(shm_id);\n\n    }\n\n    sysv_info sysv_allocator::sysv_info_for_pointer(void* ptr)\n    {\n        return sysv_detail::sysv_manager::sysv_info_for_pointer(ptr);\n    }\n\n    bool sysv_allocator::release_on_deallocate()\n    {\n        return sysv_detail::sysv_manager::release_on_deallocate();\n    }\n\n    bool sysv_allocator::release_on_deallocate(bool val)\n    {\n        return sysv_detail::sysv_manager::release_on_deallocate(val);\n    }\n\n} // namespace trtlab\n} // namespace memory\n} // namespace foonathan"
  },
  {
    "path": "trtlab/core/src/memory/tensor_shape.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/tensor_shape.h\"\n\n#include <glog/logging.h>\n\nnamespace trtlab {\n\nvoid TensorShapeGeneric::Initialize()\n{\n    CheckShape();\n    if(m_Strides.size() == 0) { SetStridesCompactRowMajor(); }\n    ValidateDimensions();\n}\n\nvoid TensorShapeGeneric::CheckShape()\n{\n    if(m_Shape.size() == 0)\n    {\n        throw std::runtime_error(\"Shape must have at least a dimension of 1\");\n    }\n    for(const auto& d : m_Shape)\n    {\n        if(d <= 0)\n        {\n            throw std::runtime_error(\"Negative dimensions in Shape is not allowed\");\n        }\n    }\n}\n\nvoid TensorShapeGeneric::ValidateDimensions()\n{\n    if(m_Shape.size() != m_Strides.size())\n    {\n        throw std::runtime_error(\"Shape and Strides must be of the same dimension\");\n    }\n\n    if(Size())\n    {\n        for(int i = 0; i < m_Shape.size(); i++)\n        {\n            m_Items += (m_Shape[i] - 1) * m_Strides[i];\n        }\n        m_Items++;\n    }\n}\n\nvoid TensorShapeGeneric::SetStridesCompactRowMajor()\n{\n    m_Strides.resize(m_Shape.size());\n\n    int64_t offset = 1;\n    for(int i = 1; i <= m_Shape.size(); i++)\n    {\n        m_Strides[m_Shape.size() - i] = offset;\n        offset *= m_Shape[m_Shape.size() - i];\n    }\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/src/types.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/types.h\"\n\n#include <glog/logging.h>\n\nnamespace trtlab {\nnamespace types {\n\ndtype::dtype(const DLDataType& dlpack) : m_DLPackType(dlpack)\n{\n    m_Bytes = (bits() * lanes() + 7) / 8;\n    if(code() > 2) { throw std::runtime_error(\"Invalid DLDataTypeCode: \"); }\n}\n\ndtype::dtype(uint8_t code, uint8_t bits, uint16_t lanes) : dtype(DLDataType{code, bits, lanes}) {}\n\ndtype::dtype() : dtype(0, 0, 0) {}\n\ndtype::dtype(dtype&& other) noexcept { *this = std::move(other); }\n\ndtype& dtype::operator=(dtype&& other) noexcept\n{\n    m_DLPackType = std::exchange(other.m_DLPackType, dtype().to_dlpack());\n    m_Bytes = std::exchange(other.m_Bytes, 0);\n}\n\ndtype::dtype(const dtype& other) { *this = other; }\n\ndtype& dtype::operator=(const dtype& other)\n{\n    if(&other == this)\n    {\n        return *this;\n    }\n    m_DLPackType = other.m_DLPackType;\n    m_Bytes = other.m_Bytes;\n}\n\nbool dtype::operator==(const dtype& other) const\n{\n    if(m_DLPackType.code == other.m_DLPackType.code &&\n       m_DLPackType.bits == other.m_DLPackType.bits &&\n       m_DLPackType.lanes == other.m_DLPackType.lanes)\n    {\n        return true;\n    }\n    return false;\n}\n\nint64_t dtype::bytes() const { return m_Bytes; }\n\nconst DLDataType& dtype::to_dlpack() const { return m_DLPackType; }\n\n\nstd::string dtype::Description() const\n{\n    std::ostringstream os;\n    std::string t = \"unknown\";\n    uint32_t bits = m_DLPackType.bits;\n    uint32_t lanes = m_DLPackType.lanes;\n    if(bits == 0 || lanes == 0)\n    {\n        os << \"nil\";\n    }\n    else\n    {\n        // clang-format off\n        if(m_DLPackType.code == kDLInt) { t = \"int\"; }\n        else if(m_DLPackType.code == kDLUInt) { t = \"uint\"; }\n        else if(m_DLPackType.code == kDLFloat) { t = \"fp\"; }\n        os << t << (uint32_t)m_DLPackType.bits;\n        if(lanes > 1U) { os << \"x\" << lanes; }\n        // clang-format on\n    }\n    return os.str();\n}\n\nstd::ostream& operator<<(std::ostream& os, const dtype& dt)\n{\n    os << dt.Description();\n    return os;\n}\n\n} // namespace types\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/src/utils.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/utils.h\"\n\n#include <math.h>\n#include <stdio.h>\n\n#include <cmath>\n#include <regex>\n\n#include <glog/logging.h>\n\nnamespace trtlab {\n/**\n * @brief Converts bytes into a more friend human readable format\n *\n * @param bytes\n * @return std::string\n */\nstd::string BytesToString(size_t bytes)\n{\n    // C++ implentation inspired from: https://stackoverflow.com/questions/3758606\n    char buffer[50];\n    int unit = 1024;\n    const char prefixes[] = \"KMGTPE\";\n    if(bytes < unit)\n    {\n        sprintf(buffer, \"%ld B\", bytes);\n        return std::string(buffer);\n    }\n    int exp = (int)(std::log(bytes) / std::log(unit));\n    sprintf(buffer, \"%.1f %ciB\", bytes / std::pow(unit, exp), prefixes[exp - 1]);\n    return std::string(buffer);\n}\n\nstd::uint64_t StringToBytes(const std::string str)\n{\n    // https://regex101.com/r/UVm5wT/1\n    std::smatch m;\n    std::regex r(\"(\\\\d+[.\\\\d+]*)([KMGTkmgt]*)([i]*)[bB]\");\n    std::map<char, int> prefix = {\n        {'k', 1}, {'m', 2}, {'g', 3}, {'t', 4}, {'K', 1}, {'M', 2}, {'G', 3}, {'T', 4},\n    };\n\n    if(!std::regex_search(str, m, r))\n        LOG(FATAL) << \"Unable to convert \\\"\" << str << \"\\\" to bytes. \"\n                   << \"Expected format: 10b, 1024B, 1KiB, 10MB, 2.4gb, etc.\";\n\n    const std::uint64_t base = m.empty() || (m.size() > 3 && m[3] == \"\") ? 1000 : 1024;\n    auto exponent = prefix[m[2].str()[0]];\n    auto scalar = std::stod(m[1]);\n    return (std::uint64_t)(scalar * std::pow(base, exponent));\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/core/tests/BUILD.bazel",
    "content": "cc_test(\n    name = \"test_core\",\n    srcs = glob([\"test_*.cc\"]),\n    deps = [\n        \"//trtlab/core:core\",\n        \"@com_google_googletest//:gtest_main\",\n    ]\n)"
  },
  {
    "path": "trtlab/core/tests/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(GTest)\n\nadd_executable(test_core\n  test_main.cc\n# test_batcher.cc\n  test_common.cc\n  test_cyclic_windowed_buffer.cc\n  test_async.cc\n# test_types.cc\n  test_memory.cc\n# test_memory_stack.cc\n  test_pool.cc\n  test_thread_pool.cc\n# test_cyclic_allocator.cc\n  test_async_compute.cc\n# test_tensor.cc\n# test_stl_allocator.cc\n# test_foo_memory.cc\n# test_sysv_allocator.cc\n# test_affinity.cc\n)\n\ntarget_link_libraries(test_core\n  PRIVATE\n    ${PROJECT_NAME}::core\n    GTest::gtest\n)\n\ntarget_include_directories(test_core\n  PRIVATE\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>\n)\n\nadd_test(\n  NAME core\n  COMMAND $<TARGET_FILE:test_core\n)\n"
  },
  {
    "path": "trtlab/core/tests/test_affinity.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"trtlab/core/affinity.h\"\n\n#include \"glog/logging.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\n\nclass TestAffinity : public ::testing::Test {};\n\nTEST_F(TestAffinity, Basics)\n{\n    auto cpus = Affinity::GetAffinity();\n    LOG(INFO) << cpus;\n    LOG(INFO) << cpus.GetCpuString();\n\n    // docker desktop uses a VM that screws up all affinity settings\n    // this is similar to how aws vms disguise numa information\n    // in both casses, each logical gpu shows up as a separate socket\n    // and the numa_nodes is -1\n\n    cpus = Affinity::GetCpusBySocket(0);\n    LOG(INFO) << cpus;\n    LOG(INFO) << \"socket 0: \" << cpus.GetCpuString();\n\n    cpus = Affinity::GetCpusBySocket(1);\n    LOG(INFO) << cpus;\n    LOG(INFO) << \"Socket 1: \" << cpus.GetCpuString();\n/*\n    cpus = Affinity::GetCpusByNuma(0);\n    LOG(INFO) << \"numa 0: \" << cpus.GetCpuString();\n\n    cpus = Affinity::GetCpusByNuma(1);\n    LOG(INFO) << \"numa 1: \" << cpus.GetCpuString();\n*/\n}\n\nTEST_F(TestAffinity, IntString)\n{\n    std::set<int> ints = { 0, 1, 3, 4, 5, 9, 10 };\n    std::string str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"0-1,3-5,9-10\"));\n\n    ints = { 0 };\n    str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"0\"));\n\n    ints = { 1 };\n    str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"1\"));\n\n    ints = { 1,2,3 };\n    str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"1-3\"));\n\n    ints = { 1,2,3,4,5,7,6 };\n    str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"1-7\"));\n\n    ints = { 1,2,4,5,7,6 };\n    str = CpuSet::IntString(ints);\n    CHECK_EQ(str, std::string(\"1-2,4-7\"));\n}"
  },
  {
    "path": "trtlab/core/tests/test_async.cc",
    "content": "#include <gtest/gtest.h>\n\n#include <boost/fiber/all.hpp>\n\nclass TestAsync : public ::testing::Test\n{\n};\n\nTEST_F(TestAsync, FibersHello)\n{\n    int i = 1;\n\n    boost::fibers::fiber f([&i] { i=2; });\n    f.join();\n\n    ASSERT_EQ(i, 2);\n}"
  },
  {
    "path": "trtlab/core/tests/test_async_compute.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/async_compute.h\"\n#include \"gtest/gtest.h\"\n\n#include <glog/logging.h>\n\nusing namespace trtlab;\n\nnamespace {\n\nclass TestAsyncCompute : public ::testing::Test\n{\n};\n\nTEST_F(TestAsyncCompute, EvenTest)\n{\n    auto compute = async_compute<void(int)>::wrap([](int i) -> bool { return (bool)((i % 2) == 0); });\n\n    /*\n    // fails to compile: the class was defined to accept a user function with only 1 int, not 2\n    auto compute2ints = async_compute<void(int)>::wrap([](int i, int j) -> bool {\n         return (bool)((i % 2) == 0);\n    });\n    */\n\n    auto future = compute->get_future();\n    (*compute)(42);\n    // (*compute)(42, -2); // fails to compile, 2 ints instead of 1\n    auto value = future.get();\n\n    EXPECT_TRUE(value);\n}\n\nTEST_F(TestAsyncCompute, OddTest)\n{\n    auto compute =\n        async_compute<void(int)>::wrap([](int i) -> bool { return (bool)((i % 2) == 0); });\n\n    auto future = compute->get_future();\n    (*compute)(41);\n    auto value = future.get();\n\n    EXPECT_FALSE(value);\n}\n\nTEST_F(TestAsyncCompute, ReturnUniquePtr)\n{\n    auto compute = async_compute<void(int)>::wrap([](int i) -> std::unique_ptr<bool> {\n        return std::make_unique<bool>((bool)((i % 2) == 0));\n    });\n\n    auto future = compute->get_future();\n    (*compute)(41);\n    auto value = std::move(future.get());\n\n    EXPECT_TRUE(value); // this the unique ptr\n    EXPECT_FALSE(*value); // this the unique ptr\n    EXPECT_ANY_THROW(future.get()); // this is the unique ptr - value moved out\n}\n\nTEST_F(TestAsyncCompute, ReturnVoid)\n{\n    auto compute = async_compute<void(int)>::wrap([](int i) { DVLOG(1) << \"Inner\"; });\n\n    auto future = compute->get_future();\n    (*compute)(42);\n    future.wait();\n}\n\nTEST_F(TestAsyncCompute, PackagedTask)\n{\n    auto task = std::make_shared<std::packaged_task<void(int)>>([](int i) { DVLOG(1) << \"Inner : \" << i; });\n\n    auto future = task->get_future();\n    (*task)(42);\n    future.wait();\n}\n\n/*\nTEST_F(TestAsyncCompute, ReturnBoolInputs1xInt)\n{\n    struct ReturnBoolInputs1xInt : public async_compute<bool(int)>\n    {\n        template<typename T, typename ...Args>\n        auto Compute(T(Args...) UserFn) {\n            std::vector<std::future<T>> futures;\n            for(int i=0; i<10; i++) {\n                auto compute = wrap(UserFn);\n                futures.push_back(std::move(compute->get_future()));\n                m_ThreadPool.enqueue([compute](int i) {\n                    (*compute)(i);\n                })\n            }\n\n        }\n      protected:\n        template<typename T, typename... Args>\n        auto Enqueue(std::shared_ptr<async_compute<T>> UserFn, Args&&... args)\n        {\n            auto compute = wrap(UserFn);\n            auto future = compute->get_future();\n            m_ThreadPool.enqueue([compute](Args&&... args) mutable {\n                (*compute)(args...);\n            });\n        }\n\n      private:\n        ThreadPool m_ThreadPool;\n    };\n\n    ReturnBoolInputs1xInt compute()\n}\n*/\n\n} // namespace"
  },
  {
    "path": "trtlab/core/tests/test_batcher.cc",
    "content": "\n#include <gtest/gtest.h>\n\n#include <trtlab/core/standard_threads.h>\n#include <trtlab/core/userspace_threads.h>\n\n#include <trtlab/core/batcher.h>\n#include <trtlab/core/dispatcher.h>\n#include <trtlab/core/task_pool.h>\n\nclass TestBatcher : public ::testing::Test\n{\n};\n\nusing namespace trtlab;\n\nTEST_F(TestBatcher, StandardBatcher)\n{\n    StandardBatcher<int, standard_threads> batcher(5);\n\n    for (int i = 0; i < 9; i++)\n    {\n        auto f     = batcher.enqueue(i);\n        auto batch = batcher.update();\n\n        if (i == 4)\n        {\n            EXPECT_TRUE(batch);\n            EXPECT_EQ(batch->items.size(), 5);\n\n            EXPECT_EQ(f.wait_until(std::chrono::high_resolution_clock::now()), std::future_status::timeout);\n            batch->promise.set_value();\n            EXPECT_EQ(f.wait_until(std::chrono::high_resolution_clock::now()), std::future_status::ready);\n        }\n        else\n        {\n            EXPECT_FALSE(batch);\n        }\n    }\n\n    auto batch = batcher.update();\n    EXPECT_FALSE(batch);\n\n    batch = batcher.close_batch();\n    EXPECT_TRUE(batch);\n    EXPECT_EQ(batch->items.size(), 4);\n}\n\nTEST_F(TestBatcher, FullBatcher)\n{\n    auto execute_on_batch = [](const std::vector<int>& batch, std::function<void()> release) {\n        LOG(INFO) << \"executing on \" << batch.size() << \" items\";\n        std::this_thread::sleep_for(std::chrono::milliseconds(2));\n        LOG(INFO) << \"freeing inputs ...\";\n        release();\n    };\n\n    StandardBatcher<int, standard_threads> batcher(5);\n    auto                                   thread_pool = std::make_shared<ThreadPool>(1);\n    auto                                   task_pool   = std::make_shared<DeferredShortTaskPool>();\n\n    Dispatcher<decltype(batcher)> dispatcher(std::move(batcher), std::chrono::milliseconds(15), thread_pool, task_pool, execute_on_batch);\n\n    std::queue<std::shared_future<void>> futures;\n\n    for (int i = 0; i < 9; i++)\n    {\n        futures.push(dispatcher.enqueue(i));\n    }\n\n    // wait on first batch to complete\n    for (int i = 0; i < 5; i++)\n    {\n        futures.front().wait();\n        futures.pop();\n    }\n\n    EXPECT_EQ(futures.front().wait_until(std::chrono::high_resolution_clock::now()), std::future_status::timeout);\n    //dispatcher.shutdown();\n    std::this_thread::sleep_for(std::chrono::milliseconds(16));\n    EXPECT_EQ(futures.front().wait_until(std::chrono::high_resolution_clock::now()), std::future_status::ready);\n    futures.pop();\n\n    LOG(INFO) << \"waiting on futures\";\n    while (!futures.empty())\n    {\n        futures.front().wait();\n        futures.pop();\n    }\n    LOG(INFO) << \"futures complete\";\n}\n\nTEST_F(TestBatcher, FullBatcherUserThreads)\n{\n    boost::fibers::use_scheduling_algorithm<boost::fibers::algo::shared_work>();\n\n    auto execute_on_batch = [](const std::vector<int>& batch, std::function<void()> release) {\n        LOG(INFO) << \"exectue_fn: this_thread: \" << std::this_thread::get_id() << \"; this_fiber: \" << boost::this_fiber::get_id();\n        boost::this_fiber::sleep_for(std::chrono::milliseconds(2));\n        LOG(INFO) << \"exectue_fn - sleep complete: this_thread: \" << std::this_thread::get_id() << \"; this_fiber: \" << boost::this_fiber::get_id();\n        release();\n    };\n\n    StandardBatcher<int, userspace_threads> batcher(5);\n    Dispatcher<decltype(batcher)> dispatcher(std::move(batcher), std::chrono::milliseconds(15), execute_on_batch);\n\n    using dispatcher_type = Dispatcher<decltype(batcher)>;\n\n    std::queue<typename dispatcher_type::future_type> futures;\n\n    for (int i = 0; i < 9; i++)\n    {\n        LOG(INFO) << \"enqueue: \" << i;\n        futures.push(dispatcher.enqueue(i));\n    }\n\n    // wait on first batch to complete\n    for (int i = 0; i < 5; i++)\n    {\n        LOG(INFO) << \"wait: \" << i;\n        futures.front().wait();\n        futures.pop();\n    }\n\n    EXPECT_EQ(futures.front().wait_until(std::chrono::high_resolution_clock::now()), boost::fibers::future_status::timeout);\n    boost::this_fiber::sleep_for(std::chrono::milliseconds(16));\n    EXPECT_EQ(futures.front().wait_until(std::chrono::high_resolution_clock::now()), boost::fibers::future_status::ready);\n    futures.pop();\n\n    LOG(INFO) << \"waiting on futures\";\n    while (!futures.empty())\n    {\n        futures.front().wait();\n        futures.pop();\n    }\n    LOG(INFO) << \"futures complete\";\n}\n\nTEST_F(TestBatcher, ShortDeferredTaskPool)\n{\n    std::mutex              mu;\n    std::condition_variable cv;\n    std::size_t             count = 0;\n\n    auto task = [&mu, &cv, &count](std::chrono::milliseconds ms) {\n        DLOG(INFO) << \"deferred for \" << ms.count() << \" ms\";\n        {\n            std::lock_guard<std::mutex> lock(mu);\n            count += ms.count();\n        }\n        cv.notify_one();\n    };\n\n    DeferredShortTaskPool pool;\n\n    using namespace std::chrono_literals;\n    using clock = std::chrono::high_resolution_clock;\n\n    auto start = clock::now();\n\n    pool.enqueue_deferred(clock::now() + 25ms, [task]() { task(25ms); });\n    pool.enqueue_deferred(clock::now() + 5ms, [task]() { task(5ms); });\n    pool.enqueue_deferred(clock::now() + 10ms, [task]() {\n        task(10ms);\n        std::this_thread::sleep_for(std::chrono::microseconds(5)); // should print a warning\n    });\n\n    std::unique_lock<std::mutex> lock(mu);\n    ASSERT_EQ(count, 0);\n    cv.wait(lock, [&count]() { return count != 0; });\n    ASSERT_EQ(count, 5);\n    cv.wait(lock, [&count]() { return count != 5; });\n    ASSERT_EQ(count, 15);\n    cv.wait(lock, [&count]() { return count != 15; });\n    ASSERT_EQ(count, 40);\n\n    auto elapsed = clock::now() - start;\n    auto wall    = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();\n\n    ASSERT_GE(wall, 25);\n    ASSERT_LT(wall, 26);\n\n    pool.shutdown();\n\n    EXPECT_ANY_THROW(pool.enqueue_deferred(clock::now() + 3ms, [] {}));\n}"
  },
  {
    "path": "trtlab/core/tests/test_common.cc",
    "content": "\n#include \"test_common.h\"\n\n#include <glog/logging.h>\n\nstd::size_t log_tracker::node_total = 0;\nstd::size_t log_tracker::node_count = 0;\n\nvoid TrackedTest::SetUp()\n{\n    ASSERT_EQ(log_tracker::node_total, 0);\n    ASSERT_EQ(log_tracker::node_count, 0);\n}\n\nvoid TrackedTest::TearDown()\n{\n    DVLOG(1) << \"^^^ deallocation of stack messages from end of test to start of teardown ^^^\";\n    ASSERT_EQ(log_tracker::node_total, 0);\n    ASSERT_EQ(log_tracker::node_count, 0);\n}\n\nvoid TrackedTest::EndTest()\n{\n    DVLOG(1) << \"*-----------* end of test *-----------*\";\n}\n\nvoid log_tracker::on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n{\n    DVLOG(1) << name << \": node allocated: \" << ptr << \"; size: \" << size << \"; alignment: \" << alignment;\n    node_total += size;\n    node_count++;\n}\n\nvoid log_tracker::on_node_deallocation(void *ptr, std::size_t size, std::size_t alignment) noexcept\n{\n    EXPECT_GT(node_total, 0);\n    EXPECT_GT(node_count, 0);\n    DVLOG(1) << name << \": node deallocated: \" << ptr << \"; \" << size << \"; \" << alignment;\n    node_count--;\n    node_total -= size;\n}\n\nvoid log_tracker::on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n{\n    DVLOG(1) << name << \": array allocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    node_count += count;\n    node_total += count * size;\n}\n\nvoid log_tracker::on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n{\n    EXPECT_GT(node_total, 0);\n    EXPECT_GT(node_count, 0);\n    DVLOG(1) << name << \": array deallocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    node_count -= count;\n    node_total -= count * size;\n}\n\nvoid timeout_mutex::lock()\n{\n    auto now = std::chrono::steady_clock::now();\n    auto success = this->try_lock_until(now + std::chrono::milliseconds(MUTEX_TIMEOUT_MS));\n    if(!success) throw timeout_error();\n}\n\nvoid timeout_mutex::unlock()\n{\n    std::timed_mutex::unlock();\n}\n\nbool timeout_mutex::try_lock()\n{\n    return std::timed_mutex::try_lock();\n}\n\n#include <trtlab/core/ranges.h>\nusing namespace trtlab;\n\nclass TestCore : public ::testing::Test {};\n\nTEST_F(TestCore, FindRanges0)\n{\n    std::vector<int> a { 1 };\n    std::vector<std::pair<int, int>> a_ranges { {1,1} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1\");\n}\n\n\nTEST_F(TestCore, FindRanges1)\n{\n    std::vector<int> a { 1,2 };\n    std::vector<std::pair<int, int>> a_ranges { {1,2} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-2\");\n}\n\nTEST_F(TestCore, FindRanges2)\n{\n    std::vector<int> a { 1,2,3 };\n    std::vector<std::pair<int, int>> a_ranges { {1,3} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-3\");\n}\n\nTEST_F(TestCore, FindRanges3)\n{\n    std::vector<int> a { 1,3 };\n    std::vector<std::pair<int, int>> a_ranges { {1,1}, {3,3} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1,3\");\n}\n\nTEST_F(TestCore, FindRanges4)\n{\n    std::vector<int> a { 1,2,4,5,6,10 };\n    std::vector<std::pair<int, int>> a_ranges { {1,2}, {4,6}, {10,10} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-2,4-6,10\");\n}\n\nTEST_F(TestCore, FindRanges5)\n{\n    std::vector<int> a { 0,1,2,3,4,5,6 };\n    std::vector<std::pair<int, int>> a_ranges { {0,6} };\n    auto ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"0-6\");\n}"
  },
  {
    "path": "trtlab/core/tests/test_common.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <cstdint>\n#include <cstring>\n#include <mutex>\n\n#include <gtest/gtest.h>\n\n#define MUTEX_TIMEOUT_MS 1000\n\nclass TrackedTest : public ::testing::Test\n{\n  public:\n    void EndTest();\n    \n  protected:\n    virtual void SetUp() override;\n    virtual void TearDown() override;\n};\n\nstruct log_tracker\n{\n    void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept;\n\n    void on_node_deallocation(void *ptr, std::size_t size, std::size_t alignment) noexcept;\n\n    void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n\n    void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n\n    const char* name;\n    static std::size_t node_total;\n    static std::size_t node_count;\n};\n\nstruct timeout_error : std::exception\n{\n    const char* what() const throw ()\n    {\n        return \"timed out\";\n    }\n};\n\nclass timeout_mutex : std::timed_mutex\n{\n  public:\n    timeout_mutex() = default;\n    timeout_mutex(const timed_mutex&) = delete;\n\n    void lock();\n    void unlock();\n    bool try_lock();\n};"
  },
  {
    "path": "trtlab/core/tests/test_cyclic_allocator.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/cyclic_allocator.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/sysv_allocator.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\n\nnamespace {\n\nstatic size_t one_mb = 1024 * 1024;\n\ntemplate<typename T>\nclass TestCyclicStacks : public ::testing::Test\n{\n};\n\nusing MemoryTypes = ::testing::Types<Malloc, SystemV>;\n\nTYPED_TEST_CASE(TestCyclicStacks, MemoryTypes);\n\nTYPED_TEST(TestCyclicStacks, EmptyOnCreate)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    EXPECT_EQ(5, stack->AvailableSegments());\n    EXPECT_EQ(5 * one_mb, stack->AvailableBytes());\n}\n\nTYPED_TEST(TestCyclicStacks, AddSegment)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    stack->AddSegment();\n    EXPECT_EQ(6, stack->AvailableSegments());\n}\n\nTYPED_TEST(TestCyclicStacks, DropSegment)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    stack->DropSegment();\n    EXPECT_EQ(4, stack->AvailableSegments());\n}\n\nTYPED_TEST(TestCyclicStacks, Allocate)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    {\n        auto seg_0_0 = stack->Allocate(1);\n        EXPECT_EQ(5 * one_mb - stack->Alignment(), stack->AvailableBytes());\n    }\n    // even though seg_0_0 is released, the current segment does not get reset/recycled\n    // because the stack still owns reference to seg_0\n    // a segment is only recycled after it becomes detached and its reference count goes to 0\n    EXPECT_EQ(5 * one_mb - stack->Alignment(), stack->AvailableBytes());\n\n    {\n        auto seg_0_1 = stack->Allocate(1024);\n        EXPECT_EQ(5, stack->AvailableSegments()); // seg_0 is still active\n        auto seg_1_0 = stack->Allocate(one_mb);\n        EXPECT_EQ(3,\n                  stack->AvailableSegments()); // seg_0 is detached; seg_1 detaches if capacity is 0\n        auto seg_2_0 = stack->Allocate(1024);\n        EXPECT_EQ(3, stack->AvailableSegments()); // seg_2 is now active; 0 and 1 are detached\n        seg_1_0.reset(); // we can release seg_0/1 in any order\n        EXPECT_EQ(4, stack->AvailableSegments());\n        seg_0_1.reset(); // we can release seg_0/1 in any order\n        EXPECT_EQ(5, stack->AvailableSegments());\n    }\n    // seg_0 has had 2 allocation, then failed to have capacity for the 3rd allocation\n    // seg_1 is completely used from the 3rd allocation, but is still the active segment\n    // until seg_2 is allocated\n    EXPECT_EQ(5, stack->AvailableSegments());\n\n    {\n        // everything has been released, so we can grab 5 x one_mb buffers\n        // but we will OOM on our 6th\n        auto b0 = stack->Allocate(one_mb);\n        auto b1 = stack->Allocate(one_mb);\n        auto b2 = stack->Allocate(one_mb);\n        auto b3 = stack->Allocate(one_mb);\n        auto b4 = stack->Allocate(one_mb);\n        EXPECT_EQ(0, stack->AvailableSegments());\n\n        // The following will hang and deadlock the test\n        // stack->Allocate(one_mb);\n    }\n}\n\nTYPED_TEST(TestCyclicStacks, AllocateThenReleaseStack)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    auto buf = stack->Allocate(1024);\n    stack.reset();\n    EXPECT_EQ(buf->Size(), 1024);\n    DLOG(INFO) << \"Deallocation should hppen after this statement\";\n}\n\n/*\nTYPED_TEST(TestCyclicStacks, CastToMemoryType)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    std::unique_ptr<TypeParam> buf = std::move(stack->Allocate(1024));\n    EXPECT_EQ(buf->Size(), 1024);\n    stack.reset();\n    EXPECT_EQ(buf->Size(), 1024);\n    DLOG(INFO) << \"Deallocation should hppen after this statement\";\n}\n*/\n\nTYPED_TEST(TestCyclicStacks, AllocateShouldFail)\n{\n    auto stack = std::make_unique<CyclicAllocator<TypeParam>>(5, one_mb);\n    EXPECT_DEATH(stack->Allocate(one_mb + 1), \"\");\n}\n\n} // namespace\n"
  },
  {
    "path": "trtlab/core/tests/test_cyclic_windowed_buffer.cc",
    "content": "/* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"gtest/gtest.h\"\n\n#include <cstdlib>\n\n#include <chrono>\n#include <future>\n#include <numeric>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/malloc_allocator.h>\n\n#include <trtlab/core/thread_pool.h>\n#include <trtlab/core/cyclic_buffer.h>\n#include <trtlab/core/standard_threads.h>\n\nusing namespace trtlab;\nusing namespace trtlab::memory;\n\nclass TestWindowedBuffer : public ::testing::Test\n{\n};\n\nTEST_F(TestWindowedBuffer, SynchronousNonOverlapping)\n{\n    auto alloc    = make_allocator(malloc_allocator());\n    auto int_x100 = alloc.allocate_descriptor(100 * sizeof(int));\n\n    // external state will the buffer will modify\n    // no mutex needed in this case, but could be captured and passed\n    auto sums = std::vector<long>();\n\n    HostCyclicBuffer buffer(std::move(int_x100), 40, 0, [&sums](std::size_t id, const void* data, std::size_t bytes) -> auto {\n        DCHECK_EQ(bytes % sizeof(int), 0);\n        EXPECT_EQ(id, sums.size());\n        auto array = static_cast<const int*>(data);\n        auto count = bytes / sizeof(int);\n        long sum   = 0;\n        for (int i = 0; i < count; i++)\n        {\n            sum += array[i];\n        }\n        sums.push_back(sum);\n        return [](bool) { return true; };\n    });\n\n    ASSERT_EQ(sums.size(), 0);\n\n    std::vector<int> vec;\n    vec.resize(10);\n\n    for (int i = 0; i < 20; i++)\n    {\n        std::iota(vec.begin(), vec.end(), i);\n        buffer.AppendData(vec.data(), vec.size() * sizeof(int));\n\n        EXPECT_EQ(sums.size(), i + 1);\n        EXPECT_EQ(sums[i], 45 + 10 * i);\n    }\n}\n\nTEST_F(TestWindowedBuffer, SynchronousOverlapping)\n{\n    auto alloc    = make_allocator(malloc_allocator());\n    auto int_x100 = alloc.allocate_descriptor(110 * sizeof(int));\n\n    // external state will the buffer will modify\n    // no mutex needed in this case, but could be captured and passed\n    auto sums = std::vector<long>();\n\n    HostCyclicBuffer buffer(std::move(int_x100), 40, 20, [&sums](std::size_t id, const void* data, std::size_t bytes) -> auto {\n        DCHECK_EQ(bytes % sizeof(int), 0);\n        EXPECT_EQ(id, sums.size());\n        auto array = static_cast<const int*>(data);\n        auto count = bytes / sizeof(int);\n        long sum   = 0;\n        for (int i = 0; i < count; i++)\n        {\n            sum += array[i];\n        }\n        sums.push_back(sum);\n        return [](bool) { return true; };\n    });\n\n    ASSERT_EQ(sums.size(), 0);\n\n    std::vector<int> vec;\n    vec.resize(10);\n\n    for (int i = 0; i < 40; i++)\n    {\n        std::iota(vec.begin(), vec.end(), i);\n        buffer.AppendData(vec.data(), vec.size() * sizeof(int));\n    }\n\n    for (int i = 0; i < sums.size(); i++)\n    {\n        EXPECT_EQ(sums[i], 45 + 5 * i);\n    }\n}\n\ntemplate <typename T>\nstd::function<bool(bool)> SyncFnFromFuture(std::shared_future<T>&& shared)\n{\n    return [f = std::move(shared)](bool wait) -> bool {\n        if (wait)\n        {\n            f.wait();\n            return true;\n        }\n        auto rc = f.wait_for(std::chrono::nanoseconds(100));\n        if (rc == std::future_status::ready)\n        {\n            return true;\n        }\n        return false;\n    };\n}\n\nTEST_F(TestWindowedBuffer, AsynchronousNonOverlapping)\n{\n    auto alloc    = make_allocator(malloc_allocator());\n    auto int_x100 = alloc.allocate_descriptor(100 * sizeof(int));\n\n    ThreadPool thread_pool(5);\n\n    // external state will the buffer will modify\n    // no mutex needed in this case, but could be captured and passed\n    auto sums = std::vector<long>();\n\n    HostCyclicBuffer buffer(std::move(int_x100), 40, 0,\n                            [&sums, &thread_pool ](std::size_t id, const void* data, std::size_t bytes) -> auto {\n                                EXPECT_EQ(id, sums.size());\n                                sums.push_back(-1);\n                                auto index = id;\n                                DVLOG(2) << \"callback \" << index << \" handing off to thread pool\";\n                                auto future = thread_pool.enqueue([&sums, index, data, bytes]() {\n                                    auto rand = 1 + std::rand() / ((RAND_MAX + 1u) / 10);\n                                    DVLOG(2) << \"sleep for \" << rand << \" millseconds\";\n                                    std::this_thread::sleep_for(std::chrono::milliseconds(rand));\n                                    DCHECK_EQ(bytes % sizeof(int), 0);\n                                    auto array = static_cast<const int*>(data);\n                                    auto count = bytes / sizeof(int);\n                                    long sum   = 0;\n                                    for (int i = 0; i < count; i++)\n                                    {\n                                        sum += array[i];\n                                    }\n                                    DVLOG(2) << \"sum[ \" << index << \" ]: \" << sum;\n                                    sums[index] = sum;\n                                });\n                                return SyncFnFromFuture(std::move(future.share()));\n                            });\n\n    ASSERT_EQ(sums.size(), 0);\n\n    std::vector<int> vec;\n    vec.resize(10);\n\n    for (int i = 0; i < 20; i++)\n    {\n        std::iota(vec.begin(), vec.end(), i);\n        buffer.AppendData(vec.data(), vec.size() * sizeof(int));\n    }\n\n    buffer.Sync();\n\n    for (int i = 0; i < 20; i++)\n    {\n        EXPECT_EQ(sums[i], 45 + 10 * i);\n    }\n}\n\nTEST_F(TestWindowedBuffer, AsynchronousOverlapping)\n{\n    auto alloc    = make_allocator(malloc_allocator());\n    auto int_x100 = alloc.allocate_descriptor(100 * sizeof(int));\n\n    ThreadPool thread_pool(5);\n\n    // external state will the buffer will modify\n    // no mutex needed in this case, but could be captured and passed\n    auto sums = std::vector<long>();\n\n    HostCyclicBuffer buffer(std::move(int_x100), 40, 20,\n                            [&sums, &thread_pool ](std::size_t id, const void* data, std::size_t bytes) -> auto {\n                                EXPECT_EQ(id, sums.size());\n                                sums.push_back(-1);\n                                auto index = id;\n                                DVLOG(2) << \"callback \" << index << \" handing off to thread pool\";\n                                auto future = thread_pool.enqueue([&sums, index, data, bytes]() {\n                                    auto rand = 1 + std::rand() / ((RAND_MAX + 1u) / 10);\n                                    DVLOG(2) << \"sleep for \" << rand << \" millseconds\";\n                                    std::this_thread::sleep_for(std::chrono::milliseconds(rand));\n                                    DCHECK_EQ(bytes % sizeof(int), 0);\n                                    auto array = static_cast<const int*>(data);\n                                    auto count = bytes / sizeof(int);\n                                    long sum   = 0;\n                                    for (int i = 0; i < count; i++)\n                                    {\n                                        sum += array[i];\n                                    }\n                                    DVLOG(2) << \"sum[ \" << index << \" ]: \" << sum;\n                                    sums[index] = sum;\n                                });\n                                return SyncFnFromFuture(std::move(future.share()));\n                            });\n\n    ASSERT_EQ(sums.size(), 0);\n\n    std::vector<int> vec;\n    vec.resize(10);\n\n    for (int i = 0; i < 20; i++)\n    {\n        std::iota(vec.begin(), vec.end(), i);\n        buffer.AppendData(vec.data(), vec.size() * sizeof(int));\n    }\n\n    buffer.Sync();\n\n    for (int i = 0; i < 20; i++)\n    {\n        EXPECT_EQ(sums[i], 45 + 5 * i);\n    }\n}\n\n#include <trtlab/core/cyclic_windowed_buffer.h>\n\n// make protected members public for testing\nstruct test_cw_stack : public ::trtlab::cyclic_windowed_stack<memory::host_memory, standard_threads>\n{\n    using cyclic_windowed_stack = ::trtlab::cyclic_windowed_stack<memory::host_memory, standard_threads>;\n\npublic:\n    using cyclic_windowed_stack::available;\n    using cyclic_windowed_stack::cyclic_windowed_stack;\n    using cyclic_windowed_stack::push_window;\n};\n\nTEST_F(TestWindowedBuffer, Stack)\n{\n    auto alloc = make_allocator(malloc_allocator());\n    auto md    = alloc.allocate_descriptor(100 * sizeof(int));\n\n    test_cw_stack stack(std::move(md), 40, 20);\n\n    EXPECT_EQ(stack.buffer().window_count(), 19);\n\n    std::size_t sync_count = 0;\n    auto        syncfn     = [&sync_count] {\n        ++sync_count;\n        DVLOG(1) << \"syncfn called \" << sync_count << \" times\";\n    };\n\n    EXPECT_EQ(stack.available(), 40);\n\n    for (int i = 0; i < stack.buffer().window_count() - 1; i++)\n    {\n        stack.push_window(syncfn);\n        EXPECT_EQ(sync_count, 0);\n        EXPECT_EQ(stack.available(), 20);\n    }\n\n    // the push_window causes the stack to recycle\n    // in this scenario, two syncs are needed:\n    // 1) to reserve space for the 20 bytes of replicated data\n    // 2) a second sync to free the remainder of the first window\n    stack.push_window(syncfn);\n    EXPECT_EQ(sync_count, 2);\n\n    stack.push_window(syncfn);\n    EXPECT_EQ(sync_count, 3);\n\n    for (int i = 0; i < stack.buffer().window_count() * 3; i++)\n    {\n        stack.push_window(syncfn);\n        EXPECT_EQ(stack.available(), 20);\n    }\n}\n\n/*\nTEST_F(TestWindowedBuffer, TaskExecutor)\n{\n    auto alloc = make_allocator(malloc_allocator());\n    auto md    = alloc.allocate_descriptor(100 * sizeof(int));\n\n    cyclic_windowed_stack<memory::host_memory, standard_threads> stack(std::move(md), 10*sizeof(int), 5*sizeof(int));\n\n    // clang-format off\n    cyclic_windowed_task_executor<memory::host_memory, standard_threads> buffer(std::move(stack),\n        [](std::size_t id, const void* data, std::size_t count) -> auto {\n            auto f = std::async([id] {\n                std::this_thread::sleep_for(std::chrono::milliseconds(100*id));\n                LOG(INFO) << \"task \" << id << \" complete\";\n            }).share();\n            return f;\n        });\n    // clang-format on \n\n    std::vector<int> source(100);\n    std::iota(source.begin(), source.end(), 0);\n\n    buffer.append_data(&source[0], 100*sizeof(int));\n    buffer.append_data(&source[0], 100*sizeof(int));\n}\n*/\n\n#include <trtlab/core/userspace_threads.h>\n\nTEST_F(TestWindowedBuffer, Reservation)\n{\n    auto alloc = make_allocator(malloc_allocator());\n    auto md    = alloc.allocate_descriptor(20 * sizeof(int));\n\n    cyclic_windowed_stack<memory::host_memory, userspace_threads> base(std::move(md), 10 * sizeof(int), 8 * sizeof(int));\n\n    cyclic_windowed_reserved_stack<memory::host_memory, userspace_threads> stack(std::move(base)); \n\n    for (int i = 0; i < stack.buffer().window_count() * 3; i++)\n    {\n        auto r = stack.reserve_window();\n        int *top = static_cast<int*>(r.data_start);\n        auto count = r.data_size / sizeof(int);\n        LOG(INFO) << \"reservation \" << i << \": filling \" << count << \" entries\";\n        std::fill(top, top + count, i);\n        top = static_cast<int*>(r.window_start);\n        for(int i=0; i<10; i++)\n        {\n            LOG(INFO) << *(top + i);\n        }\n        r.release();\n    }\n}"
  },
  {
    "path": "trtlab/core/tests/test_foo_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/block_allocators.h\"\n#include \"trtlab/core/memory/containers.h\"\n#include \"trtlab/core/memory/transactional_allocator.h\"\n#include \"trtlab/core/memory/host_first_touch_allocator.h\"\n\n#include <foonathan/memory/aligned_allocator.hpp>\n#include <foonathan/memory/container.hpp>\n#include <foonathan/memory/smart_ptr.hpp>\n#include <foonathan/memory/tracking.hpp>\n#include <foonathan/memory/namespace_alias.hpp>\n\n#include <glog/logging.h>\n#include <gtest/gtest.h>\n\n#include <chrono>\n#include <future>\n#include <thread>\n\n#include \"test_common.h\"\n\nusing namespace memory::literals;\n\n\n\ntemplate<typename T, typename RawAllocator>\nauto make_vector(RawAllocator&& alloc)\n{\n    return memory::vector<T, RawAllocator>(alloc);\n}\n\ntemplate<typename T, typename RawAllocator, typename Mutex>\nauto make_vector(memory::trtlab::allocator<RawAllocator, Mutex> alloc)\n{\n    return memory::vector<T, memory::trtlab::allocator<RawAllocator, Mutex>>(alloc);\n}\n\nclass TestFooMemory : public TrackedTest {};\n\nTEST_F(TestFooMemory, BlankTest) \n{\n    DVLOG(1) << \"FooMemory testing\";\n    ASSERT_TRUE(true); \n}\n\nTEST_F(TestFooMemory, Malloc)\n{\n    auto raw = memory::malloc_allocator();\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(alloc));\n\n    auto p0 = tracked.allocate_node(1024, 8);\n\n    ASSERT_EQ(log_tracker::node_total, 1024);\n    ASSERT_EQ(log_tracker::node_count, 1);\n\n    tracked.deallocate_node(p0, 1024, 8);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, MallocTraits)\n{\n    auto raw = memory::malloc_allocator();\n    auto adp = memory::make_allocator_adapter(std::move(memory::malloc_allocator()));\n    auto ref = memory::make_allocator_reference(raw);\n    auto mt_ref = memory::make_allocator_reference<std::mutex>(raw);\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, ref);\n\n    // default malloc implementation does not provide a memory_type\n    static_assert(std::is_same<decltype(adp)::memory_type, memory::host_memory>::value, \"should be host_memory\");\n    static_assert(std::is_same<decltype(ref)::memory_type, memory::host_memory>::value, \"should be host_memory\");\n    static_assert(std::is_same<decltype(mt_ref)::memory_type, memory::host_memory>::value, \"should be host_memory\");\n    static_assert(std::is_same<decltype(tracked)::memory_type, memory::host_memory>::value, \"should be host_memory\");\n\n    DVLOG(1) << \"access allocator traits from adapter\";\n    auto context_adp = adp.device_context();\n    ASSERT_EQ(context_adp.device_type, kDLCPU);\n    ASSERT_EQ(context_adp.device_id, 0);\n\n    DVLOG(1) << \"access allocator traits from reference\";\n    auto context_ref = ref.device_context();\n    ASSERT_EQ(context_ref.device_type, kDLCPU);\n    ASSERT_EQ(context_ref.device_id, 0);\n\n    DVLOG(1) << \"access allocator traits from mt reference\";\n    auto context_mt_ref = mt_ref.device_context();\n    ASSERT_EQ(context_mt_ref.device_type, kDLCPU);\n    ASSERT_EQ(context_mt_ref.device_id, 0);\n\n    DVLOG(1) << \"access allocator traits from tracker\";\n    auto context_trk = tracked.device_context();\n    ASSERT_EQ(context_trk.device_type, kDLCPU);\n    ASSERT_EQ(context_trk.device_id, 0);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, MallocAsStdAllocator)\n{\n    auto raw = memory::malloc_allocator();\n    auto ref = memory::make_allocator_reference(raw);\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, ref);\n\n    std::size_t count = 64;\n    auto vec = memory::vector<std::size_t, decltype(tracked)>(tracked);\n    vec.reserve(count);\n\n    ASSERT_GE(log_tracker::node_total, count * sizeof(std::size_t));\n    ASSERT_GE(log_tracker::node_count, count);\n\n    std::size_t tmp_total = log_tracker::node_total;\n\n    for(std::size_t i=0; i<count; i++)\n    {\n        vec.push_back(i);\n    }\n\n    ASSERT_EQ(log_tracker::node_total, tmp_total);\n\n    DVLOG(1) << \"pushing beyond vector capacity - expect new alloc/dealloc/copy\";\n    vec.push_back(count+1);\n    DVLOG(1) << \"^^^ should see alloc/dealloc messages ^^^\";\n\n    ASSERT_GT(log_tracker::node_total, tmp_total);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, MallocThreadSafe)\n{\n    auto raw = memory::malloc_allocator();\n    auto ref = memory::make_allocator_reference<std::mutex>(raw);\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, ref);\n\n    std::size_t count = 64;\n    auto vec = memory::vector<std::size_t, decltype(tracked)>(tracked);\n    vec.reserve(count);\n\n    ASSERT_GE(log_tracker::node_total, count * sizeof(std::size_t));\n    ASSERT_GE(log_tracker::node_count, count);\n\n    std::size_t tmp_total = log_tracker::node_total;\n\n    for(std::size_t i=0; i<count; i++)\n    {\n        vec.push_back(i);\n    }\n\n    ASSERT_EQ(log_tracker::node_total, tmp_total);\n\n    DVLOG(1) << \"pushing beyond vector capacity - expect new alloc/dealloc/copy\";\n    vec.push_back(count+1);\n    DVLOG(1) << \"^^^ should see alloc/dealloc messages ^^^\";\n\n    ASSERT_GT(log_tracker::node_total, tmp_total);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, GrowthCappedBlockAllocator)\n{\n\n    // base allocator\n    auto malloc_raw = memory::malloc_allocator();\n    auto malloc_ref = memory::make_allocator_reference(malloc_raw);\n    auto malloc_tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, malloc_ref);\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 2, malloc_tracked);\n\n    auto context = block_alloc.device_context();\n    ASSERT_EQ(context.device_type, kDLCPU);\n    ASSERT_EQ(context.device_id, 0);\n\n    DVLOG(1) << \"allocate first block - should pass\";\n    auto block_0 = block_alloc.allocate_block();\n    ASSERT_NE(block_0.memory, nullptr);\n    ASSERT_EQ(block_0.size, 1_MiB);\n\n    DVLOG(1) << \"allocate second block - should pass\";\n    auto block_1 = block_alloc.allocate_block();\n    ASSERT_NE(block_1.memory, nullptr);\n    ASSERT_EQ(block_1.size, 1_MiB);\n\n    DVLOG(1) << \"allocate third block - should throw an exception\";\n    ASSERT_ANY_THROW(auto block_2 = block_alloc.allocate_block());\n\n    DVLOG(1) << \"increasing limit to 3; allocate third block - should pass\";\n    block_alloc.set_max_block_count(3);\n    auto block_2 = block_alloc.allocate_block();\n\n    DVLOG(1) << \"deallocate blocks\";\n    block_alloc.deallocate_block(block_0);\n    block_alloc.deallocate_block(block_1);\n    block_alloc.deallocate_block(block_2);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, BlockArena)\n{\n\n    // base allocator\n    auto malloc_raw = memory::malloc_allocator();\n    auto malloc_ref = memory::make_allocator_reference(malloc_raw);\n    auto malloc_tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, malloc_ref);\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 2, malloc_tracked);\n\n    ASSERT_EQ(log_tracker::node_count, 0);\n    \n    // arena with caching\n    auto arena = memory::trtlab::make_block_arena(std::move(block_alloc));\n\n    arena.reserve_blocks(2);\n    ASSERT_EQ(log_tracker::node_count, 2);\n\n    DVLOG(1) << \"allocate first block - should pass\";\n    auto block_0 = arena.allocate_block();\n    ASSERT_NE(block_0.memory, nullptr);\n    ASSERT_EQ(block_0.size, 1_MiB);\n    ASSERT_EQ(log_tracker::node_count, 2);\n\n    DVLOG(1) << \"allocate second block - should pass\";\n    auto block_1 = arena.allocate_block();\n    ASSERT_NE(block_1.memory, nullptr);\n    ASSERT_EQ(block_1.size, 1_MiB);\n    ASSERT_EQ(log_tracker::node_count, 2);\n\n    DVLOG(1) << \"allocate third block - should throw an exception\";\n    ASSERT_ANY_THROW(auto block_2 = arena.allocate_block());\n    ASSERT_EQ(log_tracker::node_count, 2);\n\n    DVLOG(1) << \"increasing limit to 3; allocate third block - should pass\";\n    arena.get_block_allocator().set_max_block_count(3);\n    auto block_2 = arena.allocate_block();\n    ASSERT_EQ(log_tracker::node_count, 3);\n\n    DVLOG(1) << \"deallocate blocks\";\n\n    DVLOG(1) << \"deallocate block_0; then force the cache to shrink_to_fit\";\n    arena.deallocate_block(block_0);\n    ASSERT_EQ(log_tracker::node_count, 3);\n    arena.shrink_to_fit();\n    ASSERT_EQ(log_tracker::node_count, 2);\n\n    DVLOG(1) << \"deallocate remaining blocks\";\n    arena.deallocate_block(block_1);\n    arena.deallocate_block(block_2);\n    ASSERT_EQ(log_tracker::node_count, 2);\n    DVLOG(1) << \"there should be two deallocations after the * end of test * from the block_arena destructor\";\n\n    EndTest();\n}\n\ntemplate<typename StatelessAllocator>\nauto make_raw_transactional_allocator(std::size_t block_size, std::size_t block_count = 2)\n{\n    // base allocator\n    auto raw = StatelessAllocator();\n\n    // convert to full fledged allocator - use direct_storage which optimizes out mutexes for stateless allocators\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n\n    static_assert(!decltype(alloc)::is_stateful::value, \"should be stateless\");\n    static_assert(std::is_same<memory::no_mutex, typename decltype(alloc)::mutex>::value, \"should use memory::no_mutex\");\n\n    // create a tracker for calls to the malloc allocator\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: base **\"}, std::move(alloc));\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(block_size, block_count, std::move(tracked));\n\n    // transactional allocator\n    return memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n}\n\ntemplate<typename StatelessAllocator = memory::malloc_allocator>\nauto make_smart_transactional_allocator(std::size_t block_size, std::size_t block_count = 2)\n{\n    // transactional allocator\n    auto alloc = make_raw_transactional_allocator<StatelessAllocator>(block_size, block_count);\n\n    // populate the cache\n    alloc.reserve_blocks(block_count);\n\n    // smart allocator\n    // use a special timeout_mutex - throws an exception if the lock is not obtained in MUTEX_TIMEOUT_MS\n    return memory::trtlab::make_allocator<timeout_mutex>(std::move(alloc));\n}\n\nTEST_F(TestFooMemory, TransactionalLifeCycle)\n{\n\n    auto smart = make_smart_transactional_allocator(1_MiB);\n\n    static_assert(decltype(smart)::is_stateful::value, \"should be stateful\");\n    static_assert(std::is_same<decltype(smart)::mutex, timeout_mutex>::value, \"should be a timeout mutex\");\n\n    // we can safely make copies of allocators\n    // because all allocators hold a shared_ptr to the underlying allocator storage (raw allocator + mutex)\n    auto tracker = memory::make_tracked_allocator(log_tracker{\"** transactional **\"}, smart.copy());\n\n    static_assert(decltype(tracker)::is_stateful::value, \"should be stateful\");\n\n    {\n        DVLOG(1) << \"make some shared_ptr<int> objects with the reference\";\n        auto int_0 = memory::allocate_shared<int>(smart, 2);\n        auto int_1 = memory::allocate_shared<int>(smart, 4);\n    }\n\n    {\n        auto lock = smart.lock();\n        DVLOG(1) << \"got lock - should hang if trying to use the allocator\";\n        ASSERT_THROW(auto int_0 = memory::allocate_shared<int>(smart, 2), timeout_error);\n    }\n\n    {\n        DVLOG(1) << \"make some shared_ptr<int> objects with the tracker\";\n        auto int_0 = memory::allocate_shared<int>(tracker, 2);\n        auto int_1 = memory::allocate_shared<int>(tracker, 4);\n    }\n\n    {\n        auto lock = smart.lock();\n        ASSERT_THROW(auto int_0 = memory::allocate_shared<int>(tracker, 2), timeout_error);\n    }\n\n    EndTest();\n}\n\n\nTEST_F(TestFooMemory, TransactionalAllocatorFullyCaptured)\n{\n    auto trans = make_raw_transactional_allocator<memory::malloc_allocator>(1_MiB);\n\n    auto ptr = trans.allocate_node(1024*1024, 8);\n\n    DVLOG(1) << ptr;\n\n    trans.deallocate_node(ptr, 1024*1024, 8);\n\n    EndTest();\n}\n\n\n\nTEST_F(TestFooMemory, SmartTransactionalLifeCycle)\n{\n    auto smart = make_smart_transactional_allocator(1_MiB, 2);\n\n    // smart allocators should be shared\n    static_assert(memory::is_shared_allocator<decltype(smart)>::value, \"not shared\");\n\n    // ensure we can reach the raw allocator\n    smart.get_raw_allocator().get_block_allocator().set_max_block_count(3);\n\n    // basic allocation\n    auto ptr = smart.allocate_node(1024, 8);\n    ASSERT_NE(ptr, nullptr) << \"should have thrown an exception or a valid ptr\";\n    smart.deallocate_node(ptr, 1024, 8);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, SmartTransactionalBase)\n{\n    auto smart = make_smart_transactional_allocator(1_MiB, 2);\n\n    // smart allocators should be shared\n    static_assert(memory::is_shared_allocator<decltype(smart)>::value, \"not shared\");\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, SmartTransactionalDescriptor)\n{\n    auto smart = make_smart_transactional_allocator(1_MiB, 2);\n\n    // smart allocators should be shared\n    static_assert(memory::is_shared_allocator<decltype(smart)>::value, \"not shared\");\n\n    // a smart descriptor holds a shared_ptr to the allocator\n    DVLOG(1) << \"create descriptor\";\n    auto md = smart.allocate_descriptor(1024, 8);\n    DVLOG(1) << \"created descriptor\";\n    ASSERT_EQ(smart.use_count(), 2);\n    ASSERT_NE(md.data(), nullptr);\n    ASSERT_EQ(md.size(), 1024);\n    ASSERT_EQ(md.device_context().device_type, kDLCPU);\n\n    // a smart descriptor is only moveable, not copyable\n    DVLOG(1) << \"move descriptor\";\n    auto moved_md = std::move(md);\n    ASSERT_EQ(md.data(), nullptr);\n    ASSERT_EQ(smart.use_count(), 2);\n    static_assert(!std::is_copy_constructible<decltype(md)>::value, \"should not be copyable\");\n    static_assert(!std::is_copy_assignable<decltype(md)>::value, \"should not be copyable\");\n\n    // to make a smart descriptor copyable, you can create a shared_ptr to it\n    DVLOG(1) << \"convert to shared descriptor\";\n    auto shared_md = moved_md.make_shared();\n    ASSERT_EQ(smart.use_count(), 2);\n    ASSERT_EQ(shared_md.use_count(), 1);\n\n    // copying the descriptor does not increment the ref count of the allocator\n    // the descriptor holds a shared_ptr to the allocator,\n    // but the descriptor is not copied, rather it becomes a shared pointer\n    auto copied_md = shared_md;\n    ASSERT_EQ(smart.use_count(), 2);\n    ASSERT_EQ(shared_md.use_count(), 2);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, AlignedSmartAllocator)\n{\n\n    // base allocator\n    auto malloc_raw = memory::malloc_allocator();\n\n    // convert to full fledged allocator - use direct_storage which optimizes out mutexes for stateless allocators\n    auto malloc_alloc = memory::make_allocator_adapter(std::move(malloc_raw));\n\n    static_assert(!decltype(malloc_alloc)::is_stateful::value, \"should be stateless\");\n    static_assert(std::is_same<memory::no_mutex, typename decltype(malloc_alloc)::mutex>::value, \"should use memory::no_mutex\");\n\n    // create a tracker for calls to the malloc allocator\n    auto malloc_tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(malloc_alloc));\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 2, std::move(malloc_tracked));\n\n    // transactional allocator\n    auto alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    alloc.reserve_blocks(2);\n\n    auto aligned = memory::make_aligned_allocator(256, std::move(alloc));\n\n    auto smart = memory::trtlab::make_allocator(std::move(aligned));\n\n    auto p0 = smart.allocate_node(64, 8);\n    auto p1 = smart.allocate_node(64, 8);\n\n    auto i0 = std::uintptr_t(p0);\n    auto i1 = std::uintptr_t(p1);\n\n    ASSERT_EQ(i0 % 256, 0);\n    ASSERT_EQ(i1 % 256, 0);\n\n    ASSERT_GE(i1 - i0, 256);\n\n    smart.deallocate_node(p0, 64, 0);\n    smart.deallocate_node(p1, 64, 0);\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, SmartAllocatorStateful)\n{\n\n    void *ptr;\n\n    // base allocator\n    auto malloc_raw = memory::malloc_allocator();\n\n    // convert to full fledged allocator - use direct_storage which optimizes out mutexes for stateless allocators\n    auto malloc_alloc = memory::make_allocator_adapter(std::move(malloc_raw));\n\n    static_assert(!decltype(malloc_alloc)::is_stateful::value, \"should be stateless\");\n    static_assert(std::is_same<memory::no_mutex, typename decltype(malloc_alloc)::mutex>::value, \"should use memory::no_mutex\");\n\n    // create a tracker for calls to the malloc allocator\n    auto malloc_tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(malloc_alloc));\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(1_MiB, 2, std::move(malloc_tracked));\n\n    // transactional allocator\n    auto alloc = memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n    alloc.reserve_blocks(2);\n\n    // smart allocator\n    // use a special timeout_mutex - throws an exception if the lock is not obtained in MUTEX_TIMEOUT_MS\n    auto smart = memory::trtlab::make_allocator<timeout_mutex>(std::move(alloc));\n    ASSERT_EQ(smart.use_count(), 1);\n\n    // smart allocators should be shared\n    static_assert(memory::is_shared_allocator<decltype(smart)>::value, \"not shared\");\n\n    // ensure we can reach the raw allocator\n    smart.get_raw_allocator().get_block_allocator().set_max_block_count(3);\n\n    // basic allocation\n    ptr = smart.allocate_node(1024, 8);\n    ASSERT_NE(ptr, nullptr) << \"should have thrown an exception or a valid ptr\";\n    smart.deallocate_node(ptr, 1024, 8);\n\n    // smart descriptor\n    {\n        // a smart descriptor holds a shared_ptr to the allocator\n        auto md = smart.allocate_descriptor(1024, 8);\n        ASSERT_EQ(smart.use_count(), 2);\n        ASSERT_NE(md.data(), nullptr);\n        ASSERT_EQ(md.size(), 1024);\n\n        // a smart descriptor is only moveable, not copyable\n        auto moved_md = std::move(md);\n        ASSERT_EQ(md.data(), nullptr);\n        ASSERT_EQ(smart.use_count(), 2);\n        static_assert(!std::is_copy_constructible<decltype(md)>::value, \"should not be copyable\");\n        static_assert(!std::is_copy_assignable<decltype(md)>::value, \"should not be copyable\");\n\n        // to make a smart descriptor copyable, you can create a shared_ptr to it\n        auto shared_md = moved_md.make_shared();\n        ASSERT_EQ(smart.use_count(), 2);\n        ASSERT_EQ(shared_md.use_count(), 1);\n\n        // copying the descriptor does not increment the ref count of the allocator\n        // the descriptor holds a shared_ptr to the allocator,\n        // but the descriptor is not copied, rather it becomes a shared pointer\n        auto copied_md = shared_md;\n        ASSERT_EQ(smart.use_count(), 2);\n        ASSERT_EQ(shared_md.use_count(), 2);\n    }\n\n    // smart allocators are copyable\n    auto smart_copy = smart;\n    ASSERT_EQ(smart.use_count(), 2);\n    ASSERT_EQ(smart_copy.use_count(), 2);\n\n    {\n        auto lock = smart.lock();\n        ASSERT_EQ(smart.use_count(), 2);\n        ASSERT_EQ(smart_copy.use_count(), 2);\n\n        ptr = lock->allocate_node(1024, 8);\n        lock->deallocate_node(ptr, 1024, 8);\n\n        ASSERT_THROW(ptr = smart_copy.allocate_node(1024, 8), timeout_error);\n    }\n\n    // smart allocators are also moveable\n    auto smart_move = std::move(smart_copy);\n    ASSERT_EQ(smart.use_count(), 2);\n    ASSERT_EQ(smart_move.use_count(), 2);\n    ASSERT_EQ(smart_copy.use_count(), 0);\n\n    // create a tracked allocator\n    // if we were not explicity about the copy, smart would have been moved\n    {\n        auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: smart **\"}, smart.copy());\n        ASSERT_EQ(smart.use_count(), 3);\n\n        ptr = tracked.allocate_node(1024, 8);\n        tracked.deallocate_node(ptr, 1024, 8);\n\n        auto lock = smart.lock();\n        ASSERT_THROW(ptr = tracked.allocate_node(1024, 8), timeout_error);\n    }\n\n    ASSERT_EQ(smart.use_count(), 2);\n\n    // without the explicit copy, the passed allocator is moved into the tracker\n    {\n        auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: smart **\"}, smart_move);\n        ASSERT_EQ(smart.use_count(), 2);\n        ASSERT_EQ(smart_move.use_count(), 0);\n\n        ptr = tracked.allocate_node(1024, 8);\n        tracked.deallocate_node(ptr, 1024, 8);\n\n        // tracked.lock() is inaccessible\n        auto lock = tracked.get_allocator().lock();\n        ASSERT_THROW(ptr = smart.allocate_node(1024, 8), timeout_error);\n    }\n\n    ASSERT_EQ(smart.use_count(), 1);\n\n    //\n\n    {\n        // pass by reference which for a shared allocator would call the copy constructor\n        auto v = memory::trtlab::make_vector<int>(smart);\n        ASSERT_EQ(smart.use_count(), 2);\n        v.reserve(1024);\n    }\n\n    ASSERT_EQ(smart.use_count(), 1);\n\n    {\n        // this fails to move the smart allocator into the std_allocator owned by the vector\n        auto v = memory::trtlab::make_vector<int>(std::move(smart));\n        ASSERT_EQ(smart.use_count(), 2);\n        v.reserve(1024);\n    }\n\n    ASSERT_EQ(smart.use_count(), 1);\n\n    // test smart pointers\n\n    {\n        auto shared = memory::allocate_shared<int>(smart, 1);\n        ASSERT_EQ(smart.use_count(), 2);\n    }\n\n    ASSERT_EQ(smart.use_count(), 1);\n\n\n    EndTest();\n}\n\nTEST_F(TestFooMemory, SmartAllocatorStateless)\n{\n    void *ptr;\n\n    // base allocator\n    auto malloc_raw = memory::malloc_allocator();\n    auto malloc_smart = memory::trtlab::make_allocator(std::move(malloc_raw));\n\n    ASSERT_EQ(malloc_smart.use_count(), 1);\n\n    ptr = malloc_smart.allocate_node(1024, 8);\n    malloc_smart.deallocate_node(ptr, 1024, 8);\n\n    auto smart_copy = malloc_smart;\n    ASSERT_EQ(malloc_smart.use_count(), 2);\n    ASSERT_EQ(smart_copy.use_count(), 2);\n\n    {\n        auto lock = malloc_smart.lock();\n        ASSERT_EQ(malloc_smart.use_count(), 2);\n        ASSERT_EQ(smart_copy.use_count(), 2);\n\n        ptr = lock->allocate_node(1024, 8);\n        lock->deallocate_node(ptr, 1024, 8);\n\n        DVLOG(1) << \"this should not hang - stateless allocators, even if requesting std::mutex use no_mutex\";\n        ptr = smart_copy.allocate_node(1024, 8);\n        smart_copy.deallocate_node(ptr, 1024, 8);\n    }\n\n    EndTest();\n}\n\n\nstruct backend {};\nstruct backend_a : backend {};\nstruct backend_b : backend_a {};\nstruct backend_c : backend {};\n\ntemplate<typename BackendType>\nclass md : public BackendType\n{\n  public:\n    md() : m_ptr(nullptr) {}\n    md(void* ptr) : m_ptr(ptr) {}\n\n  private:\n    void* m_ptr;\n};\n\n\ntemplate<typename BackendType>\nvoid do_a(md<BackendType>& require_a_or_derived_from_a)\n{\n    static_assert(std::is_base_of<backend_a, md<BackendType>>::value, \"Backend needs to be derived from backend_a\");\n    DVLOG(1) << \"yep\";\n}\n\n\nTEST_F(TestFooMemory, TemplateInheritance)\n{\n    static_assert(std::is_base_of<backend, md<backend>>::value, \"should be true\");\n    static_assert(std::is_base_of<backend_a, md<backend_b>>::value, \"should be true\");\n\n    auto a = std::move(md<backend_a>());\n    auto b = std::move(md<backend_b>());\n    auto c = std::move(md<backend_c>());\n\n    do_a(a);\n    do_a(b);\n\n    // will fail to compile\n    //do_a(c);\n}\n\nstruct pinned_memory : memory::host_memory\n{\n    static constexpr DLDeviceType device_type() { return kDLCPUPinned; }\n};\n\n#include <typeinfo>\n\nTEST_F(TestFooMemory, OtherMemoryTypes)\n{\n    ASSERT_EQ(memory::host_memory::device_type(), kDLCPU);\n    ASSERT_EQ(pinned_memory::device_type(), kDLCPUPinned);\n    ASSERT_EQ(pinned_memory::min_alignment(), 8UL);\n}\n\n\n/*\n\nmin_alignment CAN be overridden, but ONLY IF the value is GREATER than the base memory_type.\n\nIn this test, malloc_allocator has memory_type == host_memory which has a default min_alignment of 8.\n\n1024 CAN be used as a min_alignment override.\n1 CANNOT be used as a min_alignment override.\n\n*/\n\nstruct malloc_allocator_1024 : public memory::malloc_allocator\n{\n    constexpr static std::size_t min_alignment() { return 1024UL; }\n};\n\nstruct malloc_allocator_1 : public memory::malloc_allocator\n{\n    constexpr static std::size_t min_alignment() { return 1UL; }\n};\n\nTEST_F(TestFooMemory, MinAlignment)\n{\n    auto raw_1 = malloc_allocator_1();\n    auto malloc_1 = memory::trtlab::make_allocator(std::move(raw_1));\n\n    auto raw = memory::malloc_allocator();\n    auto malloc_8 = memory::trtlab::make_allocator(std::move(raw));\n\n    auto raw_1024 = malloc_allocator_1024();\n    auto malloc_1024 = memory::trtlab::make_allocator(std::move(raw_1024));\n\n    ASSERT_EQ(malloc_1.min_alignment(), 8UL);\n    ASSERT_EQ(malloc_8.min_alignment(), 8UL);\n    ASSERT_EQ(malloc_1024.min_alignment(), 1024UL);\n}\n\n\nTEST_F(TestFooMemory, FirstTouch)\n{\n    trtlab::CpuSet cpus = trtlab::Affinity::GetCpusFromString(\"0,1\");\n    auto raw = memory::malloc_allocator();\n    auto ft = memory::trtlab::make_first_touch_allocator(cpus, std::move(raw));\n    auto alloc = memory::trtlab::make_allocator(std::move(ft));\n\n    auto md = alloc.allocate_descriptor(1_MiB);\n}"
  },
  {
    "path": "trtlab/core/tests/test_main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <glog/logging.h>\n#include <gtest/gtest.h>\n\nint main(int argc, char **argv) {\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"trtlab::test_core\");\n    ::testing::InitGoogleTest(&argc, argv);\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n    return RUN_ALL_TESTS();\n}"
  },
  {
    "path": "trtlab/core/tests/test_memory.cc",
    "content": "#include <gtest/gtest.h>\n\n#include <trtlab/core/memory/first_touch_allocator.h>\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/malloc_allocator.h>\n\nclass TestMemory : public ::testing::Test {};\n\nusing namespace trtlab::memory;\n\nTEST_F(TestMemory, FirstTouchAllocator)\n{\n    auto raw = first_touch_allocator<malloc_allocator, 0x42>(0);\n    auto alloc = make_allocator(std::move(raw));\n\n    auto md = alloc.allocate_descriptor(16);\n\n    char *data = (char *) md.data();\n    for(int i=0; i<16; i++)\n    {\n        EXPECT_EQ(data[i], 0x42);\n    }\n}"
  },
  {
    "path": "trtlab/core/tests/test_memory_old.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/bytes.h\"\n#include \"trtlab/core/memory/bytes_allocator.h\"\n#include \"trtlab/core/memory/tensor.h\"\n#include \"trtlab/core/memory/copy.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/sysv_allocator.h\"\n#include \"trtlab/core/memory/transactional_allocator.h\"\n#include \"trtlab/core/utils.h\"\n\n#include <cstring>\n#include <list>\n\n#include <gtest/gtest.h>\n\n#include <foonathan/memory/container.hpp> // vector, list, list_node_size\n#include <foonathan/memory/memory_pool.hpp> // memory_pool\n#include <foonathan/memory/smart_ptr.hpp> // allocate_unique\n#include <foonathan/memory/static_allocator.hpp> // static_allocator_storage, static_block_allocator\n#include <foonathan/memory/temporary_allocator.hpp> // temporary_allocator\n#include <foonathan/memory/allocator_storage.hpp>\n#include <foonathan/memory/tracking.hpp>\n\n#include <foonathan/memory/namespace_alias.hpp>\n\nusing namespace trtlab;\n\nnamespace {\n\nstatic mem_size_t one_kb = 1024;\nstatic mem_size_t one_mb = one_kb * one_kb;\ntypedef std::vector<mem_size_t> shape_t;\n\ntemplate<typename T>\nclass TestMemory : public ::testing::Test\n{\n};\n\nusing MemoryTypes = ::testing::Types<Malloc, SystemV>;\n\nTYPED_TEST_CASE(TestMemory, MemoryTypes);\n\n/*\nTYPED_TEST(TestMemory, should_not_compile)\n{\n    TypeParam memory(one_mb);\n}\n*/\n\nTYPED_TEST(TestMemory, make_shared)\n{\n    auto shared = std::make_shared<Allocator<TypeParam>>(one_mb);\n\n    EXPECT_TRUE(shared->Data());\n    EXPECT_EQ(shared->Size(), one_mb);\n    EXPECT_EQ(shared->Capacity(), one_mb);\n    EXPECT_EQ(shared->Shape().size(), 1);\n    EXPECT_EQ(shared->Shape()[0], one_mb);\n    EXPECT_EQ(shared->DataType(), types::bytes);\n    EXPECT_EQ(shared->DeviceInfo().device_type, kDLCPU);\n    EXPECT_EQ(shared->DeviceInfo().device_id, 0);\n\n    shared.reset();\n    EXPECT_FALSE(shared);\n}\n\nTYPED_TEST(TestMemory, make_unique)\n{\n    auto unique = std::make_unique<Allocator<TypeParam>>(one_mb);\n\n    EXPECT_TRUE(unique->Data());\n    EXPECT_EQ(unique->Size(), one_mb);\n    EXPECT_EQ(unique->Capacity(), one_mb);\n    EXPECT_EQ(unique->Shape().size(), 1);\n    EXPECT_EQ(unique->Shape()[0], one_mb);\n    EXPECT_EQ(unique->DataType(), types::bytes);\n    EXPECT_EQ(unique->DeviceInfo().device_type, kDLCPU);\n    EXPECT_EQ(unique->DeviceInfo().device_id, 0);\n\n    unique.reset();\n    EXPECT_FALSE(unique);\n}\n\nTYPED_TEST(TestMemory, ctor)\n{\n    Allocator<TypeParam> memory(one_mb);\n\n    EXPECT_TRUE(memory.Data());\n    EXPECT_EQ(memory.Size(), one_mb);\n    EXPECT_EQ(memory.Capacity(), one_mb);\n    EXPECT_EQ(memory.Shape().size(), 1);\n    EXPECT_EQ(memory.Shape()[0], one_mb);\n    EXPECT_EQ(memory.DataType(), types::bytes);\n    EXPECT_EQ(memory.DeviceInfo().device_type, kDLCPU);\n    EXPECT_EQ(memory.DeviceInfo().device_id, 0);\n}\n\nTYPED_TEST(TestMemory, move_ctor)\n{\n    Allocator<TypeParam> memory(one_mb);\n    Allocator<TypeParam> host(std::move(memory));\n\n    EXPECT_TRUE(host.Data());\n    EXPECT_EQ(one_mb, host.Size());\n    EXPECT_EQ(host.Shape()[0], one_mb);\n\n    EXPECT_FALSE(memory.Data());\n    EXPECT_EQ(memory.Size(), 0);\n    EXPECT_EQ(memory.Capacity(), 0);\n    EXPECT_EQ(memory.Shape().size(), 0);\n}\n\nTYPED_TEST(TestMemory, move_ctor_with_reshape)\n{\n    Allocator<TypeParam> memory(one_mb);\n\n    memory.Reshape({512, 512}, types::fp32);\n    DLOG(INFO) << \"reshaped\";\n    DLOG(INFO) << memory;\n    DLOG(INFO) << \"reshaped\";\n    EXPECT_EQ(memory.Size(), one_mb);\n    EXPECT_EQ(memory.Capacity(), one_mb);\n    EXPECT_EQ(memory.Shape()[0], 512);\n    EXPECT_EQ(memory.Shape()[1], 512);\n    EXPECT_EQ(memory.DataType(), types::fp32);\n\n    Allocator<TypeParam> host(std::move(memory));\n    DLOG(INFO) << \"moved\";\n\n    // moved location\n    EXPECT_TRUE(host.Data());\n    EXPECT_EQ(host.Size(), one_mb);\n    EXPECT_EQ(host.Capacity(), one_mb);\n    EXPECT_EQ(host.Shape()[0], 512);\n    EXPECT_EQ(host.Shape()[1], 512);\n    EXPECT_EQ(host.DataType(), types::fp32);\n\n    // original location\n    EXPECT_FALSE(memory.Data());\n    EXPECT_EQ(memory.Size(), 0);\n    EXPECT_EQ(memory.Capacity(), 0);\n    EXPECT_EQ(memory.DataType(), types::nil);\n}\n\nTYPED_TEST(TestMemory, move_to_shared_ptr)\n{\n    Allocator<TypeParam> memory(one_mb);\n    auto ptr = std::make_shared<Allocator<TypeParam>>(std::move(memory));\n    EXPECT_TRUE(ptr);\n    EXPECT_TRUE(ptr->Data());\n    EXPECT_FALSE(memory.Data());\n}\n\nTYPED_TEST(TestMemory, smart_move)\n{\n    auto shared = std::make_shared<Allocator<TypeParam>>(one_mb);\n    std::weak_ptr<TypeParam> weak = shared;\n\n    {\n        std::vector<std::shared_ptr<CoreMemory>> core_segs;\n        std::vector<std::shared_ptr<HostMemory>> host_segs;\n\n        core_segs.push_back(shared);\n        host_segs.push_back(std::move(shared));\n\n        EXPECT_FALSE(weak.expired());\n    }\n\n    EXPECT_TRUE(weak.expired());\n}\n\nTYPED_TEST(TestMemory, shape)\n{\n    Allocator<TypeParam> memory(one_mb);\n    shape_t shape = {one_mb};\n\n    EXPECT_EQ(memory.Shape(), shape);\n\n    // Exact Size\n    memory.Reshape({512, 512}, types::fp32);\n    EXPECT_EQ(memory.Shape()[0], 512);\n    EXPECT_EQ(memory.Shape()[1], 512);\n    EXPECT_EQ(memory.DataType(), types::fp32);\n    EXPECT_EQ(memory.Size(), memory.Capacity());\n\n    // Exact Size\n    memory.Reshape({1024, 512}, types::fp16);\n    EXPECT_EQ(memory.Shape()[0], 1024);\n    EXPECT_EQ(memory.Shape()[1], 512);\n    EXPECT_EQ(memory.DataType(), types::fp16);\n\n    // Exact Size\n    memory.Reshape({1024, 1024}, types::int8);\n    EXPECT_EQ(memory.Shape()[0], 1024);\n    EXPECT_EQ(memory.Shape()[1], 1024);\n    EXPECT_EQ(memory.DataType(), types::int8);\n\n    // Reshape to smaller than allocated\n    memory.Reshape({256, 128}, types::int8);\n    EXPECT_EQ(memory.Shape()[0], 256);\n    EXPECT_EQ(memory.Shape()[1], 128);\n    EXPECT_EQ(memory.Capacity(), one_mb);\n    EXPECT_EQ(memory.Size(), 256 * 128 * types::int8.bytes());\n    EXPECT_LT(memory.Size(), memory.Capacity());\n\n    // Reshape to larger than allocated\n    try\n    {\n        memory.Reshape({512, 513}, types::fp32);\n        FAIL() << \"Expected std::length_error\";\n    }\n    catch(std::length_error const& err)\n    {\n        EXPECT_EQ(err.what(), std::string(\"Reshape exceeds capacity\"));\n    }\n    catch(...)\n    {\n        FAIL() << \"Expected std::length_error\";\n    }\n}\n\nTYPED_TEST(TestMemory, alignment)\n{\n    EXPECT_EQ(TypeParam::DefaultAlignment(), 64);\n    EXPECT_EQ(TypeParam::AlignedSize(1), 64);\n    EXPECT_EQ(TypeParam::AlignedSize(64), 64);\n    EXPECT_EQ(TypeParam::AlignedSize(65), 128);\n\n    /*\n        EXPECT_EQ(TypeParam::AlignedSize<float>(15), 64);\n        EXPECT_EQ(TypeParam::AlignedSize<float>(16), 64);\n        EXPECT_EQ(TypeParam::AlignedSize<float>(17), 128);\n\n        EXPECT_EQ(TypeParam::AlignedSize<double>(7), 64);\n        EXPECT_EQ(TypeParam::AlignedSize<double>(8), 64);\n        EXPECT_EQ(TypeParam::AlignedSize<double>(9), 128);\n    */\n}\n\n// This tests an object very similar to the pybind11\n// DLPack Descriptor\ntemplate<typename MemoryType>\nclass DescFromSharedPointer : public Descriptor<MemoryType>\n{\n  public:\n    DescFromSharedPointer(std::shared_ptr<MemoryType> shared)\n        : Descriptor<MemoryType>(\n              shared,\n              std::string(\"SharedPointer<\" + std::string(shared->TypeName()) + \">\").c_str()),\n          m_ManagedMemory(shared)\n    {\n    }\n\n    ~DescFromSharedPointer() override {}\n\n    std::function<void()> CaptureSharedObject()\n    {\n        return [mem = m_ManagedMemory] { DLOG(INFO) << *mem; };\n    }\n\n  private:\n    std::shared_ptr<MemoryType> m_ManagedMemory;\n};\n\nTYPED_TEST(TestMemory, DescriptorFromSharedPointer)\n{\n    auto shared = std::make_shared<Allocator<TypeParam>>(one_mb);\n\n    std::weak_ptr<TypeParam> weak = shared;\n    ASSERT_EQ(weak.use_count(), 1);\n\n    std::function<void()> captured_obj;\n\n    {\n        // the descriptor captures the shared ptr twice\n        // once in the descriptors deleter and the other\n        // as the m_ManagedMemory shared_ptr\n        DescFromSharedPointer<TypeParam> desc(shared);\n        ASSERT_EQ(weak.use_count(), 3);\n\n        captured_obj = desc.CaptureSharedObject();\n        ASSERT_EQ(weak.use_count(), 4);\n    }\n\n    // descriptor out of scope\n    ASSERT_EQ(weak.use_count(), 2);\n\n    shared.reset();\n    ASSERT_EQ(weak.use_count(), 1);\n\n    // calling does not release\n    captured_obj();\n\n    // release\n    DLOG(INFO) << \"ref count to zero\";\n    captured_obj = nullptr;\n\n    ASSERT_TRUE(weak.expired());\n}\n\nclass TestSystemVMemory : public ::testing::Test\n{\n};\n\nTEST_F(TestSystemVMemory, same_process)\n{\n    Allocator<SystemV> first(one_mb);\n    ASSERT_GE(first.ShmID(), 0);\n    ASSERT_EQ(first.Size(), one_mb);\n    ASSERT_EQ(first.Capacity(), one_mb);\n\n    // test move\n    auto master = std::move(first);\n    ASSERT_GE(master.ShmID(), 0);\n    ASSERT_EQ(master.Size(), one_mb);\n    ASSERT_EQ(master.Capacity(), one_mb);\n    ASSERT_EQ(first.ShmID(), -1);\n\n    {\n        auto attached = SystemV::Attach(master.ShmID());\n        EXPECT_EQ(master.ShmID(), attached->ShmID());\n        EXPECT_EQ(master.Size(), attached->Size());\n        // different virtual address pointing at the same memory\n        EXPECT_NE(master.Data(), attached->Data());\n        auto master_ptr = static_cast<long*>(master.Data());\n        auto attach_ptr = static_cast<long*>(attached->Data());\n        *master_ptr = 0xDEADBEEF;\n        EXPECT_EQ(*master_ptr, *attach_ptr);\n        EXPECT_EQ(*attach_ptr, 0xDEADBEEF);\n        DLOG(INFO) << \"finished with attached\";\n    }\n    DLOG(INFO) << \"finished with test\";\n}\n\nTEST_F(TestSystemVMemory, smart_ptrs)\n{\n    auto master = std::make_unique<Allocator<SystemV>>(one_mb);\n    EXPECT_TRUE(master->ShmID());\n    auto attached = SystemV::Attach(master->ShmID());\n    EXPECT_EQ(master->ShmID(), attached->ShmID());\n    EXPECT_EQ(master->Size(), attached->Size());\n\n    // different virtual address pointing at the same memory\n    EXPECT_NE(master->Data(), attached->Data());\n\n    // ensure both segments point to the same data\n    auto master_ptr = static_cast<long*>(master->Data());\n    auto attach_ptr = static_cast<long*>(attached->Data());\n    *master_ptr = 0xDEADBEEF;\n    EXPECT_EQ(*master_ptr, *attach_ptr);\n\n    DLOG(INFO) << \"releasing the attached segment\";\n    attached.reset();\n    DLOG(INFO) << \"released the attached segment\";\n}\n\nTEST_F(TestSystemVMemory, TryAttachingToDeletedSegment)\n{\n    auto master = std::make_unique<Allocator<SystemV>>(one_mb);\n    EXPECT_TRUE(master->ShmID());\n    auto shm_id = master->ShmID();\n    master.reset();\n    DLOG(INFO) << \"trying to attach to a deleted segment\";\n    EXPECT_DEATH(auto attached = SystemV::Attach(shm_id), \"\");\n}\n\nclass TestCopy : public ::testing::Test\n{\n};\n\nTEST_F(TestCopy, MallocToMalloc)\n{\n    char v0 = 111;\n    char v1 = 222;\n\n    Allocator<Malloc> m0(one_kb);\n    std::memset(m0.Data(), v0, one_kb);\n\n    auto m0_array = static_cast<char*>(m0.Data());\n    EXPECT_EQ(m0_array[0], v0);\n    EXPECT_EQ(m0_array[0], m0_array[1023]);\n\n    auto m1 = std::make_unique<Allocator<Malloc>>(one_mb);\n    std::memset(m1->Data(), v1, one_mb);\n\n    auto m1_array = static_cast<char*>(m1->Data());\n    EXPECT_EQ(m1_array[0], v1);\n    EXPECT_EQ(m1_array[0], m1_array[1024]);\n\n    EXPECT_NE(m0_array[0], m1_array[0]);\n\n    // Copy smaller into larger\n    Copy(*m1, m0, 1024);\n\n    EXPECT_EQ(m1_array[0], v0);\n    EXPECT_EQ(m1_array[1024], v1);\n}\n\nclass TestGeneric : public ::testing::Test\n{\n};\n\nTEST_F(TestGeneric, AllocatedPolymorphism)\n{\n    auto malloc = std::make_shared<Allocator<Malloc>>(1024);\n    auto sysv = std::make_shared<Allocator<SystemV>>(1024);\n\n    std::vector<std::shared_ptr<CoreMemory>> memory;\n\n    memory.push_back(std::move(malloc));\n    memory.push_back(std::move(sysv));\n}\n\ntemplate<typename T>\nclass TestProvider : public BytesProvider<T>\n{\n  public:\n    TestProvider() : m_Memory(one_mb) {}\n\n    Bytes<T> Allocate(size_t offset, size_t size)\n    {\n        CHECK(m_Memory[offset + size]);\n        CHECK(m_Memory[offset]);\n        return this->BytesFromThis(m_Memory[offset], size);\n    }\n\n  private:\n    const void* BytesProviderData() const final override { return m_Memory.Data(); }\n    mem_size_t BytesProviderSize() const final override { return m_Memory.Size(); }\n    const DLContext& BytesProviderDeviceInfo() const final override\n    {\n        return m_Memory.DeviceInfo();\n    }\n    const T& BytesProviderMemory() const final override { return m_Memory; }\n\n    Allocator<T> m_Memory;\n};\n\n#if ENABLED_BYTES_HANDLE\nTEST_F(TestGeneric, BytesHandleLifecycle)\n{\n    auto provider = std::make_shared<TestProvider<Malloc>>();\n    auto obj = provider->Allocate(one_kb, one_kb);\n    auto d1 = obj.Handle();\n    // auto p1 = detail::BytesHandleFactory::HostPinned((void*)0xFACEBEEF, 2048);\n    // auto g1 = detail::BytesHandleFactory::Device((void*)0xFACEB000, 1024*1024);\n\n    auto d2 = d1;\n    ASSERT_EQ(d2.Data(), d1.Data());\n    ASSERT_EQ(d2.Size(), d1.Size());\n\n    auto d3 = std::move(d2);\n    ASSERT_EQ(d3.Data(), d1.Data());\n    ASSERT_EQ(d3.Size(), d1.Size());\n    ASSERT_EQ(d2.Data(), nullptr);\n    ASSERT_EQ(d2.Size(), 0);\n\n    BytesHandle<Malloc> d4(std::move(d3));\n    ASSERT_EQ(d4.Data(), d1.Data());\n    ASSERT_EQ(d4.Size(), d1.Size());\n    ASSERT_EQ(d3.Data(), nullptr);\n    ASSERT_EQ(d3.Size(), 0);\n\n    BytesHandle<Malloc> d5(d4);\n    ASSERT_EQ(d4.Data(), d1.Data());\n    ASSERT_EQ(d4.Size(), d1.Size());\n    ASSERT_EQ(d5.Data(), d1.Data());\n    ASSERT_EQ(d5.Size(), d1.Size());\n\n    // Downcasting from Malloc to HostMemory is allowed\n    auto h1 = d5.BaseHandle();\n\n    // Upcasting from HostMemory to Malloc is forbidden\n    // EXPECT_THROW(auto m1 = h1.Cast<Malloc>(), std::bad_cast);\n\n    // compiler error; different types\n    // h1 = d4;\n    // h1 = std::move(d4);\n    // BytesHandle<Malloc> copy_ctor(h1);\n    // BytesHandle<Malloc> move_ctor(std::move(h1));\n}\n#endif\n\nnamespace middleman {\nclass base\n{\n};\n\ntemplate<typename T>\nclass derived_base : public base\n{\n};\n\ntemplate<typename T>\nclass derived : public derived_base<typename T::BaseType>\n{\n};\n} // namespace middleman\n\nTEST_F(TestGeneric, TemplatedMiddleman)\n{\n    auto t = middleman::derived<Malloc>();\n    auto derived = std::make_shared<middleman::derived<Malloc>>(std::move(t));\n    std::shared_ptr<middleman::derived_base<HostMemory>> host = derived;\n\n    // derived<Malloc> : derived_base<HostName>\n\n    // std::shared_ptr<middleman::derived<HostMemory>> host = derived;\n}\n\nTEST_F(TestGeneric, ProtectedInheritance)\n{\n    struct a\n    {\n    };\n    struct b : protected a\n    {\n    };\n\n    EXPECT_FALSE((std::is_convertible<b*, a*>::value));\n\n    struct c : public a\n    {\n    };\n\n    EXPECT_TRUE((std::is_convertible<c*, a*>::value));\n\n    struct d : protected a\n    {\n        operator const a&() { return *this; }\n    };\n\n    d objd;\n    a obja = (const a&)objd;\n\n    EXPECT_FALSE((std::is_convertible<const d&, const a&>::value));\n}\n\nTEST_F(TestGeneric, BytesCapture)\n{\n    auto provider = std::make_shared<TestProvider<Malloc>>();\n    CHECK(provider);\n    std::weak_ptr<TestProvider<Malloc>> weak = provider;\n\n    {\n        auto bytes = std::move(provider->Allocate(0, one_mb));\n        ASSERT_EQ(bytes.Size(), one_mb);\n\n        provider.reset();\n        ASSERT_FALSE(weak.expired());\n    }\n    ASSERT_TRUE(weak.expired());\n}\n\nTEST_F(TestGeneric, BytesCopyMoveAssignment)\n{\n    auto provider = std::make_shared<TestProvider<Malloc>>();\n    CHECK(provider);\n    std::weak_ptr<TestProvider<Malloc>> weak = provider;\n    ASSERT_EQ(provider.use_count(), 1);\n    const auto half_mb = one_mb / 2;\n\n    {\n        // move assignment\n        auto mv_assign = std::move(provider->Allocate(0, one_mb));\n        auto ptr = mv_assign.Data();\n        ASSERT_EQ(weak.use_count(), 2);\n        EXPECT_EQ(mv_assign.Size(), one_mb);\n        EXPECT_EQ(mv_assign.NDims(), 1);\n        EXPECT_EQ(mv_assign.Shape()[0], one_mb);\n        EXPECT_EQ(mv_assign.Strides()[0], 1);\n\n        Bytes<Malloc> mv_ctor(std::move(mv_assign));\n        ASSERT_EQ(weak.use_count(), 2);\n        ASSERT_EQ(mv_ctor.Data(), ptr);\n        ASSERT_EQ(mv_assign.Data(), nullptr);\n\n        // check to ensure we can get back to the Provider's Memory object\n        ASSERT_EQ(mv_ctor.Memory().Data(), ptr);\n\n        // release the shared_ptr to the provider; our Bytes object still has a ref\n        provider.reset();\n        ASSERT_EQ(weak.use_count(), 1);\n        ASSERT_EQ(mv_ctor.Data(), ptr);\n\n        auto derived = std::make_shared<Bytes<Malloc>>(std::move(mv_ctor));\n        std::shared_ptr<BytesBase> base = derived;\n        ASSERT_EQ(derived->Data(), ptr);\n        ASSERT_EQ(base->Data(), ptr);\n\n        auto take_away = std::move(*derived);\n        EXPECT_EQ(take_away.Data(), ptr);\n        EXPECT_EQ(derived->Data(), nullptr);\n        EXPECT_EQ(base->Data(), nullptr);\n\n        // should not compile\n        // public inheritance; protected copy/move ctors/assignments\n        // BytesBase base = std::move(*derived);\n\n        // should not compile\n        // copy ctor deleted\n        // Bytes<Malloc> copy_ctor(*derived);\n        ASSERT_FALSE(std::is_copy_constructible<Bytes<Malloc>>::value);\n        ASSERT_TRUE(std::is_move_constructible<Bytes<Malloc>>::value);\n\n        // should not compile\n        // copy ctor/assignment deleted\n        // auto copy = *derived\n        ASSERT_FALSE(std::is_copy_assignable<Bytes<Malloc>>::value);\n        ASSERT_TRUE(std::is_move_assignable<Bytes<Malloc>>::value);\n\n        BytesBaseType<HostMemory> host = std::move(take_away);\n        ASSERT_EQ(weak.use_count(), 1);\n        EXPECT_EQ(host.Data(), ptr);\n        EXPECT_EQ(take_away.Data(), nullptr);\n        EXPECT_EQ(take_away.Size(), 0);\n        EXPECT_EQ(take_away.NDims(), 0);\n        EXPECT_EQ(take_away.Shape()[0], 0);\n        EXPECT_EQ(take_away.Strides()[0], 0);\n\n        host.Release();\n        ASSERT_EQ(weak.use_count(), 0);\n    }\n    ASSERT_EQ(weak.use_count(), 0);\n}\n\n\nTEST_F(TestGeneric, MemoryProvider)\n{\n    auto sysv = Allocator<SystemV>(2*one_mb);\n    auto mb = BytesAllocator<Malloc>::Allocate(one_mb);\n    auto sb = BytesAllocator<SystemV>::Expose(std::move(sysv));\n\n}\n\n\n\nTEST_F(TestGeneric, FooNathanAlignOffset)\n{\n/*\n    using memory::detail::align_offset;\n    auto val = align_offset((void*)(1), 64);\n    EXPECT_EQ(val, 63);\n\n    val = align_offset((void*)128, 64);\n    EXPECT_EQ(val, 0);\n\n    // this line should not compile in debug mode - alignments must be powers of 2\n    // auto compile = align_offset((void*)(1), 63);\n\n    // ASSERT_EQ(memory::unordered_set_node_size<int>::value, 0);\n\n    struct log_tracker\n    {\n        void on_node_allocation(void* ptr, std::size_t size, std::size_t) noexcept\n        {\n            LOG(INFO) << \" node allocated: \" << ptr << \"; \" << size;\n        }\n\n        void on_node_deallocation(void *ptr, std::size_t size, std::size_t) noexcept\n        {\n            LOG(INFO) << \" node deallocated: \" << ptr << \"; \" << size;\n        }\n    };\n\n    //auto heap = memory::MallocAllocator();\n    auto storage = memory::make_allocator_adapter(memory::MallocAllocator());\n    auto tracked = memory::make_tracked_allocator(log_tracker{}, std::move(storage));\n\n    void *ptr = tracked.allocate_node(4096u, 64u);\n    tracked.deallocate_node(ptr, 4096u, 64u);\n\n    auto unique = memory::allocate_unique<int>(tracked, 1024);\n    LOG(INFO) << *unique;\n\n    memory::static_allocator_storage<4096u> static_storage;\n    using static_pool_t = memory::memory_pool<memory::node_pool, memory::static_block_allocator>;\n    static_pool_t static_pool(64u, 4096u, static_storage);\n    auto tracked_pool = memory::make_tracked_allocator(log_tracker{}, std::move(static_pool));\n    auto v1 = memory::allocate_unique<int>(tracked_pool, 2048);\n    auto v2 = memory::allocate_unique<int>(tracked_pool, 4096);\n    v1.reset();\n    v1 = memory::allocate_unique<int>(tracked_pool, 1024);\n*/\n}\n\nstatic void* make_ptr(std::size_t addr)\n{\n    return reinterpret_cast<void*>(addr);\n}\n\nstatic std::size_t make_int(void* addr)\n{\n    return reinterpret_cast<std::size_t>(addr);\n}\n\nstatic std::size_t make_int(const char* addr)\n{\n    return std::size_t(addr);\n}\n\n\n\n\nTEST_F(TestGeneric, FooFixedSizedStackAllocator)\n{\n    /*\n    memory::trtlab::transactional_detail::FixedSizeStackAllocator alloc(make_ptr(128), 1024);\n\n    std::size_t remaining = 1024;\n    auto a0 = alloc.Allocate(1, 1);\n    EXPECT_EQ(alloc.Available(), remaining -= 1);\n    auto a1 = alloc.Allocate(1, 1);\n    EXPECT_EQ(alloc.Available(), remaining -= 1);\n    auto a2 = alloc.Allocate(1, 8);\n    EXPECT_EQ(alloc.Available(), remaining = 1024 - 8 - 1);\n    auto out_of_range = alloc.Allocate(2048, 8);\n\n    char p = 128;\n\n    EXPECT_EQ(make_int(a0), 128);\n    EXPECT_EQ(make_int(a1), 129);\n    EXPECT_EQ(make_int(a2), 128 + 8);\n    EXPECT_EQ(out_of_range, nullptr);\n\n    auto moved_alloc = std::move(alloc);\n\n    auto should_be_nullptr = alloc.Allocate(8, 8);\n    EXPECT_EQ(should_be_nullptr, nullptr);\n    EXPECT_EQ(alloc.Available(), 0u);\n\n    EXPECT_EQ(moved_alloc.Available(), remaining);\n    auto a3 = moved_alloc.Allocate(128, 64);\n    EXPECT_EQ(moved_alloc.Available(), remaining = 1024 - 64 - 128);\n\n\n    EXPECT_TRUE(moved_alloc.Contains(make_ptr(128)));\n    EXPECT_TRUE(moved_alloc.Contains(make_ptr(1024+128-1)));\n    EXPECT_FALSE(moved_alloc.Contains(make_ptr(1024+128)));\n    EXPECT_FALSE(moved_alloc.Contains(make_ptr(127)));\n\n    EXPECT_FALSE(alloc.Contains(make_ptr(128)));\n    EXPECT_FALSE(alloc.Contains(make_ptr(1024+128-1)));\n    EXPECT_FALSE(alloc.Contains(make_ptr(1024+128)));\n    EXPECT_FALSE(alloc.Contains(make_ptr(127)));\n\n    EXPECT_TRUE(alloc.Contains(nullptr));\n    EXPECT_FALSE(moved_alloc.Contains(nullptr));\n    */\n}\n\nTEST_F(TestGeneric, FooTransactionalStackAllocator)\n{\n    /*\n    std::size_t remaining = 1024;\n    memory::trtlab::transactional_detail::StackAllocator alloc(make_ptr(128), remaining);\n\n    auto a0 = alloc.Allocate(1, 1);\n    EXPECT_EQ(alloc.Available(), remaining -= 1);\n    EXPECT_EQ(alloc.InUseCount(), 1);\n\n    auto a1 = alloc.Allocate(1, 1);\n    EXPECT_EQ(alloc.Available(), remaining -= 1);\n    EXPECT_EQ(alloc.InUseCount(), 2);\n\n    auto a2 = alloc.Allocate(1, 8);\n    EXPECT_EQ(alloc.Available(), remaining = 1024 - 8 - 1);\n    EXPECT_EQ(alloc.InUseCount(), 3);\n\n    EXPECT_ANY_THROW(auto out_of_range = alloc.Allocate(2048, 8));\n    EXPECT_EQ(alloc.InUseCount(), 3);\n\n    EXPECT_FALSE(alloc.ShouldReleaseAfterDeallocate(a1));\n    EXPECT_FALSE(alloc.ShouldReleaseAfterDeallocate(a2));\n    EXPECT_TRUE(alloc.ShouldReleaseAfterDeallocate(a0));\n    */\n}\n\ntemplate<typename RawAllocator>\nauto make_balloc(std::size_t block_size, std::size_t max_blocks, RawAllocator&& alloc)\n{\n    return memory::trtlab::GrowthCappedFixedSizeBlockAllocator<RawAllocator>(block_size, max_blocks, std::move(alloc));\n}\n\n\n/*\nTEST_F(TestGeneric, HostDescriptorDLTensorLifecycle)\n{\n    void *ptr = (void*)0xDEADBEEF;\n    mem_size_t size = 13370;\n    DLTensor dltensor;\n    std::shared_ptr<nextgen::SharedDescriptor<HostMemory>> shared_hdesc;\n\n    {\n        nextgen::HostDescriptor hdesc(ptr, size, [&ptr, &size]{\n            ptr = nullptr;\n            size = 0;\n        });\n        EXPECT_EQ(hdesc.Data(), (void*)0xDEADBEEF);\n        EXPECT_EQ(hdesc.Size(), 13370);\n        hdesc.Reshape({13370/2, 1}, types::fp16);\n\n        // regular descriptors can not expose a dltensor\n        // dltensor = (DLTensor)hdesc;\n\n        shared_hdesc =\nstd::make_shared<nextgen::SharedDescriptor<HostMemory>>(std::move(hdesc)); dltensor =\n(DLTensor)(*shared_hdesc);\n\n        EXPECT_EQ(shared_hdesc->Data(), dltensor.data);\n        EXPECT_EQ(shared_hdesc->Capacity(), 13370);\n        EXPECT_EQ(dltensor.ctx.device_type, kDLCPU);\n        EXPECT_EQ(dltensor.dtype.code, kDLFloat);\n        EXPECT_EQ(dltensor.dtype.bits, 16U);\n        EXPECT_EQ(dltensor.dtype.lanes, 1U);\n        EXPECT_EQ(dltensor.ndim, 2);\n    }\n\n    // dltensor is still valid as shared_hdesc is still valid\n    EXPECT_EQ(ptr, (void*)0xDEADBEEF);\n    EXPECT_EQ(size, 13370);\n    EXPECT_EQ(dltensor.ndim, 2);\n    EXPECT_EQ(dltensor.shape[0], 13370/2);\n    EXPECT_EQ(dltensor.shape[1], 1);\n/*\n    {\n        HostDescriptor hdesc(dltensor, [shared_hdesc]{});\n        // shared_hdesc and hdesc do share the same memory;\n        // however, they have difference DLPack descriptors that were equivalent\n        // on instantiate, but can change with their respective objects\n        // changes to hdesc are not seen by shared_hdesc\n        EXPECT_EQ(hdesc.Data(), dltensor.data);\n        EXPECT_EQ(hdesc.Capacity(), 13370);\n        EXPECT_EQ(dltensor.ndim, 2);\n        EXPECT_EQ(hdesc.Shape().size(), dltensor.ndim);\n        hdesc.ReshapeToBytes();\n        EXPECT_EQ(hdesc.Shape()[0], 13370);\n        EXPECT_EQ(dltensor.shape[0], 13370/2);\n    }\n}\n*/\n\nTEST_F(TestGeneric, MallocAndHostDescriptors)\n{\n    // auto mdesc = nextgen::Malloc::Allocate(one_mb);\n\n    // Unable to move from from Malloc -> HostMemory\n    // Descriptor<HostMemory> hdesc(std::move(mdesc));\n\n    // auto shared = std::make_shared<Descriptor<Malloc>>(std::move(mdesc));\n\n    // auto shared_from = std::make_shared<Descriptor<Malloc>>(mdesc);\n}\n\nclass TestBytesToString : public ::testing::Test\n{\n};\n\nTEST_F(TestBytesToString, BytesToString)\n{\n    // Edge cases inspired from example output: https://stackoverflow.com/questions/3758606\n    using std::string;\n    EXPECT_EQ(string(\"0 B\"), BytesToString(0));\n    EXPECT_EQ(string(\"1000 B\"), BytesToString(1000));\n    EXPECT_EQ(string(\"1023 B\"), BytesToString(1023));\n    EXPECT_EQ(string(\"1.0 KiB\"), BytesToString(1024));\n    EXPECT_EQ(string(\"1.7 KiB\"), BytesToString(1728));\n    EXPECT_EQ(string(\"108.0 KiB\"), BytesToString(110592));\n    EXPECT_EQ(string(\"6.8 MiB\"), BytesToString(7077888));\n    EXPECT_EQ(string(\"432.0 MiB\"), BytesToString(452984832));\n    EXPECT_EQ(string(\"27.0 GiB\"), BytesToString(28991029248));\n    EXPECT_EQ(string(\"1.7 TiB\"), BytesToString(1855425871872));\n}\n\nTEST_F(TestBytesToString, StringToBytes)\n{\n    EXPECT_EQ(0, StringToBytes(\"0B\"));\n    EXPECT_EQ(0, StringToBytes(\"0GB\"));\n    EXPECT_EQ(1000, StringToBytes(\"1000B\"));\n    EXPECT_EQ(1000, StringToBytes(\"1000b\"));\n    EXPECT_EQ(1000, StringToBytes(\"1kb\"));\n    EXPECT_EQ(1023, StringToBytes(\"1023b\"));\n    //  EXPECT_EQ(       1023, StringToBytes(\"1.023kb\")); // no effort to control rounding -\n    //  this fails with 1022\n    EXPECT_EQ(1024, StringToBytes(\"1kib\"));\n    EXPECT_EQ(1024, StringToBytes(\"1.0KiB\"));\n    EXPECT_EQ(8000000, StringToBytes(\"8.0MB\"));\n    EXPECT_EQ(8388608, StringToBytes(\"8.0MiB\"));\n    EXPECT_EQ(18253611008, StringToBytes(\"17GiB\"));\n    EXPECT_DEATH(StringToBytes(\"17G\"), \"\");\n    EXPECT_DEATH(StringToBytes(\"yais\"), \"\");\n}\n\n} // namespace\n"
  },
  {
    "path": "trtlab/core/tests/test_memory_stack.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/cyclic_allocator.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/memory_stack.h\"\n#include \"trtlab/core/memory/smart_stack.h\"\n#include \"trtlab/core/memory/sysv_allocator.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\nusing namespace trtlab;\n\nnamespace {\n\nstatic size_t one_mb = 1024 * 1024;\n\n// template <typename T>\nclass TestMemoryStack : public ::testing::Test\n{\n  protected:\n    virtual void SetUp() { stack = std::make_shared<MemoryStack<Malloc>>(one_mb); }\n\n    virtual void TearDown() { stack->Reset(); }\n\n    std::shared_ptr<MemoryStack<Malloc>> stack;\n};\n\nclass TestSmartStack : public ::testing::Test\n{\n  protected:\n    virtual void SetUp() { stack = SmartStack<SystemV>::Create(one_mb); }\n\n    virtual void TearDown()\n    {\n        if(stack) stack->Reset();\n    }\n\n    std::shared_ptr<SmartStack<SystemV>> stack;\n};\n\n// using MemoryTypes = ::testing::Types<Malloc>;\n// TYPED_TEST_CASE(TestMemoryStack, MemoryTypes);\n\nTEST_F(TestMemoryStack, EmptyOnCreate)\n{\n    ASSERT_EQ(one_mb, stack->Size());\n    ASSERT_EQ(one_mb, stack->Available());\n    ASSERT_EQ(0, stack->Allocated());\n}\n\nTEST_F(TestMemoryStack, AllocateAndReset)\n{\n    auto p0 = stack->Allocate(128 * 1024);\n    ASSERT_TRUE(p0);\n    EXPECT_EQ(128 * 1024, stack->Allocated());\n    stack->Reset();\n    EXPECT_EQ(0, stack->Allocated());\n    auto p1 = stack->Allocate(1);\n    EXPECT_EQ(p0, p1);\n}\n\nTEST_F(TestMemoryStack, Unaligned)\n{\n    auto p0 = stack->Allocate(1);\n    ASSERT_TRUE(p0);\n    EXPECT_EQ(stack->Alignment(), stack->Allocated());\n\n    auto p1 = stack->Allocate(1);\n    ASSERT_TRUE(p1);\n    EXPECT_EQ(2 * stack->Alignment(), stack->Allocated());\n\n    auto len = (char*)p1 - (char*)p0;\n    EXPECT_EQ(len, stack->Alignment());\n\n    EXPECT_EQ(stack->Offset(p0), 0);\n    EXPECT_EQ(stack->Offset(p1), stack->Alignment());\n}\n\nTEST_F(TestSmartStack, EmptyOnCreate)\n{\n    ASSERT_EQ(one_mb, stack->Size());\n    ASSERT_EQ(one_mb, stack->Available());\n    ASSERT_EQ(0, stack->Allocated());\n}\n\nTEST_F(TestSmartStack, AllocateAndReset)\n{\n    auto p0 = stack->Allocate(128 * 1024);\n    ASSERT_TRUE(p0);\n    EXPECT_EQ(128 * 1024, stack->Allocated());\n    EXPECT_EQ(p0->DataType(), types::bytes);\n    stack->Reset();\n    EXPECT_EQ(0, stack->Allocated());\n    auto p1 = stack->Allocate(1);\n    EXPECT_EQ(p0->Data(), p1->Data());\n}\n\nTEST_F(TestSmartStack, Unaligned)\n{\n    auto p0 = stack->Allocate(1);\n    ASSERT_TRUE(p0->Data());\n    EXPECT_EQ(stack->Alignment(), stack->Allocated());\n\n    auto p1 = stack->Allocate(1);\n    ASSERT_TRUE(p1);\n    EXPECT_EQ(2 * stack->Alignment(), stack->Allocated());\n\n    auto len = (char*)p1->Data() - (char*)p0->Data();\n    EXPECT_EQ(len, stack->Alignment());\n\n    EXPECT_EQ(stack->Offset(p0->Data()), 0);\n    EXPECT_EQ(stack->Offset(p1->Data()), stack->Alignment());\n\n    EXPECT_EQ(p0->Offset(), 0);\n    EXPECT_EQ(p1->Offset(), stack->Alignment());\n\n    EXPECT_GE(p0->Stack().Memory().ShmID(), 0);\n    // EXPECT_EQ(p0->ShmID(), -1);\n\n    DLOG(INFO) << \"delete descriptors\";\n\n    p0.reset();\n    p1.reset();\n\n    DLOG(INFO) << \"delete stack\";\n\n    stack.reset();\n}\n\nTEST_F(TestSmartStack, PassMemory)\n{\n    auto memory = std::make_unique<Allocator<Malloc>>(one_mb);\n    auto s = SmartStack<Malloc>::Create(std::move(memory));\n}\n\nTEST_F(TestSmartStack, PassSpecializedMemory)\n{\n    auto memory = std::make_unique<Allocator<Malloc>>(one_mb);\n    memory->Reshape({512, 512}, types::fp32);\n    EXPECT_EQ(memory->DataType(), types::fp32);\n\n    auto s = SmartStack<Malloc>::Create(std::move(memory));\n    // MemoryStack will Reshape any CoreMemory object to bytes at full capacity\n    // This is ok since the MemoryStack is taking ownership of the object.\n    EXPECT_EQ(s->Memory().DataType(), types::bytes);\n\n    // This no longer fails because MemoryStack is converting our memory object\n    // back into a useable form\n    // EXPECT_THROW(auto p0 = s->Allocate(1), std::invalid_argument);\n}\n\n} // namespace"
  },
  {
    "path": "trtlab/core/tests/test_pool.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"glog/logging.h\"\n#include \"trtlab/core/pool.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\n\nstruct Object\n{\n    Object(std::string name) : m_Name(name), m_Original(name) {}\n    ~Object()\n    {\n        DVLOG(2) << \"Destroying Object \" << m_Name;\n    }\n\n    Object(Object&& other) noexcept = default;\n    Object& operator=(Object&& other) noexcept = default;\n\n    void SetName(std::string name)\n    {\n        m_Name = name;\n    }\n    const std::string GetName() const\n    {\n        return m_Name;\n    }\n\n    void Reset()\n    {\n        m_Name = m_Original;\n    }\n\nprivate:\n    std::string m_Name;\n    std::string m_Original;\n};\n\nstruct ShareableObject : public Object, public std::enable_shared_from_this<ShareableObject> \n{\n    using Object::Object;\n    auto Copy() { return shared_from_this(); }\n};\n\n\nclass TestPool : public ::testing::Test\n{\nprotected:\n    virtual void SetUp()\n    {\n        p0 = Pool<Object>::Create();\n\n        p1 = Pool<Object>::Create();\n        p1->EmplacePush(\"Foo\");\n\n        p2 = Pool<Object>::Create();\n        p2->EmplacePush(\"Foo\");\n        p2->EmplacePush(\"Bar\");\n    }\n\n    virtual void TearDown() {}\n\n    std::shared_ptr<Pool<Object>> p0;\n    std::shared_ptr<Pool<Object>> p1;\n    std::shared_ptr<Pool<Object>> p2;\n};\n\nTEST_F(TestPool, EmptyOnCreate)\n{\n    ASSERT_EQ(0, p0->Size());\n}\n\nTEST_F(TestPool, Push)\n{\n    ASSERT_EQ(0, p0->Size());\n\n    p0->EmplacePush(Object(\"Baz\"));\n    ASSERT_EQ(1, p0->Size());\n}\n\nTEST_F(TestPool, Pop)\n{\n    ASSERT_EQ(1, p1->Size());\n\n    auto obj = p1->Pop();\n    ASSERT_TRUE(obj);\n    ASSERT_EQ(0, p1->Size());\n    obj.reset();\n    ASSERT_EQ(1, p1->Size());\n\n    {\n        auto scoped_obj = p1->Pop();\n        ASSERT_EQ(0, p1->Size());\n    }\n    ASSERT_EQ(1, p1->Size());\n}\n\nTEST_F(TestPool, PopOnReturn)\n{\n    auto foo = std::string(\"Foo\");\n    auto bar = std::string(\"Bar\");\n    {\n        auto obj = p1->Pop([](Object& obj) { obj.Reset(); });\n        ASSERT_TRUE(obj);\n        ASSERT_EQ(foo, obj->GetName());\n        obj->SetName(bar);\n    }\n    ASSERT_EQ(1, p1->Size());\n    {\n        auto obj = p1->Pop();\n        ASSERT_TRUE(obj);\n        ASSERT_EQ(foo, obj->GetName());\n        obj->SetName(bar);\n    }\n    ASSERT_EQ(1, p1->Size());\n    {\n        auto obj = p1->Pop();\n        ASSERT_TRUE(obj);\n        ASSERT_EQ(bar, obj->GetName());\n    }\n    ASSERT_EQ(1, p1->Size());\n}\n\nTEST_F(TestPool, PopOnReturnWithCapture)\n{\n    auto foo = std::string(\"Foo\");\n    auto bar = std::string(\"Bar\");\n\n    auto obj = p1->Pop([](Object& obj) { obj.Reset(); });\n    ASSERT_TRUE(obj);\n    ASSERT_EQ(foo, obj->GetName());\n    obj->SetName(bar);\n    ASSERT_EQ(0, p1->Size());\n    ASSERT_EQ(1, obj.use_count());\n\n    // Capture obj in onReturn lambda\n    auto from_p2_0 = p2->Pop([obj](Object& obj) {});\n    ASSERT_EQ(2, obj.use_count());\n\n    // Capture obj again a second onReturn lambda\n    auto from_p2_1 = p2->Pop([obj](Object& obj) {});\n    ASSERT_EQ(3, obj.use_count());\n\n    // Free one of the resources that captured obj\n    from_p2_0.reset();\n    ASSERT_EQ(0, p1->Size());\n    ASSERT_EQ(2, obj.use_count());\n    ASSERT_EQ(bar, obj->GetName());\n\n    // Free the original - it's still captured by from_p2_1\n    obj.reset();\n    ASSERT_EQ(0, p1->Size());\n\n    // Free the last holder of obj\n    from_p2_1.reset();\n    ASSERT_EQ(1, p1->Size());\n\n    {\n        // Ensure the obj onReturn was called\n        auto scoped = p1->Pop();\n        ASSERT_EQ(foo, scoped->GetName());\n    }\n}\n\nTEST_F(TestPool, PopWithoutReturn)\n{\n    ASSERT_EQ(1, p1->Size());\n\n    auto obj = p1->PopWithoutReturn();\n    ASSERT_TRUE(obj);\n    ASSERT_EQ(0, p1->Size());\n    obj.reset();\n    ASSERT_EQ(0, p1->Size());\n}\n\n/*\nTEST_F(TestPool, EnableSharedFromThis)\n{\n    auto p1 = Pool<std::shared_ptr<ShareableObject>>::Create();\n    p1->Push(std::move(std::make_shared<ShareableObject>(\"Foo\")));\n\n    {\n        auto scoped_obj = p1->Pop();\n        ASSERT_EQ(scoped_obj.use_count(), 1);\n        ASSERT_EQ(0, p1->Size());\n\n        auto explicit_copy = scoped_obj;\n        ASSERT_EQ(scoped_obj.use_count(), 2);\n        ASSERT_EQ(explicit_copy.use_count(), 2);\n        ASSERT_EQ(0, p1->Size());\n        explicit_copy.reset();\n        ASSERT_EQ(scoped_obj.use_count(), 1);\n        ASSERT_EQ(0, p1->Size());\n\n        auto copy_via_sft = scoped_obj->Copy();\n        ASSERT_EQ(copy_via_sft.get(), scoped_obj.get());\n        ASSERT_EQ(scoped_obj.use_count(), 2);\n        ASSERT_EQ(copy_via_sft.use_count(), 2);\n\n        scoped_obj.reset();\n        ASSERT_EQ(copy_via_sft.use_count(), 1);\n        ASSERT_EQ(0, p1->Size());\n    }\n}\n*/"
  },
  {
    "path": "trtlab/core/tests/test_stl_allocator.cc",
    "content": "\n\n#include \"trtlab/core/memory/cyclic_allocator.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/bytes.h\"\n\n#include \"trtlab/core/memory/stl_allocator.h\"\n\n#include <gtest/gtest.h>\n\nusing namespace trtlab;\n\nstatic const uint64_t one_mb = 1024 * 1024;\n\nclass TestCustomAllocator : public ::testing::Test\n{\n};\n\ntemplate<typename T>\nusing custom_vector = std::vector<T, stl::temporary_allocator<T, Malloc>>;\n\nTEST_F(TestCustomAllocator, CustomVector)\n{\n    auto v1 = custom_vector<int> {1, 2, 4, 8};\n    ASSERT_EQ(v1[0], 1);\n    ASSERT_EQ(v1[1], 2);\n    ASSERT_EQ(v1[2], 4);\n    ASSERT_EQ(v1[3], 8);\n\n    auto v2 = v1;\n    ASSERT_EQ(v2[0], 1);\n    ASSERT_EQ(v2[1], 2);\n    ASSERT_EQ(v2[2], 4);\n    ASSERT_EQ(v2[3], 8);\n\n    v2[0] = 10;\n    ASSERT_NE(v1[0], v2[0]);\n\n    void* before = v2.data();\n    v2.resize(1024);\n    void* after = v2.data();\n    ASSERT_NE(before, after);\n    DLOG(INFO) << \"finished resize\";\n    ASSERT_EQ(v1[0], 1);\n    ASSERT_EQ(v1[1], 2);\n    ASSERT_EQ(v1[2], 4);\n    ASSERT_EQ(v1[3], 8);\n\n    auto v3 = std::move(v2);\n}\n\n"
  },
  {
    "path": "trtlab/core/tests/test_sysv_allocator.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <chrono>\n#include <thread>\n#include <glog/logging.h>\n\n#include \"test_common.h\"\n\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/sysv_allocator.h\"\n\n#include <foonathan/memory/namespace_alias.hpp>\n\n#include \"test_transactional_allocator.h\"\n\nusing namespace memory::literals;\n\nclass TestSysV : public TrackedTest\n{\n};\n\nTEST_F(TestSysV, BlankTest) \n{\n    ASSERT_TRUE(true);\n    auto alloc = memory::trtlab::sysv_allocator();\n    ASSERT_TRUE(true);\n}\n\nTEST_F(TestSysV, LifeCycle)\n{\n    auto raw = memory::trtlab::sysv_allocator();\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n\n    auto ptr = alloc.allocate_node(1024, 8);\n    alloc.deallocate_node(ptr, 1024, 8);\n\n    EndTest();\n}\n\nTEST_F(TestSysV, Attach)\n{\n    auto raw = memory::trtlab::sysv_allocator();\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n\n    auto ptr = alloc.allocate_node(1024, 8);\n    ASSERT_NE(ptr, nullptr);\n\n    auto info = alloc.get_allocator().sysv_info_for_pointer(ptr);\n    ASSERT_NE(info.shm_id, -1);\n    ASSERT_EQ(info.offset, 0);\n    ASSERT_EQ(info.attachment_count, 1);\n\n    auto attached_ptr = alloc.get_allocator().attach(info.shm_id);\n    auto updated_info = alloc.get_allocator().sysv_info_for_pointer(attached_ptr);\n    ASSERT_NE(attached_ptr, nullptr);\n    ASSERT_NE(ptr, attached_ptr);\n    ASSERT_EQ(updated_info.attachment_count, 2);\n\n    alloc.deallocate_node(ptr, 1024, 8);\n\n    auto info_post_dealloc = alloc.get_allocator().sysv_info_for_pointer(attached_ptr);\n    ASSERT_EQ(info_post_dealloc.attachment_count, 1);\n\n    alloc.deallocate_node(attached_ptr, 1024, 8);\n\n    EndTest();\n}\n\nTEST_F(TestSysV, AttachShouldFailIfSegmentHasBeenReleased)\n{\n    auto raw = memory::trtlab::sysv_allocator();\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n\n    auto ptr = alloc.allocate_node(1024, 8);\n    ASSERT_NE(ptr, nullptr);\n\n    auto info = alloc.get_allocator().sysv_info_for_pointer(ptr);\n    ASSERT_NE(info.shm_id, -1);\n    ASSERT_EQ(info.offset, 0);\n    ASSERT_EQ(info.attachment_count, 1);\n    ASSERT_TRUE(info.is_attachable);\n\n    alloc.get_allocator().release(info.shm_id);\n    info = alloc.get_allocator().sysv_info_for_pointer(ptr);\n    ASSERT_EQ(info.attachment_count, 1);\n    ASSERT_FALSE(info.is_attachable);\n\n    ASSERT_ANY_THROW(alloc.get_allocator().attach(info.shm_id));\n\n    alloc.deallocate_node(ptr, 1024, 8);\n\n    EndTest();\n}\n\n\nTEST_F(TestSysV, AsBaseForHighLevelAllocators)\n{\n    auto alloc = make_smart_transactional_allocator<memory::trtlab::sysv_allocator>(1_MiB, 2);\n\n    auto ptr_0 = alloc.allocate_node(1024, 8);\n    auto ptr_1 = alloc.allocate_node(2048, 8);\n    auto ptr_2 = alloc.allocate_node(1_MiB, 8);\n\n    auto info_0 = memory::trtlab::sysv_allocator::sysv_info_for_pointer(ptr_0);\n    auto info_1 = memory::trtlab::sysv_allocator::sysv_info_for_pointer(ptr_1);\n    auto info_2 = memory::trtlab::sysv_allocator::sysv_info_for_pointer(ptr_2);\n    ASSERT_EQ(info_0.offset, 0);\n    ASSERT_EQ(info_1.offset, 1024);\n    ASSERT_EQ(info_0.shm_id, info_1.shm_id);\n    ASSERT_NE(info_0.shm_id, info_2.shm_id);\n    ASSERT_NE(info_1.shm_id, info_2.shm_id);\n\n    alloc.deallocate_node(ptr_0, 1024, 8);\n    alloc.deallocate_node(ptr_1, 2048, 8);\n    alloc.deallocate_node(ptr_2, 1_MiB, 8);\n\n    EndTest();\n}"
  },
  {
    "path": "trtlab/core/tests/test_tensor.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/bytes.h\"\n#include \"trtlab/core/memory/bytes_allocator.h\"\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/core/memory/tensor.h\"\n\n#include <gtest/gtest.h>\n\nusing namespace trtlab;\n\nstatic const uint64_t one_mb = 1024 * 1024;\n\nclass TestTensor : public ::testing::Test\n{\n};\n\nTEST_F(TestTensor, StateFromBytes)\n{\n    auto bytes = BytesAllocator<Malloc>::Allocate(one_mb);\n    auto tensor = TensorAllocator::FromBytes(std::move(bytes));\n\n    ASSERT_NE(tensor.Data(), nullptr);\n    ASSERT_EQ(tensor.NDims(), 1);\n    ASSERT_EQ(tensor.Shape()[0], one_mb);\n    ASSERT_EQ(tensor.Strides()[0], 1);\n    ASSERT_EQ(tensor.NBytes(), one_mb);\n    ASSERT_EQ(tensor.ItemSize(), 1);\n    ASSERT_FALSE(tensor.IsShared());\n\n    Tensor<HostMemory> moved(std::move(tensor));\n    ASSERT_FALSE(moved.IsShared());\n    ASSERT_THROW(tensor.IsShared(), std::runtime_error);\n\n    {\n        Tensor<HostMemory> copied(moved);\n        ASSERT_TRUE(moved.IsShared());\n        ASSERT_TRUE(copied.IsShared());\n    }\n\n    ASSERT_FALSE(moved.IsShared());\n\n    {\n        auto cp_assign = moved;\n        ASSERT_TRUE(moved.IsShared());\n        ASSERT_TRUE(cp_assign.IsShared());\n    }\n}\n\nTEST_F(TestTensor, ReshapeView)\n{\n    auto bytes = BytesAllocator<Malloc>::Allocate(one_mb);\n    auto tensor = TensorAllocator::FromBytes(std::move(bytes));\n\n    ASSERT_NE(tensor.Data(), nullptr);\n    ASSERT_EQ(tensor.NDims(), 1);\n    ASSERT_EQ(tensor.Shape()[0], one_mb);\n    ASSERT_EQ(tensor.Strides()[0], 1);\n    ASSERT_EQ(tensor.NBytes(), one_mb);\n    ASSERT_EQ(tensor.ItemSize(), 1);\n    ASSERT_FALSE(tensor.IsShared());\n\n    tensor.ReshapeView({512, 512}, types::fp32);\n    ASSERT_EQ(tensor.NDims(), 2);\n    ASSERT_EQ(tensor.Shape()[0], 512);\n    ASSERT_EQ(tensor.Shape()[1], 512);\n    ASSERT_EQ(tensor.Strides()[1], 1);\n    ASSERT_EQ(tensor.Strides()[0], 512);\n    ASSERT_EQ(tensor.ItemSize(), 4);\n    ASSERT_EQ(tensor.NBytes(), one_mb);\n    ASSERT_FALSE(tensor.IsShared());\n\n    {\n        Tensor<HostMemory> copied(tensor);\n        ASSERT_TRUE(tensor.IsShared());\n        ASSERT_TRUE(copied.IsShared());\n\n        ASSERT_THROW(tensor.ReshapeView({512, 256}, types::fp32), std::runtime_error);\n    }\n\n    ASSERT_THROW(tensor.ReshapeView({512, 513}, types::fp32), std::runtime_error);\n\n    tensor.ReshapeView({2, 128, 64}, types::int16);\n    ASSERT_EQ(tensor.NDims(), 3);\n    ASSERT_EQ(tensor.Shape()[0], 2);\n    ASSERT_EQ(tensor.Shape()[1], 128);\n    ASSERT_EQ(tensor.Shape()[2], 64);\n    ASSERT_EQ(tensor.Strides()[2], 1);\n    ASSERT_EQ(tensor.Strides()[1], 64);\n    ASSERT_EQ(tensor.Strides()[0], 128*64);\n    ASSERT_EQ(tensor.ItemSize(), 2);\n    ASSERT_EQ(tensor.NBytes(), 32768);\n}\n\n\nTEST_F(TestTensor, Shapes1D)\n{\n    TensorShapeGeneric array(one_mb);\n    ASSERT_EQ(array.NDims(), 1);\n    ASSERT_EQ(array.Size(), one_mb);\n    ASSERT_EQ(array.Shape()[0], one_mb);\n    ASSERT_EQ(array.Strides()[0], 1);\n    ASSERT_TRUE(array.IsCompact());\n    ASSERT_FALSE(array.IsStrided());\n    ASSERT_FALSE(array.IsBroadcasted());\n}\n\nTEST_F(TestTensor, ShapesNDGeneric)\n{\n    TensorShapeGeneric nd({8, 3, 224, 224});\n    ASSERT_EQ(nd.NDims(), 4);\n    ASSERT_EQ(nd.Size(), 1204224);\n    ASSERT_EQ(nd.Strides()[3], 1);\n    ASSERT_EQ(nd.Strides()[2], 224);\n    ASSERT_EQ(nd.Strides()[1], 224 * 224);\n    ASSERT_EQ(nd.Strides()[0], 224 * 224 * 3);\n    ASSERT_TRUE(nd.IsCompact());\n    ASSERT_FALSE(nd.IsStrided());\n    ASSERT_FALSE(nd.IsBroadcasted());\n}\n\nTEST_F(TestTensor, ShapesNDGenericWithStrides)\n{\n    // exposed as NCHW\n    // stored as NHWC\n    TensorShapeGeneric nd({8, 3, 224, 224}, {224 * 224 * 3, 1, 224 * 3, 3});\n    ASSERT_EQ(nd.NDims(), 4);\n    ASSERT_EQ(nd.Size(), 1204224);\n    ASSERT_TRUE(nd.IsCompact());\n    ASSERT_FALSE(nd.IsStrided());\n    ASSERT_FALSE(nd.IsBroadcasted());\n}\n\nTEST_F(TestTensor, ShapesEmpty)\n{\n    // exposed as NCHW\n    // stored as NHWC\n    ASSERT_ANY_THROW(TensorShapeGeneric nd({}));\n}\n\n\n"
  },
  {
    "path": "trtlab/core/tests/test_thread_pool.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"glog/logging.h\"\n#include \"trtlab/core/thread_pool.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\n\nclass TestThreadPool : public ::testing::Test\n{\n  protected:\n    virtual void SetUp() { thread_pool = std::make_shared<ThreadPool>(3); }\n\n    virtual void TearDown() {}\n\n    std::shared_ptr<ThreadPool> thread_pool;\n};\n\nTEST_F(TestThreadPool, ReturnInt)\n{\n    auto should_be_1 = thread_pool->enqueue([] { return 1; });\n    ASSERT_EQ(1, should_be_1.get());\n}\n\nTEST_F(TestThreadPool, ReturnChainedInt)\n{\n    auto should_be_1 =\n        thread_pool->enqueue([this] { return thread_pool->enqueue([] { return 1; }); });\n    ASSERT_EQ(1, should_be_1.get().get());\n}\n\nTEST_F(TestThreadPool, MakeUnique) { auto unqiue = std::make_unique<ThreadPool>(1); }\n\nTEST_F(TestThreadPool, CaptureThis)\n{\n    class ObjectThatOwnsAThreadPool\n    {\n        class ValueObject;\n\n      public:\n        ObjectThatOwnsAThreadPool()\n            : m_ThreadPool(std::move(std::make_unique<ThreadPool>(1))),\n              m_Object(std::move(std::make_unique<ValueObject>()))\n        {\n        }\n\n        DELETE_COPYABILITY(ObjectThatOwnsAThreadPool);\n        DELETE_MOVEABILITY(ObjectThatOwnsAThreadPool);\n\n        ~ObjectThatOwnsAThreadPool()\n        {\n            DVLOG(2) << \"Destroying ObjectThatOwnsAThreadPool: \" << this;\n        }\n        auto test()\n        {\n            DVLOG(2) << \"[before queue] val = \" << m_Object.get();\n            return m_ThreadPool->enqueue([this]() {\n                DVLOG(2) << \"[before sleep] val = \" << m_Object.get();\n                std::this_thread::sleep_for(std::chrono::milliseconds(1000));\n                DVLOG(2) << \"[after  sleep] val = \" << m_Object.get();\n                return m_Object->value;\n            });\n        }\n\n      private:\n        class ValueObject\n        {\n          public:\n            ValueObject() : value(42) {}\n            DELETE_COPYABILITY(ValueObject);\n            DELETE_MOVEABILITY(ValueObject);\n            ~ValueObject() { DVLOG(2) << \"Destroying ValueObject\"; }\n            int value;\n        };\n        std::unique_ptr<ValueObject> m_Object;\n        std::unique_ptr<ThreadPool> m_ThreadPool;\n    };\n\n    auto obj = std::make_unique<ObjectThatOwnsAThreadPool>();\n    auto future = obj->test();\n    obj.reset();\n    EXPECT_EQ(future.get(), 42);\n}"
  },
  {
    "path": "trtlab/core/tests/test_transactional_allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/core/memory/block_allocators.h\"\n#include \"trtlab/core/memory/transactional_allocator.h\"\n\n#include <foonathan/memory/tracking.hpp>\n\n#include \"test_common.h\"\n\ntemplate<typename StatelessAllocator>\nauto make_raw_transactional_allocator(std::size_t block_size, std::size_t block_count = 2)\n{\n    namespace memory = foonathan::memory;\n\n    // base allocator\n    auto raw = StatelessAllocator();\n\n    // convert to full fledged allocator - use direct_storage which optimizes out mutexes for stateless allocators\n    auto alloc = memory::make_allocator_adapter(std::move(raw));\n\n    static_assert(!decltype(alloc)::is_stateful::value, \"should be stateless\");\n    static_assert(std::is_same<memory::no_mutex, typename decltype(alloc)::mutex>::value, \"should use memory::no_mutex\");\n\n    // create a tracker for calls to the malloc allocator\n    auto tracked = memory::make_tracked_allocator(log_tracker{\"** tracker: base **\"}, std::move(alloc));\n\n    // malloc block allocator\n    auto block_alloc = memory::trtlab::make_growth_capped_block_allocator(block_size, block_count, std::move(tracked));\n\n    // transactional allocator\n    return memory::trtlab::make_transactional_allocator(std::move(block_alloc));\n}\n\ntemplate<typename StatelessAllocator = memory::malloc_allocator>\nauto make_smart_transactional_allocator(std::size_t block_size, std::size_t block_count = 2)\n{\n    namespace memory = foonathan::memory;\n\n    // transactional allocator\n    auto alloc = make_raw_transactional_allocator<StatelessAllocator>(block_size, block_count);\n\n    // populate the cache\n    alloc.reserve_blocks(block_count);\n\n    // smart allocator\n    // use a special timeout_mutex - throws an exception if the lock is not obtained in MUTEX_TIMEOUT_MS\n    return memory::trtlab::make_allocator<timeout_mutex>(std::move(alloc));\n}"
  },
  {
    "path": "trtlab/core/tests/test_types.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"glog/logging.h\"\n#include \"gtest/gtest.h\"\n\n#include \"trtlab/core/types.h\"\n\nusing namespace trtlab;\nusing namespace trtlab::types;\n\nclass TestTypes : public ::testing::Test\n{\n};\n\nTEST_F(TestTypes, int8)\n{\n    EXPECT_EQ(types::int8.to_dlpack().code, (uint8_t)kDLInt);\n    EXPECT_EQ(types::int8.to_dlpack().bits, (uint8_t)8U);\n    EXPECT_EQ(types::int8.to_dlpack().lanes, (uint16_t)1U);\n}\n\nTEST_F(TestTypes, uint8)\n{\n    EXPECT_EQ(types::uint8.to_dlpack().code, (uint8_t)kDLUInt);\n    EXPECT_EQ(types::uint8.to_dlpack().bits, (uint8_t)8U);\n    EXPECT_EQ(types::uint8.to_dlpack().lanes, (uint16_t)1U);\n}\n\nTEST_F(TestTypes, fp32)\n{\n    EXPECT_EQ(types::fp32.to_dlpack().code, (uint8_t)kDLFloat);\n    EXPECT_EQ(types::fp32.to_dlpack().bits, (uint8_t)32U);\n    EXPECT_EQ(types::fp32.to_dlpack().lanes, (uint8_t)1U);\n}\n\nTEST_F(TestTypes, ctors_and_assignment)\n{\n    // copy assignment\n    auto bytes = types::uint8;\n    EXPECT_EQ(bytes.bytes(), 1);\n\n    // copy ctor\n    types::dtype bytes2(bytes);\n\n    EXPECT_EQ(bytes, bytes2);\n\n    // move ctor\n    auto bytes3 = std::move(bytes2);\n    EXPECT_EQ(bytes, bytes3);\n    EXPECT_NE(bytes, bytes2);\n    EXPECT_EQ(bytes2.to_dlpack().bits, 0);\n    EXPECT_EQ(bytes2.bytes(), 0);\n\n    // move assignment\n    bytes2 = std::move(bytes3);\n    EXPECT_EQ(bytes, bytes2);\n    EXPECT_NE(bytes, bytes3);\n\n}\n\nTEST_F(TestTypes, Equivalence)\n{\n    auto bytes = types::uint8;\n    EXPECT_EQ(bytes, types::uint8);\n    EXPECT_NE(bytes, types::int8);\n    EXPECT_NE(bytes, types::fp32);\n\n    DLDataType dlpack = bytes.to_dlpack();\n    EXPECT_EQ(dlpack.code, (uint8_t)kDLUInt);\n    EXPECT_EQ(dlpack.bits, (uint8_t)8U);\n    EXPECT_EQ(dlpack.lanes, (uint16_t)1U);\n\n    types::dtype test(dlpack);\n    EXPECT_EQ(test, types::uint8);\n}\n\nTEST_F(TestTypes, TypeVsObject)\n{\n    ASSERT_EQ(dtype::from<void>(), bytes);\n}\n\nTEST_F(TestTypes, ArbituaryDLDataTypes)\n{\n    DLDataType dt;\n\n    dt.code = kDLFloat;\n    dt.bits = 32;\n    dt.lanes = 1;\n\n    dtype float32(dt);\n    ASSERT_TRUE(float32.is_compatible<float>());\n\n    // todo: we could allow this to be compatible\n    dt.lanes = 3;\n    dtype float3(dt);\n    ASSERT_FALSE(float3.is_compatible<float>());\n    ASSERT_TRUE(float3.is_compatible<void>());\n\n    dt.lanes = 1;\n    dt.bits = 33;\n    dtype float33(dt);\n    ASSERT_EQ(float33.bytes(), 5); // round to nearest byte\n    ASSERT_FALSE(float3.is_compatible<float>());\n    ASSERT_TRUE(float3.is_compatible<void>());\n\n    dt.bits = 32;\n    dt.code = 7;\n    ASSERT_THROW(dtype unknown(dt), std::runtime_error);\n}\n\nTEST_F(TestTypes, CheckAllForCompatibility)\n{\n    for(const auto& t : types::All)\n    {\n        int count = 0;\n        count += (int)t.is_compatible<int8_t>();\n        count += (int)t.is_compatible<int16_t>();\n        count += (int)t.is_compatible<int32_t>();\n        count += (int)t.is_compatible<int64_t>();\n        count += (int)t.is_compatible<uint8_t>();\n        count += (int)t.is_compatible<uint16_t>();\n        count += (int)t.is_compatible<uint32_t>();\n        count += (int)t.is_compatible<uint64_t>();\n        count += (int)t.is_compatible<float>();\n        count += (int)t.is_compatible<double>();\n\n        if(t == types::fp16) { count++; }\n\n        DVLOG(2) << t;\n        ASSERT_EQ(count, 1);\n    }\n}"
  },
  {
    "path": "trtlab/cuda/BUILD.bazel",
    "content": "\ncc_library(\n    name = \"cuda\",\n    srcs = glob([\n        \"src/**/*.cc\",\n        \"src/**/*.h\",\n    ]),\n    hdrs = glob([\n        \"include/**/*.h\",\n    ]),\n    deps = [\n        \"//trtlab/core\",\n        \"@local_config_cuda//:cuda_headers\",\n        \"@local_config_cuda//:cuda_runtime\",\n    ],\n    linkopts = [\n#       \"-L/usr/local/cuda/lib64/stubs\",\n        \"-lnvidia-ml\",\n    ],\n    strip_include_prefix = \"include\",\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "trtlab/cuda/CMakeLists.txt",
    "content": "# Find CUDA\nfind_package(CUDA REQUIRED)\nmessage(STATUS \"CUDA IncludeDir ${CUDA_INCLUDE_DIRS}\")\n\nset(header_path ${CMAKE_CURRENT_SOURCE_DIR}/include/trtlab/cuda)\n\nadd_library(cuda\n# src/copy.cc\n# src/cuda_device.cc\n# src/cuda_managed.cc\n# src/cuda_pinned_host.cc\n  src/device_info.cc\n  src/device_guard.cc\n# src/device_memory.cc\n  src/cuda_allocators.cc\n)\n\nadd_library(${PROJECT_NAME}::cuda ALIAS cuda)\n\ntarget_link_libraries(cuda\n    ${PROJECT_NAME}::core\n    ${CUDA_LIBRARIES}\n    nvidia-ml\n)\n\ntarget_include_directories(cuda\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n    ${CUDA_INCLUDE_DIRS}\n  PRIVATE\n    ${header_path}\n)\n\nset_target_properties(cuda PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-cuda)\n\ninstall(\n  TARGETS cuda\n  EXPORT ${PROJECT_NAME}-targets\n  RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\ninstall(\n  DIRECTORY include/\n  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\n  add_subdirectory(tests)\n\n# add_subdirectory(benchmarks)\n"
  },
  {
    "path": "trtlab/cuda/benchmarks/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(benchmark REQUIRED)\n\nadd_executable(bench_cuda\n  bench_main.cc\n  bench_cuda_memory.cc\n)\n\ntarget_link_libraries(bench_cuda \n  PRIVATE \n    trtlab::cuda\n    trtlab_memory\n    benchmark::benchmark\n)\n\n#set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} \"-pg\")\n\nadd_test(NAME bench_cuda COMMAND $<TARGET_FILE:bench_cuda>)\n"
  },
  {
    "path": "trtlab/cuda/benchmarks/bench_cuda_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/transactional_allocator.h>\n#include <trtlab/memory/literals.h>\n\n#include <trtlab/cuda/common.h>\n#include <trtlab/cuda/memory/cuda_allocators.h>\n\nusing namespace trtlab::memory;\nusing namespace literals;\n\nnamespace bench\n{\n\ntemplate <typename Allocator>\nstatic void run_allocate_node_x1(benchmark::State& state, Allocator& alloc)\n{\n    for(auto _ : state)\n    {\n        auto p0 = (int*)alloc.allocate_node(33_MiB, 256);\n        benchmark::DoNotOptimize(p0);\n        alloc.deallocate_node(p0, 33_MiB, 256);\n    }\n}\n\ntemplate <typename Allocator>\nstatic void run_allocate_node_x10(benchmark::State& state, Allocator& alloc)\n{\n    for(auto _ : state)\n    {\n        auto p0 = alloc.allocate_node(33_MiB, 8UL);\n        auto p1 = alloc.allocate_node(44_MiB, 8UL);\n        auto p2 = alloc.allocate_node(78_MiB, 8UL);\n        auto p3 = alloc.allocate_node(12_MiB, 8UL);\n        auto p4 = alloc.allocate_node(32_MiB, 8UL);\n        auto p5 = alloc.allocate_node(100_MiB, 8UL);\n        auto p6 = alloc.allocate_node(18_MiB, 8UL);\n        auto p7 = alloc.allocate_node(21_MiB, 8UL);\n        auto p8 = alloc.allocate_node(15_MiB, 8UL);\n        auto p9 = alloc.allocate_node(71_MiB, 8UL);\n\n        benchmark::DoNotOptimize(p0);\n        benchmark::DoNotOptimize(p1);\n        benchmark::DoNotOptimize(p2);\n        benchmark::DoNotOptimize(p3);\n        benchmark::DoNotOptimize(p4);\n        benchmark::DoNotOptimize(p5);\n        benchmark::DoNotOptimize(p6);\n        benchmark::DoNotOptimize(p7);\n        benchmark::DoNotOptimize(p8);\n        benchmark::DoNotOptimize(p9);\n\n        alloc.deallocate_node(p3, 12_MiB, 8UL);\n        alloc.deallocate_node(p1, 44_MiB, 8UL);\n        alloc.deallocate_node(p7, 21_MiB, 8UL);\n        alloc.deallocate_node(p8, 15_MiB, 8UL);\n        alloc.deallocate_node(p0, 33_MiB, 8UL);\n        alloc.deallocate_node(p4, 32_MiB, 8UL);\n        alloc.deallocate_node(p6, 18_MiB, 8UL);\n        alloc.deallocate_node(p5, 100_MiB, 8UL);\n        alloc.deallocate_node(p9, 71_MiB, 8UL);\n        alloc.deallocate_node(p2, 78_MiB, 8UL);\n    }\n}\n\ntemplate <typename Allocator>\nstatic void run_allocate_descriptor_x1(benchmark::State& state, Allocator& alloc)\n{\n    for(auto _ : state)\n    {\n        auto p0 = alloc.allocate_descriptor(33_MiB, 8UL);\n    }\n}\n\ntemplate <typename Allocator>\nstatic void run_allocate_descriptor_x10(benchmark::State& state, Allocator& alloc)\n{\n    for(auto _ : state)\n    {\n        auto p0 = alloc.allocate_descriptor(33_MiB, 8UL);\n        auto p1 = alloc.allocate_descriptor(44_MiB, 8UL);\n        auto p2 = alloc.allocate_descriptor(78_MiB, 8UL);\n        auto p3 = alloc.allocate_descriptor(12_MiB, 8UL);\n        auto p4 = alloc.allocate_descriptor(32_MiB, 8UL);\n        auto p5 = alloc.allocate_descriptor(100_MiB, 8UL);\n        auto p6 = alloc.allocate_descriptor(18_MiB, 8UL);\n        auto p7 = alloc.allocate_descriptor(21_MiB, 8UL);\n        auto p8 = alloc.allocate_descriptor(15_MiB, 8UL);\n        auto p9 = alloc.allocate_descriptor(71_MiB, 8UL);\n    }\n}\n\nstatic auto make_transactional_allocator()\n{\n    constexpr std::size_t block_size = 128_MiB;\n    constexpr std::size_t block_count = 6;\n\n    auto malloc  = make_allocator_adapter(cuda_malloc_allocator(0));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(malloc), block_size);\n    auto counted = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), block_count);\n    auto arena   = make_cached_block_arena(std::move(counted));\n    auto alloc   = make_transactional_allocator(std::move(arena));    \n\n    alloc.reserve_blocks(block_count);\n\n    return alloc;\n}\n}\n\n// malloc\n\nstatic void memory_cuda_malloc_raw_x1(benchmark::State& state)\n{\n    auto alloc = make_allocator(cuda_malloc_allocator(0));\n    bench::run_allocate_node_x1(state, alloc);\n    CHECK_CUDA(cudaDeviceSynchronize());\n}\n\nstatic void memory_cuda_malloc_raw_x10(benchmark::State& state)\n{\n    auto alloc = make_allocator(cuda_malloc_allocator(0));\n    bench::run_allocate_descriptor_x10(state, alloc);\n    CHECK_CUDA(cudaDeviceSynchronize());\n}\n\n// transactional\n\nstatic void memory_transactional_raw_x1(benchmark::State& state)\n{\n    auto alloc = bench::make_transactional_allocator();\n    bench::run_allocate_node_x1(state, alloc);\n}\n\nstatic void memory_transactional_raw_x10(benchmark::State& state)\n{\n    auto alloc = bench::make_transactional_allocator();\n    bench::run_allocate_node_x10(state, alloc);\n}\n\nstatic void memory_transactional_allocator_x1(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc =   make_allocator(std::move(txalloc));\n    bench::run_allocate_node_x1(state, alloc);\n}\n\nstatic void memory_transactional_allocator_x10(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc =   make_allocator(std::move(txalloc));\n    bench::run_allocate_node_x10(state, alloc);\n}\n\nstatic void memory_transactional_descriptor_x1(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc =   make_allocator(std::move(txalloc));\n    bench::run_allocate_descriptor_x1(state, alloc);\n}\n\nstatic void memory_transactional_descriptor_x10(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc =   make_allocator(std::move(txalloc));\n    bench::run_allocate_descriptor_x10(state, alloc);\n}\n\nBENCHMARK(memory_cuda_malloc_raw_x1);\nBENCHMARK(memory_cuda_malloc_raw_x10);\n\nBENCHMARK(memory_transactional_raw_x1);\nBENCHMARK(memory_transactional_allocator_x1);\nBENCHMARK(memory_transactional_descriptor_x1);\n\nBENCHMARK(memory_transactional_raw_x10);\nBENCHMARK(memory_transactional_allocator_x10);\nBENCHMARK(memory_transactional_descriptor_x10);"
  },
  {
    "path": "trtlab/cuda/benchmarks/bench_main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\nBENCHMARK_MAIN();"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/common.h",
    "content": "#pragma once\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <glog/logging.h>\n\n#define CHECK_CUDA(code) { CHECK_EQ((code), cudaSuccess) << cudaGetErrorString((code)); }\n"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/cyclic_windowed_buffer.h",
    "content": "#pragma once\n\n#include <trtlab/core/cyclic_windowed_buffer.h>\n\n#include \"memory/device_memory.h\"\n#include \"sync.h\"\n\nnamespace trtlab\n{\n    template <typename ThreadType>\n    class cyclic_windowed_stack<memory::device_memory, ThreadType> : public detail::cyclic_windowed_stack_impl\n    {\n    public:\n        using memory_type = memory::device_memory;\n\n        cyclic_windowed_stack() : cyclic_windowed_stack_impl(), m_Stream(nullptr) {}\n\n        cyclic_windowed_stack(memory::descriptor md, std::size_t window_size, std::size_t overlap_size, cudaStream_t stream)\n        : cyclic_windowed_stack_impl(std::move(md), window_size, overlap_size), m_Stream(stream)\n        {\n        }\n\n        cyclic_windowed_stack(cyclic_windowed_stack&&) noexcept = default;\n        cyclic_windowed_stack& operator=(cyclic_windowed_stack&&) noexcept = default;\n\n        ~cyclic_windowed_stack() override {}\n\n    private:\n        void copy(void* dst, const void* src, std::size_t size) final override\n        {\n            CHECK_EQ(cudaMemcpyAsync(dst, src, size, cudaMemcpyDefault, m_Stream), cudaSuccess);\n            cuda_sync<ThreadType>::stream_sync(m_Stream);\n        }\n\n        void replicate(void* dst, const void* src, std::size_t size) final override\n        {\n            CHECK_EQ(cudaMemcpyAsync(dst, src, size, cudaMemcpyDefault, m_Stream), cudaSuccess);\n            cuda_sync<ThreadType>::stream_sync(m_Stream);\n        }\n\n        cudaStream_t m_Stream;\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/device_guard.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <string>\n\n#include \"trtlab/core/utils.h\"\n\nnamespace trtlab\n{\n    class device_guard final\n    {\n    public:\n        device_guard(int device_id);\n        ~device_guard();\n\n        DELETE_COPYABILITY(device_guard);\n        DELETE_MOVEABILITY(device_guard);\n\n    private:\n        int m_DeviceID;\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/device_info.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <string>\n\n#include <trtlab/core/affinity.h>\n#include <nvml.h>\n\nnamespace trtlab\n{\n    struct DeviceInfo\n    {\n        static auto Affinity(int device_id) -> cpu_set;\n        static auto Alignment() -> std::size_t;\n        static auto EnergyConsumption(int device_id) -> double;\n        static auto MemoryInfo(int device_id) -> nvmlMemory_t;\n        static auto PowerUsage(int device_id) -> double;\n        static auto PowerLimit(int device_id) -> double;\n        static auto UUID(int device_id) -> std::string;\n        static auto Count() -> int;\n        static auto IsValidDeviceID(int device_id) -> bool;\n    };\n\n    namespace cuda\n    {\n        namespace nvml\n        {\n            std::size_t  device_count();\n            nvmlMemory_t memory_info(int device_id);\n\n        } // namespace nvml\n    }     // namespace cuda\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/memory/cuda_allocators.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/allocator_traits.h>\n\n#include \"device_memory.h\"\n#include \"../device_guard.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace cuda_detail\n        {\n            struct cuda_malloc\n            {\n                using memory_type = device_memory;\n                static cudaError_t allocate(void** ptr, std::size_t size)\n                {\n                    return cudaMalloc(ptr, size);\n                }\n                static cudaError_t deallocate(void* ptr) noexcept\n                {\n                    return cudaFree(ptr);\n                }\n                static allocator_info info()\n                {\n                    return {\"cudaMalloc\", nullptr};\n                }\n            };\n\n            struct cuda_malloc_managed\n            {\n                using memory_type = device_managed_memory;\n                static cudaError_t allocate(void** ptr, std::size_t size)\n                {\n                    return cudaMallocManaged(ptr, size);\n                }\n                static cudaError_t deallocate(void* ptr) noexcept\n                {\n                    return cudaFree(ptr);\n                }\n                static allocator_info info()\n                {\n                    return {\"cudaMallocManaged\", nullptr};\n                }\n            };\n\n            struct cuda_malloc_host\n            {\n                using memory_type = host_pinned_memory;\n                static cudaError_t allocate(void** ptr, std::size_t size)\n                {\n                    return cudaMallocHost(ptr, size);\n                }\n                static cudaError_t deallocate(void* ptr) noexcept\n                {\n                    return cudaFreeHost(ptr);\n                }\n                static allocator_info info()\n                {\n                    return {\"cudaMallocHost\", nullptr};\n                }\n            };\n\n            template <typename CudaAllocator>\n            struct generic_allocator\n            {\n                using is_stateful = std::false_type;\n                using memory_type = typename CudaAllocator::memory_type;\n\n                static void* allocate_node(std::size_t size, std::size_t)\n                {\n                    void* addr = nullptr;\n                    auto  rc   = CudaAllocator::allocate((void**)&addr, size);\n                    if (rc != cudaSuccess)\n                    {\n                        LOG(ERROR) << info().name << \" failed to allocate \" << size;\n                        throw std::bad_alloc();\n                    }\n                    return addr;\n                }\n\n                static void deallocate_node(void* ptr, std::size_t, std::size_t) noexcept\n                {\n                    CHECK_EQ(CudaAllocator::deallocate(ptr), cudaSuccess) << \"freeing \" << info().name << \": \" << ptr;\n                }\n\n                // note: requires implementation\n                static allocator_info info()\n                {\n                    return CudaAllocator::info();\n                }\n            };\n        } // namespace cuda_detail\n\n        using cuda_malloc         = cuda_detail::generic_allocator<cuda_detail::cuda_malloc>;\n        using cuda_malloc_managed = cuda_detail::generic_allocator<cuda_detail::cuda_malloc_managed>;\n        using cuda_malloc_host    = cuda_detail::generic_allocator<cuda_detail::cuda_malloc_host>;\n\n        namespace cuda_detail\n        {\n            template <typename CudaAllocator>\n            class device_allocator\n            {\n                static_assert(std::is_base_of<device_memory, typename CudaAllocator::memory_type>::value, \"should be device_memory\");\n\n            public:\n                using allocator_type = device_allocator<CudaAllocator>;\n                using is_stateful    = std::true_type;\n                using memory_type    = typename CudaAllocator::memory_type;\n\n                device_allocator(int device_id) : m_DeviceID(device_id) {}\n                virtual ~device_allocator() {}\n\n                device_allocator(allocator_type&&)      = default;\n                device_allocator(const allocator_type&) = default;\n\n                allocator_type& operator=(allocator_type&&) = default;\n                allocator_type& operator=(const allocator_type&) = default;\n\n                void* allocate_node(std::size_t size, std::size_t)\n                {\n                    device_guard guard(m_DeviceID);\n                    return CudaAllocator::allocate_node(size, 0);\n                }\n\n                void deallocate_node(void* ptr, std::size_t, std::size_t) noexcept\n                {\n                    CudaAllocator::deallocate_node(ptr, 0, 0);\n                }\n\n                bool operator==(const allocator_type& other)\n                {\n                    return m_DeviceID == other.DeviceID;\n                }\n\n            private:\n                int m_DeviceID;\n            };\n        } // namespace cuda_detail\n\n        using cuda_malloc_allocator         = cuda_detail::device_allocator<cuda_malloc>;\n        using cuda_malloc_managed_allocator = cuda_detail::device_allocator<cuda_malloc_managed>;\n        using cuda_malloc_host_allocator    = cuda_malloc_host;\n\n        static auto make_cuda_allocator(int device_id = -1)\n        {\n            if (device_id == -1)\n            {\n                CHECK_EQ(cudaGetDevice(&device_id), cudaSuccess);\n            }\n            return memory::make_allocator(cuda_malloc_allocator(device_id));\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/memory/device_memory.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <trtlab/memory/error.h>\n#include <trtlab/memory/memory_type.h>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        struct device_memory : detail::any_memory\n        {\n            constexpr static DLDeviceType device_type() noexcept\n            {\n                return kDLGPU;\n            }\n            constexpr static std::size_t min_allocation_alignment() noexcept\n            {\n                return 256UL;\n            }\n            constexpr static std::size_t max_access_alignment() noexcept\n            {\n                return 64UL;\n            }\n            static std::size_t access_alignment_for(std::size_t size)\n            {\n                using impl = detail::any_memory;\n                return impl::alignment_for<device_memory>(size);\n            }\n        };\n\n        namespace detail\n        {\n            template <typename T>\n            struct check_device_memory\n            {\n                using has_base = typename std::is_base_of<device_memory, T>::type;\n                using has_impl = decltype(is_memory_type_impl<T>(0));\n\n                using valid = std::integral_constant<bool, has_base::value && has_impl::value>;\n            };\n        } // namespace detail\n\n        template <typename T>\n        struct is_device_memory : detail::check_memory_type<T>::valid\n        {\n        };\n\n        struct device_managed_memory : device_memory\n        {\n        };\n\n        struct host_pinned_memory : host_memory\n        {\n            constexpr static DLDeviceType device_type()\n            {\n                return kDLCPUPinned;\n            }\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/include/trtlab/cuda/sync.h",
    "content": "#pragma once\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#include <trtlab/core/standard_threads.h>\n#include <trtlab/core/userspace_threads.h>\n\n#include <trtlab/cuda/common.h>\n\nnamespace trtlab\n{\n    template <typename ThreadType>\n    struct cuda_sync;\n\n    template <>\n    struct cuda_sync<userspace_threads>\n    {\n        static void event_sync(cudaEvent_t event)\n        {\n            cudaError_t rc = cudaEventQuery(event);\n            while (rc != cudaSuccess)\n            {\n                if (rc != cudaErrorNotReady)\n                {\n                    LOG(ERROR) << cudaGetErrorName(rc);\n                    throw std::runtime_error(\"cuda event query failed\");\n                }\n                boost::this_fiber::yield();\n                rc = cudaEventQuery(event);\n            }\n        }\n\n        static void stream_sync(cudaStream_t stream)\n        {\n            cudaError_t rc = cudaStreamQuery(stream);\n            while (rc != cudaSuccess)\n            {\n                if (rc != cudaErrorNotReady)\n                {\n                    LOG(ERROR) << cudaGetErrorName(rc);\n                    throw std::runtime_error(\"cuda stream query failed\");\n                }\n                boost::this_fiber::yield();\n                rc = cudaStreamQuery(stream);\n            }\n        }\n    };\n\n    template<>\n    struct cuda_sync<standard_threads>\n    {\n        static void event_sync(cudaEvent_t event)\n        {\n            CHECK_CUDA(cudaEventSynchronize(event));\n        }\n\n        static void stream_sync(cudaStream_t stream)\n        {\n            CHECK_CUDA(cudaStreamSynchronize(stream));\n        }\n    };\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/src/copy.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/cuda/memory/copy.h\"\n\n#include <cstring>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <glog/logging.h>\n\n#include \"trtlab/core/memory/memory.h\"\n\nusing trtlab::CoreMemory;\n\nnamespace {\n\nvoid Copy(CoreMemory& dst, size_t dst_offset, const CoreMemory& src, size_t src_offset, size_t size)\n{\n    CHECK_LE(size, dst.Size() - dst_offset) << \"Copy: dst range is invalid\";\n    CHECK_LE(size, src.Size() - src_offset) << \"Copy: src range is invalid\";\n    CHECK_EQ(cudaMemcpy(dst[dst_offset], src[src_offset], size, cudaMemcpyDefault), CUDA_SUCCESS);\n}\n\n} // namespace\n\nnamespace trtlab {\n\nvoid Copy(HostMemory& dst, size_t dst_offset, const DeviceMemory& src, size_t src_offset,\n          size_t size)\n{\n    Copy(dst, dst_offset, src, src_offset, size);\n}\n\nvoid Copy(DeviceMemory& dst, size_t dst_offset, const HostMemory& src, size_t src_offset,\n          size_t size)\n{\n    Copy(dst, dst_offset, src, src_offset, size);\n}\n\nvoid Copy(DeviceMemory& dst, size_t dst_offset, const DeviceMemory& src, size_t src_offset,\n          size_t size)\n{\n    Copy(dst, dst_offset, src, src_offset, size);\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/src/cuda_allocators.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <trtlab/cuda/memory/cuda_allocators.h>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace trtlab\n        {\n            namespace cuda_detail\n            {\n            }\n        } // namespace trtlab\n    }     // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/src/device_guard.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/cuda/device_guard.h\"\n#include \"trtlab/cuda/device_info.h\"\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <glog/logging.h>\n\nnamespace trtlab {\n\ndevice_guard::device_guard(int device_id)\n{\n    DCHECK_GE(device_id, 0);\n    DCHECK_LT(device_id, DeviceInfo::Count());\n    CHECK_EQ(cudaGetDevice(&m_DeviceID), CUDA_SUCCESS);\n    CHECK_EQ(cudaSetDevice(device_id), CUDA_SUCCESS);\n}\n\ndevice_guard::~device_guard()\n{\n    CHECK_EQ(cudaSetDevice(m_DeviceID), CUDA_SUCCESS);\n}\n\n} // namespace trtlab"
  },
  {
    "path": "trtlab/cuda/src/device_info.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/cuda/device_info.h\"\n\n#include <algorithm>\n\n#include <glog/logging.h>\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <nvml.h>\n\n#define test_bit(_n, _p) (_n & (1UL << _p))\n\nnamespace\n{\n    struct nvmlState\n    {\n        nvmlState()\n        {\n            CHECK_EQ(nvmlInit(), NVML_SUCCESS) << \"Failed to initialize NVML\";\n        }\n        ~nvmlState()\n        {\n            CHECK_EQ(nvmlShutdown(), NVML_SUCCESS) << \"Failed to Shutdown NVML\";\n        }\n    };\n\n    static auto nvmlInstatnce = std::make_unique<nvmlState>();\n\n    nvmlDevice_t GetHandleById(unsigned int device_id)\n    {\n        nvmlDevice_t handle;\n        CHECK_EQ(nvmlDeviceGetHandleByIndex(device_id, &handle), NVML_SUCCESS);\n        return handle;\n    }\n\n} // namespace\n\nnamespace trtlab\n{\n    cpu_set DeviceInfo::Affinity(int device_id)\n    {\n        nvmlDevice_t  gpu      = GetHandleById(device_id);\n        unsigned long cpu_mask = 0;\n        cpu_set       cpus;\n\n        CHECK_EQ(nvmlDeviceGetCpuAffinity(gpu, sizeof(cpu_mask), &cpu_mask), NVML_SUCCESS)\n            << \"Failed to retrieve CpusSet for GPU=\" << device_id;\n\n        for (unsigned int i = 0; i < 8 * sizeof(cpu_mask); i++)\n        {\n            if (test_bit(cpu_mask, i))\n            {\n                cpus.insert(affinity::system::cpu_from_logical_id(i));\n            }\n        }\n\n        DLOG(INFO) << \"CPU Affinity for GPU \" << device_id << \": \" << cpus;\n        return std::move(cpus);\n    }\n\n    std::size_t DeviceInfo::Alignment()\n    {\n        struct cudaDeviceProp properties;\n        CHECK_EQ(CUDA_SUCCESS, cudaGetDeviceProperties(&properties, 0));\n        return properties.textureAlignment;\n    }\n\n    double DeviceInfo::PowerUsage(int device_id)\n    {\n        unsigned int power;\n        CHECK_EQ(nvmlDeviceGetPowerUsage(GetHandleById(device_id), &power), NVML_SUCCESS);\n        return static_cast<double>(power) * 0.001;\n    }\n\n    double DeviceInfo::PowerLimit(int device_id)\n    {\n        unsigned int limit;\n        CHECK_EQ(nvmlDeviceGetPowerManagementLimit(GetHandleById(device_id), &limit), NVML_SUCCESS);\n        return static_cast<double>(limit) * 0.001;\n    }\n\n    std::string DeviceInfo::UUID(int device_id)\n    {\n        char buffer[256];\n        CHECK_EQ(nvmlDeviceGetUUID(GetHandleById(device_id), buffer, 256), NVML_SUCCESS);\n        return buffer;\n    }\n\n    int DeviceInfo::Count()\n    {\n        int device_count;\n        CHECK_EQ(cudaGetDeviceCount(&device_count), CUDA_SUCCESS);\n        return device_count;\n    }\n\n    bool DeviceInfo::IsValidDeviceID(int device_id)\n    {\n        return (device_id > 0) && (device_id < DeviceInfo::Count());\n    }\n\n    nvmlMemory_t DeviceInfo::MemoryInfo(int device_id)\n    {\n        nvmlMemory_t info;\n        CHECK_EQ(nvmlDeviceGetMemoryInfo(GetHandleById(device_id), &info), NVML_SUCCESS);\n        return info;\n    }\n\n    namespace cuda\n    {\n        namespace nvml\n        {\n            std::size_t device_count()\n            {\n                return DeviceInfo::Count();\n            }\n\n            nvmlMemory_t memory_info(int device_id)\n            {\n                return DeviceInfo::MemoryInfo(device_id);\n            }\n        } // namespace nvml\n    }     // namespace cuda\n\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/cuda/tests/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(GTest)\n\nadd_executable(test_cuda\n# test_memory.cc\n  test_main.cc\n  test_allocators.cc\n  test_device_info.cc\n)\n\ntarget_link_libraries(test_cuda\n  PRIVATE \n    ${PROJECT_NAME}::core\n    ${PROJECT_NAME}::cuda\n    GTest::gtest\n)\n\nadd_test(\n  NAME cuda\n  COMMAND $<TARGET_FILE:test_cuda\n)\n"
  },
  {
    "path": "trtlab/cuda/tests/test_allocators.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/block_allocators.h>\n#include <trtlab/memory/literals.h>\n#include <trtlab/memory/transactional_allocator.h>\n\n#include <trtlab/cuda/memory/cuda_allocators.h>\n\n#include <glog/logging.h>\n#include <gtest/gtest.h>\n\n#include <chrono>\n#include <future>\n#include <thread>\n\nusing namespace trtlab;\nusing namespace memory;\nusing namespace literals;\n\nclass TestCudaAllocators : public ::testing::Test\n{\n};\n\nTEST_F(TestCudaAllocators, cudaMalloc)\n{\n    auto raw   = cuda_malloc_allocator(0);\n    auto alloc = make_allocator(std::move(raw));\n\n    auto p0 = alloc.allocate_node(1024, 256);\n    alloc.deallocate_node(p0, 1024, 256);\n\n    auto info = alloc.device_context();\n    ASSERT_EQ(info.device_type, kDLGPU);\n\n    auto md = alloc.allocate_descriptor(1024);\n}\n\nTEST_F(TestCudaAllocators, TrasactionalCudaMalloc)\n{\n    auto raw     = cuda_malloc_allocator(0);\n    auto tracked = make_allocator_adapter(std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n    auto counted = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 3);\n    auto arena   = make_cached_block_arena(std::move(counted));\n    auto txalloc = make_transactional_allocator(std::move(arena));\n    auto alloc   = make_allocator(std::move(txalloc));\n\n    alloc.get_allocator().reserve_blocks(3);\n\n    auto p0 = alloc.allocate_descriptor(1024);\n}"
  },
  {
    "path": "trtlab/cuda/tests/test_device_info.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"glog/logging.h\"\n#include \"trtlab/cuda/device_info.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\n\nclass TestDeviceInfo : public ::testing::Test\n{\n  protected:\n    virtual void SetUp() {}\n\n    virtual void TearDown() {}\n};\n\nTEST_F(TestDeviceInfo, Affinity)\n{\n    auto affinity = DeviceInfo::Affinity(0);\n    LOG(INFO) << affinity;\n}"
  },
  {
    "path": "trtlab/cuda/tests/test_main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <glog/logging.h>\n#include <gtest/gtest.h>\n\nint main(int argc, char **argv) {\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"trtlab::test_cuda\");\n    ::testing::InitGoogleTest(&argc, argv);\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n    return RUN_ALL_TESTS();\n}"
  },
  {
    "path": "trtlab/cuda/tests/test_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <list>\n#include <memory>\n\n#include \"trtlab/core/memory/allocator.h\"\n#include \"trtlab/cuda/memory/cuda_device.h\"\n#include \"trtlab/cuda/memory/cuda_managed.h\"\n#include \"trtlab/cuda/memory/cuda_pinned_host.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace trtlab;\nusing namespace trtlab;\n\nnamespace {\n\nstatic size_t one_mb = 1024 * 1024;\n\ntemplate<typename T>\nclass TestMemory : public ::testing::Test\n{\n};\n\nusing MemoryTypes = ::testing::Types<CudaDeviceMemory, CudaManagedMemory, CudaPinnedHostMemory>;\n\nTYPED_TEST_CASE(TestMemory, MemoryTypes);\n\nTYPED_TEST(TestMemory, make_shared)\n{\n    auto shared = std::make_shared<Allocator<TypeParam>>(one_mb);\n    EXPECT_TRUE(shared->Data());\n    EXPECT_EQ(one_mb, shared->Size());\n\n    if(std::dynamic_pointer_cast<DeviceMemory>(shared))\n    {\n        EXPECT_EQ(shared->DeviceInfo().device_type, kDLGPU);\n    }\n    else\n    {\n        EXPECT_EQ(shared->DeviceInfo().device_type, kDLCPUPinned);\n    }\n\n    shared.reset();\n    EXPECT_FALSE(shared);\n}\n\nTYPED_TEST(TestMemory, make_unique)\n{\n    auto unique = std::make_unique<Allocator<TypeParam>>(one_mb);\n    EXPECT_TRUE(unique->Data());\n    EXPECT_EQ(one_mb, unique->Size());\n    unique.reset();\n    EXPECT_FALSE(unique);\n}\n\nTYPED_TEST(TestMemory, ctor)\n{\n    Allocator<TypeParam> memory(one_mb);\n    EXPECT_TRUE(memory.Data());\n    EXPECT_EQ(one_mb, memory.Size());\n}\n\n/*\nTYPED_TEST(TestMemory, move_ctor)\n{\n    Allocator<TypeParam> memory(one_mb);\n    Allocator<TypeParam> host(std::move(memory));\n\n    EXPECT_TRUE(host.Data());\n    EXPECT_EQ(one_mb, host.Size());\n\n    EXPECT_FALSE(memory.Data());\n    EXPECT_EQ(0, memory.Size());\n}\n\nTYPED_TEST(TestMemory, move_to_shared_ptr)\n{\n    Allocator<TypeParam> memory(one_mb);\n    auto ptr = std::make_shared<Allocator<TypeParam>>(std::move(memory));\n    EXPECT_TRUE(ptr);\n    EXPECT_TRUE(ptr->Data());\n}\n*/\n\n} // namespace\n"
  },
  {
    "path": "trtlab/memory/CMakeLists.txt",
    "content": "# MODIFICATION MESSAGE\n\n# Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n# This file is subject to the license terms in the LICENSE file\n# found in the top-level directory of this distribution.\n\n# root CMakeLists.txt, specifies option and interface library\n\ncmake_minimum_required(VERSION 3.1)\n\nproject (TRTLAB_MEMORY)\n\nset(TRTLAB_MEMORY_VERSION_MAJOR 0 CACHE STRING \"major version of memory\" FORCE)\nset(TRTLAB_MEMORY_VERSION_MINOR 1 CACHE STRING \"minor version of memory\" FORCE)\nset(TRTLAB_MEMORY_VERSION_PATCH 0 CACHE STRING \"patch version of memory\" FORCE)\nset(TRTLAB_MEMORY_VERSION \"${TRTLAB_MEMORY_VERSION_MAJOR}.${TRTLAB_MEMORY_VERSION_MINOR}.${TRTLAB_MEMORY_VERSION_PATCH}\"\n                             CACHE STRING \"version of memory\" FORCE)\n\n# set a debug postfix\nset(CMAKE_DEBUG_POSTFIX \"-dbg\")\n\nif(UNIX)\n    include(GNUInstallDirs)\n\n    set(TRTLAB_MEMORY_INC_INSTALL_DIR \"${CMAKE_INSTALL_INCLUDEDIR}/trtlab_memory\") \n    set(TRTLAB_MEMORY_RUNTIME_INSTALL_DIR \"${CMAKE_INSTALL_BINDIR}\") \n    set(TRTLAB_MEMORY_LIBRARY_INSTALL_DIR \"${CMAKE_INSTALL_LIBDIR}\")\n    set(TRTLAB_MEMORY_ARCHIVE_INSTALL_DIR \"${CMAKE_INSTALL_LIBDIR}\")\n    set(TRTLAB_MEMORY_FRAMEWORK_INSTALL_DIR \"${CMAKE_INSTALL_LIBDIR}\")\n\n    set(TRTLAB_MEMORY_CMAKE_CONFIG_INSTALL_DIR \"${CMAKE_INSTALL_DATADIR}/trtlab_memory/cmake\")\n    set(TRTLAB_MEMORY_ADDITIONAL_FILES_INSTALL_DIR \"${CMAKE_INSTALL_DATADIR}/trtlab_memory\")\n\n    set(TRTLAB_MEMORY_RUNTIME_INSTALL_DIR \"bin\") # for the nodesize_dbg, just ignore version and the like\n    set(TRTLAB_MEMORY_INC_INSTALL_DIR \"include/trtlab_memory\") # header filestree\n\nelseif(WIN32)\n    set(TRTLAB_MEMORY_INC_INSTALL_DIR \"include/trtlab_memory\")\n    set(TRTLAB_MEMORY_RUNTIME_INSTALL_DIR   \"bin\") \n    set(TRTLAB_MEMORY_LIBRARY_INSTALL_DIR   \"bin\")\n    set(TRTLAB_MEMORY_ARCHIVE_INSTALL_DIR   \"lib\")\n    set(TRTLAB_MEMORY_FRAMEWORK_INSTALL_DIR \"bin\")\n\n    set(TRTLAB_MEMORY_CMAKE_CONFIG_INSTALL_DIR \"cmake\")\n    set(TRTLAB_MEMORY_ADDITIONAL_FILES_INSTALL_DIR \"./\")\n    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)\nelse()\n\tmessage(FATAL_ERROR \"Could not set install folders for this platform!\")\nendif()\n\n#include(cmake/compatibility.cmake)\ninclude(cmake/configuration.cmake)\n\nset(CMAKE_CXX_STANDARD 17)\n\n# subdirectories\nadd_subdirectory(src)\n\nif(TRTLAB_MEMORY_BUILD_TESTS)\n    enable_testing()\n    add_subdirectory(tests)\nendif()\n\nif(TRTLAB_MEMORY_BUILD_BENCHMARKS)\n    enable_testing()\n    add_subdirectory(benchmarks)\nendif()\n\nif(TRTLAB_MEMORY_BUILD_TOOLS)\n    add_subdirectory(tools)\nendif()\n\nif(TRTLAB_MEMORY_BUILD_EXAMPLES)\n    add_subdirectory(examples)\nendif()\n\n# install readme and license\ninstall(FILES \"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE\" \"${CMAKE_CURRENT_SOURCE_DIR}/README.md\" DESTINATION ${TRTLAB_MEMORY_ADDITIONAL_FILES_INSTALL_DIR})\n\n#install(EXPORT trtlab_memoryTargets DESTINATION ${TRTLAB_MEMORY_CMAKE_CONFIG_INSTALL_DIR} FILE trtlab_memory-config.cmake)\n"
  },
  {
    "path": "trtlab/memory/benchmarks/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(benchmark REQUIRED)\n\nadd_executable(bench_memory\n  main.cc\n  bench_memory.cc\n  bench_memory_pool.cc\n)\n\ntarget_link_libraries(bench_memory \n  PRIVATE \n    trtlab_memory\n    benchmark::benchmark\n)\n\nset(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} \"-pg\")\n\nadd_test(NAME bench_memory COMMAND $<TARGET_FILE:bench_memory>)\n"
  },
  {
    "path": "trtlab/memory/benchmarks/bench_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/bfit_allocator.h>\n#include <trtlab/memory/malloc_allocator.h>\n#include <trtlab/memory/transactional_allocator.h>\n#include <trtlab/memory/literals.h>\n\nusing namespace trtlab::memory;\nusing namespace literals;\n\nnamespace bench\n{\n    template <typename Allocator>\n    static void run_allocate_node_x1(benchmark::State& state, Allocator& alloc)\n    {\n        for (auto _ : state)\n        {\n            auto p0 = (int*)alloc.allocate_node(33_MiB, 8UL);\n            benchmark::DoNotOptimize(p0);\n            alloc.deallocate_node(p0, 33_MiB, 8UL);\n        }\n\n        state.SetItemsProcessed(static_cast<int64_t>(state.iterations()));\n    }\n\n    template <typename Allocator>\n    static void run_allocate_node_x10(benchmark::State& state, Allocator& alloc)\n    {\n        for (auto _ : state)\n        {\n            void* p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;\n\n            benchmark::DoNotOptimize(p0 = alloc.allocate_node(33_MiB, 8UL));\n            benchmark::DoNotOptimize(p1 = alloc.allocate_node(44_MiB, 8UL));\n            benchmark::DoNotOptimize(p2 = alloc.allocate_node(78_MiB, 8UL));\n            benchmark::DoNotOptimize(p3 = alloc.allocate_node(12_MiB, 8UL));\n            benchmark::DoNotOptimize(p4 = alloc.allocate_node(32_MiB, 8UL));\n            benchmark::DoNotOptimize(p5 = alloc.allocate_node(100_MiB, 8UL));\n            benchmark::DoNotOptimize(p6 = alloc.allocate_node(18_MiB, 8UL));\n            benchmark::DoNotOptimize(p7 = alloc.allocate_node(21_MiB, 8UL));\n            benchmark::DoNotOptimize(p8 = alloc.allocate_node(15_MiB, 8UL));\n            benchmark::DoNotOptimize(p9 = alloc.allocate_node(71_MiB, 8UL));\n\n            alloc.deallocate_node(p3, 12_MiB, 8UL);\n            alloc.deallocate_node(p1, 44_MiB, 8UL);\n            alloc.deallocate_node(p7, 21_MiB, 8UL);\n            alloc.deallocate_node(p8, 15_MiB, 8UL);\n            alloc.deallocate_node(p0, 33_MiB, 8UL);\n            alloc.deallocate_node(p4, 32_MiB, 8UL);\n            alloc.deallocate_node(p6, 18_MiB, 8UL);\n            alloc.deallocate_node(p5, 100_MiB, 8UL);\n            alloc.deallocate_node(p9, 71_MiB, 8UL);\n            alloc.deallocate_node(p2, 78_MiB, 8UL);\n        }\n\n        state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * 10);\n    }\n\n    template <typename Allocator>\n    static void run_allocate_descriptor_x1(benchmark::State& state, Allocator& alloc)\n    {\n        for (auto _ : state)\n        {\n            auto p0 = alloc.allocate_descriptor(33_MiB, 8UL);\n        }\n\n        state.SetItemsProcessed(static_cast<int64_t>(state.iterations()));\n    }\n\n    template <typename Allocator>\n    static void run_allocate_descriptor_x10(benchmark::State& state, Allocator& alloc)\n    {\n        for (auto _ : state)\n        {\n            auto p0 = alloc.allocate_descriptor(33_MiB, 8UL);\n            auto p1 = alloc.allocate_descriptor(44_MiB, 8UL);\n            auto p2 = alloc.allocate_descriptor(78_MiB, 8UL);\n            auto p3 = alloc.allocate_descriptor(12_MiB, 8UL);\n            auto p4 = alloc.allocate_descriptor(32_MiB, 8UL);\n            auto p5 = alloc.allocate_descriptor(100_MiB, 8UL);\n            auto p6 = alloc.allocate_descriptor(18_MiB, 8UL);\n            auto p7 = alloc.allocate_descriptor(21_MiB, 8UL);\n            auto p8 = alloc.allocate_descriptor(15_MiB, 8UL);\n            auto p9 = alloc.allocate_descriptor(71_MiB, 8UL);\n        }\n\n        state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * 10);\n    }\n\n    static auto make_transactional_allocator()\n    {\n        constexpr std::size_t block_size  = 128_MiB;\n        constexpr std::size_t block_count = 6;\n\n        auto malloc  = make_allocator_adapter(malloc_allocator());\n        auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(malloc), block_size);\n        auto counted = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), block_count);\n        auto arena   = make_cached_block_arena(std::move(counted));\n        auto alloc   = make_transactional_allocator(std::move(arena));\n\n        alloc.reserve_blocks(block_count);\n\n        return alloc;\n    }\n\n    static auto make_bfit_allocator()\n    {\n        constexpr std::size_t heap_size = 128_MB * 6;\n        auto bfit = make_bfit_allocator(heap_size, malloc_allocator());\n        return bfit;\n    }\n\n} // namespace bench\n\n// malloc\n\nstatic void memory_malloc_raw_x1(benchmark::State& state)\n{\n    auto alloc = make_allocator_adapter(malloc_allocator());\n    bench::run_allocate_node_x1(state, alloc);\n}\n\nstatic void memory_malloc_raw_x10(benchmark::State& state)\n{\n    auto alloc = make_allocator_adapter(malloc_allocator());\n    bench::run_allocate_node_x10(state, alloc);\n}\n\n// transactional\n\nstatic void memory_transactional_raw_x1(benchmark::State& state)\n{\n    auto alloc = bench::make_transactional_allocator();\n    bench::run_allocate_node_x1(state, alloc);\n}\n\nstatic void memory_transactional_raw_x10(benchmark::State& state)\n{\n    auto alloc = bench::make_transactional_allocator();\n    bench::run_allocate_node_x10(state, alloc);\n}\n\nstatic void memory_transactional_allocator_x1(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc   = make_allocator(std::move(txalloc));\n    bench::run_allocate_node_x1(state, alloc);\n}\n\nstatic void memory_transactional_allocator_x10(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc   = make_allocator(std::move(txalloc));\n    bench::run_allocate_node_x10(state, alloc);\n}\n\nstatic void memory_transactional_descriptor_x1(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc   = make_allocator(std::move(txalloc));\n    bench::run_allocate_descriptor_x1(state, alloc);\n}\n\nstatic void memory_transactional_descriptor_x10(benchmark::State& state)\n{\n    auto txalloc = bench::make_transactional_allocator();\n    auto alloc   = make_allocator(std::move(txalloc));\n    bench::run_allocate_descriptor_x10(state, alloc);\n}\n\nstatic void memory_bfit_raw_x10(benchmark::State& state)\n{\n    auto bfit = bench::make_bfit_allocator();\n    bench::run_allocate_node_x10(state, bfit);    \n}\n\nstatic void memory_bfit_allocator_x10(benchmark::State& state)\n{\n    auto bfit = bench::make_bfit_allocator();\n    auto alloc = make_allocator(std::move(bfit));\n    bench::run_allocate_node_x10(state, alloc);\n}\n\nstatic void memory_bfit_descriptor_x10(benchmark::State& state)\n{\n    auto bfit = bench::make_bfit_allocator();\n    auto alloc = make_allocator(std::move(bfit));\n    bench::run_allocate_descriptor_x10(state, alloc);\n}\n\nBENCHMARK(memory_malloc_raw_x1);\nBENCHMARK(memory_malloc_raw_x10);\n\n//BENCHMARK(memory_transactional_raw_x1);\n//BENCHMARK(memory_transactional_allocator_x1);\n//BENCHMARK(memory_transactional_descriptor_x1);\n\nBENCHMARK(memory_transactional_raw_x10);\nBENCHMARK(memory_transactional_allocator_x10);\nBENCHMARK(memory_transactional_descriptor_x10);\n\n//BENCHMARK(memory_bit_raw_x1);\n//BENCHMARK(memory_bfit_allocator_x1);\n//BENCHMARK(memory_bfit_descriptor_x1);\n\nBENCHMARK(memory_bfit_raw_x10);\nBENCHMARK(memory_bfit_allocator_x10);\nBENCHMARK(memory_bfit_descriptor_x10);"
  },
  {
    "path": "trtlab/memory/benchmarks/bench_memory_pool.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\n#include <map>\n\n#include <trtlab/memory/allocator.h>\n#include <trtlab/memory/block_arena.h>\n#include <trtlab/memory/malloc_allocator.h>\n#include <trtlab/memory/memory_pool.h>\n#include <trtlab/memory/std_allocator.h>\n#include <trtlab/memory/literals.h>\n\nusing namespace trtlab::memory;\nusing namespace literals;\n\nstatic void memory_pool_map_default(benchmark::State& state)\n{\n    std::map<std::size_t, std::size_t> m;\n\n    for(auto _ : state)\n    {\n        auto upper = state.range(0);\n        for(std::size_t i=0; i<upper; i++)\n        {\n            m[i] = i;\n        }\n        m.clear();\n    }\n}\n\nstatic void memory_pool_map_malloc_raw(benchmark::State& state)\n{\n    auto malloc = malloc_allocator();\n\n    // create map\n    auto m = std::map<std::size_t, std::size_t, std::less<std::size_t>, std_allocator<std::pair<std::size_t, std::size_t>, decltype(malloc)>>(malloc);\n\n    for(auto _ : state)\n    {\n        auto upper = state.range(0);\n        for(std::size_t i=0; i<upper; i++)\n        {\n            m[i] = i;\n        }\n        m.clear();\n    }\n}\n\ntemplate<typename Key, typename Value, typename BlockAllocator>\nauto make_map(BlockAllocator&& block_alloc)\n{\n    static_assert(is_block_allocator<BlockAllocator>::value, \"\");\n\n    using node_type = std::pair<Key, Value>;\n    auto node_size = alignof(node_type) + sizeof(node_type) + 64;\n\n    auto stack = make_block_stack<uncached>(std::move(block_alloc));\n    auto pool  = memory_pool<BlockAllocator>(node_size, std::move(stack));\n    return pool;\n    //auto alloc = make_thread_unsafe_allocator(std::move(pool));\n\n    //return std::map<Key, Value, std::less<Key>, std_allocator<node_type, decltype(alloc)>>(alloc);\n}\n\nstatic void memory_pool_map_malloc_pooled(benchmark::State& state)\n{\n    auto malloc = make_allocator_adapter(malloc_allocator());\n    auto block  = make_block_allocator<single_block_allocator>(std::move(malloc), 4_MiB);\n\n    // create map\n    auto p = make_map<std::size_t, std::size_t>(std::move(block));\n\n    // create map\n    auto m = std::map<std::size_t, std::size_t, std::less<std::size_t>, std_allocator<std::pair<std::size_t, std::size_t>, decltype(p)>>(p);\n\n\n    for(auto _ : state)\n    {\n        auto upper = state.range(0);\n        for(std::size_t i=0; i<upper; i++)\n        {\n            m[i] = i;\n        }\n        m.clear();\n    }\n}\n\nBENCHMARK(memory_pool_map_default)->RangeMultiplier(2)->Range(1<<0, 1<<12);\nBENCHMARK(memory_pool_map_malloc_raw)->RangeMultiplier(2)->Range(1<<0, 1<<12);\nBENCHMARK(memory_pool_map_malloc_pooled)->RangeMultiplier(2)->Range(1<<0, 1<<12);"
  },
  {
    "path": "trtlab/memory/benchmarks/main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <benchmark/benchmark.h>\n\nBENCHMARK_MAIN();"
  },
  {
    "path": "trtlab/memory/cmake/configuration.cmake",
    "content": "# MODIFICATION MESSAGE\n\n# Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n# This file is subject to the license terms in the LICENSE file\n# found in the top-level directory of this distribution.\n\n# defines configuration options\n# note: only include it in memory's top-level CMakeLists.txt, after compatibility.cmake\n\n# what to build\n# examples/tests if toplevel directory (i.e. direct build, not as subdirectory) and hosted\n# tools if hosted\n\noption(TRTLAB_MEMORY_BUILD_TOOLS \"whether or not to build the tools\" ON)\noption(TRTLAB_MEMORY_BUILD_TESTS \"whether or not to build the tests\" ON)\noption(TRTLAB_MEMORY_BUILD_BENCHMARKS \"whether or not to build the tools\" ON)\noption(TRTLAB_MEMORY_BUILD_EXAMPLES \"whether or not to build the examples\" OFF)\n\n#SET(CPUAFF_ROOT \"/usr/local\" CACHE STRING \"Location of cpuaff header files\")\n#add_library(cpuaff INTERFACE)\n#target_include_directories(cpuaff INTERFACE \"${CPUAFF_ROOT}/include\")\n\nset(TRTLAB_MEMORY_DEBUG_ASSERT OFF CACHE BOOL \"\" FORCE)\nset(TRTLAB_MEMORY_DEBUG_FILL OFF CACHE BOOL \"\" FORCE)\nset(TRTLAB_MEMORY_DEBUG_FENCE 0 CACHE STRING \"\" FORCE)\nset(TRTLAB_MEMORY_DEBUG_LEAK_CHECK OFF CACHE BOOL \"\" FORCE)\nset(TRTLAB_MEMORY_DEBUG_POINTER_CHECK OFF CACHE BOOL \"\" FORCE)\nset(TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK OFF CACHE BOOL \"\" FORCE)\n\n# most of the debugging aspects of foonathan/memory have been disabled\n# debug options, pre-set by build type\n# if(\"${CMAKE_BUILD_TYPE}\" STREQUAL \"Debug\")\n#     # disable force to allow external CMakeLists.txt to override the defaults\n#     set(TRTLAB_MEMORY_DEBUG_ASSERT ON CACHE BOOL \"\")\n#     set(TRTLAB_MEMORY_DEBUG_FILL ON CACHE BOOL \"\")\n#     set(TRTLAB_MEMORY_DEBUG_FENCE 8 CACHE STRING \"\")\n#     set(TRTLAB_MEMORY_DEBUG_LEAK_CHECK ON CACHE BOOL \"\")\n#     set(TRTLAB_MEMORY_DEBUG_POINTER_CHECK ON CACHE BOOL \"\")\n#     set(TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK ON CACHE BOOL \"\")\n# elseif(\"${CMAKE_BUILD_TYPE}\" STREQUAL \"RelWithDebInfo\")\n#     set(TRTLAB_MEMORY_DEBUG_ASSERT OFF CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_FILL ON CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_FENCE 0 CACHE STRING \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_LEAK_CHECK ON CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_POINTER_CHECK ON CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK OFF CACHE BOOL \"\" FORCE)\n# elseif(\"${CMAKE_BUILD_TYPE}\" STREQUAL \"Release\")\n#     set(TRTLAB_MEMORY_DEBUG_ASSERT OFF CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_FILL OFF CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_FENCE 0 CACHE STRING \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_LEAK_CHECK OFF CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_POINTER_CHECK OFF CACHE BOOL \"\" FORCE)\n#     set(TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK OFF CACHE BOOL \"\" FORCE)\n# else()\n#     option(TRTLAB_MEMORY_DEBUG_ASSERT \"whether or not internal assertions (like the macro assert) are enabled\" OFF)\n#     option(TRTLAB_MEMORY_DEBUG_FILL   \"whether or not the (de-)allocated memory will be pre-filled\" OFF)\n#     set(TRTLAB_MEMORY_DEBUG_FENCE 0 CACHE STRING \"the amount of memory used as fence to help catching overflow errors\" )\n#     option(TRTLAB_MEMORY_DEBUG_LEAK_CHECK \"whether or not leak checking is active\" OFF)\n#     option(TRTLAB_MEMORY_DEBUG_POINTER_CHECK \"whether or not pointer checking on deallocation is active\" OFF)\n#     option(TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK \"whether or not the (sometimes expensive) check for double deallocation is active\" OFF)\n# endif()\n\n# other options\noption(TRTLAB_MEMORY_EXTERN_TEMPLATE\n    \"whether or not common template instantiations are already provided by the library\" ON)\noption(TRTLAB_MEMORY_CHECK_ALLOCATION_SIZE\n        \"whether or not the size of the allocation will be checked\" ON)\noption(TRTLAB_MEMORY_THREAD_SAFE_REFERENCE\n    \"whether or not allocator_reference is thread safe by default\" ON)\n\nset(TRTLAB_MEMORY_DEFAULT_ALLOCATOR heap_allocator CACHE STRING\n    \"the default implementation allocator for higher-level ones\")\nset(TRTLAB_MEMORY_MEMORY_RESOURCE_HEADER \"<foonathan/pmr.hpp>\" CACHE STRING\n    \"the header of the memory_resource class used\")\nset(TRTLAB_MEMORY_MEMORY_RESOURCE foonathan_comp::memory_resource CACHE STRING\n    \"the memory_resource class used\")\nset(TRTLAB_MEMORY_TEMPORARY_STACK_MODE 2 CACHE STRING\n     \"set to 0 to disable the per-thread stack completely, to 1 to disable the nitfy counter and to 2 to enable everything\")\n"
  },
  {
    "path": "trtlab/memory/cmake/dependencies.cmake",
    "content": "include (ExternalProject)\n\nset (DEPENDENCIES)\nset (EXTRA_CMAKE_ARGS)\n\n# trtlab external dependencies\nlist (APPEND DEPENDENCIES boost gflags glog benchmark googletest cpuaff)\n\n# customize the folder for external projects\n# download, source and builds for dependencies \n# will be in <build-dir>/Dependencies\nset_property (DIRECTORY PROPERTY EP_BASE Dependencies)\n\n# all dependencies will be installed here\n# typical directories: bin, include and lib\nset (INSTALL_ROOT ${CMAKE_CURRENT_BINARY_DIR}/local)\n\n# set cmake search paths to pick up installed .cmake files\nlist(INSERT CMAKE_MODULE_PATH 0 \"${INSTALL_ROOT}/lib/cmake\")\nlist(INSERT CMAKE_PREFIX_PATH 0 \"${INSTALL_ROOT}/lib/cmake\")\n\n# cmake config args forwarded to trtlab\nlist(APPEND EXTRA_CMAKE_ARGS\n  -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\n  -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}\n# -DBoost_VERBOSE=ON\n  -DBoost_USE_STATIC_LIBS=ON\n  -DFIND_GTEST=OFF\n  -DFIND_BENCHMARK=OFF\n  -DCPUAFF_ROOT=${INSTALL_ROOT}\n)\n\n# short-cut to dependencies build path\nset (BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build)\n\n# Boost\n# =====\n# - Use static linking to avoid issues with system-wide installations of Boost.\n# - Use numa=on to ensure the numa component of fiber gets built\nset(BOOST_COMPONENTS \"context,fiber,filesystem\")\nExternalProject_Add (boost\n  URL https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.tar.gz\n  URL_HASH SHA256=c66e88d5786f2ca4dbebb14e06b566fb642a1a6947ad8cc9091f9f445134143f\n  CONFIGURE_COMMAND ./bootstrap.sh --prefix=${INSTALL_ROOT} --with-libraries=${BOOST_COMPONENTS} numa=on\n  BUILD_COMMAND ./b2 link=static cxxflags=-fPIC cflags=-fPIC cxxflags=\"-std=c++14\" numa=on \n                     --build-dir=${BUILD_ROOT}/boost --stagedir=${BUILD_ROOT}/boost\n  BUILD_IN_SOURCE 1\n  INSTALL_COMMAND ./b2 install numa=on\n)\n\n# gflags\n# ======\n# config, build and install to INSTALL_ROOT\nExternalProject_Add(gflags\n  GIT_REPOSITORY \"https://github.com/gflags/gflags.git\"\n  GIT_TAG \"v2.2.2\"\n  CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n             -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DBUILD_SHARED_LIBS=ON\n             -DBUILD_STATIC_LIBS=ON\n             -DBUILD_PACKAGING=OFF\n             -DBUILD_TESTING=OFF\n             -BUILD_CONFIG_TESTS=OFF\n             -DINSTALL_HEADERS=ON\n             -DBUILD_gflags_LIB=OFF\n             -DBUILD_gflags_nothreads_LIB=ON\n             -DGFLAGS_NAMESPACE=google\n# INSTALL_COMMAND   \"\"\n)\n\n# glog\n# ====\n# - link against shared \n# - todo: compile with -DWITH_GFLAGS=OFF and remove gflags dependency\nExternalProject_Add(glog\n  DEPENDS gflags\n  GIT_REPOSITORY \"https://github.com/google/glog\"\n  GIT_TAG \"v0.4.0\"\n  CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n             -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DBUILD_TESTING=OFF\n# INSTALL_COMMAND   \"\"\n)\n\n# google benchmark\n# ================\nExternalProject_Add(benchmark\n  DEPENDS \n  GIT_REPOSITORY    https://github.com/google/benchmark.git\n  GIT_TAG           \"v1.5.0\"\n  BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build/benchmark\"\n  CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n             -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n             -DBENCHMARK_ENABLE_TESTING=OFF\n  INSTALL_COMMAND   \"\"\n)\n\n# google test\n# ===========\nExternalProject_Add(googletest\n  DEPENDS glog gflags\n  GIT_REPOSITORY    https://github.com/google/googletest.git\n  GIT_TAG           \"release-1.10.0\"\n  BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/Dependencies/Build/googletest\"\n  CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n             -DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}\n  INSTALL_COMMAND   \"\"\n)\n\n# cpuaff\n# ======\nExternalProject_Add(cpuaff\n  URL http://dcdillon.github.io/cpuaff/releases/cpuaff-1.0.6.tar.gz\n  CONFIGURE_COMMAND ./configure --prefix=${INSTALL_ROOT}\n  BUILD_COMMAND     make include\n  INSTALL_COMMAND   make install include\n  BUILD_IN_SOURCE 1\n)\n\n\n# trtlab\n# ======\nExternalProject_Add (trtlab_memory\n  DEPENDS ${DEPENDENCIES}\n  SOURCE_DIR ${PROJECT_SOURCE_DIR}\n  CMAKE_ARGS -DBUILD_DEPENDENCIES=OFF ${EXTRA_CMAKE_ARGS}\n  INSTALL_COMMAND \"\"\n  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/align.h",
    "content": "// MODIFICATION_MESSAGE\n\n// Modification notes:\n// - alignment is no longer a detail\n// - removed compat headers for alignas, alignof and max_align_t\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAIL_ALIGN_H_INCLUDED\n#define TRTLAB_MEMORY_DETAIL_ALIGN_H_INCLUDED\n\n#include <cstdint>\n\n#include \"config.h\"\n#include \"detail/assert.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        using addr_t = unsigned char*;\n\n        // whether or not an alignment is valid, i.e. a power of two and not zero\n        constexpr bool is_valid_alignment(std::size_t alignment) noexcept\n        {\n            return alignment && (alignment & (alignment - 1)) == 0u;\n        }\n\n        // align up to a power of 2, align_bytes is expected to be a nonzero\n        inline std::size_t align_up(std::size_t v, std::size_t alignment) noexcept\n        {\n            return (v + (alignment - 1)) & ~(alignment - 1);\n        }\n\n        // returns the offset needed to align ptr for given alignment\n        // alignment must be valid\n        inline std::size_t align_offset(std::uintptr_t address, std::size_t alignment) noexcept\n        {\n            TRTLAB_MEMORY_ASSERT(is_valid_alignment(alignment));\n            auto misaligned = address & (alignment - 1);\n            return misaligned != 0 ? (alignment - misaligned) : 0;\n        }\n\n        inline std::size_t align_offset(void* ptr, std::size_t alignment) noexcept\n        {\n            return align_offset(reinterpret_cast<std::uintptr_t>(ptr), alignment);\n        }\n\n        inline void* memory_shift(void* memory, std::int64_t size)\n        {\n            return static_cast<void*>(reinterpret_cast<addr_t>(memory) + size);\n        }\n\n        inline std::pair<void*, std::size_t> align_shift(void* ptr, std::size_t alignment) noexcept\n        {\n            auto offset = align_offset(ptr, alignment);\n            return std::make_pair(memory_shift(ptr, offset), offset);\n        }\n\n        // whether or not the pointer is aligned for given alignment\n        // alignment must be valid\n        bool is_aligned(void* ptr, std::size_t alignment) noexcept;\n\n        // this need to be abstracted into memory_type\n        // returns the minimum alignment required for a node of given size\n        std::size_t alignment_for(std::size_t size) noexcept;\n\n\n\n        std::size_t ilog2(std::size_t x);\n        std::size_t ilog2_ceil(std::size_t x);\n\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_DETAIL_ALIGN_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <memory>\n\n#include <glog/logging.h>\n\n#include \"trtlab/memory/allocator_storage.h\"\n#include \"trtlab/memory/descriptor.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace allocator_detail\n        {\n            template <typename RawAllocator, typename Mutex>\n            class smart_storage : public iallocator,\n                                  public std::enable_shared_from_this<smart_storage<RawAllocator, Mutex>>,\n                                  private allocator_storage<direct_storage<RawAllocator>, Mutex>\n            {\n                using storage_type = allocator_storage<direct_storage<RawAllocator>, Mutex>;\n\n            public:\n                using allocator_type = typename storage_type::allocator_type;\n                using memory_type    = typename storage_type::memory_type;\n                using mutex          = typename storage_type::mutex;\n\n                explicit smart_storage(storage_type&& storage) : storage_type(std::move(storage)),\n                  m_min_alignment(storage_type::min_alignment()),\n                  m_max_alignment(storage_type::max_alignment()) {}\n\n                smart_storage(smart_storage&& other)\n                : storage_type(std::move(other)),\n                  m_min_alignment(storage_type::min_alignment()),\n                  m_max_alignment(storage_type::max_alignment())\n                {\n                }\n                smart_storage& operator=(smart_storage&& other)\n                {\n                    storage_type::operator=(std::move(other));\n                    m_min_alignment = other.min_alignment();\n                    m_max_alignment = other.max_alignment();\n                    return *this;\n                }\n\n                ~smart_storage() override {}\n\n                allocator_type& get_allocator() noexcept\n                {\n                    return storage_type::get_allocator();\n                }\n\n                const allocator_type& get_allocator() const noexcept\n                {\n                    return storage_type::get_allocator();\n                }\n\n                // disambiguate method in both iallocator and storage_type\n\n                using iallocator::allocate_descriptor;\n                using iallocator::device_context;\n                using iallocator::max_alignment;\n                using iallocator::min_alignment;\n\n            private:\n                inline void* do_allocate(std::size_t size, std::size_t alignment) final override\n                {\n                    return storage_type::allocate_node(size, alignment);\n                }\n\n                inline void do_deallocate(void* ptr, std::size_t size, std::size_t alignment) noexcept final override\n                {\n                    storage_type::deallocate_node(ptr, size, alignment);\n                }\n\n                inline descriptor do_allocate_descriptor(std::size_t size, std::size_t alignment) final override\n                {\n                    alignment = std::min(std::max(alignment, m_min_alignment), m_max_alignment);\n                    return descriptor(std::move(this->shared_from_this()), size, alignment);\n                }\n\n                inline std::size_t do_max_alignment() const final override\n                {\n                    return m_max_alignment;\n                }\n\n                inline std::size_t do_min_alignment() const final override\n                {\n                    return m_min_alignment;\n                }\n\n                inline std::size_t do_max_size() const final override\n                {\n                    return storage_type::max_node_size();\n                }\n\n                inline DLContext do_device_context() const final override\n                {\n                    return storage_type::device_context();\n                }\n\n                std::size_t m_min_alignment;\n                std::size_t m_max_alignment;\n            };\n\n            template <typename Mutex, typename RawAllocator>\n            auto make_allocator_storage(RawAllocator&& alloc)\n            {\n                auto storage = allocator_storage<direct_storage<RawAllocator>, Mutex>(std::move(alloc));\n                return std::make_shared<smart_storage<RawAllocator, Mutex>>(std::move(storage));\n            }\n\n            template <typename StorageType>\n            class allocator_impl\n            {\n                using storage_type = StorageType;\n\n                std::shared_ptr<storage_type> m_storage;\n\n            public:\n                using allocator_type = typename storage_type::allocator_type;\n                using memory_type    = typename storage_type::memory_type;\n                using mutex          = typename storage_type::mutex;\n                using is_stateful    = std::true_type;\n\n                explicit allocator_impl(std::shared_ptr<storage_type> storage) : m_storage(storage) \n                {\n                    static_assert(std::is_base_of<iallocator, storage_type>::value, \"storage must be derived from iallocator\");\n                }\n                virtual ~allocator_impl() = default;\n\n                allocator_impl(const allocator_impl<StorageType>& other) = default;\n                allocator_impl& operator=(const allocator_impl<StorageType>& other) = default;\n\n                allocator_impl(allocator_impl&& other) : m_storage(std::exchange(other.m_storage, nullptr)) {}\n\n                allocator_impl& operator=(allocator_impl&& other)\n                {\n                    m_storage = std::exchange(other.m_storage, nullptr);\n                    return *this;\n                }\n\n                allocator_impl copy() const noexcept\n                {\n                    return *this;\n                }\n\n                // iallocator\n\n                void* allocate(std::size_t size, std::size_t alignment = 0UL)\n                {\n                    DCHECK(m_storage);\n                    return m_storage->allocate(size, alignment);\n                }\n\n                void deallocate(void* ptr, std::size_t size = 0UL, std::size_t alignment = 0UL)\n                {\n                    DCHECK(m_storage);\n                    m_storage->deallocate(ptr, size, alignment);\n                }\n\n                descriptor allocate_descriptor(std::size_t size, std::size_t alignment = 0UL)\n                {\n                    return m_storage->allocate_descriptor(size, alignment);\n                }\n\n                // allocator_traits\n\n                void* allocate_node(std::size_t size, std::size_t alignment)\n                {\n                    DCHECK(m_storage);\n                    return m_storage->allocate(size, alignment);\n                }\n\n                void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)\n                {\n                    DCHECK(m_storage);\n                    return m_storage->allocate(count * size, alignment);\n                }\n\n                void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n                {\n                    DCHECK(m_storage);\n                    m_storage->deallocate(ptr, size, alignment);\n                }\n\n                void deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n                {\n                    DCHECK(m_storage);\n                    m_storage->deallocate(ptr, count * size, alignment);\n                }\n\n                DLContext device_context() const\n                {\n                    DCHECK(m_storage);\n                    return m_storage->device_context();\n                }\n\n                std::size_t max_alignment() const\n                {\n                    DCHECK(m_storage);\n                    return m_storage->max_alignment();\n                }\n\n                std::size_t min_alignment() const\n                {\n                    DCHECK(m_storage);\n                    return m_storage->min_alignment();\n                }\n\n                std::size_t max_node_size() const\n                {\n                    DCHECK(m_storage);\n                    return m_storage->max_size();\n                }\n\n                std::size_t max_array_size() const\n                {\n                    DCHECK(m_storage);\n                    return m_storage->max_size();\n                }\n\n                // storage policy methods\n\n                allocator_type& get_allocator() noexcept\n                {\n                    return m_storage->get_allocator();\n                }\n\n                const allocator_type& get_allocator() const noexcept\n                {\n                    return *m_storage->get_allocator();\n                }\n\n                // access raw allocator\n\n                auto use_count() const noexcept\n                {\n                    return m_storage.use_count();\n                }\n\n                // allocator interface\n\n                iallocator& get_iallocator()\n                {\n                    return *m_storage;\n                }\n\n                std::shared_ptr<storage_type> shared() const\n                {\n                    return m_storage;\n                }\n\n            private:\n                template <typename T>\n                friend bool operator==(const allocator_impl<T>& lhs, const allocator_impl<T>& rhs) noexcept;\n            };\n\n            template <typename T>\n            bool operator==(const allocator_impl<T>& lhs, const allocator_impl<T>& rhs) noexcept\n            {\n                return lhs.m_storage.get() == rhs.m_storage.get();\n            }\n\n        } // namespace allocator_detail\n\n        template <typename RawAllocator, typename Mutex>\n        using allocator = allocator_detail::allocator_impl<allocator_detail::smart_storage<RawAllocator, Mutex>>;\n\n        // convenience methods to create allocators from raw allocators\n\n        template <typename RawAllocator>\n        auto make_allocator(RawAllocator&& alloc)\n        {\n            auto storage = allocator_detail::make_allocator_storage<detail::mutex_for<RawAllocator, std::mutex>>(std::move(alloc));\n            return allocator<RawAllocator, detail::mutex_for<RawAllocator, std::mutex>>(std::move(storage));\n        }\n\n        template <typename Mutex, typename RawAllocator>\n        auto make_allocator(RawAllocator&& alloc)\n        {\n            auto storage = allocator_detail::make_allocator_storage<detail::mutex_for<RawAllocator, Mutex>>(std::move(alloc));\n            return allocator<RawAllocator, detail::mutex_for<RawAllocator, Mutex>>(std::move(storage));\n        }\n\n        // only stateless or threadsafe RawAllocators can be used with this method\n        template <typename RawAllocator>\n        auto make_thread_unsafe_allocator(RawAllocator&& alloc)\n        {\n            auto storage = allocator_detail::make_allocator_storage<detail::mutex_for<RawAllocator, no_mutex>>(std::move(alloc));\n            return allocator<RawAllocator, no_mutex>(std::move(storage));\n        }\n\n        // this specialization of is_shared_allocator\n        // the allocator is shared, if - like \\ref allocator_reference -\n        //   if multiple objects refer to the same internal allocator and if it can be copied.\n        template <typename RawAllocator, typename Mutex>\n        struct is_shared_allocator<allocator<RawAllocator, Mutex>> : std::true_type\n        {\n        };\n\n        template <typename RawAllocator, typename Mutex>\n        struct is_thread_safe_allocator<allocator<RawAllocator, Mutex>> : std::true_type\n        {\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/allocator_storage.h",
    "content": "// MODIFICATION MESSAGE\n\n// Modification notes:\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_ALLOCATOR_STORAGE_H_INCLUDED\n#define TRTLAB_MEMORY_ALLOCATOR_STORAGE_H_INCLUDED\n\n/// \\file\n/// Class template \\ref foonathan::memory::allocator_storage, some policies and resulting typedefs.\n#include <glog/logging.h>\n\n#include <new>\n#include <type_traits>\n\n#include \"detail/utility.h\"\n#include \"config.h\"\n#include \"allocator_traits.h\"\n#include \"threading.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n#if !defined(DOXYGEN)\n        template <class StoragePolicy, class Mutex>\n        class allocator_storage;\n#endif\n\n        namespace detail\n        {\n            // whether or not the allocator of the storage policy is a raw allocator itself\n            template <class StoragePolicy>\n            using is_nested_policy = is_instantiation_of<allocator_storage, typename StoragePolicy::allocator_type>;\n\n            template <class Alloc>\n            void* try_allocate_node(std::true_type, Alloc& alloc, std::size_t size, std::size_t alignment) noexcept\n            {\n                return composable_allocator_traits<Alloc>::try_allocate_node(alloc, size, alignment);\n            }\n\n            template <class Alloc>\n            void* try_allocate_array(std::true_type, Alloc& alloc, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                return composable_allocator_traits<Alloc>::try_allocate_array(alloc, count, size, alignment);\n            }\n\n            template <class Alloc>\n            bool try_deallocate_node(std::true_type, Alloc& alloc, void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                return composable_allocator_traits<Alloc>::try_deallocate_node(alloc, ptr, size, alignment);\n            }\n\n            template <class Alloc>\n            bool try_deallocate_array(std::true_type, Alloc& alloc, void* ptr, std::size_t count, std::size_t size,\n                                      std::size_t alignment) noexcept\n            {\n                return composable_allocator_traits<Alloc>::try_deallocate_array(alloc, ptr, count, size, alignment);\n            }\n\n            template <class Alloc>\n            void* try_allocate_node(std::false_type, Alloc&, std::size_t, std::size_t) noexcept\n            {\n                TRTLAB_MEMORY_UNREACHABLE(\"Allocator is not compositioning\");\n                return nullptr;\n            }\n\n            template <class Alloc>\n            void* try_allocate_array(std::false_type, Alloc&, std::size_t, std::size_t, std::size_t) noexcept\n            {\n                TRTLAB_MEMORY_UNREACHABLE(\"Allocator is not compositioning\");\n                return nullptr;\n            }\n\n            template <class Alloc>\n            bool try_deallocate_node(std::false_type, Alloc&, void*, std::size_t, std::size_t) noexcept\n            {\n                TRTLAB_MEMORY_UNREACHABLE(\"Allocator is not compositioning\");\n                return false;\n            }\n\n            template <class Alloc>\n            bool try_deallocate_array(std::false_type, Alloc&, void*, std::size_t, std::size_t, std::size_t) noexcept\n            {\n                TRTLAB_MEMORY_UNREACHABLE(\"Allocator is not compositioning\");\n                return false;\n            }\n        } // namespace detail\n\n        /// A \\concept{concept_rawallocator,RawAllocator} that stores another allocator.\n        /// The \\concept{concept_storagepolicy,StoragePolicy} defines the allocator type being stored and how it is stored.\n        /// The \\c Mutex controls synchronization of the access.\n        /// \\requires The \\c StoragePolicy itself must not store an instance of this class.\n        /// \\ingroup memory storage\n        template <class StoragePolicy, class Mutex>\n        class allocator_storage\n        : private TRTLAB_EBO(StoragePolicy, detail::mutex_storage<detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>)\n//      : private TRTLAB_EBO(StoragePolicy, detail::mutex_storage<Mutex>)\n        {\n            static_assert(!detail::is_nested_policy<StoragePolicy>::value,\n                          \"allocator_storage instantiated with another allocator_storage, double wrapping!\");\n\n            using traits            = allocator_traits<typename StoragePolicy::allocator_type>;\n            using composable_traits = composable_allocator_traits<typename StoragePolicy::allocator_type>;\n            using composable        = is_composable_allocator<typename StoragePolicy::allocator_type>;\n            using actual_mutex      = const detail::mutex_storage<detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>;\n\n        public:\n            using allocator_type = typename StoragePolicy::allocator_type;\n            using storage_policy = StoragePolicy;\n            using mutex          = detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>;\n            using is_stateful    = typename traits::is_stateful;\n            using memory_type    = typename traits::memory_type;\n\n            /// \\effects Creates it by default-constructing the \\c StoragePolicy.\n            /// \\requires The \\c StoragePolicy must be default-constructible.\n            /// \\notes The default constructor may create an invalid allocator storage not associated with any allocator.\n            /// If that is the case, it must not be used.\n            allocator_storage() = default;\n            ~allocator_storage() {}\n\n            /// \\effects Creates it by passing it an allocator.\n            /// The allocator will be forwarded to the \\c StoragePolicy, it decides whether it will be moved, its address stored or something else.\n            /// \\requires The expression <tt>new storage_policy(std::forward<Alloc>(alloc))</tt> must be well-formed,\n            /// otherwise this constructor does not participate in overload resolution.\n            template <class Alloc,\n                      // MSVC seems to ignore access rights in SFINAE below\n                      // use this to prevent this constructor being chosen instead of move for types inheriting from it\n                      TRTLAB_REQUIRES((!std::is_base_of<allocator_storage, typename std::decay<Alloc>::type>::value))>\n            allocator_storage(Alloc&& alloc, TRTLAB_SFINAE(new storage_policy(detail::forward<Alloc>(alloc))))\n            : storage_policy(detail::forward<Alloc>(alloc))\n            {\n            }\n\n            /// \\effects Creates it by passing it another \\c allocator_storage with a different \\c StoragePolicy but the same \\c Mutex type.\n            /// Initializes it with the result of \\c other.get_allocator().\n            /// \\requires The expression <tt>new storage_policy(other.get_allocator())</tt> must be well-formed,\n            /// otherwise this constructor does not participate in overload resolution.\n            template <class OtherPolicy>\n            allocator_storage(const allocator_storage<OtherPolicy, Mutex>& other, TRTLAB_SFINAE(new storage_policy(other.get_allocator())))\n            : storage_policy(other.get_allocator())\n            {\n            }\n\n            /// @{\n            /// \\effects Moves the \\c allocator_storage object.\n            /// A moved-out \\c allocator_storage object must still store a valid allocator object.\n            allocator_storage(allocator_storage&& other) noexcept\n            : storage_policy(detail::move(other)),\n              detail::mutex_storage<detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>(detail::move(other))\n            {\n            }\n\n            allocator_storage& operator=(allocator_storage&& other) noexcept\n            {\n                storage_policy::                                                                         operator=(detail::move(other));\n                detail::mutex_storage<detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>::operator=(detail::move(other));\n                return *this;\n            }\n            /// @}\n\n            /// @{\n            /// \\effects Copies the \\c allocator_storage object.\n            /// \\requires The \\c StoragePolicy must be copyable.\n            allocator_storage(const allocator_storage&) = default;\n            allocator_storage& operator=(const allocator_storage&) = default;\n            /// @}\n\n            /// @{\n            /// \\effects Calls the function on the stored allocator.\n            /// The \\c Mutex will be locked during the operation.\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                alignment = validate_alignment(alignment);\n                return traits::allocate_node(alloc, size, alignment);\n            }\n\n            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                alignment = validate_alignment(alignment);\n                return traits::allocate_array(alloc, count, size, alignment);\n            }\n\n            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                alignment = validate_alignment(alignment);\n                traits::deallocate_node(alloc, ptr, size, alignment);\n            }\n\n            void deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                alignment = validate_alignment(alignment);\n                traits::deallocate_array(alloc, ptr, count, size, alignment);\n            }\n\n            std::size_t max_node_size() const\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                return traits::max_node_size(alloc);\n            }\n\n            std::size_t max_array_size() const\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                return traits::max_array_size(alloc);\n            }\n\n            std::size_t max_alignment() const\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                return traits::max_alignment(alloc);\n            }\n\n            std::size_t min_alignment() const\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                return traits::min_alignment(alloc);\n            }\n\n            DLContext device_context() const\n            {\n                std::lock_guard<actual_mutex> lock(*this);\n\n                auto&& alloc = get_allocator();\n                return traits::device_context(alloc);\n            }\n            /// @}\n\n            /// @{\n            /// \\effects Calls the function on the stored composable allocator.\n            /// The \\c Mutex will be locked during the operation.\n            /// \\requires The allocator must be composable,\n            /// i.e. \\ref is_composable() must return `true`.\n            /// \\note This check is done at compile-time where possible,\n            /// and at runtime in the case of type-erased storage.\n            TRTLAB_ENABLE_IF(composable::value)\n            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(is_composable());\n                std::lock_guard<actual_mutex> lock(*this);\n                auto&&                        alloc = get_allocator();\n                return composable_traits::try_allocate_node(alloc, size, alignment);\n            }\n\n            TRTLAB_ENABLE_IF(composable::value)\n            void* try_allocate_array(std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(is_composable());\n                std::lock_guard<actual_mutex> lock(*this);\n                auto&&                        alloc = get_allocator();\n                return composable_traits::try_allocate_array(alloc, count, size, alignment);\n            }\n\n            TRTLAB_ENABLE_IF(composable::value)\n            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(is_composable());\n                std::lock_guard<actual_mutex> lock(*this);\n                auto&&                        alloc = get_allocator();\n                return composable_traits::try_deallocate_node(alloc, ptr, size, alignment);\n            }\n\n            TRTLAB_ENABLE_IF(composable::value)\n            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(is_composable());\n                std::lock_guard<actual_mutex> lock(*this);\n                auto&&                        alloc = get_allocator();\n                return composable_traits::try_deallocate_array(alloc, ptr, count, size, alignment);\n            }\n            /// @}\n\n            /// @{\n            /// \\effects Forwards to the \\c StoragePolicy.\n            /// \\returns Returns a reference to the stored allocator.\n            /// \\note This does not lock the \\c Mutex.\n            auto get_allocator() noexcept -> decltype(std::declval<storage_policy>().get_allocator())\n            {\n                return storage_policy::get_allocator();\n            }\n\n            auto get_allocator() const noexcept -> decltype(std::declval<const storage_policy>().get_allocator())\n            {\n                return storage_policy::get_allocator();\n            }\n            /// @}\n\n            /// @{\n            /// \\returns A proxy object that acts like a pointer to the stored allocator.\n            /// It cannot be reassigned to point to another allocator object and only moving is supported, which is destructive.\n            /// As long as the proxy object lives and is not moved from, the \\c Mutex will be kept locked.\n            auto lock() noexcept -> TRTLAB_IMPL_DEFINED(decltype(detail::lock_allocator(std::declval<storage_policy>().get_allocator(),\n                                                                                        std::declval<actual_mutex&>())))\n            {\n                return detail::lock_allocator(get_allocator(), static_cast<actual_mutex&>(*this));\n            }\n\n            auto lock() const noexcept\n                -> TRTLAB_IMPL_DEFINED(decltype(detail::lock_allocator(std::declval<const storage_policy>().get_allocator(),\n                                                                       std::declval<actual_mutex&>())))\n            {\n                return detail::lock_allocator(get_allocator(), static_cast<actual_mutex&>(*this));\n            }\n            /// @}.\n\n            /// \\returns Whether or not the stored allocator is composable,\n            /// that is you can use the compositioning functions.\n            /// \\note Due to type-erased allocators,\n            /// this function can not be `constexpr`.\n            bool is_composable() const noexcept\n            {\n                return StoragePolicy::is_composable();\n            }\n\n          private:\n            inline std::size_t validate_alignment(std::size_t alignment)\n            {\n                auto&& alloc = get_allocator();\n                auto min_alignment = traits::min_alignment(alloc);\n                auto max_alignment = traits::max_alignment(alloc);\n                if(alignment > max_alignment || alignment < min_alignment)\n                {\n                    DLOG(WARNING) << \"invalid alignment \" << alignment << \" passed; using \" << min_alignment;\n                    return min_alignment;\n                }\n                return alignment;\n            }\n        };\n\n        /// Tag type that enables type-erasure in \\ref reference_storage.\n        /// It can be used everywhere a \\ref allocator_reference is used internally.\n        /// \\ingroup memory storage\n        struct any_allocator\n        {\n        };\n\n        /// A \\concept{concept_storagepolicy,StoragePolicy} that stores the allocator directly.\n        /// It embeds the allocator inside it, i.e. moving the storage policy will move the allocator.\n        /// \\ingroup memory storage\n        template <class RawAllocator>\n        class direct_storage : TRTLAB_EBO(allocator_traits<RawAllocator>::allocator_type)\n        {\n            static_assert(!std::is_same<RawAllocator, any_allocator>::value, \"cannot type-erase in direct_storage\");\n\n        public:\n            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;\n\n            /// \\effects Creates it by default-constructing the allocator.\n            /// \\requires The \\c RawAllcoator must be default constructible.\n            direct_storage() = default;\n\n            /// \\effects Creates it by moving in an allocator object.\n            direct_storage(allocator_type&& allocator) noexcept : allocator_type(detail::move(allocator)) {}\n\n            /// @{\n            /// \\effects Moves the \\c direct_storage object.\n            /// This will move the stored allocator.\n            direct_storage(direct_storage&& other) noexcept : allocator_type(detail::move(other)) {}\n\n            direct_storage& operator=(direct_storage&& other) noexcept\n            {\n                allocator_type::operator=(detail::move(other));\n                return *this;\n            }\n            /// @}\n\n            /// @{\n            /// \\returns A (\\c const) reference to the stored allocator.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n\n        protected:\n            ~direct_storage() noexcept = default;\n\n            bool is_composable() const noexcept\n            {\n                return is_composable_allocator<allocator_type>::value;\n            }\n        };\n\n        /// An alias template for \\ref allocator_storage using the \\ref direct_storage policy without a mutex.\n        /// It has the effect of giving any \\concept{concept_rawallocator,RawAllocator} the interface with all member functions,\n        /// avoiding the need to wrap it inside the \\ref allocator_traits.\n        /// \\ingroup memory storage\n        template <class RawAllocator>\n        TRTLAB_ALIAS_TEMPLATE(allocator_adapter, allocator_storage<direct_storage<RawAllocator>, no_mutex>);\n\n        /// \\returns A new \\ref allocator_adapter object created by forwarding to the constructor.\n        /// \\relates allocator_adapter\n        template <class RawAllocator>\n        auto make_allocator_adapter(RawAllocator&& allocator) noexcept -> allocator_adapter<typename std::decay<RawAllocator>::type>\n        {\n            return {detail::forward<RawAllocator>(allocator)};\n        }\n\n/// An alias template for \\ref allocator_storage using the \\ref direct_storage policy with a mutex.\n/// It has a similar effect as \\ref allocator_adapter but performs synchronization.\n/// The \\c Mutex will default to \\c std::mutex if threading is supported,\n/// otherwise there is no default.\n/// \\ingroup memory\n#if TRTLAB_HAS_THREADING_SUPPORT\n        template <class RawAllocator, class Mutex = std::mutex>\n        TRTLAB_ALIAS_TEMPLATE(thread_safe_allocator, allocator_storage<direct_storage<RawAllocator>, Mutex>);\n#else\n        template <class RawAllocator, class Mutex>\n        TRTLAB_ALIAS_TEMPLATE(thread_safe_allocator, allocator_storage<direct_storage<RawAllocator>, Mutex>);\n#endif\n\n#if TRTLAB_HAS_THREADING_SUPPORT\n        /// \\returns A new \\ref thread_safe_allocator object created by forwarding to the constructor/\n        /// \\relates thread_safe_allocator\n        template <class RawAllocator>\n        auto make_thread_safe_allocator(RawAllocator&& allocator) -> thread_safe_allocator<typename std::decay<RawAllocator>::type>\n        {\n            return detail::forward<RawAllocator>(allocator);\n        }\n#endif\n\n        /// \\returns A new \\ref thread_safe_allocator object created by forwarding to the constructor,\n        /// specifying a certain mutex type.\n        /// \\requires It requires threading support from the implementation.\n        /// \\relates thread_safe_allocator\n        template <class Mutex, class RawAllocator>\n        auto make_thread_safe_allocator(RawAllocator&& allocator) -> thread_safe_allocator<typename std::decay<RawAllocator>::type, Mutex>\n        {\n            return detail::forward<RawAllocator>(allocator);\n        }\n\n        namespace detail\n        {\n            struct reference_stateful\n            {\n            };\n            struct reference_stateless\n            {\n            };\n            struct reference_shared\n            {\n            };\n\n            reference_stateful  reference_type(std::true_type stateful, std::false_type shared);\n            reference_stateless reference_type(std::false_type stateful, std::true_type shared);\n            reference_stateless reference_type(std::false_type stateful, std::false_type shared);\n            reference_shared    reference_type(std::true_type stateful, std::true_type shared);\n\n            template <class RawAllocator, class Tag>\n            class reference_storage_impl;\n\n            // reference to stateful: stores a pointer to an allocator\n            template <class RawAllocator>\n            class reference_storage_impl<RawAllocator, reference_stateful>\n            {\n            protected:\n                reference_storage_impl() noexcept : alloc_(nullptr) {}\n\n                reference_storage_impl(RawAllocator& allocator) noexcept : alloc_(&allocator) {}\n\n                bool is_valid() const noexcept\n                {\n                    return alloc_ != nullptr;\n                }\n\n                RawAllocator& get_allocator() const noexcept\n                {\n                    TRTLAB_MEMORY_ASSERT(alloc_ != nullptr);\n                    return *alloc_;\n                }\n\n            private:\n                RawAllocator* alloc_;\n            };\n\n            // reference to stateless: store in static storage\n            template <class RawAllocator>\n            class reference_storage_impl<RawAllocator, reference_stateless>\n            {\n            protected:\n                reference_storage_impl() noexcept = default;\n\n                reference_storage_impl(const RawAllocator&) noexcept {}\n\n                bool is_valid() const noexcept\n                {\n                    return true;\n                }\n\n                RawAllocator& get_allocator() const noexcept\n                {\n                    static RawAllocator alloc;\n                    return alloc;\n                }\n            };\n\n            // reference to shared: stores RawAllocator directly\n            template <class RawAllocator>\n            class reference_storage_impl<RawAllocator, reference_shared>\n            {\n            protected:\n                reference_storage_impl() noexcept = default;\n\n                reference_storage_impl(const RawAllocator& alloc) noexcept : alloc_(alloc) {}\n\n                bool is_valid() const noexcept\n                {\n                    return true;\n                }\n\n                RawAllocator& get_allocator() const noexcept\n                {\n                    return alloc_;\n                }\n\n            private:\n                mutable RawAllocator alloc_;\n            };\n        } // namespace detail\n\n        /// Specifies whether or not a \\concept{concept_rawallocator,RawAllocator} has shared semantics.\n        /// It is shared, if - like \\ref allocator_reference - if multiple objects refer to the same internal allocator and if it can be copied.\n        /// This sharing is stateful, however, stateless allocators are not considered shared in the meaning of this traits. <br>\n        /// If a \\c RawAllocator is shared, it will be directly embedded inside \\ref reference_storage since it already provides \\ref allocator_reference like semantics, so there is no need to add them manually,<br>\n        /// Specialize it for your own types, if they provide sharing semantics and can be copied.\n        /// They also must provide an `operator==` to check whether two allocators refer to the same shared one.\n        /// \\note This makes no guarantees about the lifetime of the shared object, the sharing allocators can either own or refer to a shared object.\n        /// \\ingroup memory storage\n        template <class RawAllocator>\n        struct is_shared_allocator : std::false_type\n        {\n        };\n\n        /// A \\concept{concept_storagepolicy,StoragePolicy} that stores a reference to an allocator.\n        /// For stateful allocators it only stores a pointer to an allocator object and copying/moving only copies the pointer.\n        /// For stateless allocators it does not store anything, an allocator will be constructed as needed.\n        /// For allocators that are already shared (determined through \\ref is_shared_allocator) it will store the allocator type directly.\n        /// \\note It does not take ownership over the allocator in the stateful case, the user has to ensure that the allocator object stays valid.\n        /// In the other cases the lifetime does not matter.\n        /// \\ingroup memory storage\n        template <class RawAllocator>\n        class reference_storage\n#ifndef DOXYGEN\n        : TRTLAB_EBO(detail::reference_storage_impl<typename allocator_traits<RawAllocator>::allocator_type,\n                                                    decltype(detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},\n                                                                                    is_shared_allocator<RawAllocator>{}))>)\n#endif\n        {\n            using storage =\n                detail::reference_storage_impl<typename allocator_traits<RawAllocator>::allocator_type,\n                                               decltype(detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},\n                                                                               is_shared_allocator<RawAllocator>{}))>;\n\n        public:\n            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;\n            using memory_type    = typename allocator_traits<RawAllocator>::memory_type;\n\n            /// Default constructor.\n            /// \\effects If the allocator is stateless, this has no effect and the object is usable as an allocator.\n            /// If the allocator is stateful, creates an invalid reference without any associated allocator.\n            /// Then it must not be used.\n            /// If the allocator is shared, default constructs the shared allocator.\n            /// If the shared allocator does not have a default constructor, this constructor is ill-formed.\n            reference_storage() noexcept = default;\n\n            /// \\effects Creates it from a stateless or shared allocator.\n            /// It will not store anything, only creates the allocator as needed.\n            /// \\requires The \\c RawAllocator is stateless or shared.\n            reference_storage(const allocator_type& alloc) noexcept : storage(alloc) {}\n\n            /// \\effects Creates it from a reference to a stateful allocator.\n            /// It will store a pointer to this allocator object.\n            /// \\note The user has to take care that the lifetime of the reference does not exceed the allocator lifetime.\n            reference_storage(allocator_type& alloc) noexcept : storage(alloc) {}\n\n            /// @{\n            /// \\effects Copies the \\c allocator_reference object.\n            /// Only copies the pointer to it in the stateful case.\n            reference_storage(const reference_storage&) noexcept = default;\n            reference_storage& operator=(const reference_storage&) noexcept = default;\n            /// @}\n\n            /// \\returns Whether or not the reference is valid.\n            /// It is only invalid, if it was created by the default constructor and the allocator is stateful.\n            explicit operator bool() const noexcept\n            {\n                return storage::is_valid();\n            }\n\n            /// \\returns Returns a reference to the allocator.\n            /// \\requires The reference must be valid.\n            allocator_type& get_allocator() const noexcept\n            {\n                return storage::get_allocator();\n            }\n\n        protected:\n            ~reference_storage() noexcept = default;\n\n            bool is_composable() const noexcept\n            {\n                return is_composable_allocator<allocator_type>::value;\n            }\n        };\n\n        /// Specialization of the class template \\ref reference_storage that is type-erased.\n        /// It is triggered by the tag type \\ref any_allocator.\n        /// The specialization can store a reference to any allocator type.\n        /// \\ingroup memory storage\n        template <>\n        class reference_storage<any_allocator>\n        {\n            class base_allocator\n            {\n            public:\n                using is_stateful = std::true_type;\n\n                virtual ~base_allocator() = default;\n\n                virtual void clone(void* storage) const noexcept = 0;\n\n                void* allocate_node(std::size_t size, std::size_t alignment)\n                {\n                    return allocate_impl(1, size, alignment);\n                }\n\n                void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)\n                {\n                    return allocate_impl(count, size, alignment);\n                }\n\n                void deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept\n                {\n                    deallocate_impl(node, 1, size, alignment);\n                }\n\n                void deallocate_array(void* array, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n                {\n                    deallocate_impl(array, count, size, alignment);\n                }\n\n                void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept\n                {\n                    return try_allocate_impl(1, size, alignment);\n                }\n\n                void* try_allocate_array(std::size_t count, std::size_t size, std::size_t alignment) noexcept\n                {\n                    return try_allocate_impl(count, size, alignment);\n                }\n\n                bool try_deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept\n                {\n                    return try_deallocate_impl(node, 1, size, alignment);\n                }\n\n                bool try_deallocate_array(void* array, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n                {\n                    return try_deallocate_impl(array, count, size, alignment);\n                }\n\n                // count 1 means node\n                virtual void* allocate_impl(std::size_t count, std::size_t size, std::size_t alignment)                       = 0;\n                virtual void  deallocate_impl(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept = 0;\n\n                virtual void* try_allocate_impl(std::size_t count, std::size_t size, std::size_t alignment) noexcept = 0;\n\n                virtual bool try_deallocate_impl(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept = 0;\n\n                std::size_t max_node_size() const\n                {\n                    return max(query::node_size);\n                }\n\n                std::size_t max_array_size() const\n                {\n                    return max(query::array_size);\n                }\n\n                std::size_t max_alignment() const\n                {\n                    return max(query::max_alignment);\n                }\n\n                std::size_t min_alignment() const\n                {\n                    return max(query::min_alignment);\n                }\n\n                DLContext device_context() const\n                {\n                    return context_impl();\n                }\n\n                virtual bool is_composable() const noexcept = 0;\n\n            protected:\n                enum class query\n                {\n                    node_size,\n                    array_size,\n                    max_alignment,\n                    min_alignment\n                };\n\n                virtual std::size_t max(query q) const   = 0;\n                virtual DLContext   context_impl() const = 0;\n            };\n\n            static constexpr std::size_t padding_bytes = 16UL;\n\n        public:\n            using allocator_type = TRTLAB_IMPL_DEFINED(base_allocator);\n\n            /// \\effects Creates it from a reference to any stateful \\concept{concept_rawallocator,RawAllocator}.\n            /// It will store a pointer to this allocator object.\n            /// \\note The user has to take care that the lifetime of the reference does not exceed the allocator lifetime.\n            template <class RawAllocator>\n            reference_storage(RawAllocator& alloc) noexcept\n            {\n                // if you hit this assertions, then you are passing a stateful and shared allocator whose size is larger\n                // than the basic_allocator<default_instantiation> + padding bytes\n                // padding was sized such that an allocator<RawAllocator, Mutex> could be passed\n                static_assert(sizeof(basic_allocator<RawAllocator>) <= sizeof(basic_allocator<default_instantiation>) + padding_bytes,\n                              \"requires all instantiations to have certain maximum size\");\n                ::new (static_cast<void*>(&storage_)) basic_allocator<RawAllocator>(alloc);\n            }\n\n            // \\effects Creates it from any stateless \\concept{concept_rawallocator,RawAllocator}.\n            /// It will not store anything, only creates the allocator as needed.\n            /// \\requires The \\c RawAllocator is stateless.\n            template <class RawAllocator>\n            reference_storage(const RawAllocator& alloc, TRTLAB_REQUIRES(!allocator_traits<RawAllocator>::is_stateful::value)) noexcept\n            {\n                static_assert(sizeof(basic_allocator<RawAllocator>) <= sizeof(basic_allocator<default_instantiation>),\n                              \"requires all instantiations to have certain maximum size\");\n                ::new (static_cast<void*>(&storage_)) basic_allocator<RawAllocator>(alloc);\n            }\n\n            /// \\effects Creates it from the internal base class for the type-erasure.\n            /// Has the same effect as if the actual stored allocator were passed to the other constructor overloads.\n            /// \\note This constructor is used internally to avoid double-nesting.\n            reference_storage(const TRTLAB_IMPL_DEFINED(base_allocator) & alloc) noexcept\n            {\n                alloc.clone(&storage_);\n            }\n\n            /// @{\n            /// \\effects Copies the \\c reference_storage object.\n            /// It only copies the pointer to the allocator.\n            reference_storage(const reference_storage& other) noexcept\n            {\n                other.get_allocator().clone(&storage_);\n            }\n\n            reference_storage& operator=(const reference_storage& other) noexcept\n            {\n                get_allocator().~allocator_type();\n                other.get_allocator().clone(&storage_);\n                return *this;\n            }\n            /// @}\n\n            /// \\returns A reference to the allocator.\n            /// The actual type is implementation-defined since it is the base class used in the type-erasure,\n            /// but it provides the full \\concept{concept_rawallocator,RawAllocator} member functions.\n            /// \\note There is no way to access any custom member functions of the allocator type.\n            allocator_type& get_allocator() const noexcept\n            {\n                auto mem = static_cast<void*>(&storage_);\n                return *static_cast<base_allocator*>(mem);\n            }\n\n        protected:\n            ~reference_storage() noexcept\n            {\n                get_allocator().~allocator_type();\n            }\n\n            bool is_composable() const noexcept\n            {\n                return get_allocator().is_composable();\n            }\n\n        private:\n            template <class RawAllocator>\n            class basic_allocator\n            : public base_allocator,\n              private detail::reference_storage_impl<typename allocator_traits<RawAllocator>::allocator_type,\n                                                     decltype(detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},\n                                                                                     is_shared_allocator<RawAllocator>{}))>\n            {\n                using traits     = allocator_traits<RawAllocator>;\n                using composable = is_composable_allocator<typename traits::allocator_type>;\n                using storage =\n                    detail::reference_storage_impl<typename allocator_traits<RawAllocator>::allocator_type,\n                                                   decltype(detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},\n                                                                                   is_shared_allocator<RawAllocator>{}))>;\n\n            public:\n                // non stateful\n                basic_allocator(const RawAllocator& alloc) noexcept : storage(alloc) {}\n\n                // stateful\n                basic_allocator(RawAllocator& alloc) noexcept : storage(alloc) {}\n\n            private:\n                typename traits::allocator_type& get() const noexcept\n                {\n                    return storage::get_allocator();\n                }\n\n                void clone(void* storage) const noexcept override\n                {\n                    ::new (storage) basic_allocator(get());\n                }\n\n                void* allocate_impl(std::size_t count, std::size_t size, std::size_t alignment) override\n                {\n                    auto&& alloc = get();\n                    if (count == 1u)\n                        return traits::allocate_node(alloc, size, alignment);\n                    else\n                        return traits::allocate_array(alloc, count, size, alignment);\n                }\n\n                void deallocate_impl(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept override\n                {\n                    auto&& alloc = get();\n                    if (count == 1u)\n                        traits::deallocate_node(alloc, ptr, size, alignment);\n                    else\n                        traits::deallocate_array(alloc, ptr, count, size, alignment);\n                }\n\n                void* try_allocate_impl(std::size_t count, std::size_t size, std::size_t alignment) noexcept override\n                {\n                    auto&& alloc = get();\n                    if (count == 1u)\n                        return detail::try_allocate_node(composable{}, alloc, size, alignment);\n                    else\n                        return detail::try_allocate_array(composable{}, alloc, count, size, alignment);\n                }\n\n                bool try_deallocate_impl(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept override\n                {\n                    auto&& alloc = get();\n                    if (count == 1u)\n                        return detail::try_deallocate_node(composable{}, alloc, ptr, size, alignment);\n                    else\n                        return detail::try_deallocate_array(composable{}, alloc, ptr, count, size, alignment);\n                }\n\n                bool is_composable() const noexcept override\n                {\n                    return composable::value;\n                }\n\n                std::size_t max(query q) const override\n                {\n                    auto&& alloc = get();\n                    if (q == query::node_size)\n                        return traits::max_node_size(alloc);\n                    else if (q == query::array_size)\n                        return traits::max_array_size(alloc);\n                    else if (q == query::max_alignment)\n                        return traits::max_alignment(alloc);\n                    return traits::min_alignment(alloc);\n                }\n\n                DLContext context_impl() const override\n                {\n                    auto&& alloc = get();\n                    return traits::device_context(alloc);\n                }\n            };\n\n            // use a stateful instantiation to determine size and alignment\n            // base_allocator is stateful\n            using default_instantiation = basic_allocator<base_allocator>;\n            using storage = std::aligned_storage<sizeof(default_instantiation) + padding_bytes, alignof(default_instantiation)>::type;\n            mutable storage storage_;\n        };\n\n        /// An alias template for \\ref allocator_storage using the \\ref reference_storage policy with a given \\c Mutex.\n        /// It will store a reference to the given allocator type. The tag type \\ref any_allocator enables type-erasure.\n        /// The \\c Mutex defaults to the \\ref default_mutex.\n        /// \\ingroup memory storage\n        template <class RawAllocator>\n        TRTLAB_ALIAS_TEMPLATE(allocator_reference, allocator_storage<reference_storage<RawAllocator>, no_mutex>);\n\n        /// \\returns A new \\ref allocator_reference object by forwarding the allocator to the constructor.\n        /// \\relates allocator_reference\n        template <class RawAllocator>\n        auto make_allocator_reference(RawAllocator&& allocator) noexcept -> allocator_reference<typename std::decay<RawAllocator>::type>\n        {\n            return {std::forward<RawAllocator>(allocator)};\n        }\n\n        /// An alias for the \\ref reference_storage specialization using type-erasure.\n        /// \\ingroup memory storage\n        using any_reference_storage = reference_storage<any_allocator>;\n\n        /// An alias for \\ref allocator_storage using the \\ref any_reference_storage.\n        /// It will store a reference to any \\concept{concept_rawallocator,RawAllocator}.\n        /// Wrap the allocator in a \\ref thread_safe_allocator if you want thread safety.\n        using any_allocator_reference = allocator_storage<any_reference_storage, no_mutex>;\n\n        /// \\returns A new \\ref any_allocator_reference object by forwarding the allocator to the constructor.\n        /// \\relates any_allocator_reference\n        template <class RawAllocator>\n        auto make_any_allocator_reference(RawAllocator&& allocator) noexcept -> any_allocator_reference\n        {\n            return {std::forward<RawAllocator>(allocator)};\n        }\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_ALLOCATOR_STORAGE_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/allocator_traits.h",
    "content": "// MODIFICATION MESSAGE\n\n// Modification notes:\n// - dlpack added to project\n// - removal of max_alignment trait\n// - addition of memory_type trait [required/no-default]\n// - adding allocator_alignment -> allocate_node should be aligned to this value\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_ALLOCATOR_TRAITS_H_INCLUDED\n#define TRTLAB_MEMORY_ALLOCATOR_TRAITS_H_INCLUDED\n\n/// \\file\n/// The default specialization of the \\ref foonathan::memory::allocator_traits.\n\n#include <cstddef>\n#include <type_traits>\n#include <memory>\n\n#include \"detail/utility.h\"\n\n#include \"config.h\"\n#include \"align.h\"\n#include \"memory_type.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            template <class Allocator>\n            std::true_type has_construct(\n                int, TRTLAB_SFINAE(std::declval<Allocator>().construct(std::declval<typename Allocator::pointer>(),\n                                                                       std::declval<typename Allocator::value_type>())));\n\n            template <class Allocator>\n            std::false_type has_construct(short);\n\n            template <class Allocator>\n            std::true_type has_destroy(int, TRTLAB_SFINAE(std::declval<Allocator>().destroy(std::declval<typename Allocator::pointer>())));\n\n            template <class Allocator>\n            std::false_type has_destroy(short);\n\n            template <class Allocator>\n            struct check_standard_allocator\n            {\n                using custom_construct = decltype(has_construct<Allocator>(0));\n                using custom_destroy   = decltype(has_destroy<Allocator>(0));\n\n                using valid = std::integral_constant<bool, !custom_construct::value && !custom_destroy::value>;\n            };\n        } // namespace detail\n\n        /// Traits class that checks whether or not a standard \\c Allocator can be used as \\concept{concept_rawallocator,RawAllocator}.\n        /// It checks the existence of a custom \\c construct(), \\c destroy() function, if provided,\n        /// it cannot be used since it would not be called.<br>\n        /// Specialize it for custom \\c Allocator types to override this check.\n        /// \\ingroup memory core\n        template <class Allocator>\n        struct allocator_is_raw_allocator : TRTLAB_EBO(detail::check_standard_allocator<Allocator>::valid)\n        {\n        };\n\n        /// Specialization of \\ref allocator_is_raw_allocator that allows \\c std::allocator again.\n        /// \\ingroup memory core\n        template <typename T>\n        struct allocator_is_raw_allocator<std::allocator<T>> : std::true_type\n        {\n        };\n\n        namespace traits_detail // use seperate namespace to avoid name clashes\n        {\n            // full_concept has the best conversion rank, error the lowest\n            // used to give priority to the functions\n            struct error\n            {\n                operator void*() const noexcept\n                {\n                    TRTLAB_MEMORY_UNREACHABLE(\"this is just to hide an error and move static_assert to the front\");\n                    return nullptr;\n                }\n            };\n            struct std_concept : error\n            {\n            };\n            struct min_concept : std_concept\n            {\n            };\n            struct full_concept : min_concept\n            {\n            };\n\n            // used to delay assert in handle_error() until instantiation\n            template <typename T>\n            struct invalid_allocator_concept\n            {\n                static const bool error = false;\n            };\n\n            //=== allocator_type ===//\n            // if Allocator has a member template `rebind`, use that to rebind to `char`\n            // else if Allocator has a member `value_type`, rebind by changing argument\n            // else does nothing\n            template <class Allocator>\n            auto rebind_impl(int) -> typename Allocator::template rebind<char>::other&;\n\n            template <class Allocator, typename T>\n            struct allocator_rebinder\n            {\n                using type = Allocator&;\n            };\n\n            template <template <typename, typename...> class Alloc, typename U, typename... Args, typename T>\n            struct allocator_rebinder<Alloc<U, Args...>, T>\n            {\n                using type = Alloc<T, Args...>&;\n            };\n\n            template <class Allocator, typename = typename Allocator::value_type>\n            auto rebind_impl(char) -> typename allocator_rebinder<Allocator, char>::type;\n\n            template <class Allocator>\n            auto rebind_impl(...) -> Allocator&;\n\n            template <class Allocator>\n            struct allocator_type_impl // required for MSVC\n            {\n                using type = decltype(rebind_impl<Allocator>(0));\n            };\n\n            template <class Allocator>\n            using allocator_type = typename std::decay<typename allocator_type_impl<Allocator>::type>::type;\n\n            //=== is_stateful ===//\n            // first try to access Allocator::is_stateful,\n            // then use whether or not the type is empty\n            template <class Allocator>\n            auto is_stateful(full_concept) -> decltype(typename Allocator::is_stateful{});\n\n            template <class Allocator, bool IsEmpty>\n            struct is_stateful_impl;\n\n            template <class Allocator>\n            struct is_stateful_impl<Allocator, true>\n            {\n                static_assert(std::is_default_constructible<Allocator>::value,\n                              \"RawAllocator is empty but not default constructible .\"\n                              \"This means it is not a stateless allocator. \"\n                              \"If this is actually intended provide the appropriate is_stateful \"\n                              \"typedef in your class.\");\n                using type = std::false_type;\n            };\n\n            template <class Allocator>\n            struct is_stateful_impl<Allocator, false>\n            {\n                using type = std::true_type;\n            };\n\n            template <class Allocator>\n            auto is_stateful(min_concept) -> typename is_stateful_impl<Allocator, std::is_empty<Allocator>::value>::type;\n\n            //=== allocate_node() ===//\n            // first try Allocator::allocate_node\n            // then assume std_allocator and call Allocator::allocate\n            // then error\n            template <class Allocator>\n            auto allocate_node(full_concept, Allocator& alloc, std::size_t size, std::size_t alignment)\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.allocate_node(size, alignment), void*)\n\n                    template <class Allocator>\n                    auto allocate_node(std_concept, Allocator& alloc, std::size_t size, std::size_t)\n                        -> TRTLAB_AUTO_RETURN(static_cast<void*>(alloc.allocate(size)))\n\n                            template <class Allocator>\n                            error allocate_node(error, Allocator&, std::size_t, std::size_t)\n            {\n                static_assert(invalid_allocator_concept<Allocator>::error, \"type is not a RawAllocator as it does not provide: void* \"\n                                                                           \"allocate_node(std::size_t, std::size_t)\");\n                return {};\n            }\n\n            //=== deallocate_node() ===//\n            // first try Allocator::deallocate_node\n            // then assume std_allocator and call Allocator::deallocate\n            // then error\n            template <class Allocator>\n            auto deallocate_node(full_concept, Allocator& alloc, void* ptr, std::size_t size, std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.deallocate_node(ptr, size, alignment), void)\n\n                    template <class Allocator>\n                    auto deallocate_node(std_concept, Allocator& alloc, void* ptr, std::size_t size, std::size_t) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.deallocate(static_cast<char*>(ptr), size), void)\n\n                    template <class Allocator>\n                    error deallocate_node(error, Allocator&, void*, std::size_t, std::size_t)\n            {\n                static_assert(invalid_allocator_concept<Allocator>::error, \"type is not a RawAllocator as it does not provide: void \"\n                                                                           \"deallocate_node(void*, std::size_t, \"\n                                                                           \"std::size_t)\");\n                return error{};\n            }\n\n            //=== allocate_array() ===//\n            // first try Allocator::allocate_array\n            // then forward to allocate_node()\n            template <class Allocator>\n            auto allocate_array(full_concept, Allocator& alloc, std::size_t count, std::size_t size, std::size_t alignment)\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.allocate_array(count, size, alignment), void*)\n\n                    template <class Allocator>\n                    void* allocate_array(min_concept, Allocator& alloc, std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                return allocate_node(full_concept{}, alloc, count * size, alignment);\n            }\n\n            //=== deallocate_array() ===//\n            // first try Allocator::deallocate_array\n            // then forward to deallocate_node()\n            template <class Allocator>\n            auto deallocate_array(full_concept, Allocator& alloc, void* ptr, std::size_t count, std::size_t size,\n                                  std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.deallocate_array(ptr, count, size, alignment), void)\n\n                    template <class Allocator>\n                    void deallocate_array(min_concept, Allocator& alloc, void* ptr, std::size_t count, std::size_t size,\n                                          std::size_t alignment) noexcept\n            {\n                deallocate_node(full_concept{}, alloc, ptr, count * size, alignment);\n            }\n\n            //=== max_node_size() ===//\n            // first try Allocator::max_node_size()\n            // then return maximum value\n            template <class Allocator>\n            auto max_node_size(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.max_node_size(), std::size_t)\n\n                template <class Allocator>\n                std::size_t max_node_size(min_concept, const Allocator&) noexcept\n            {\n                return std::size_t(-1);\n            }\n\n            //=== max_node_size() ===//\n            // first try Allocator::max_array_size()\n            // then forward to max_node_size()\n            template <class Allocator>\n            auto max_array_size(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.max_array_size(), std::size_t)\n\n                template <class Allocator>\n                std::size_t max_array_size(min_concept, const Allocator& alloc)\n            {\n                return max_node_size(full_concept{}, alloc);\n            }\n\n            //=== memory_type ===//\n            template <class Allocator>\n            auto memory_type(full_concept) -> decltype(typename Allocator::memory_type{});\n\n            template <class Allocator>\n            error memory_type(error)\n            {\n                static_assert(invalid_allocator_concept<Allocator>::error, \"type is not a RawAllocator as it does not provide: using \"\n                                                                           \"memory_type\");\n                return error{};\n            }\n\n            //=== min_alignment() ===//\n            // first try Allocator::min_alignment()\n            // then return Allocator::memory_type::min_allocation_alignment()\n            template <class Allocator>\n            auto min_alignment(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.min_alignment(), std::size_t)\n\n                template <class Allocator>\n                std::size_t min_alignment(min_concept, const Allocator&)\n            {\n                return decltype(memory_type<Allocator>(full_concept{}))::min_allocation_alignment();\n            }\n\n            //=== max_alignment() ===//\n            // first try Allocator::max_alignment()\n            // then return Allocator::min_alignment() [see above]\n            template <class Allocator>\n            auto max_alignment(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.max_alignment(), std::size_t)\n\n                template <class Allocator>\n                std::size_t max_alignment(min_concept, const Allocator& alloc)\n            {\n                return min_alignment(full_concept{}, alloc);\n            }\n\n            //=== device_context ===//\n            // first try Allocator::context,\n            // otherwise default to {kDLCPU, 0}\n            template <class Allocator>\n            auto device_context(full_concept, const Allocator& alloc) -> TRTLAB_AUTO_RETURN_TYPE(alloc.device_context(), DLContext)\n\n                template <class Allocator>\n                DLContext device_context(min_concept, const Allocator&)\n            {\n                return {decltype(memory_type<Allocator>(full_concept{}))::device_type(), 0};\n            }\n\n        } // namespace traits_detail\n\n        /// The default specialization of the allocator_traits for a \\concept{concept_rawallocator,RawAllocator}.\n        /// See the last link for the requirements on types that do not specialize this class and the interface documentation.\n        /// Any specialization must provide the same interface.\n        /// \\ingroup memory core\n        template <class Allocator>\n        class allocator_traits\n        {\n        public:\n            using allocator_type = traits_detail::allocator_type<Allocator>;\n            using is_stateful    = decltype(traits_detail::is_stateful<Allocator>(traits_detail::full_concept{}));\n            using memory_type    = decltype(traits_detail::memory_type<Allocator>(traits_detail::full_concept{}));\n\n            static void* allocate_node(allocator_type& state, std::size_t size, std::size_t alignment)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::allocate_node(traits_detail::full_concept{}, state, size, alignment);\n            }\n\n            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::allocate_array(traits_detail::full_concept{}, state, count, size, alignment);\n            }\n/*\n            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                auto alignment = traits_detail::min_alignment(traits_detail::full_concept{}, state);\n                return traits_detail::allocate_array(traits_detail::full_concept{}, state, count, size, alignment);\n            }\n*/\n            static void deallocate_node(allocator_type& state, void* node, std::size_t size, std::size_t alignment) noexcept\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                traits_detail::deallocate_node(traits_detail::full_concept{}, state, node, size, alignment);\n            }\n\n            static void deallocate_array(allocator_type& state, void* array, std::size_t count, std::size_t size,\n                                         std::size_t alignment) noexcept\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                traits_detail::deallocate_array(traits_detail::full_concept{}, state, array, count, size, alignment);\n            }\n\n            static void deallocate_array(allocator_type& state, void* array, std::size_t count, std::size_t size) noexcept\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                auto alignment = traits_detail::min_alignment(traits_detail::full_concept{}, state);\n                traits_detail::deallocate_array(traits_detail::full_concept{}, state, array, count, size, alignment);\n            }\n\n            static std::size_t max_node_size(const allocator_type& state)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::max_node_size(traits_detail::full_concept{}, state);\n            }\n\n            static std::size_t max_array_size(const allocator_type& state)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::max_array_size(traits_detail::full_concept{}, state);\n            }\n\n            static std::size_t min_alignment(const allocator_type& state)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::min_alignment(traits_detail::full_concept{}, state);\n            }\n\n            static std::size_t max_alignment(const allocator_type& state)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::max_alignment(traits_detail::full_concept{}, state);\n            }\n\n            static DLContext device_context(const allocator_type& state)\n            {\n                static_assert(allocator_is_raw_allocator<Allocator>::value,\n                              \"Allocator cannot be used as RawAllocator because it provides custom construct()/destroy()\");\n                return traits_detail::device_context(traits_detail::full_concept{}, state);\n            }\n\n#if !defined(DOXYGEN)\n            using trtlab_memory_default_traits = std::true_type;\n#endif\n        };\n\n        namespace detail\n        {\n            template <class RawAllocator>\n            typename allocator_traits<RawAllocator>::trtlab_memory_default_traits alloc_uses_default_traits(RawAllocator&);\n\n            std::false_type alloc_uses_default_traits(...);\n\n            template <typename T>\n            struct has_invalid_alloc_function\n            : std::is_same<decltype(traits_detail::allocate_node(traits_detail::full_concept{},\n                                                                 std::declval<typename allocator_traits<T>::allocator_type&>(), 0, 0)),\n                           traits_detail::error>\n            {\n            };\n\n            template <typename T>\n            struct has_invalid_dealloc_function\n            : std::is_same<decltype(traits_detail::deallocate_node(traits_detail::full_concept{},\n                                                                   std::declval<typename allocator_traits<T>::allocator_type&>(), nullptr,\n                                                                   0, 0)),\n                           traits_detail::error>\n            {\n            };\n\n            template <typename T, class DefaultTraits>\n            struct is_raw_allocator : std::true_type\n            {\n            };\n\n            template <typename T>\n            struct is_raw_allocator<T, std::integral_constant<bool, true>>\n            : std::integral_constant<bool, allocator_is_raw_allocator<T>::value\n                                               && !(has_invalid_alloc_function<T>::value || has_invalid_dealloc_function<T>::value)>\n            {\n            };\n        } // namespace detail\n\n        /// Traits that check whether a type models concept \\concept{concept_rawallocator,RawAllocator}.<br>\n        /// It must either provide the necessary functions for the default traits specialization or has specialized it.\n        /// \\ingroup memory core\n        template <typename T>\n        struct is_raw_allocator : detail::is_raw_allocator<T, decltype(detail::alloc_uses_default_traits(std::declval<T&>()))>\n        {\n        };\n\n        namespace traits_detail\n        {\n            //=== try_allocate_node() ===//\n            // try Allocator::try_allocate_node\n            // otherwise error\n            template <class Allocator>\n            auto try_allocate_node(full_concept, Allocator& alloc, std::size_t size, std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.try_allocate_node(size, alignment), void*)\n\n                    template <class Allocator>\n                    error try_allocate_node(error, Allocator&, std::size_t, std::size_t)\n            {\n                static_assert(invalid_allocator_concept<Allocator>::error,\n                              \"type is not a composable RawAllocator as it does not provide: void* \"\n                              \"try_allocate_node(std::size_t, \"\n                              \"std::size_t)\");\n                return {};\n            }\n\n            //=== try_deallocate_node() ===//\n            // try Allocator::try_deallocate_node\n            // otherwise error\n            template <class Allocator>\n            auto try_deallocate_node(full_concept, Allocator& alloc, void* ptr, std::size_t size, std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.try_deallocate_node(ptr, size, alignment), bool)\n\n                    template <class Allocator>\n                    error try_deallocate_node(error, Allocator&, void*, std::size_t, std::size_t)\n            {\n                static_assert(invalid_allocator_concept<Allocator>::error,\n                              \"type is not a composable RawAllocator as it does not provide: bool \"\n                              \"try_deallocate_node(void*, std::size_t, \"\n                              \"std::size_t)\");\n                return error{};\n            }\n\n            //=== try_allocate_array() ===//\n            // first try Allocator::try_allocate_array\n            // then forward to try_allocate_node()\n            template <class Allocator>\n            auto try_allocate_array(full_concept, Allocator& alloc, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.try_allocate_array(count, size, alignment), void*)\n\n                    template <class Allocator>\n                    void* try_allocate_array(min_concept, Allocator& alloc, std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                return try_allocate_node(full_concept{}, alloc, count * size, alignment);\n            }\n\n            //=== try_deallocate_array() ===//\n            // first try Allocator::try_deallocate_array\n            // then forward to try_deallocate_node()\n            template <class Allocator>\n            auto try_deallocate_array(full_concept, Allocator& alloc, void* ptr, std::size_t count, std::size_t size,\n                                      std::size_t alignment) noexcept\n                -> TRTLAB_AUTO_RETURN_TYPE(alloc.try_deallocate_array(ptr, count, size, alignment), bool)\n\n                    template <class Allocator>\n                    bool try_deallocate_array(min_concept, Allocator& alloc, void* ptr, std::size_t count, std::size_t size,\n                                              std::size_t alignment) noexcept\n            {\n                return try_deallocate_node(full_concept{}, alloc, ptr, count * size, alignment);\n            }\n        } // namespace traits_detail\n\n        /// The default specialization of the composable_allocator_traits for a \\concept{concept_composableallocator,ComposableAllocator}.\n        /// See the last link for the requirements on types that do not specialize this class and the interface documentation.\n        /// Any specialization must provide the same interface.\n        /// \\ingroup memory core\n        template <class Allocator>\n        class composable_allocator_traits\n        {\n        public:\n            using allocator_type = typename allocator_traits<Allocator>::allocator_type;\n\n            static void* try_allocate_node(allocator_type& state, std::size_t size, std::size_t alignment) noexcept\n            {\n                static_assert(is_raw_allocator<Allocator>::value, \"ComposableAllocator must be RawAllocator\");\n                return traits_detail::try_allocate_node(traits_detail::full_concept{}, state, size, alignment);\n            }\n\n            static void* try_allocate_array(allocator_type& state, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                static_assert(is_raw_allocator<Allocator>::value, \"ComposableAllocator must be RawAllocator\");\n                return traits_detail::try_allocate_array(traits_detail::full_concept{}, state, count, size, alignment);\n            }\n\n            static bool try_deallocate_node(allocator_type& state, void* node, std::size_t size, std::size_t alignment) noexcept\n            {\n                static_assert(is_raw_allocator<Allocator>::value, \"ComposableAllocator must be RawAllocator\");\n                return traits_detail::try_deallocate_node(traits_detail::full_concept{}, state, node, size, alignment);\n            }\n\n            static bool try_deallocate_array(allocator_type& state, void* array, std::size_t count, std::size_t size,\n                                             std::size_t alignment) noexcept\n            {\n                static_assert(is_raw_allocator<Allocator>::value, \"ComposableAllocator must be RawAllocator\");\n                return traits_detail::try_deallocate_array(traits_detail::full_concept{}, state, array, count, size, alignment);\n            }\n\n#if !defined(DOXYGEN)\n            using trtlab_memory_default_traits = std::true_type;\n#endif\n        };\n\n        namespace detail\n        {\n            template <class RawAllocator>\n            typename composable_allocator_traits<RawAllocator>::trtlab_memory_default_traits composable_alloc_uses_default_traits(\n                RawAllocator&);\n\n            std::false_type composable_alloc_uses_default_traits(...);\n\n            template <typename T>\n            struct has_invalid_try_alloc_function\n            : std::is_same<decltype(traits_detail::try_allocate_node(traits_detail::full_concept{},\n                                                                     std::declval<typename allocator_traits<T>::allocator_type&>(), 0, 0)),\n                           traits_detail::error>\n            {\n            };\n\n            template <typename T>\n            struct has_invalid_try_dealloc_function\n            : std::is_same<decltype(traits_detail::try_deallocate_node(traits_detail::full_concept{},\n                                                                       std::declval<typename allocator_traits<T>::allocator_type&>(),\n                                                                       nullptr, 0, 0)),\n                           traits_detail::error>\n            {\n            };\n\n            template <typename T, class DefaultTraits>\n            struct is_composable_allocator : memory::is_raw_allocator<T>\n            {\n            };\n\n            template <typename T>\n            struct is_composable_allocator<T, std::integral_constant<bool, true>>\n            : std::integral_constant<bool, memory::is_raw_allocator<T>::value\n                                               && !(has_invalid_try_alloc_function<T>::value || has_invalid_try_dealloc_function<T>::value)>\n            {\n            };\n        } // namespace detail\n\n        /// Traits that check whether a type models concept \\concept{concept_rawallocator,ComposableAllocator}.<br>\n        /// It must be a \\concept[concept_rawallocator,RawAllocator} and either provide the necessary functions for the default traits specialization or has specialized it.\n        /// \\ingroup memory core\n        template <typename T>\n        struct is_composable_allocator\n        : detail::is_composable_allocator<T, decltype(detail::composable_alloc_uses_default_traits(std::declval<T&>()))>\n        {\n        };\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_ALLOCATOR_TRAITS_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/bfit_allocator.h",
    "content": "#pragma once\n#include <set>\n#include <utility>\n#include <experimental/propagate_const>\n\n#include <glog/logging.h>\n\n#include \"align.h\"\n#include \"memory_block.h\"\n#include \"utils.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace bfit_detail\n        {\n            // node for double linked list holding all memory blocks - both allocated and free\n            // offset allows for aligned allocation if the block start is not aligned as requested\n            struct memory_node : public memory_block\n            {\n                memory_node() : memory_block(), is_allocated(false), prev_node(nullptr), next_node(nullptr), offset(0) {}\n                memory_node(const memory_block& block)\n                : memory_block(block), is_allocated(false), prev_node(nullptr), next_node(nullptr), offset(0)\n                {\n                }\n\n                memory_node(const memory_node&) = delete;\n                memory_node& operator=(const memory_node&) = delete;\n\n                memory_node(memory_node&&) = delete;\n                memory_node& operator=(memory_node&&) = delete;\n\n                // memory_block::memory will is the start of the data segment\n                // i.e. the value of the pointer returned to the user by allocate\n\n                // memory_block::size is the entire size of the block including any\n                // left and right padding\n\n                bool         is_allocated;\n                memory_node* prev_node;\n                memory_node* next_node;\n                std::size_t  offset;\n            };\n\n            template <typename Compare = std::less<>>\n            struct memory_node_compare_size : public memory_block_compare_size<Compare>\n            {\n                constexpr bool operator()(std::size_t size, const memory_node* node) const\n                {\n                    return memory_block_compare_size<Compare>::operator()(size, *node);\n                }\n\n                constexpr bool operator()(const memory_node* node, std::size_t size) const\n                {\n                    return memory_block_compare_size<Compare>::operator()(*node, size);\n                }\n\n                constexpr bool operator()(const memory_node* lhs, const memory_node* rhs) const\n                {\n                    return memory_block_compare_size<Compare>::operator()(*lhs, *rhs);\n                }\n            };\n\n            template <typename Compare = std::less<>>\n            struct memory_node_compare_addr : public memory_block_compare_addr<Compare>\n            {\n                constexpr bool operator()(void* addr, const memory_node* node) const\n                {\n                    return memory_block_compare_addr<Compare>::operator()(addr, *node);\n                }\n\n                constexpr bool operator()(const memory_node* node, void* addr) const\n                {\n                    return memory_block_compare_addr<Compare>::operator()(*node, addr);\n                }\n\n                constexpr bool operator()(const memory_node* lhs, const memory_node* rhs) const\n                {\n                    return memory_block_compare_addr<Compare>::operator()(*lhs, *rhs);\n                }\n            };\n\n            class node_in_place\n            {\n            };\n\n            class node_external\n            {\n            };\n\n        } // namespace bfit_detail\n\n        class bfit_options\n        {\n        public:\n            bfit_options();\n\n            bfit_options(const bfit_options&) = delete;\n            bfit_options& operator=(const bfit_options&) = delete;\n\n            bfit_options(bfit_options&&) noexcept;\n            bfit_options& operator=(bfit_options&&) noexcept;\n\n            void set_initial_size(std::size_t);\n            void set_max_size(std::size_t);\n            void set_allow_growth(bool);\n            void set_growth_factor(float);\n\n            std::size_t initial_size() const;\n            std::size_t max_size() const;\n            bool        allow_growth() const;\n            float       growth_factor() const;\n\n        private:\n            class impl;\n            std::experimental::propagate_const<std::unique_ptr<impl>> p_impl;\n        };\n\n        template <typename RawAllocator>\n        class bfit_allocator : TRTLAB_EBO(RawAllocator)\n        {\n            using node_t = bfit_detail::memory_node;\n            using traits = allocator_traits<RawAllocator>;\n\n            struct stats;\n\n        public:\n            using is_stateful    = std::true_type;\n            using memory_type    = typename traits::memory_type;\n            using allocator_type = typename traits::allocator_type;\n\n            bfit_allocator(std::size_t initial_size, RawAllocator&& alloc) : allocator_type(std::move(alloc))\n            {\n                m_min_alignment = traits::min_alignment(get_allocator());\n                auto memory     = traits::allocate_node(get_allocator(), initial_size, m_min_alignment);\n                auto node       = priv_create_node({memory, initial_size});\n                auto root       = priv_create_node({memory, initial_size});\n\n                // special case: mark as allocated to avoid being merged during a free\n                root->is_allocated = true;\n                root->next_node    = node;\n                node->prev_node    = root;\n\n                m_heads.push_back(root);\n                m_free_nodes.insert(node);\n            }\n\n            ~bfit_allocator()\n            {\n                if (!m_heads.empty())\n                {\n                    auto& alloc = get_allocator();\n                    VLOG(3) << \"deallocating \" << m_heads.size() << \" root allocations\";\n                    for (auto& block_ptr : m_heads)\n                    {\n                        DCHECK(block_ptr->next_node);\n                        DCHECK(!block_ptr->next_node->next_node);\n                        traits::deallocate_node(alloc, block_ptr->next_node->memory, block_ptr->next_node->size, m_min_alignment);\n                    }\n                }\n            }\n\n            bfit_allocator(const bfit_allocator&) = delete;\n            bfit_allocator& operator=(const bfit_allocator&) = delete;\n\n            bfit_allocator(bfit_allocator&&) = default;\n            bfit_allocator& operator=(bfit_allocator&&) = default;\n\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                auto search = m_free_nodes.lower_bound(size);\n                if (search == m_free_nodes.end())\n                {\n                    // no memory block available to handle request\n                    // trigger fallback -- possible fallbacks:\n                    // 1) request caches to be depopulated\n                    // 2) attempt to grow the allocation pool\n                    // for now, just fail\n                    LOG(ERROR) << \"unable to find block to fullfil request of \" << size << \" bytes\";\n                    throw std::bad_alloc();\n                }\n\n                // partition the best fit memory block\n                auto [alloc_node, free_node] = priv_split_node(*search, size, alignment);\n                DCHECK(alloc_node) << \"internal allocation failure\";\n\n                // remove from free nodes\n                m_free_nodes.erase(search);\n\n                // insert new allocation in to allocated nodes\n                m_alloc_nodes.insert(alloc_node);\n\n                // if sufficient remaining free space, add to free nodes\n                if (free_node)\n                {\n                    m_free_nodes.insert(free_node);\n                }\n\n                DVLOG(3) << \"allocate_node succeeded: \" << alloc_node->memory << \" - \" << bytes_to_string(alloc_node->size) << \" bytes\";\n                return alloc_node->memory;\n            }\n\n            void deallocate_node(void* memory, std::size_t size, std::size_t alignment) noexcept\n            {\n                DVLOG(5) << \"deallocating node at \" << memory;\n\n                // todo: this lookup could be skipped entirely if we allocate a descriptor that holds\n                // the linked list node info as part of the descriptor\n                auto search = m_alloc_nodes.find(memory);\n                if (search == m_alloc_nodes.end())\n                {\n                    LOG(ERROR) << \"failed to find allocation for \" << memory;\n                    auto node = debug_scan_for_node(memory);\n                    if (node)\n                    {\n                        LOG(ERROR) << \"found node containing \" << memory << \"; marked as \" << (node->is_allocated ? \"ALLOCATED\" : \"FREED\");\n                    }\n                    LOG(FATAL) << \"this is a fatal allocation error: aborting...\";\n                }\n\n                // note: erasing the pointer from alloc_nodes does not free the node's allocation\n                node_t* free_node = *search;\n                m_alloc_nodes.erase(search);\n\n                // mark as deallocated\n                free_node->is_allocated = false;\n\n                // remove any offset - the memory_block starting addres and size make it contiguous\n                // with its left and right neighbors\n                priv_collapse_alignment(free_node);\n\n                // merge with neighboring free/deallocated blocks\n                if (free_node->next_node && free_node->next_node->is_allocated == false)\n                {\n                    DVLOG(5) << \"merge current node (\" << free_node << \") with right neighbor (\" << free_node->next_node << \")\";\n                    // erasing the node only removes the pointer from the set; it does not deallocate it\n                    CHECK_EQ(m_free_nodes.erase(free_node->next_node), 1);\n                    auto destroy_node = free_node->next_node;\n                    priv_merge_node(free_node, free_node->next_node);\n                    priv_destroy_node(destroy_node);\n                }\n                if (free_node->prev_node && free_node->prev_node->is_allocated == false)\n                {\n                    DVLOG(5) << \"merge left node (\" << free_node->prev_node << \") with current node (\" << free_node << \")\";\n                    // erasing the node only removes the pointer from the set; it does not deallocate it\n                    CHECK_EQ(m_free_nodes.erase(free_node->prev_node), 1);\n                    free_node         = free_node->prev_node;\n                    auto destroy_node = free_node->next_node;\n                    priv_merge_node(free_node, free_node->next_node);\n                    priv_destroy_node(destroy_node);\n                }\n\n                m_free_nodes.insert(free_node);\n            }\n\n            allocator_type& get_allocator()\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const\n            {\n                return *this;\n            }\n\n            std::string debug_print_allocate_blocks() const\n            {\n                return priv_list_of_nodes(m_alloc_nodes);\n            }\n\n            std::size_t free_nodes() const\n            {\n                return m_free_nodes.size();\n            }\n\n            std::size_t used_nodes() const\n            {\n                return m_alloc_nodes.size();\n            }\n\n            const node_t* debug_scan_for_node(void* memory)\n            {\n                for (auto& head : m_heads)\n                {\n                    auto node = head;\n                    while (true)\n                    {\n                        node = node->next_node;\n                        if (!node)\n                            break;\n                        if (node->contains(memory))\n                            return node;\n                    }\n                }\n                return nullptr;\n            }\n\n            bool allocation_found(void* memory)\n            {\n                auto search = m_alloc_nodes.find(memory);\n                return search != m_alloc_nodes.end();\n            }\n\n        private:\n            std::pair<node_t*, node_t*> priv_split_node(const node_t* bfit, std::size_t size, std::size_t alignment)\n            {\n                DVLOG(5) << \"spliting node with \" << bfit->size << \" bytes into allocation of \" << size << \" bytes\";\n\n                // create one or two new nodes in the double linked list\n                // when complete, the bfit node is removed from the list\n                auto alloc_node            = priv_create_node(*bfit);\n                auto [data_start, loffset] = align_shift(alloc_node->memory, alignment);\n\n                // the loffset + size was larger than the block (unlikely)\n                if (size + loffset > bfit->size)\n                    return std::pair<node_t*, node_t*>(nullptr, nullptr);\n\n                auto data_end              = memory_shift(data_start, size);\n                auto [free_start, roffset] = align_shift(data_end, m_min_alignment);\n\n                alloc_node->memory       = data_start;\n                alloc_node->offset       = loffset;\n                alloc_node->size         = loffset + size + roffset;\n                alloc_node->is_allocated = true;\n\n                DVLOG(10) << \"new used_node; memory=\" << data_start << \"; size=\" << alloc_node->size << \"; offset=\" << loffset;\n\n                // partial linked_list update; insert alloc_node after bfit->prev_node\n                // [bfit->prev_node] [alloc_node]\n                alloc_node->prev_node = bfit->prev_node;\n                if (bfit->prev_node)\n                    bfit->prev_node->next_node = alloc_node;\n\n                // compute the remaining free space\n                std::size_t free_size = bfit->size - alloc_node->size;\n\n                if (free_size < 1024)\n                {\n                    DVLOG(5) << \"remaining free space is not sufficent for a free_node: \" << free_size;\n                    // complete linked list update\n                    // [bfit->prev_node] [alloc_node] [bfit->next_node]\n                    alloc_node->next_node = bfit->next_node;\n                    if (bfit->next_node)\n                        bfit->next_node->prev_node = alloc_node;\n                    return std::pair<node_t*, node_t*>(alloc_node, nullptr);\n                }\n\n                // there is enough free memory in the allocated block to warrant a new free node\n                auto free_node = priv_create_node({free_start, free_size});\n\n                // insert free_node into linked list after alloc_node\n                // [bfit->prev_node] [alloc_node] [free_node]\n                alloc_node->next_node = free_node;\n                free_node->prev_node  = alloc_node;\n\n                // complete final linked list update\n                // [bfit->prev_node] [alloc_node] [free_node] [bfit->next_node]\n                free_node->next_node = bfit->next_node;\n                if (bfit->next_node)\n                    bfit->next_node->prev_node = free_node;\n\n                return std::make_pair(alloc_node, free_node);\n            }\n\n            void priv_merge_node(node_t* dst, node_t* src)\n            {\n                CHECK(!src->is_allocated);\n                DCHECK_EQ(memory_shift(dst->memory, dst->size), src->memory);\n                DCHECK_EQ(src->prev_node, dst);\n                DCHECK_EQ(src->offset, 0);\n                DCHECK(!dst->is_allocated);\n\n                // extend the dst node to include the src node\n                dst->size += src->size;\n\n                // remove src from the linked list\n                dst->next_node = src->next_node;\n                if (dst->next_node)\n                    dst->next_node->prev_node = dst;\n            }\n\n            void priv_collapse_alignment(node_t* node)\n            {\n                if (node->offset)\n                {\n                    node->memory = memory_shift(node->memory, -1 * node->offset);\n                    node->offset = 0;\n                }\n            }\n\n            node_t* priv_create_node(const memory_block& block)\n            {\n                // this is where you call your templated node allocator\n                // whether the node is allocated \"in-block\", i.e. as part of the actuall backing memory\n                // or if th node is allocated \"out-of-block\", i.e. the node data is stored apart from the backing memory\n                // the latter is needed for gpu memory\n\n                auto node = new node_t(block);\n\n                // move to constructor\n                node->memory       = block.memory;\n                node->size         = block.size;\n                node->offset       = 0;\n                node->is_allocated = false;\n                node->next_node    = nullptr;\n                node->prev_node    = nullptr;\n\n                return node;\n            }\n\n            void priv_destroy_node(node_t* node) noexcept\n            {\n                // this is where you call your templated node deallocator\n                delete node;\n            }\n\n            template <typename Container>\n            std::string priv_list_of_nodes(const Container& container) const\n            {\n                std::stringstream os;\n                os << std::endl;\n                for (auto& item : container)\n                {\n                    os << item->memory << \" - \" << item->size << \" - \" << item->offset << std::endl;\n                }\n                return os.str();\n            }\n\n            std::size_t                                                m_min_alignment;\n            std::vector<const node_t*>                                 m_heads;\n            std::set<node_t*, bfit_detail::memory_node_compare_size<>> m_free_nodes;\n            std::set<node_t*, bfit_detail::memory_node_compare_addr<>> m_alloc_nodes;\n        };\n\n        template <typename RawAllocator>\n        auto make_bfit_allocator(std::size_t initial_size, RawAllocator&& alloc)\n        {\n            return bfit_allocator<RawAllocator>(initial_size, std::move(alloc));\n        }\n\n    } // namespace memory\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/block_allocators.h",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#pragma once\n\n#include <type_traits>\n\n#include \"detail/utility.h\"\n#include \"allocator_traits.h\"\n#include \"memory_block.h\"\n#include \"config.h\"\n#include \"error.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            static std::size_t max_size_t = std::size_t(-1);\n\n            template <class BlockAllocator>\n            std::true_type is_block_allocator_impl(\n                int, TRTLAB_SFINAE(std::declval<memory_block&>() = std::declval<BlockAllocator&>().allocate_block()),\n                TRTLAB_SFINAE(std::declval<std::size_t&>() = std::declval<BlockAllocator&>().next_block_size()),\n                TRTLAB_SFINAE(std::declval<BlockAllocator>().deallocate_block(memory_block{})));\n\n            template <typename T>\n            std::false_type is_block_allocator_impl(short);\n        } // namespace detail\n\n        /// Traits that check whether a type models concept \\concept{concept_blockallocator,BlockAllocator}.\n        /// \\ingroup memory core\n        template <typename T>\n        struct is_block_allocator : decltype(detail::is_block_allocator_impl<T>(0))\n        {\n        };\n\n        /// A \\concept{concept_blockallocator,BlockAllocator} that allows only one block allocation.\n        /// It can be used to prevent higher-level allocators from expanding.\n        /// The one block allocation is performed through the \\c allocate_array() function of the given \\concept{concept_rawallocator,RawAllocator}.\n        /// \\ingroup memory adapter\n\n        template <class RawAllocator>\n        class single_block_allocator : TRTLAB_EBO(allocator_traits<RawAllocator>::allocator_type)\n        {\n            using traits = allocator_traits<RawAllocator>;\n\n        public:\n            using allocator_type = typename traits::allocator_type;\n            using memory_type    = typename traits::memory_type;\n\n            /// \\effects Creates it by passing it the size of the block and the allocator object.\n            /// \\requires \\c block_size must be greater than 0,\n            explicit single_block_allocator(std::size_t block_size, allocator_type alloc = allocator_type()) noexcept\n            : allocator_type(detail::move(alloc)), block_size_(block_size), initial_size_(block_size)\n            {\n            }\n\n            /// \\effects Allocates a new memory block or throws an exception if there was already one allocation.\n            /// \\returns The new \\ref memory_block.\n            /// \\throws Anything thrown by the \\c allocate_array() function of the \\concept{concept_rawallocator,RawAllocator} or \\ref out_of_memory if this is not the first call.\n            memory_block allocate_block()\n            {\n                if (block_size_)\n                {\n                    auto alignment = traits::min_alignment(get_allocator());\n                    auto memory = traits::allocate_array(get_allocator(), block_size_, 1UL, alignment);\n                    block_size_ = 0u;\n                    return {memory, initial_size_};\n                }\n                throw out_of_fixed_memory(info(), block_size_);\n            }\n\n            /// \\effects Deallocates the previously allocated memory block.\n            /// It also resets and allows a new call again.\n            void deallocate_block(memory_block block) noexcept\n            {\n                DCHECK_EQ(block.size, initial_size_);\n                traits::deallocate_array(get_allocator(), block.memory, block.size, 1UL);\n                block_size_ = block.size;\n            }\n\n            /// \\returns The size of the next block which is either the initial size or \\c 0.\n            std::size_t next_block_size() const noexcept\n            {\n                return block_size_;\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return traits::device_context(get_allocator());\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::single_block_allocator\", this};\n            }\n\n            std::size_t block_size_;\n            std::size_t initial_size_;\n        };\n\n        template <class RawAllocator>\n        class fixed_size_block_allocator : TRTLAB_EBO(allocator_traits<RawAllocator>::allocator_type)\n        {\n            using traits = allocator_traits<RawAllocator>;\n\n        public:\n            using allocator_type = typename traits::allocator_type;\n            using memory_type    = typename traits::memory_type;\n\n            /// \\effects Creates it by passing it the size of the block and the allocator object.\n            /// \\requires \\c block_size must be greater than 0,\n            explicit fixed_size_block_allocator(std::size_t block_size, allocator_type alloc = allocator_type()) noexcept\n            : allocator_type(detail::move(alloc)), block_size_(block_size)\n            {\n            }\n\n            /// \\effects Allocates a new memory block or throws an exception if there was already one allocation.\n            /// \\returns The new \\ref memory_block.\n            /// \\throws Anything thrown by the \\c allocate_array() function of the \\concept{concept_rawallocator,RawAllocator} or \\ref out_of_memory if this is not the first call.\n            memory_block allocate_block()\n            {\n                auto alignment = traits::min_alignment(get_allocator());\n                auto         mem = traits::allocate_array(get_allocator(), block_size_, 1, alignment);\n                memory_block block(mem, block_size_);\n                return block;\n            }\n\n            /// \\effects Deallocates the previously allocated memory block.\n            /// It also resets and allows a new call again.\n            void deallocate_block(memory_block block) noexcept\n            {\n                DCHECK_EQ(block.size, block_size_);\n                traits::deallocate_array(get_allocator(), block.memory, block.size, 1);\n            }\n\n            /// \\returns The size of the next block which is either the initial size or \\c 0.\n            std::size_t next_block_size() const noexcept\n            {\n                return block_size_;\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return traits::device_context(get_allocator());\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::fixed_size_block_allocator\", this};\n            }\n\n            std::size_t block_size_;\n        };\n\n        template <class RawAllocator>\n        class growing_block_allocator : TRTLAB_EBO(allocator_traits<RawAllocator>::allocator_type)\n        {\n            using traits = allocator_traits<RawAllocator>;\n\n        public:\n            using allocator_type = typename traits::allocator_type;\n            using memory_type    = typename traits::memory_type;\n\n            /// \\effects Creates it by passing it the size of the block and the allocator object.\n            /// \\requires \\c block_size must be greater than 0,\n            explicit growing_block_allocator(std::size_t block_size, allocator_type alloc = allocator_type(),\n                                             std::size_t max_size = detail::max_size_t, double scale_factor = 2) noexcept\n            : allocator_type(detail::move(alloc)), block_size_(block_size), max_size_(max_size), scale_factor_(scale_factor)\n            {\n            }\n\n            /// \\effects Allocates a new memory block or throws an exception if there was already one allocation.\n            /// \\returns The new \\ref memory_block.\n            /// \\throws Anything thrown by the \\c allocate_array() function of the \\concept{concept_rawallocator,RawAllocator} or \\ref out_of_memory if this is not the first call.\n            memory_block allocate_block()\n            { \n                auto alignment = traits::min_alignment(get_allocator());\n                auto         mem = traits::allocate_array(get_allocator(), block_size_, 1, alignment);\n                memory_block block(mem, block_size_);\n                std::size_t  next_size = block_size_ * scale_factor_;\n                if (next_size <= max_size_)\n                    block_size_ = next_size;\n                return block;\n            }\n\n            /// \\effects Deallocates the previously allocated memory block.\n            /// It also resets and allows a new call again.\n            void deallocate_block(memory_block block) noexcept\n            {\n                DCHECK_LE(block.size, max_size_);\n                traits::deallocate_array(get_allocator(), block.memory, block.size, 1);\n            }\n\n            /// \\returns The size of the next block which is either the initial size or \\c 0.\n            std::size_t next_block_size() const noexcept\n            {\n                return block_size_;\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return traits::device_context(get_allocator());\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::growing_block_allocator\", this};\n            }\n\n            std::size_t block_size_;\n            std::size_t max_size_;\n            double      scale_factor_;\n        };\n\n        template <typename BlockAllocator>\n        class count_limited_block_allocator : TRTLAB_EBO(BlockAllocator)\n        {\n\n        public:\n            using block_allocator_type = BlockAllocator;\n            using allocator_type = typename block_allocator_type::allocator_type;\n            using memory_type    = typename block_allocator_type::memory_type;\n\n            count_limited_block_allocator(BlockAllocator&& alloc, std::size_t max_blocks)\n            : block_allocator_type(std::move(alloc)), m_max_blocks(max_blocks), m_block_count(0)\n            {\n                DCHECK(max_blocks);\n                static_assert(is_block_allocator<BlockAllocator>::value, \"needs to be a valid block allocator\");\n            }\n\n            memory_block allocate_block()\n            {\n                if (m_block_count < m_max_blocks)\n                {\n                    m_block_count++;\n                    return block_allocator_type::allocate_block();\n                }\n                throw std::bad_alloc();\n            }\n\n            /// \\effects Deallocates the previously allocated memory block.\n            /// It also resets and allows a new call again.\n            void deallocate_block(memory_block block) noexcept\n            {\n                DCHECK(m_block_count);\n                block_allocator_type::deallocate_block(block);\n                m_block_count--;\n            }\n\n            /// \\returns The size of the next block which is either the initial size or \\c 0.\n            std::size_t next_block_size() const noexcept\n            {\n                return block_allocator_type::next_block_size();\n            }\n\n            std::size_t block_count() const noexcept\n            {\n                return m_block_count;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return block_allocator_type::device_context();\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            allocator_type& get_allocator() noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            block_allocator_type& get_block_allocator() noexcept\n            {\n                return *this;\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            const block_allocator_type& get_block_allocator() const noexcept\n            {\n                return *this;\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::count_limited_block_allocator\", this};\n            }\n\n            std::size_t m_max_blocks;\n            std::size_t m_block_count;\n        };\n\n        template <typename BlockAllocator>\n        class size_limited_block_allocator : TRTLAB_EBO(BlockAllocator)\n        {\n        public:\n            using block_allocator_type = BlockAllocator;\n            using allocator_type       = typename block_allocator_type::allocator_type;\n            using memory_type          = typename block_allocator_type::memory_type;\n\n            size_limited_block_allocator(BlockAllocator&& alloc, std::size_t max_size)\n            : block_allocator_type(std::move(alloc)), m_max_size(max_size), m_size(0)\n            {\n                DCHECK(m_max_size);\n                static_assert(is_block_allocator<BlockAllocator>::value, \"needs to be a valid block allocator\");\n            }\n\n            memory_block allocate_block()\n            {\n                if (m_size + block_allocator_type::next_block_size() <= m_max_size)\n                {\n                    auto block = block_allocator_type::allocate_block();\n                    m_size += block.size;\n                    return block;\n                }\n                throw std::bad_alloc();\n            }\n\n            /// \\effects Deallocates the previously allocated memory block.\n            /// It also resets and allows a new call again.\n            void deallocate_block(memory_block block) noexcept\n            {\n                DCHECK_LE(block.size, m_size);\n                block_allocator_type::deallocate_block(block);\n                m_size -= block.size;\n            }\n\n            /// \\returns The size of the next block which is either the initial size or \\c 0.\n            std::size_t next_block_size() const noexcept\n            {\n                return block_allocator_type::next_block_size();\n            }\n\n            std::size_t bytes_allocated() const noexcept\n            {\n                return m_size;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return block_allocator_type::device_context();\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            allocator_type& get_allocator() noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            const allocator_type& get_allocator() const noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            block_allocator_type& get_block_allocator() noexcept\n            {\n                return *this;\n            }\n\n            /// \\returns A reference to the used \\concept{concept_rawallocator,RawAllocator} object.\n            const block_allocator_type& get_block_allocator() const noexcept\n            {\n                return *this;\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::size_limited_block_allocator\", this};\n            }\n\n            std::size_t m_max_size;\n            std::size_t m_size;\n        };\n\n        namespace detail\n        {\n            template <class RawAlloc>\n            using default_block_wrapper = fixed_size_block_allocator<RawAlloc>;\n\n            template <template <class...> class Wrapper, class BlockAllocator, typename... Args>\n            BlockAllocator make_block_allocator(std::true_type, BlockAllocator&& block_alloc, std::size_t block_size, Args&&... args)\n            {\n                return Wrapper<BlockAllocator>(std::forward<Args>(args)..., std::move(block_alloc));\n            }\n\n            template <template <class...> class BlockAllocator, class RawAlloc, typename... Args>\n            auto make_block_allocator(std::false_type, RawAlloc&& alloc, std::size_t block_size, Args&&... args) -> BlockAllocator<RawAlloc>\n            {\n                return BlockAllocator<RawAlloc>(block_size, std::move(alloc), std::forward<Args>(args)...);\n            }\n\n        } // namespace detail\n\n        /// Takes either a \\concept{concept_blockallocator,BlockAllocator} or a \\concept{concept_rawallocator,RawAllocator}.\n        /// In the first case simply aliases the type unchanged, in the second to \\ref growing_block_allocator (or the template in `BlockAllocator`) with the \\concept{concept_rawallocator,RawAllocator}.\n        /// Using this allows passing normal \\concept{concept_rawallocator,RawAllocators} as \\concept{concept_blockallocator,BlockAllocators}.\n        /// \\ingroup memory core\n        template <class BlockOrRawAllocator, template <typename...> class BlockAllocator>\n        using make_block_allocator_t =\n            TRTLAB_IMPL_DEFINED(typename std::conditional<is_block_allocator<BlockOrRawAllocator>::value, BlockOrRawAllocator,\n                                                          BlockAllocator<BlockOrRawAllocator>>::type);\n\n        /// @{\n        /// Helper function make a \\concept{concept_blockallocator,BlockAllocator}.\n        /// \\returns A \\concept{concept_blockallocator,BlockAllocator} of the given type created with the given arguments.\n        /// \\requires Same requirements as the constructor.\n        /// \\ingroup memory core\n        /*\n        template <class BlockOrRawAllocator, typename... Args>\n        make_block_allocator_t<BlockOrRawAllocator> make_block_allocator(std::size_t block_size, Args&&... args)\n        {\n            return detail::make_block_allocator<\n                detail::default_block_wrapper,\n                BlockOrRawAllocator>(is_block_allocator<BlockOrRawAllocator>{}, block_size,\n                                     detail::forward<Args>(args)...);\n        }\n        */\n\n        /*\n        template <template <class...> class BlockAllocator, typename RawAllocator, typename... Args>\n        BlockAllocator<RawAllocator> make_block_allocator(RawAllocator&& alloc, std::size_t block_size, Args&&... args)\n        {\n            return BlockAllocator<RawAllocator>(block_size, std::move(alloc), std::forward<Args>(args)...);\n        }\n*/\n        template <template <class...> class BlockAllocator, class BlockOrRawAllocator, typename... Args>\n        make_block_allocator_t<BlockOrRawAllocator, BlockAllocator> make_block_allocator(BlockOrRawAllocator&& alloc, Args&&... args)\n        {\n            return detail::make_block_allocator<BlockAllocator, BlockOrRawAllocator>(is_block_allocator<BlockOrRawAllocator>{},\n                                                                                     std::move(alloc), std::forward<Args>(args)...);\n        }\n\n        template <template <class...> class BlockAllocator, class BlockOrRawAllocator, typename... Args>\n        make_block_allocator_t<BlockOrRawAllocator, BlockAllocator> make_block_allocator(Args&&... args)\n        {\n            static_assert(!is_block_allocator<BlockOrRawAllocator>{}, \"should be a raw\");\n            BlockOrRawAllocator raw;\n            return detail::make_block_allocator<BlockAllocator, BlockOrRawAllocator>(std::false_type{}, std::move(raw),\n                                                                                     std::forward<Args>(args)...);\n        }\n\n        template <template <class...> class Extension, class BlockAllocator, typename... Args>\n        Extension<BlockAllocator> make_extended_block_allocator(BlockAllocator&& block_alloc, Args&&... args)\n        {\n            static_assert(is_block_allocator<BlockAllocator>{}, \"should be a block allocator\");\n            return Extension<BlockAllocator>(std::move(block_alloc), std::forward<Args>(args)...);\n        }\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/block_arena.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstddef>\n#include <map>\n\n#include <utility>\n\n#include <glog/logging.h>\n\n#include \"block_allocators.h\"\n#include \"detail/block_list.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        constexpr bool cached_arena   = true;\n        constexpr bool uncached_arena = false;\n\n        namespace detail\n        {\n            template <bool Cached, typename BlockList = detail::block_list>\n            class block_cache;\n\n            template <typename BlockList>\n            class block_cache<cached_arena, BlockList>\n            {\n            public:\n                block_cache() noexcept {}\n\n                block_cache(block_cache<cached_arena>&& other) noexcept : m_cache(std::move(other.m_cache))\n                {\n                    DVLOG(3) << \"block_cache was moved via move constructor\";\n                }\n\n                block_cache& operator=(block_cache<cached_arena>&& other) noexcept\n                {\n                    DVLOG(3) << \"block_cache was moved via move assignment\";\n                    m_cache = std::move(other.m_cache);\n                }\n\n                bool cache_empty() const noexcept\n                {\n                    return m_cache.empty();\n                }\n\n                std::size_t cache_size() const noexcept\n                {\n                    return m_cache.size();\n                }\n\n                bool take_from_cache(memory_block& block) noexcept\n                {\n                    if (m_cache.empty())\n                    {\n                        return false;\n                    }\n                    block = m_cache.allocate();\n                    DVLOG(3) << \"Acquired memory_block from cache: \" << block.memory << \"; \" << block.size;\n                    return true;\n                }\n\n                template <typename BlockAllocator>\n                void deallocate_block(BlockAllocator&, memory_block&& block) noexcept\n                {\n\n                    DVLOG(3) << \"deallocate_block \" << block.memory << \" was cached instead of released\";\n                    m_cache.insert(std::move(block));\n                    DVLOG(3) << \"deallocate_block \" << block.memory << \" was cached instead of released\";\n                }\n\n                std::size_t cache_next_block_size() const noexcept\n                {\n                    return m_cache.next_block_size();\n                }\n\n                template <typename BlockAllocator>\n                void cache_shrink_to_fit(BlockAllocator& alloc) noexcept\n                {\n                    static_assert(is_block_allocator<BlockAllocator>{}, \"BlockAllocator is not a BlockAllocator!\");\n                    while (!m_cache.empty())\n                    {\n                        alloc.deallocate_block(m_cache.allocate());\n                    }\n                }\n\n                template <typename BlockAllocator>\n                void cache_reserve(BlockAllocator& alloc, std::size_t block_count)\n                {\n                    static_assert(is_block_allocator<BlockAllocator>{}, \"BlockAllocator is not a BlockAllocator!\");\n                    while (m_cache.size() < block_count)\n                    {\n                        DVLOG(4) << \"cache size: \" << m_cache.size();\n                        m_cache.insert(alloc.allocate_block());\n                    }\n                }\n\n            private:\n                BlockList m_cache;\n            };\n\n            template <typename BlockList>\n            class block_cache<uncached_arena, BlockList>\n            {\n            public:\n                block_cache() noexcept {}\n\n                block_cache(block_cache<uncached_arena>&& other) noexcept {}\n\n                block_cache& operator=(block_cache<uncached_arena>&& other) noexcept {}\n\n                bool cache_empty() const noexcept\n                {\n                    return true;\n                }\n\n                std::size_t cache_size() const noexcept\n                {\n                    return 0u;\n                }\n\n                bool take_from_cache(memory_block& block) noexcept\n                {\n                    return false;\n                }\n\n                template <typename BlockAllocator>\n                void deallocate_block(BlockAllocator& alloc, memory_block&& block) noexcept\n                {\n                    static_assert(is_block_allocator<BlockAllocator>{}, \"BlockAllocator is not a BlockAllocator!\");\n                    alloc.deallocate_block(block);\n                }\n\n                std::size_t cache_next_block_size() const noexcept\n                {\n                    return 0u;\n                }\n\n                template <typename BlockAllocator>\n                void cache_shrink_to_fit(BlockAllocator&) noexcept\n                {\n                }\n\n                template <typename BlockAllocator>\n                void cache_reserve(BlockAllocator&, std::size_t)\n                {\n                }\n            };\n        } // namespace detail\n\n        template <typename BlockAllocator, bool Cached, typename BlockList>\n        class block_arena : TRTLAB_EBO(BlockAllocator), TRTLAB_EBO(detail::block_cache<Cached, BlockList>)\n        {\n            static_assert(is_block_allocator<BlockAllocator>::value, \"BlockAllocator is not a BlockAllocator!\");\n\n            using cache_type       = detail::block_cache<Cached, BlockList>;\n            using block_arena_type = block_arena<BlockAllocator, Cached, BlockList>;\n\n        public:\n            using block_allocator_type = BlockAllocator;\n            using allocator_type       = typename block_allocator_type::allocator_type;\n            using memory_type          = typename block_allocator_type::memory_type;\n            using is_cached            = std::integral_constant<bool, Cached>;\n            using is_stateful          = std::true_type;\n\n            //explicit transactional_arena(std::size_t block_size, Args&&... args)\n            //    : block_allocator_type(block_size, detail::forward<Args>(args)...) {}\n\n            explicit block_arena(block_allocator_type&& block_alloc) noexcept : block_allocator_type(std::move(block_alloc)) {}\n\n            block_arena(block_arena_type&& other) noexcept : block_allocator_type(std::move(other)), cache_type(std::move(other)) {}\n\n            block_arena_type& operator=(block_arena_type&& other) noexcept\n            {\n                block_allocator_type::operator=(std::move(other));\n                cache_type::          operator=(std::move(other));\n            }\n\n            // explicitly delete copy ctor and assignment\n            block_arena(const block_arena_type&) = delete;\n            block_arena_type& operator=(const block_arena_type&) = delete;\n\n            ~block_arena()\n            {\n                // deallocate blocks in cache\n                shrink_to_fit();\n            }\n\n            // block_allocator methods\n\n            memory_block allocate_block()\n            {\n                memory_block block;\n                if (!this->take_from_cache(block))\n                {\n                    block = block_allocator_type::allocate_block();\n                }\n                return block;\n            }\n\n            void deallocate_block(memory_block block)\n            {\n                DCHECK(block.memory);\n                DCHECK(block.size);\n                DVLOG(3) << \"deallocate_block: \" << block.memory << \"; \" << block.size;\n                cache_type::deallocate_block(get_block_allocator(), std::move(block));\n            }\n\n            std::size_t next_block_size() const noexcept\n            {\n                if (!this->cache_empty())\n                {\n                    return this->cache_next_block_size();\n                }\n                return block_allocator_type::next_block_size();\n            }\n\n            // arena methods\n\n            void shrink_to_fit() noexcept\n            {\n                this->cache_shrink_to_fit(get_block_allocator());\n            }\n\n            void reserve_blocks(std::size_t block_count) noexcept\n            {\n                this->cache_reserve(get_block_allocator(), block_count);\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return block_allocator_type::device_context();\n            } \n\n            // allocator access and methods\n\n            allocator_type& get_allocator() noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return block_allocator_type::get_allocator();\n            }\n\n            block_allocator_type& get_block_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const block_allocator_type& get_block_allocator() const noexcept\n            {\n                return *this;\n            }\n        };\n\n        template <bool Cached, typename BlockAllocator>\n        auto make_block_arena(BlockAllocator&& block_alloc)\n        {\n            using memory_type = typename BlockAllocator::memory_type;\n            using list_type = typename std::conditional<std::is_base_of<host_memory, memory_type>::value, detail::block_list, detail::block_list_oob>::type;\n            return block_arena<BlockAllocator, Cached, list_type>(std::move(block_alloc));\n        }\n\n        template <typename BlockAllocator>\n        auto make_cached_block_arena(BlockAllocator&& block_alloc)\n        {\n            return make_block_arena<cached_arena>(std::move(block_alloc));\n        }\n\n        template <typename BlockAllocator>\n        auto make_uncached_block_arena(BlockAllocator&& block_alloc)\n        {\n            return make_block_arena<uncached_arena>(std::move(block_alloc));\n        }\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/block_manager.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstddef>\n#include <map>\n#include <queue>\n#include <utility>\n\n#include <glog/logging.h>\n\n#include \"memory_block.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        template <typename BlockType>\n        class block_manager final\n        {\n            static_assert(std::is_base_of<memory_block, BlockType>::value, \"should be derived from memory_block\");\n\n        public:\n            using block_type = BlockType;\n\n            block_manager()  = default;\n            ~block_manager() = default;\n\n            block_manager(block_manager&& other) noexcept : m_block_map(std::move(other.m_block_map)) {}\n\n            block_manager& operator=(block_manager&& other)\n            {\n                m_block_map = std::move(other.m_block_map);\n                return *this;\n            }\n\n            block_manager(const block_manager&) = delete;\n            block_manager& operator=(const block_manager&) = delete;\n\n            const block_type& add_block(block_type&& block)\n            {\n                auto key = reinterpret_cast<std::uintptr_t>(block.memory) + block.size;\n                // TODO: check if an overlapping block exists\n                // this would be a failure condition\n                DVLOG(1) << \"adding block: \" << key << \" - \" << block.memory << \"; \" << block.size;\n                m_block_map[key] = std::move(block);\n                return m_block_map[key];\n            }\n\n            block_type* find_block(const void* ptr)\n            {\n                auto search = find_entry(ptr);\n                if (search != m_block_map.end() && search->second.contains(ptr))\n                {\n                    DVLOG(3) << this << \": block found\";\n                    return &search->second;\n                }\n                DVLOG(3) << this << \": no block found for \" << ptr;\n                return nullptr;\n            }\n\n            void drop_block(void* ptr)\n            {\n                DVLOG(1) << \"dropping block: \" << ptr;\n                auto search = find_entry(ptr);\n                if (search != m_block_map.end())\n                {\n                    DVLOG(3) << \"found block; dropping block: \" << search->first << \"; \" << search->second.memory;\n                    m_block_map.erase(search);\n                }\n            }\n\n            auto size() const noexcept\n            {\n                return m_block_map.size();\n            }\n\n            void clear() noexcept\n            {\n                DVLOG(2) << \"clearing block map\";\n                m_block_map.clear();\n            }\n\n            std::vector<void*> blocks() const noexcept\n            {\n                DVLOG(2) << \"getting a vector of blocks - \" << m_block_map.size();\n                std::vector<void*> v;\n                v.reserve(m_block_map.size());\n                for (const auto& it : m_block_map)\n                {\n                    v.push_back(it.second.memory);\n                }\n                return v;\n            }\n\n            bool owns(void* addr)\n            {\n                auto block = find_block(addr);\n                return (block && block->contains(addr));\n            }\n\n        private:\n            inline auto find_entry(const void* ptr)\n            {\n                DVLOG(3) << \"looking for block containing: \" << ptr;\n                auto key = reinterpret_cast<std::uintptr_t>(ptr);\n                return m_block_map.upper_bound(key);\n            }\n\n            // todo: used a static block allocator here to avoid allocation issues\n            std::map<std::uintptr_t, block_type> m_block_map;\n        };\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/block_stack.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_MEMORY_ARENA_H_INCLUDED\n#define TRTLAB_MEMORY_MEMORY_ARENA_H_INCLUDED\n\n#include <type_traits>\n\n#include \"detail/debug_helpers.h\"\n#include \"detail/assert.h\"\n#include \"detail/utility.h\"\n#include \"allocator_traits.h\"\n#include \"config.h\"\n#include \"error.h\"\n#include \"memory_block.h\"\n#include \"block_allocators.h\"\n#include \"block_arena.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n\n        template <class BlockAllocator, bool Cached = true>\n        class block_stack;\n\n        constexpr bool cached   = true;\n        constexpr bool uncached = false;\n\n        namespace detail\n        {\n            // stores memory block in an intrusive linked list and allows LIFO access\n            class memory_block_stack\n            {\n            public:\n                memory_block_stack() noexcept : head_(nullptr) {}\n\n                ~memory_block_stack() noexcept {}\n\n                memory_block_stack(memory_block_stack&& other) noexcept : head_(other.head_)\n                {\n                    other.head_ = nullptr;\n                }\n\n                memory_block_stack& operator=(memory_block_stack&& other) noexcept\n                {\n                    memory_block_stack tmp(detail::move(other));\n                    swap(*this, tmp);\n                    return *this;\n                }\n\n                friend void swap(memory_block_stack& a, memory_block_stack& b) noexcept\n                {\n                    detail::adl_swap(a.head_, b.head_);\n                }\n\n                // the raw allocated block returned from an allocator\n                using allocated_mb = memory_block;\n\n                // the inserted block slightly smaller to allow for the fixup value\n                using inserted_mb = memory_block;\n\n                // how much an inserted block is smaller\n                static const std::size_t implementation_offset;\n\n                // pushes a memory block\n                void push(allocated_mb block) noexcept;\n\n                // pops a memory block and returns the original block\n                allocated_mb pop() noexcept;\n\n                // steals the top block from another stack\n                void steal_top(memory_block_stack& other) noexcept;\n\n                // returns the last pushed() inserted memory block\n                inserted_mb top() const noexcept\n                {\n                    TRTLAB_MEMORY_ASSERT(head_);\n                    auto mem = static_cast<void*>(head_);\n                    return {static_cast<char*>(mem) + node::offset, head_->usable_size};\n                }\n\n                bool empty() const noexcept\n                {\n                    return head_ == nullptr;\n                }\n\n                bool owns(const void* ptr) const noexcept;\n\n                // O(n) size\n                std::size_t size() const noexcept;\n\n            private:\n                struct node\n                {\n                    node*       prev;\n                    std::size_t usable_size;\n\n                    node(node* p, std::size_t size) noexcept : prev(p), usable_size(size) {}\n\n                    static const std::size_t div_alignment;\n                    static const std::size_t mod_offset;\n                    static const std::size_t offset;\n                };\n\n                node* head_;\n            };\n\n            template <bool Cached>\n            class memory_arena_cache;\n\n            template <>\n            class memory_arena_cache<cached_arena>\n            {\n            protected:\n                bool cache_empty() const noexcept\n                {\n                    return cached_.empty();\n                }\n\n                std::size_t cache_size() const noexcept\n                {\n                    return cached_.size();\n                }\n\n                std::size_t cached_block_size() const noexcept\n                {\n                    return cached_.top().size;\n                }\n\n                bool take_from_cache(detail::memory_block_stack& used) noexcept\n                {\n                    if (cached_.empty())\n                        return false;\n                    used.steal_top(cached_);\n                    return true;\n                }\n\n                template <class BlockAllocator>\n                void do_deallocate_block(BlockAllocator&, detail::memory_block_stack& used) noexcept\n                {\n                    cached_.steal_top(used);\n                }\n\n                template <class BlockAllocator>\n                void do_shrink_to_fit(BlockAllocator& alloc) noexcept\n                {\n                    detail::memory_block_stack to_dealloc;\n                    // pop from cache and push to temporary stack\n                    // this revers order\n                    while (!cached_.empty())\n                        to_dealloc.steal_top(cached_);\n                    // now dealloc everything\n                    while (!to_dealloc.empty())\n                        alloc.deallocate_block(to_dealloc.pop());\n                }\n\n            private:\n                detail::memory_block_stack cached_;\n            };\n\n            template <>\n            class memory_arena_cache<uncached_arena>\n            {\n            protected:\n                bool cache_empty() const noexcept\n                {\n                    return true;\n                }\n\n                std::size_t cache_size() const noexcept\n                {\n                    return 0u;\n                }\n\n                std::size_t cached_block_size() const noexcept\n                {\n                    return 0u;\n                }\n\n                bool take_from_cache(detail::memory_block_stack&) noexcept\n                {\n                    return false;\n                }\n\n                template <class BlockAllocator>\n                void do_deallocate_block(BlockAllocator& alloc, detail::memory_block_stack& used) noexcept\n                {\n                    alloc.deallocate_block(used.pop());\n                }\n\n                template <class BlockAllocator>\n                void do_shrink_to_fit(BlockAllocator&) noexcept\n                {\n                }\n            };\n        } // namespace detail\n\n\n        // TODO:\n        // - expose the block_allocator via get_block_allocator\n        // - expose the block_allocator's allocator via get_allocator\n\n        /// A block arena that manages huge memory blocks for a higher-level allocator.\n        /// Some allocators like \\ref memory_stack work on huge memory blocks,\n        /// this class manages them for those allocators.\n        /// It uses a \\concept{concept_blockallocator,BlockAllocator} for the allocation of those blocks.\n        /// The memory blocks in use are put onto a stack like structure, deallocation will pop from the top,\n        /// so it is only possible to deallocate the last allocated block of the arena.\n        /// Block can be cached or uncached via the Cached template parameter\n        /// \\ref cached_arena (or \\c true) enables it explicitly.\n        /// \\ingroup memory core\n        template <class BlockAllocator, bool Cached>\n        class block_stack : TRTLAB_EBO(BlockAllocator), TRTLAB_EBO(detail::memory_arena_cache<Cached>)\n        {\n            static_assert(is_block_allocator<BlockAllocator>::value, \"BlockAllocator is not a BlockAllocator!\");\n            using cache = detail::memory_arena_cache<Cached>;\n\n        public:\n            using allocator_type = BlockAllocator;\n            using memory_type    = typename BlockAllocator::memory_type;\n            using is_cached      = std::integral_constant<bool, Cached>;\n\n            /// \\effects Creates it by giving it the size and other arguments for the \\concept{concept_blockallocator,BlockAllocator}.\n            /// It forwards these arguments to its constructor.\n            /// \\requires \\c block_size must be greater than \\c 0 and other requirements depending on the \\concept{concept_blockallocator,BlockAllocator}.\n            /// \\throws Anything thrown by the constructor of the \\c BlockAllocator.\n            template <typename... Args>\n            explicit block_stack(std::size_t block_size, Args&&... args) : allocator_type(block_size, detail::forward<Args>(args)...)\n            {\n            }\n\n            block_stack(BlockAllocator&& block_alloc) noexcept : allocator_type(std::move(block_alloc)) {}\n\n            /// \\effects Deallocates all memory blocks that where requested back to the \\concept{concept_blockallocator,BlockAllocator}.\n            ~block_stack() noexcept\n            {\n                // clear cache\n                shrink_to_fit();\n                // now deallocate everything\n                while (!used_.empty())\n                    allocator_type::deallocate_block(used_.pop());\n            }\n\n            /// @{\n            /// \\effects Moves the arena.\n            /// The new arena takes ownership over all the memory blocks from the other arena object,\n            /// which is empty after that.\n            /// This does not invalidate any memory blocks.\n            block_stack(block_stack&& other) noexcept\n            : allocator_type(detail::move(other)), cache(detail::move(other)), used_(detail::move(other.used_))\n            {\n            }\n\n            block_stack& operator=(block_stack&& other) noexcept\n            {\n                block_stack tmp(detail::move(other));\n                swap(*this, tmp);\n                return *this;\n            }\n            /// @}\n\n            /// \\effects Swaps to memory arena objects.\n            /// This does not invalidate any memory blocks.\n            friend void swap(block_stack& a, block_stack& b) noexcept\n            {\n                detail::adl_swap(static_cast<allocator_type&>(a), static_cast<allocator_type&>(b));\n                detail::adl_swap(static_cast<cache&>(a), static_cast<cache&>(b));\n                detail::adl_swap(a.used_, b.used_);\n            }\n\n            /// \\effects Allocates a new memory block.\n            /// It first uses a cache of previously deallocated blocks, if caching is enabled,\n            /// if it is empty, allocates a new one.\n            /// \\returns The new \\ref memory_block.\n            /// \\throws Anything thrown by the \\concept{concept_blockallocator,BlockAllocator} allocation function.\n            memory_block allocate_block()\n            {\n                if (!cache::take_from_cache(used_))\n                    used_.push(allocator_type::allocate_block());\n\n                auto block = used_.top();\n                detail::debug_fill_internal(block.memory, block.size, false);\n                return block;\n            }\n\n            /// \\returns The current memory block.\n            /// This is the memory block that will be deallocated by the next call to \\ref deallocate_block().\n            memory_block current_block() const noexcept\n            {\n                return used_.top();\n            }\n\n            /// \\effects Deallocates the current memory block.\n            /// The current memory block is the block on top of the stack of blocks.\n            /// If caching is enabled, it does not really deallocate it but puts it onto a cache for later use,\n            /// use \\ref shrink_to_fit() to purge that cache.\n            void deallocate_block() noexcept\n            {\n                auto block = used_.top();\n                detail::debug_fill_internal(block.memory, block.size, true);\n                this->do_deallocate_block(get_allocator(), used_);\n            }\n\n            /// \\returns If `ptr` is in memory owned by the arena.\n            bool owns(const void* ptr) const noexcept\n            {\n                return used_.owns(ptr);\n            }\n\n            /// \\effects Purges the cache of unused memory blocks by returning them.\n            /// The memory blocks will be deallocated in reversed order of allocation.\n            /// Does nothing if caching is disabled.\n            void shrink_to_fit() noexcept\n            {\n                this->do_shrink_to_fit(get_allocator());\n            }\n\n            /// \\returns The capacity of the arena, i.e. how many blocks are used and cached.\n            std::size_t capacity() const noexcept\n            {\n                return size() + cache_size();\n            }\n\n            /// \\returns The size of the cache, i.e. how many blocks can be allocated without allocation.\n            std::size_t cache_size() const noexcept\n            {\n                return cache::cache_size();\n            }\n\n            /// \\returns The size of the arena, i.e. how many blocks are in use.\n            /// It is always smaller or equal to the \\ref capacity().\n            std::size_t size() const noexcept\n            {\n                return used_.size();\n            }\n\n            bool empty() const noexcept\n            {\n                return size() == 0;\n            }\n\n            /// \\returns The size of the next memory block,\n            /// i.e. of the next call to \\ref allocate_block().\n            /// If there are blocks in the cache, returns size of the next one.\n            /// Otherwise forwards to the \\concept{concept_blockallocator,BlockAllocator} and subtracts an implementation offset.\n            std::size_t next_block_size() const noexcept\n            {\n                return cache::cache_empty() ? allocator_type::next_block_size() - detail::memory_block_stack::implementation_offset :\n                                             cache::cached_block_size();\n            }\n\n            /// \\returns A reference of the \\concept{concept_blockallocator,BlockAllocator} object.\n            /// \\requires It is undefined behavior to move this allocator out into another object.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n\n            DLContext device_context() const\n            {\n                return allocator_type::device_context();\n            }\n\n        private:\n            detail::memory_block_stack used_;\n        };\n\n        template <typename BlockAllocator>\n        using cached_block_stack = block_stack<BlockAllocator, true>;\n\n        template <typename BlockAllocator>\n        using uncached_block_stack = block_stack<BlockAllocator, false>;\n\n        template<bool Cached, typename BlockAllocator>\n        auto make_block_stack(BlockAllocator&& alloc)\n        {\n            static_assert(is_block_allocator<BlockAllocator>{}, \"should be a block allocator\");\n            return block_stack<BlockAllocator, Cached>(std::move(alloc));\n        }\n\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_MEMORY_ARENA_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/config.h",
    "content": "// MODIFICATION_MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n/// \\file\n/// Configuration macros.\n\n#ifndef TRTLAB_MEMORY_CONFIG_H_INCLUDED\n#define TRTLAB_MEMORY_CONFIG_H_INCLUDED\n\n#if !defined(DOXYGEN)\n#define TRTLAB_MEMORY_IMPL_IN_CONFIG_H\n#include \"config_impl.h\"\n#undef TRTLAB_MEMORY_IMPL_IN_CONFIG_H\n#endif\n\n// general compatibility headers\n// #include <foonathan/constexpr.hpp>\n// #include <foonathan/noexcept.hpp>\n// #include <foonathan/exception_support.hpp>\n// #include <foonathan/hosted_implementation.hpp>\n\n// log prefix\n#ifndef TRTLAB_MEMORY_LOG_PREFIX\n#define TRTLAB_MEMORY_LOG_PREFIX \"trtlab::memory\"\n#endif\n\n// version\n#define TRTLAB_MEMORY_VERSION                                                                   \\\n    (TRTLAB_MEMORY_VERSION_MAJOR * 100 + TRTLAB_MEMORY_VERSION_MINOR)\n\n// use this macro to mark implementation-defined types\n// gives it more semantics and useful with doxygen\n// add PREDEFINED: TRTLAB_IMPL_DEFINED():=implementation_defined\n#ifndef TRTLAB_IMPL_DEFINED\n#define TRTLAB_IMPL_DEFINED(...) __VA_ARGS__\n#endif\n\n// use this macro to mark base class which only purpose is EBO\n// gives it more semantics and useful with doxygen\n// add PREDEFINED: TRTLAB_EBO():=\n#ifndef TRTLAB_EBO\n#define TRTLAB_EBO(...) __VA_ARGS__\n#endif\n\n#ifndef TRTLAB_ALIAS_TEMPLATE\n// defines a template alias\n// usage:\n// template <typename T>\n// TRTLAB_ALIAS_TEMPLATE(bar, foo<T, int>);\n// useful for doxygen\n#ifdef DOXYGEN\n#define TRTLAB_ALIAS_TEMPLATE(Name, ...)                                                        \\\n    class Name : public __VA_ARGS__                                                                \\\n    {                                                                                              \\\n    }\n#else\n#define TRTLAB_ALIAS_TEMPLATE(Name, ...) using Name = __VA_ARGS__\n#endif\n#endif\n\n#ifdef DOXYGEN\n// dummy definitions of config macros for doxygen\n\n/// The major version number.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_VERSION_MAJOR 1\n\n/// The minor version number.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_VERSION_MINOR 1\n\n/// The total version number of the form \\c Mmm.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_VERSION                                                                   \\\n    (TRTLAB_MEMORY_VERSION_MAJOR * 100 + TRTLAB_MEMORY_VERSION_MINOR)\n\n/// Whether or not the allocation size will be checked,\n/// i.e. the \\ref bad_allocation_size thrown.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_CHECK_ALLOCATION_SIZE 1\n\n/// Whether or not the \\ref foonathan::memory::default_mutex will be \\c std::mutex or \\ref foonathan::memory::no_mutex.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_THREAD_SAFE_REFERENCE 1\n\n/// Whether or not internal assertions in the library are enabled.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_ASSERT 1\n\n/// Whether or not allocated memory will be filled with special values.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_FILL 1\n\n/// The size of the fence memory, it has no effect if \\ref TRTLAB_MEMORY_DEBUG_FILL is \\c false.\n/// \\note For most allocators, the actual value doesn't matter and they use appropriate defaults to ensure alignment etc.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_FENCE 1\n\n/// Whether or not leak checking is enabled.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_LEAK_CHECK 1\n\n/// Whether or not the deallocation functions will check for pointers that were never allocated by an allocator.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_POINTER_CHECK 1\n\n/// Whether or not the deallocation functions will check for double free errors.\n/// This option makes no sense if \\ref TRTLAB_MEMORY_DEBUG_POINTER_CHECK is \\c false.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK 1\n\n/// Whether or not everything is in namespace <tt>foonathan::memory</tt>.\n/// If \\c false, a namespace alias <tt>namespace memory = foonathan::memory</tt> is automatically inserted into each header,\n/// allowing to qualify everything with <tt>foonathan::</tt>.\n/// \\note This option breaks in combination with using <tt>using namespace foonathan;</tt>.\n/// \\ingroup memory core\n#define TRTLAB_MEMORY_NAMESPACE_PREFIX 1\n\n/// The mode of the automatic \\ref temporary_stack creation.\n/// Set to `2` to enable automatic lifetime management of the per-thread stack through nifty counter.\n/// Then all memory will be freed upon program termination automatically.\n/// Set to `1` to disable automatic lifetime managment of the per-thread stack,\n/// requires managing it through the \\ref temporary_stack_initializer.\n/// Set to `0` to disable the per-thread stack completely.\n/// \\ref get_temporary_stack() will abort the program upon call.\n/// \\ingroup memory allocator\n#define TRTLAB_MEMORY_TEMPORARY_STACK_MODE 2\n#endif\n\n#endif // TRTLAB_MEMORY_CONFIG_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/debugging.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DEBUGGING_H_INCLUDED\n#define TRTLAB_MEMORY_DEBUGGING_H_INCLUDED\n\n/// \\file\n/// Debugging facilities.\n\n#include \"config.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        struct allocator_info;\n\n        /// The magic values that are used for debug filling.\n        /// If \\ref TRTLAB_MEMORY_DEBUG_FILL is \\c true, memory will be filled to help detect use-after-free or missing initialization errors.\n        /// These are the constants for the different types.\n        /// \\ingroup memory core\n        enum class debug_magic : unsigned char\n        {\n            /// Marks internal memory used by the allocator - \"allocated block\".\n            internal_memory = 0xAB,\n            /// Marks internal memory currently not used by the allocator - \"freed block\".\n            internal_freed_memory = 0xFB,\n            /// Marks allocated, but not yet used memory - \"clean memory\".\n            new_memory = 0xCD,\n            /// Marks freed memory - \"dead memory\".\n            freed_memory = 0xDD,\n            /// Marks buffer memory used to ensure proper alignment.\n            /// This memory can also serve as \\ref debug_magic::fence_memory.\n            alignment_memory = 0xED,\n            /// Marks buffer memory used to protect against overflow - \"fence memory\".\n            /// The option \\ref TRTLAB_MEMORY_DEBUG_FENCE controls the size of a memory fence that will be placed before or after a memory block.\n            /// It helps catching buffer overflows.\n            fence_memory = 0xFD\n        };\n\n        /// The type of the handler called when a memory leak is detected.\n        /// Leak checking can be controlled via the option \\ref TRTLAB_MEMORY_DEBUG_LEAK_CHECK\n        /// and only affects calls through the \\ref allocator_traits, not direct calls.\n        /// The handler gets the \\ref allocator_info and the amount of memory leaked.\n        /// This can also be negative, meaning that more memory has been freed than allocated.\n        /// \\requiredbe A leak handler shall log the leak, abort the program, do nothing or anything else that seems appropriate.\n        /// It must not throw any exceptions since it is called in the cleanup process.\n        /// \\defaultbe On a hosted implementation it logs the leak to \\c stderr and returns, continuing execution.\n        /// On a freestanding implementation it does nothing.\n        /// \\ingroup memory core\n        using leak_handler = void (*)(const allocator_info& info, std::ptrdiff_t amount);\n\n        /// Exchanges the \\ref leak_handler.\n        /// \\effects Sets \\c h as the new \\ref leak_handler in an atomic operation.\n        /// A \\c nullptr sets the default \\ref leak_handler.\n        /// \\returns The previous \\ref leak_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        leak_handler set_leak_handler(leak_handler h);\n\n        /// Returns the \\ref leak_handler.\n        /// \\returns The current \\ref leak_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        leak_handler get_leak_handler();\n\n        /// The type of the handler called when an invalid pointer is passed to a deallocation function.\n        /// Pointer checking can be controlled via the options \\ref TRTLAB_MEMORY_DEBUG_POINTER_CHECK and \\ref TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK.\n        /// The handler gets the \\ref allocator_info and the invalid pointer.\n        /// \\requiredbe An invalid pointer handler shall terminate the program.\n        /// It must not throw any exceptions since it might be called in the cleanup process.\n        /// \\defaultbe On a hosted implementation it logs the information to \\c stderr and calls \\c std::abort().\n        /// On a freestanding implementation it only calls \\c std::abort().\n        /// \\ingroup memory core\n        using invalid_pointer_handler = void (*)(const allocator_info& info, const void* ptr);\n\n        /// Exchanges the \\ref invalid_pointer_handler.\n        /// \\effects Sets \\c h as the new \\ref invalid_pointer_handler in an atomic operation.\n        /// A \\c nullptr sets the default \\ref invalid_pointer_handler.\n        /// \\returns The previous \\ref invalid_pointer_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        invalid_pointer_handler set_invalid_pointer_handler(invalid_pointer_handler h);\n\n        /// Returns the \\ref invalid_pointer_handler.\n        /// \\returns The current \\ref invalid_pointer_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        invalid_pointer_handler get_invalid_pointer_handler();\n\n        /// The type of the handler called when a buffer under/overflow is detected.\n        /// If \\ref TRTLAB_MEMORY_DEBUG_FILL is \\c true and \\ref TRTLAB_MEMORY_DEBUG_FENCE has a non-zero value\n        /// the allocator classes check if a write into the fence has occured upon deallocation.\n        /// The handler gets the memory block belonging to the corrupted fence, its size and the exact address.\n        /// \\requiredbe A buffer overflow handler shall terminate the program.\n        /// It must not throw any exceptions since it me be called in the cleanup process.\n        /// \\defaultbe On a hosted implementation it logs the information to \\c stderr and calls \\c std::abort().\n        /// On a freestanding implementation it only calls \\c std::abort().\n        /// \\ingroup memory core\n        using buffer_overflow_handler = void (*)(const void* memory, std::size_t size,\n                                                 const void* write_ptr);\n\n        /// Exchanges the \\ref buffer_overflow_handler.\n        /// \\effects Sets \\c h as the new \\ref buffer_overflow_handler in an atomic operation.\n        /// A \\c nullptr sets the default \\ref buffer_overflow_handler.\n        /// \\returns The previous \\ref buffer_overflow_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        buffer_overflow_handler set_buffer_overflow_handler(buffer_overflow_handler h);\n\n        /// Returns the \\ref buffer_overflow_handler.\n        /// \\returns The current \\ref buffer_overflow_handler. This is never \\c nullptr.\n        /// \\ingroup memory core\n        buffer_overflow_handler get_buffer_overflow_handler();\n    }\n} // namespace trtlab::memory\n\n#endif // TRTLAB_MEMORY_DEBUGGING_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/deleter.h",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DELETER_H_INCLUDED\n#define TRTLAB_MEMORY_DELETER_H_INCLUDED\n\n/// \\file\n/// \\c Deleter classes using a \\concept{concept_rawallocator,RawAllocator}.\n\n#include <type_traits>\n\n#include \"allocator_storage.h\"\n#include \"config.h\"\n#include \"threading.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        /// A deleter class that deallocates the memory through a specified \\concept{concept_rawallocator,RawAllocator}.\n        ///\n        /// It deallocates memory for a specified type but does not call its destructors.\n        /// Only a reference to the \\c RawAllocator is stored, access to it is synchronized by a given \\c Mutex which defaults to \\ref default_mutex.\n        /// \\ingroup memory adapter\n        template <typename Type, class RawAllocator>\n        class allocator_deallocator : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n            static_assert(!std::is_abstract<Type>::value,\n                          \"use allocator_polymorphic_deallocator for storing base classes\");\n\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = Type;\n\n            /// \\effects Creates it without any associated allocator.\n            /// The deallocator must not be used if that is the case.\n            /// \\notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.\n            allocator_deallocator() noexcept = default;\n\n            /// \\effects Creates it by passing it an \\ref allocator_reference.\n            /// It will store the reference to it and uses the referenced allocator object for the deallocation.\n            allocator_deallocator(allocator_reference<RawAllocator> alloc) noexcept\n            : allocator_reference<RawAllocator>(alloc)\n            {\n            }\n\n            /// \\effects Deallocates the memory given to it.\n            /// Calls \\c deallocate_node(pointer, sizeof(value_type), alignof(value_type)) on the referenced allocator object.\n            /// \\requires The deallocator must not have been created by the default constructor.\n            void operator()(value_type* pointer) noexcept\n            {\n                this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            /// \\requires The deallocator must not be created by the default constructor.\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n        };\n\n        /// Specialization of \\ref allocator_deallocator for array types.\n        /// Otherwise the same behavior.\n        /// \\ingroup memory adapter\n        template <typename Type, class RawAllocator>\n        class allocator_deallocator<Type[], RawAllocator>\n        : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n            static_assert(!std::is_abstract<Type>::value, \"must not create polymorphic arrays\");\n\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = Type;;\n\n            /// \\effects Creates it without any associated allocator.\n            /// The deallocator must not be used if that is the case.\n            /// \\notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.\n            allocator_deallocator() noexcept : size_(0u) {}\n\n            /// \\effects Creates it by passing it an \\ref allocator_reference and the size of the array that will be deallocated.\n            /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.\n            allocator_deallocator(allocator_reference<RawAllocator> alloc, std::size_t size) noexcept\n            : allocator_reference<RawAllocator>(alloc), size_(size) {}\n\n            /// \\effects Deallocates the memory given to it.\n            /// Calls \\c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))\n            /// on the referenced allocator object with the size given in the constructor.\n            /// \\requires The deallocator must not have been created by the default constructor.\n            void operator()(value_type* pointer) noexcept\n            {\n                this->deallocate_array(pointer, size_, sizeof(value_type),\n                                       alignof(value_type));\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            /// \\requires The deallocator must not have been created by the default constructor.\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n\n            /// \\returns The size of the array that will be deallocated.\n            /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.\n            std::size_t array_size() const noexcept\n            {\n                return size_;\n            }\n\n        private:\n            std::size_t size_;\n        };\n\n        /// A deleter class that deallocates the memory of a derived type through a specified \\concept{concept_rawallocator,RawAllocator}.\n        ///\n        /// It can only be created from a \\ref allocator_deallocator and thus must only be used for smart pointers initialized by derived-to-base conversion of the pointer.\n        /// \\ingroup memory adapter\n        template <typename BaseType, class RawAllocator>\n        class allocator_polymorphic_deallocator\n        : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = BaseType;\n\n            /// \\effects Creates it from a deallocator for a derived type.\n            /// It will deallocate the memory as if done by the derived type.\n            template <typename T, TRTLAB_REQUIRES((std::is_base_of<BaseType, T>::value))>\n            allocator_polymorphic_deallocator(allocator_deallocator<T, RawAllocator> dealloc)\n            : allocator_reference<RawAllocator>(dealloc.get_allocator()),\n              derived_size_(sizeof(T)),\n              derived_alignment_(alignof(T))\n            {\n            }\n\n            /// \\effects Deallocates the memory given to it.\n            /// Calls \\c deallocate_node(pointer, size, alignment) on the referenced allocator object,\n            /// where \\c size and \\c alignment are the values of the type it was created with.\n            void operator()(value_type* pointer) noexcept\n            {\n                this->deallocate_node(pointer, derived_size_, derived_alignment_);\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n\n        private:\n            std::size_t derived_size_, derived_alignment_;\n        };\n\n        /// Similar to \\ref allocator_deallocator but calls the destructors of the object.\n        /// Otherwise behaves the same.\n        /// \\ingroup memory adapter\n        template <typename Type, class RawAllocator>\n        class allocator_deleter : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n            static_assert(!std::is_abstract<Type>::value,\n                          \"use allocator_polymorphic_deleter for storing base classes\");\n\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = Type;\n\n            /// \\effects Creates it without any associated allocator.\n            /// The deleter must not be used if that is the case.\n            /// \\notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.\n            allocator_deleter() noexcept = default;\n\n            /// \\effects Creates it by passing it an \\ref allocator_reference.\n            /// It will store the reference to it and uses the referenced allocator object for the deallocation.\n            allocator_deleter(allocator_reference<RawAllocator> alloc) noexcept\n            : allocator_reference<RawAllocator>(alloc)\n            {\n            }\n\n            /// \\effects Calls the destructor and deallocates the memory given to it.\n            /// Calls \\c deallocate_node(pointer, sizeof(value_type), alignof(value_type))\n            /// on the referenced allocator object for the deallocation.\n            /// \\requires The deleter must not have been created by the default constructor.\n            void operator()(value_type* pointer) noexcept\n            {\n                pointer->~value_type();\n                this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n        };\n\n        /// Specialization of \\ref allocator_deleter for array types.\n        /// Otherwise the same behavior.\n        /// \\ingroup memory adapter\n        template <typename Type, class RawAllocator>\n        class allocator_deleter<Type[], RawAllocator>\n        : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n            static_assert(!std::is_abstract<Type>::value, \"must not create polymorphic arrays\");\n\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = Type;;\n\n            /// \\effects Creates it without any associated allocator.\n            /// The deleter must not be used if that is the case.\n            /// \\notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.\n            allocator_deleter() noexcept : size_(0u) {}\n\n            /// \\effects Creates it by passing it an \\ref allocator_reference and the size of the array that will be deallocated.\n            /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.\n            allocator_deleter(allocator_reference<RawAllocator> alloc, std::size_t size) noexcept\n            : allocator_reference<RawAllocator>(alloc), size_(size) {}\n\n            /// \\effects Calls the destructors and deallocates the memory given to it.\n            /// Calls \\c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))\n            /// on the referenced allocator object with the size given in the constructor for the deallocation.\n            /// \\requires The deleter must not have been created by the default constructor.\n            void operator()(value_type* pointer) noexcept\n            {\n                for (auto cur = pointer; cur != pointer + size_; ++cur)\n                    cur->~value_type();\n                this->deallocate_array(pointer, size_, sizeof(value_type),\n                                       alignof(value_type));\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            /// \\requires The deleter must not be created by the default constructor.\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n\n            /// \\returns The size of the array that will be deallocated.\n            /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.\n            std::size_t array_size() const noexcept\n            {\n                return size_;\n            }\n\n        private:\n            std::size_t size_;\n        };\n\n        /// Similar to \\ref allocator_polymorphic_deallocator but calls the destructors of the object.\n        /// Otherwise behaves the same.\n        /// \\note It has a relatively high space overhead, so only use it if you have to.\n        /// \\ingroup memory adapter\n        template <typename BaseType, class RawAllocator>\n        class allocator_polymorphic_deleter : TRTLAB_EBO(allocator_reference<RawAllocator>)\n        {\n        public:\n            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;\n            using value_type     = BaseType;\n\n            /// \\effects Creates it from a deleter for a derived type.\n            /// It will deallocate the memory as if done by the derived type.\n            template <typename T, TRTLAB_REQUIRES((std::is_base_of<BaseType, T>::value))>\n            allocator_polymorphic_deleter(allocator_deleter<T, RawAllocator> deleter)\n            : allocator_reference<RawAllocator>(deleter.get_allocator()),\n              derived_size_(sizeof(T)),\n              derived_alignment_(alignof(T))\n            {\n                TRTLAB_MEMORY_ASSERT(std::size_t(derived_size_) == sizeof(T) && std::size_t(derived_alignment_) == alignof(T));\n            }\n\n            /// \\effects Deallocates the memory given to it.\n            /// Calls \\c deallocate_node(pointer, size, alignment) on the referenced allocator object,\n            /// where \\c size and \\c alignment are the values of the type it was created with.\n            void operator()(value_type* pointer) noexcept\n            {\n                pointer->~value_type();\n                this->deallocate_node(pointer, derived_size_, derived_alignment_);\n            }\n\n            /// \\returns The reference to the allocator.\n            /// It has the same type as the call to \\ref allocator_reference::get_allocator().\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())\n            {\n                return this->allocator_reference<allocator_type>::get_allocator();\n            }\n\n        private:\n            unsigned short derived_size_, derived_alignment_; // use unsigned short here to save space\n        };\n    } // namespace memory\n} // namespace trtlab\n\n#endif //TRTLAB_MEMORY_DELETER_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/descriptor.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstdlib>\n#include <memory>\n\n#include <dlpack/dlpack.h>\n#include <glog/logging.h>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        struct iallocator;\n\n        class descriptor final\n        {\n            using storage_type = std::shared_ptr<iallocator>;\n\n        public:\n            descriptor();\n            descriptor(std::shared_ptr<iallocator> alloc, std::size_t size, std::size_t alignment);\n\n            descriptor(const descriptor& other) noexcept = delete;\n            descriptor& operator=(const descriptor& other) noexcept = delete;\n\n            descriptor(descriptor&& other) noexcept\n            : m_storage(std::exchange(other.m_storage, nullptr)),\n              m_size(std::exchange(other.m_size, 0u)),\n              m_alignment(std::exchange(other.m_alignment, 0u)),\n              m_data(std::exchange(other.m_data, nullptr))\n            {\n            }\n\n            descriptor& operator=(descriptor&& other) noexcept\n            {\n                m_data      = std::exchange(other.m_data, nullptr);\n                m_size      = std::exchange(other.m_size, 0u);\n                m_alignment = std::exchange(other.m_alignment, 0u);\n                m_storage   = std::exchange(other.m_storage, nullptr);\n                return *this;\n            }\n\n            ~descriptor()\n            {\n                release();\n            }\n\n            void* data() noexcept\n            {\n                return m_data;\n            }\n            const void* data() const noexcept\n            {\n                return m_data;\n            }\n            std::size_t size() const noexcept\n            {\n                return m_size;\n            };\n\n            DLContext device_context() const;\n\n            void release();\n\n            std::shared_ptr<descriptor> make_shared();\n\n        private:\n            storage_type m_storage;\n            std::size_t  m_size;\n            std::size_t  m_alignment;\n            void*        m_data;\n\n            friend std::ostream& operator<<(std::ostream& os, const descriptor& md);\n        };\n\n        // clang-format off\n        struct iallocator\n        {\n            virtual ~iallocator() = default;\n\n            inline void* allocate(std::size_t size, std::size_t alignment = 0UL) { return do_allocate(size, alignment); }\n            inline void deallocate(void* ptr, std::size_t size = 0UL, std::size_t alignment = 0UL) noexcept { do_deallocate(ptr, size, alignment); }\n            inline descriptor allocate_descriptor(std::size_t size, std::size_t alignment = 0UL) { return do_allocate_descriptor(size, alignment); }\n\n            inline std::size_t max_alignment() const { return do_max_alignment(); }\n            inline std::size_t min_alignment() const { return do_min_alignment(); }\n            inline std::size_t max_size() const { return do_max_size(); }\n\n            inline DLContext device_context() const { return do_device_context();}\n\n        private:\n            virtual void*       do_allocate(std::size_t, std::size_t)                   = 0;\n            virtual void        do_deallocate(void*, std::size_t, std::size_t) noexcept = 0;\n            virtual descriptor  do_allocate_descriptor(std::size_t, std::size_t)        = 0;\n            virtual std::size_t do_min_alignment() const                                = 0;\n            virtual std::size_t do_max_alignment() const                                = 0;\n            virtual std::size_t do_max_size() const                                     = 0;\n            virtual DLContext   do_device_context() const                               = 0;\n        };\n        // clang-format on \n\n        std::ostream& operator<<(std::ostream& os, const descriptor& md);\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/assert.h",
    "content": "// MODIFICATION_MESSAGE\n\n// Modification notes:\n// - Replaced in-library logging feature with glog\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAIL_ASSERT_H_INCLUDED\n#define TRTLAB_MEMORY_DETAIL_ASSERT_H_INCLUDED\n\n#include <cstdlib>\n\n#include \"../config.h\"\n\n#include <glog/logging.h>\n\n#if defined(TRTLAB_MEMORY_ASSERT)\n#define TRTLAB_MEMORY_ASSERT(Expr) CHECK(Expr)\n#define TRTLAB_MEMORY_ASSERT_MSG(Expr, Msg) CHECK(Expr) << Msg\n#define TRTLAB_MEMORY_UNREACHABLE(Msg) LOG(FATAL) << Msg\n#define TRTLAB_MEMORY_WARNING(Msg) LOG(WARNING) << Msg\n#else\n#define TRTLAB_MEMORY_ASSERT(Expr)\n#define TRTLAB_MEMORY_ASSERT_MSG(Expr, Msg)\n#define TRTLAB_MEMORY_UNREACHABLE(Msg) std::abort()\n#define TRTLAB_MEMORY_WARNING(Msg)\n#endif\n\n#endif // TRTLAB_MEMORY_DETAIL_ASSERT_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/block_list.h",
    "content": "#ifndef TRTLAB_MEMORY_DETAILL_BLOCK_LIST_H_INCLUDED\n#define TRTLAB_MEMORY_DETAILL_BLOCK_LIST_H_INCLUDED\n\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n\n#include \"../align.h\"\n#include \"utility.h\"\n#include \"../config.h\"\n#include \"../memory_block.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            // stores free blocks for a memory pool\n            // memory blocks are fragmented and stored in a list\n            // only accessible one block at a time\n            // designed for large block which themselves will be uses as backing stores\n            class block_list\n            {\n            protected:\n                struct node\n                {\n                    std::size_t size;\n                    node*       next;\n                };\n\n            public:\n                // minimum element size\n                static constexpr auto min_element_size = sizeof(node);\n                // alignment\n                static constexpr auto min_element_alignment = alignof(node);\n\n                //=== constructor ===//\n                block_list() noexcept;\n\n                block_list(block_list&& other) noexcept;\n                ~block_list() noexcept = default;\n\n                block_list& operator=(block_list&& other) noexcept;\n\n                friend void swap(block_list& a, block_list& b) noexcept;\n\n                //=== insert/allocation/deallocation ===//\n                // inserts a new memory block, by splitting it up and setting the links\n                // does not own memory!\n                // mem must be aligned for alignment()\n                // pre: size != 0\n                void insert(memory_block&&) noexcept;\n\n                // returns a single block from the list\n                // pre: !empty()\n                memory_block allocate() noexcept;\n\n                // deallocates a single block\n                void deallocate(memory_block&&) noexcept;\n\n                std::size_t next_block_size() const noexcept\n                {\n                    return (empty() ? 0u : first_->size);\n                }\n\n                // number of nodes remaining\n                std::size_t size() const noexcept\n                {\n                    return capacity_;\n                }\n\n                bool empty() const noexcept\n                {\n                    return first_ == nullptr;\n                }\n\n            private:\n                node*       first_;\n                std::size_t capacity_;\n            };\n\n            // unlike block_list; block_list_oob stores the nodes in a std::deque\n            // instead of as part of the allocations\n            // use block_list_oob when tracking blocks whose memory the cpu can not\n            // directly read/write, e.g. gpu memory\n            class block_list_oob\n            {\n            public:\n                // minimum element size\n                static constexpr auto min_element_size = sizeof(long);\n                // alignment\n                static constexpr auto min_element_alignment = alignof(long);\n\n                //=== constructor ===//\n                block_list_oob() noexcept;\n\n                block_list_oob(block_list_oob&& other) noexcept;\n                ~block_list_oob() noexcept = default;\n\n                block_list_oob& operator=(block_list_oob&& other) noexcept;\n\n                friend void swap(block_list_oob& a, block_list_oob& b) noexcept;\n\n                //=== insert/allocation/deallocation ===//\n                // inserts a new memory block, by splitting it up and setting the links\n                // does not own memory!\n                // mem must be aligned for alignment()\n                // pre: size != 0\n                void insert(memory_block&&) noexcept;\n\n                // returns a single block from the list\n                // pre: !empty()\n                memory_block allocate() noexcept;\n\n                // deallocates a single block\n                void deallocate(memory_block&&) noexcept;\n\n                std::size_t next_block_size() const noexcept\n                {\n                    return (empty() ? 0u : nodes.front().size);\n                }\n\n                // number of nodes remaining\n                std::size_t size() const noexcept\n                {\n                    return nodes.size();\n                }\n\n                bool empty() const noexcept\n                {\n                    return nodes.empty();\n                }\n\n            private:\n                std::deque<memory_block> nodes;\n            };\n\n            void swap(block_list& a, block_list& b) noexcept;\n\n            void swap(block_list_oob& a, block_list_oob& b) noexcept;\n            /*\n            // stores free blocks for a memory pool\n            // memory blocks are fragmented and stored in a list\n            // only accessible one block at a time\n            // designed for large block which themselves will be uses as backing stores\n            class sorted_block_list\n            {\n                struct block_node : public memory_block\n                {\n                    block_node* next;\n                };\n\n            public:\n                // minimum element size\n                static constexpr auto min_element_size = sizeof(char*);\n                // alignment\n                static constexpr auto min_element_alignment = alignof(char*);\n\n                //=== constructor ===//\n                sorted_block_list() noexcept;\n\n                // calls other constructor plus insert\n                sorted_block_list(const memory_block& block) noexcept;\n                sorted_block_list(void* mem, std::size_t size) noexcept;\n\n                sorted_block_list(sorted_block_list&& other) noexcept;\n                ~sorted_block_list() noexcept = default;\n\n                sorted_block_list& operator=(sorted_block_list&& other) noexcept;\n\n                friend void swap(sorted_block_list& a, sorted_block_list& b) noexcept;\n\n                //=== insert/allocation/deallocation ===//\n                // inserts a new memory block, by splitting it up and setting the links\n                // does not own memory!\n                // mem must be aligned for alignment()\n                // pre: size != 0\n                void insert(const memory_block& block) noexcept;\n                void insert(void* mem, std::size_t size) noexcept;\n\n                // returns a single block from the list\n                // pre: !empty()\n                memory_block allocate() noexcept;\n\n                // deallocates a single block\n                void deallocate(const memory_block&) noexcept;\n\n                // size of next block in the list\n                // will be the large available block\n                std::size_t next_block_size() noexcept;\n\n                // alignment of all nodes\n                std::size_t alignment() const noexcept;\n\n                // number of nodes remaining\n                std::size_t capacity() const noexcept\n                {\n                    return capacity_;\n                }\n\n                bool empty() const noexcept\n                {\n                    return first_ == nullptr;\n                }\n\n            private:\n                void insert_impl(void* mem, std::size_t size) noexcept;\n\n                block_node* first_;\n                std::size_t capacity_;\n            };\n\n            void swap(sorted_block_list& a, sorted_block_list& b) noexcept;\n*/\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab\n\n#endif"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/container_node_sizes.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAIL_CONTAINER_NODE_SIZES_H_INCLUDED\n#define TRTLAB_MEMORY_DETAIL_CONTAINER_NODE_SIZES_H_INCLUDED\n\n#include \"container_node_sizes_impl.h\"\n\n#endif //TRTLAB_MEMORY_DETAIL_CONTAINER_NODE_SIZES_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/debug_helpers.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DEBUG_HELPERS_H_INCLUDED\n#define TRTLAB_MEMORY_DEBUG_HELPERS_H_INCLUDED\n\n#include <atomic>\n#include <type_traits>\n\n#include \"../config.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        enum class debug_magic : unsigned char;\n        struct allocator_info;\n\n        namespace detail\n        {\n            using debug_fill_enabled = std::integral_constant<bool, TRTLAB_MEMORY_DEBUG_FILL>;\n            constexpr std::size_t debug_fence_size =\n                TRTLAB_MEMORY_DEBUG_FILL ? TRTLAB_MEMORY_DEBUG_FENCE : 0u;\n\n#if TRTLAB_MEMORY_DEBUG_FILL\n            #error \"boo\"\n            // fills size bytes of memory with debug_magic\n            void debug_fill(void* memory, std::size_t size, debug_magic m) noexcept;\n\n            // returns nullptr if memory is filled with debug_magic\n            // else returns pointer to mismatched byte\n            void* debug_is_filled(void* memory, std::size_t size, debug_magic m) noexcept;\n\n            // fills fence, new and fence\n            // returns after fence\n            void* debug_fill_new(void* memory, std::size_t node_size,\n                                 std::size_t fence_size = debug_fence_size) noexcept;\n\n            // fills free memory and returns memory starting at fence\n            void* debug_fill_free(void* memory, std::size_t node_size,\n                                  std::size_t fence_size = debug_fence_size) noexcept;\n\n            // fills internal memory\n            void debug_fill_internal(void* memory, std::size_t size, bool free) noexcept;\n#else\n            inline void debug_fill(void*, std::size_t, debug_magic) noexcept\n            {\n            }\n\n            inline void* debug_is_filled(void*, std::size_t, debug_magic) noexcept\n            {\n                return nullptr;\n            }\n\n            inline void* debug_fill_new(void* memory, std::size_t, std::size_t) noexcept\n            {\n                return memory;\n            }\n\n            inline void* debug_fill_free(void* memory, std::size_t, std::size_t) noexcept\n            {\n                return static_cast<char*>(memory);\n            }\n\n            inline void debug_fill_internal(void*, std::size_t, bool) noexcept\n            {\n            }\n#endif\n\n            void debug_handle_invalid_ptr(const allocator_info& info, void* ptr);\n\n            // validates given ptr by evaluating the Functor\n            // if the Functor returns false, calls the debug_leak_checker\n            // note: ptr is just used as the information passed to the invalid ptr handler\n            template <class Functor>\n            void debug_check_pointer(Functor condition, const allocator_info& info, void* ptr)\n            {\n#if TRTLAB_MEMORY_DEBUG_POINTER_CHECK\n                if (!condition())\n                    debug_handle_invalid_ptr(info, ptr);\n#else\n                (void)ptr;\n                (void)condition;\n                (void)info;\n#endif\n            }\n\n            // validates ptr by using a more expensive double-dealloc check\n            template <class Functor>\n            void debug_check_double_dealloc(Functor condition, const allocator_info& info,\n                                            void* ptr)\n            {\n#if TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK\n                debug_check_pointer(condition, info, ptr);\n#else\n                (void)condition;\n                (void)info;\n                (void)ptr;\n#endif\n            }\n\n            void debug_handle_memory_leak(const allocator_info& info, std::ptrdiff_t amount);\n\n            // does no leak checking, null overhead\n            template <class Handler>\n            class no_leak_checker\n            {\n            public:\n                no_leak_checker() noexcept\n                {\n                }\n                no_leak_checker(no_leak_checker&&) noexcept\n                {\n                }\n                ~no_leak_checker() noexcept\n                {\n                }\n\n                no_leak_checker& operator=(no_leak_checker&&) noexcept\n                {\n                    return *this;\n                }\n\n                void on_allocate(std::size_t) noexcept\n                {\n                }\n                void on_deallocate(std::size_t) noexcept\n                {\n                }\n            };\n\n            // does leak checking per-object\n            // leak is detected upon destructor\n            template <class Handler>\n            class object_leak_checker : Handler\n            {\n            public:\n                object_leak_checker() noexcept : allocated_(0)\n                {\n                }\n\n                object_leak_checker(object_leak_checker&& other) noexcept\n                    : allocated_(other.allocated_)\n                {\n                    other.allocated_ = 0;\n                }\n\n                ~object_leak_checker() noexcept\n                {\n                    if (allocated_ != 0)\n                        this->operator()(allocated_);\n                }\n\n                object_leak_checker& operator=(object_leak_checker&& other) noexcept\n                {\n                    allocated_       = other.allocated_;\n                    other.allocated_ = 0;\n                    return *this;\n                }\n\n                void on_allocate(std::size_t size) noexcept\n                {\n                    allocated_ += std::ptrdiff_t(size);\n                }\n\n                void on_deallocate(std::size_t size) noexcept\n                {\n                    allocated_ -= std::ptrdiff_t(size);\n                }\n\n            private:\n                std::ptrdiff_t allocated_;\n            };\n\n            // does leak checking on a global basis\n            // call macro TRTLAB_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name) in the header\n            // when last counter gets destroyed, leak is detected\n            template <class Handler>\n            class global_leak_checker_impl\n            {\n            public:\n                struct counter : Handler\n                {\n                    counter()\n                    {\n                        ++no_counter_objects_;\n                    }\n\n                    ~counter()\n                    {\n                        --no_counter_objects_;\n                        if (no_counter_objects_ == 0u && allocated_ != 0u)\n                            this->operator()(allocated_);\n                    }\n                };\n\n                global_leak_checker_impl() noexcept\n                {\n                }\n                global_leak_checker_impl(global_leak_checker_impl&&) noexcept\n                {\n                }\n                ~global_leak_checker_impl() noexcept\n                {\n                }\n\n                global_leak_checker_impl& operator=(global_leak_checker_impl&&) noexcept\n                {\n                    return *this;\n                }\n\n                void on_allocate(std::size_t size) noexcept\n                {\n                    allocated_ += std::ptrdiff_t(size);\n                }\n\n                void on_deallocate(std::size_t size) noexcept\n                {\n                    allocated_ -= std::ptrdiff_t(size);\n                }\n\n            private:\n                static std::atomic<std::size_t>    no_counter_objects_;\n                static std::atomic<std::ptrdiff_t> allocated_;\n            };\n\n            template <class Handler>\n            std::atomic<std::size_t> global_leak_checker_impl<Handler>::no_counter_objects_(0u);\n\n            template <class Handler>\n            std::atomic<std::ptrdiff_t> global_leak_checker_impl<Handler>::allocated_(0);\n\n#if TRTLAB_MEMORY_DEBUG_LEAK_CHECK\n            template <class Handler>\n            using global_leak_checker = global_leak_checker_impl<Handler>;\n\n#define TRTLAB_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)                                    \\\n    static foonathan::memory::detail::global_leak_checker<handler>::counter var_name;\n#else\n            template <class Handler>\n            using global_leak_checker = no_leak_checker<int>; // only one instantiation\n\n#define TRTLAB_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)\n#endif\n\n#if TRTLAB_MEMORY_DEBUG_LEAK_CHECK\n            template <class Handler>\n            using default_leak_checker = object_leak_checker<Handler>;\n#else\n            template <class Handler>\n            using default_leak_checker = no_leak_checker<Handler>;\n#endif\n        } // namespace detail\n    }\n} // namespace trtlab::memory\n\n#endif // TRTLAB_MEMORY_DEBUG_HELPERS_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/free_list.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAILL_FREE_LIST_H_INCLUDED\n#define TRTLAB_MEMORY_DETAILL_FREE_LIST_H_INCLUDED\n\n#include <cstddef>\n#include <cstdint>\n\n#include \"../align.h\"\n#include \"utility.h\"\n#include \"../config.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            // stores free blocks for a memory pool\n            // memory blocks are fragmented and stored in a list\n            // debug: fills memory and uses a bigger node_size for fence memory\n            class free_memory_list\n            {\n            public:\n                // minimum element size\n                static constexpr auto min_element_size = sizeof(char*);\n                // alignment\n                static constexpr auto min_element_alignment = alignof(char*);\n\n                //=== constructor ===//\n                free_memory_list(std::size_t node_size) noexcept;\n\n                // calls other constructor plus insert\n                free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept;\n\n                free_memory_list(free_memory_list&& other) noexcept;\n                ~free_memory_list() noexcept = default;\n\n                free_memory_list& operator=(free_memory_list&& other) noexcept;\n\n                friend void swap(free_memory_list& a, free_memory_list& b) noexcept;\n\n                //=== insert/allocation/deallocation ===//\n                // inserts a new memory block, by splitting it up and setting the links\n                // does not own memory!\n                // mem must be aligned for alignment()\n                // pre: size != 0\n                void insert(void* mem, std::size_t size) noexcept;\n\n                // returns the usable size\n                // i.e. how many memory will be actually inserted and usable on a call to insert()\n                std::size_t usable_size(std::size_t size) const noexcept\n                {\n                    return size;\n                }\n\n                // returns a single block from the list\n                // pre: !empty()\n                void* allocate() noexcept;\n\n                // returns a memory block big enough for n bytes\n                // might fail even if capacity is sufficient\n                void* allocate(std::size_t n) noexcept;\n\n                // deallocates a single block\n                void deallocate(void* ptr) noexcept;\n\n                // deallocates multiple blocks with n bytes total\n                void deallocate(void* ptr, std::size_t n) noexcept;\n\n                //=== getter ===//\n                std::size_t node_size() const noexcept\n                {\n                    return node_size_;\n                }\n\n                // alignment of all nodes\n                std::size_t alignment() const noexcept\n                {\n                    return alignment_;\n                }\n\n                // number of nodes remaining\n                std::size_t capacity() const noexcept\n                {\n                    return capacity_;\n                }\n\n                bool empty() const noexcept\n                {\n                    return first_ == nullptr;\n                }\n\n            private:\n                std::size_t fence_size() const noexcept\n                {\n                #if TRTLAB_MEMORY_DEBUG_FILL\n                    #error \"this is broken; disable debug fill\"\n                    return debug_fence_size ? node_size_ : 0u;\n                #else\n                    return 0u;\n                #endif\n                }\n\n                //std::size_t fence_size() const noexcept;\n                void insert_impl(void* mem, std::size_t size) noexcept;\n\n                char*       first_;\n                std::size_t node_size_, capacity_, alignment_;\n            };\n\n            void swap(free_memory_list& a, free_memory_list& b) noexcept;\n\n            // same as above but keeps the nodes ordered\n            // this allows array allocations, that is, consecutive nodes\n            // debug: fills memory and uses a bigger node_size for fence memory\n            class ordered_free_memory_list\n            {\n            public:\n                // minimum element size\n                static constexpr auto min_element_size = sizeof(char*);\n                // alignment\n                static constexpr auto min_element_alignment = alignof(char*);\n\n                //=== constructor ===//\n                ordered_free_memory_list(std::size_t node_size) noexcept;\n\n                ordered_free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept : ordered_free_memory_list(node_size)\n                {\n                    insert(mem, size);\n                }\n\n                ordered_free_memory_list(ordered_free_memory_list&& other) noexcept;\n\n                ~ordered_free_memory_list() noexcept = default;\n\n                ordered_free_memory_list& operator=(ordered_free_memory_list&& other) noexcept\n                {\n                    ordered_free_memory_list tmp(detail::move(other));\n                    swap(*this, tmp);\n                    return *this;\n                }\n\n                friend void swap(ordered_free_memory_list& a, ordered_free_memory_list& b) noexcept;\n\n                //=== insert/allocation/deallocation ===//\n                // inserts a new memory block, by splitting it up and setting the links\n                // does not own memory!\n                // mem must be aligned for alignment()\n                // pre: size != 0\n                void insert(void* mem, std::size_t size) noexcept;\n\n                // returns the usable size\n                // i.e. how many memory will be actually inserted and usable on a call to insert()\n                std::size_t usable_size(std::size_t size) const noexcept\n                {\n                    return size;\n                }\n\n                // returns a single block from the list\n                // pre: !empty()\n                void* allocate() noexcept;\n\n                // returns a memory block big enough for n bytes (!, not nodes)\n                // might fail even if capacity is sufficient\n                void* allocate(std::size_t n) noexcept;\n\n                // deallocates a single block\n                void deallocate(void* ptr) noexcept;\n\n                // deallocates multiple blocks with n bytes total\n                void deallocate(void* ptr, std::size_t n) noexcept;\n\n                //=== getter ===//\n                std::size_t node_size() const noexcept\n                {\n                    return node_size_;\n                }\n\n                // alignment of all nodes\n                std::size_t alignment() const noexcept;\n\n                // number of nodes remaining\n                std::size_t capacity() const noexcept\n                {\n                    return capacity_;\n                }\n\n                bool empty() const noexcept\n                {\n                    return capacity_ == 0u;\n                }\n\n            private:\n                std::size_t fence_size() const noexcept;\n\n                // returns previous pointer\n                char* insert_impl(void* mem, std::size_t size) noexcept;\n\n                char* begin_node() noexcept;\n                char* end_node() noexcept;\n\n                std::uintptr_t begin_proxy_, end_proxy_;\n                std::size_t    node_size_, capacity_;\n                char *         last_dealloc_, *last_dealloc_prev_;\n            };\n\n            void swap(ordered_free_memory_list& a, ordered_free_memory_list& b) noexcept;\n\n#if TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECk\n            // use ordered version to allow pointer check\n            using node_free_memory_list  = ordered_free_memory_list;\n            using array_free_memory_list = ordered_free_memory_list;\n#else\n            using node_free_memory_list = free_memory_list;\n            using array_free_memory_list = ordered_free_memory_list;\n#endif\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_DETAILL_FREE_LIST_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/memory_stack.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAIL_MEMORY_STACK_H_INCLUDED\n#define TRTLAB_MEMORY_DETAIL_MEMORY_STACK_H_INCLUDED\n\n#include <cstddef>\n\n#include \"../config.h\"\n#include \"../align.h\"\n#include \"debug_helpers.h\"\n#include \"../debugging.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            // simple memory stack implementation that does not support growing\n            class fixed_memory_stack\n            {\n            public:\n                fixed_memory_stack() noexcept : fixed_memory_stack(nullptr)\n                {\n                }\n\n                // gives it the current pointer, the end pointer must be maintained seperataly\n                explicit fixed_memory_stack(void* memory) noexcept\n                    : cur_(static_cast<char*>(memory))\n                {\n                }\n\n                fixed_memory_stack(fixed_memory_stack&& other) noexcept : cur_(other.cur_)\n                {\n                    other.cur_ = nullptr;\n                }\n\n                ~fixed_memory_stack() noexcept = default;\n\n                fixed_memory_stack& operator=(fixed_memory_stack&& other) noexcept\n                {\n                    cur_       = other.cur_;\n                    other.cur_ = nullptr;\n                    return *this;\n                }\n\n                // bumps the top pointer without filling it\n                void bump(std::size_t offset) noexcept\n                {\n                    cur_ += offset;\n                }\n\n                // bumps the top pointer by offset and fills\n                void bump(std::size_t offset, debug_magic m) noexcept\n                {\n                    detail::debug_fill(cur_, offset, m);\n                    bump(offset);\n                }\n\n                // same as bump(offset, m) but returns old value\n                void* bump_return(std::size_t offset,\n                                  debug_magic m = debug_magic::new_memory) noexcept\n                {\n                    auto memory = cur_;\n                    detail::debug_fill(memory, offset, m);\n                    cur_ += offset;\n                    return memory;\n                }\n\n                // allocates memory by advancing the stack, returns nullptr if insufficient\n                // debug: mark memory as new_memory, put fence in front and back\n                void* allocate(const char* end, std::size_t size, std::size_t alignment,\n                               std::size_t fence_size = debug_fence_size) noexcept\n                {\n                    if (cur_ == nullptr)\n                        return nullptr;\n\n                    auto remaining = std::size_t(end - cur_);\n                    auto offset    = align_offset(cur_ + fence_size, alignment);\n                    if (fence_size + offset + size + fence_size > remaining)\n                        return nullptr;\n\n                    return allocate_unchecked(size, offset, fence_size);\n                }\n\n                // same as allocate() but does not check the size\n                // note: pass it the align OFFSET, not the alignment\n                void* allocate_unchecked(std::size_t size, std::size_t align_offset,\n                                         std::size_t fence_size = debug_fence_size)\n                    noexcept\n                {\n                    bump(fence_size, debug_magic::fence_memory);\n                    bump(align_offset, debug_magic::alignment_memory);\n                    auto mem = bump_return(size);\n                    bump(fence_size, debug_magic::fence_memory);\n                    return mem;\n                }\n\n                // unwindws the stack to a certain older position\n                // debug: marks memory from new top to old top as freed\n                // doesn't check for invalid pointer\n                void unwind(char* top) noexcept\n                {\n                    debug_fill(top, std::size_t(cur_ - top), debug_magic::freed_memory);\n                    cur_ = top;\n                }\n\n                // returns the current top\n                char* top() const noexcept\n                {\n                    return cur_;\n                }\n\n            private:\n                char* cur_;\n            };\n        } // namespace detail\n    }\n} // namespace trtlab::memory\n\n#endif // TRTLAB_MEMORY_DETAIL_MEMORY_STACK_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/page_info.h",
    "content": "/*\n * page-info.h\n * \n\nextracted from: https://github.com/travisdowns/page-info\n \nMIT License\n\nCopyright (c) 2017 travisdowns\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n*/\n\n#ifndef PAGE_INFO_H_\n#define PAGE_INFO_H_\n\n#include <stddef.h>\n#include <inttypes.h>\n#include <stdbool.h>\n#include <stdio.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct {\n    /* page frame number: if present, the physical frame for the page */\n    uint64_t pfn;\n    /* soft-dirty set */\n    bool softdirty;\n    /* exclusively mapped, see e.g., https://patchwork.kernel.org/patch/6787921/ */\n    bool exclusive;\n    /* is a file mapping */\n    bool file;\n    /* page is swapped out */\n    bool swapped;\n    /* page is present, i.e, a physical page is allocated */\n    bool present;\n    /* if true, the kpageflags were successfully loaded, if false they were not (and are all zero) */\n    bool kpageflags_ok;\n    /* the 64-bit flag value extracted from /proc/kpageflags only if pfn is non-null */\n    uint64_t kpageflags;\n\n} page_info;\n/*\n * Information for a number of virtually consecutive pages.\n */\ntypedef struct {\n    /* how many page_info structures are in the array pointed to by info */\n    size_t num_pages;\n\n    /* pointer to the array of page_info structures */\n    page_info *info;\n} page_info_array;\n\n\ntypedef struct {\n    /* the number of pages on which this flag was set, always <= pages_available */\n    size_t pages_set;\n\n    /* the number of pages on which information could be obtained */\n    size_t pages_available;\n\n    /* the total number of pages examined, which may be greater than pages_available if\n     * the flag value could not be obtained for some pages (usually because the pfn is not available\n     * since the page is not yet present or because running as non-root.\n     */\n    size_t pages_total;\n\n    /* the flag the values were queried for */\n    int flag;\n\n} flag_count;\n\n/**\n * Examine the page info in infos to count the number of times a specified /proc/kpageflags flag was set,\n * effectively giving you a ratio, so you can say \"80% of the pages for this allocation are backed by\n * huge pages\" or whatever.\n *\n * The flags *must* come from kpageflags (these are not the same as those in /proc/pid/pagemap) and\n * are declared in linux/kernel-page-flags.h.\n *\n * Ideally, the flag information is available for all the pages in the range, so you can\n * say something about the entire range, but this is often not the case because (a) flags\n * are not available for pages that aren't present and (b) flags are generally never available\n * for non-root users. So the ratio structure indicates both the total number of pages as\n * well as the number of pages for which the flag information was available.\n */\nflag_count get_flag_count(page_info_array infos, int flag);\n\n/**\n * Given the case-insensitive name of a flag, return the flag number (the index of the bit\n * representing this flag), or -1 if the flag is not found. The \"names\" of the flags are\n * the same as the macro names in <linux/kernel-page-flags.h> without the KPF_ prefix.\n *\n * For example, the name of the transparent hugepages flag is \"THP\" and the corresponding\n * macro is KPF_THP, and the value of this macro and returned by this method is 22.\n *\n * You can generate the corresponding mask value to check the flag using (1ULL << value).\n */\nint flag_from_name(char const *name);\n\n/**\n * Print the info in the page_info structure to stdout.\n */\nvoid print_info(page_info info);\n\n/**\n * Print the info in the page_info structure to the give file.\n */\nvoid fprint_info(FILE* file, page_info info);\n\n\n/**\n * Print the table header that lines up with the tabluar format used by the \"table\" printing\n * functions. Called by fprint_ratios, or you can call it yourself if you want to prefix the\n * output with your own columns.\n */\nvoid fprint_info_header(FILE *file);\n\n/* print one info in a tabular format (as a single row) */\nvoid fprint_info_row(FILE *file, page_info info);\n\n\n/**\n * Print the ratio for each flag in infos. The ratio is the number of times the flag was set over\n * the total number of pages (or the total number of pages for which the information could be obtained).\n */\nvoid fprint_ratios_noheader(FILE *file, page_info_array infos);\n/*\n * Print a table with one row per page from the given infos.\n */\nvoid fprint_ratios(FILE *file, page_info_array infos);\n\n/*\n * Prints a summary of all the pages in the given array as ratios: the fraction of the time the given\n * flag was set.\n */\nvoid fprint_table(FILE *f, page_info_array infos);\n\n\n/**\n * Get info for a single page indicated by the given pointer (which may point anywhere in the page).\n */\npage_info get_page_info(void *p);\n\n/**\n * Get information for each page in the range from start (inclusive) to end (exclusive).\n */\npage_info_array get_info_for_range(void *start, void *end);\n\n/**\n * Free the memory associated with the given page_info_array. You shouldn't use it after this call.\n */\nvoid free_info_array(page_info_array infos);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PAGE_INFO_H_ */"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/ranges.h",
    "content": "/* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <numeric>\n#include <utility>\n#include <vector>\n#include <type_traits>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            template <typename T>\n            std::vector<std::pair<T, T>> find_ranges(const std::vector<T>& values)\n            {\n                static_assert(std::is_integral<T>::value, \"only integral types allowed\");\n\n                auto copy = values;\n                sort(copy.begin(), copy.end());\n\n                std::vector<std::pair<T, T>> ranges;\n\n                auto it  = copy.cbegin();\n                auto end = copy.cend();\n\n                while (it != end)\n                {\n                    auto low  = *it;\n                    auto high = *it;\n                    for (T i = 0; it != end && low + i == *it; it++, i++)\n                    {\n                        high = *it;\n                    }\n                    ranges.push_back(std::make_pair(low, high));\n                }\n\n                return ranges;\n            }\n\n            template <typename T>\n            std::string print_ranges(const std::vector<std::pair<T, T>>& ranges)\n            {\n                return std::accumulate(std::begin(ranges), std::end(ranges), std::string(), [](std::string r, std::pair<T, T> p) {\n                    if (p.first == p.second)\n                    {\n                        return r + (r.empty() ? \"\" : \",\") + std::to_string(p.first);\n                    }\n                    else\n                    {\n                        return r + (r.empty() ? \"\" : \",\") + std::to_string(p.first) + \"-\" + std::to_string(p.second);\n                    }\n                });\n            }\n\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/detail/utility.h",
    "content": "// MODIFICATION_MESSAGE\n\n// Modification notes:\n// - removed custom move/forward/swap implementations for std definitions\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_DETAIL_UTILITY_HPP\n#define TRTLAB_MEMORY_DETAIL_UTILITY_HPP\n\n// implementation of some functions from <utility> to prevent dependencies on it\n\n#include <type_traits>\n#include <utility>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            using std::move;\n            using std::forward;\n\n            // ADL aware swap\n            template <typename T>\n            void adl_swap(T& a, T& b) noexcept\n            {\n                std::swap(a, b);\n            }\n\n// fancier syntax for enable_if\n// used as (template) parameter\n// also useful for doxygen\n// define PREDEFINED: TRTLAB_REQUIRES(x):=\n#define TRTLAB_REQUIRES(Expr) typename std::enable_if<(Expr), int>::type = 0\n\n// same as above, but as return type\n// also useful for doxygen:\n// defined PREDEFINED: TRTLAB_REQUIRES_RET(x,r):=r\n#define TRTLAB_REQUIRES_RET(Expr, ...) typename std::enable_if<(Expr), __VA_ARGS__>::type\n\n// fancier syntax for enable_if on non-templated member function\n#define TRTLAB_ENABLE_IF(Expr)                                                                     \\\n    template <typename Dummy = std::true_type, TRTLAB_REQUIRES(Dummy::value && (Expr))>\n\n// fancier syntax for general expression SFINAE\n// used as (template) parameter\n// also useful for doxygen:\n// define PREDEFINED: TRTLAB_SFINAE(x):=\n#define TRTLAB_SFINAE(Expr) decltype((Expr), int()) = 0\n\n// avoids code repetition for one-line forwarding functions\n#define TRTLAB_AUTO_RETURN(Expr)                                                                   \\\n    decltype(Expr)                                                                                 \\\n    {                                                                                              \\\n        return Expr;                                                                               \\\n    }\n\n// same as above, but requires certain type\n#define TRTLAB_AUTO_RETURN_TYPE(Expr, T)                                                           \\\n    decltype(Expr)                                                                                 \\\n    {                                                                                              \\\n        static_assert(std::is_same<decltype(Expr), T>::value,                                      \\\n                      #Expr \" does not have the return type \" #T);                                 \\\n        return Expr;                                                                               \\\n    }\n\n            // whether or not a type is an instantiation of a template\n            template <template <typename...> class Template, typename T>\n            struct is_instantiation_of : std::false_type\n            {\n            };\n\n            template <template <typename...> class Template, typename... Args>\n            struct is_instantiation_of<Template, Template<Args...>> : std::true_type\n            {\n            };\n        } // namespace detail\n    }\n} // namespace trtlab::memory\n\n#endif //TRTLAB_MEMORY_DETAIL_UTILITY_HPP\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/error.h",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n/// \\file\n/// The exception classes.\n\n#ifndef TRTLAB_MEMORY_ERROR_H_INCLUDED\n#define TRTLAB_MEMORY_ERROR_H_INCLUDED\n\n#include <cstddef>\n#include <new>\n\n#include \"config.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        /// Contains information about an allocator.\n        /// It can be used for logging in the various handler functions.\n        /// \\ingroup memory core\n        struct allocator_info\n        {\n            /// The name of the allocator.\n            /// It is a NTBS whose lifetime is not managed by this object,\n            /// it must be stored elsewhere or be a string literal.\n            const char* name;\n\n            /// A pointer representing an allocator.\n            /// It does not necessarily point to the beginning of the allocator object,\n            /// the only guarantee is that different allocator objects result in a different pointer value.\n            /// For stateless allocators it is sometimes \\c nullptr.\n            /// \\note The pointer must not be cast back to any allocator type.\n            const void* allocator;\n\n            /// \\effects Creates it by giving it the name of the allocator and a pointer.\n            constexpr allocator_info(const char* n, const void* alloc) noexcept\n                : name(n),\n                  allocator(alloc)\n            {\n            }\n\n            /// @{\n            /// \\effects Compares two \\ref allocator_info objects, they are equal, if the \\ref allocator is the same.\n            /// \\returns The result of the comparision.\n            friend constexpr bool operator==(const allocator_info& a,\n                                                       const allocator_info& b) noexcept\n            {\n                return a.allocator == b.allocator;\n            }\n\n            friend constexpr bool operator!=(const allocator_info& a,\n                                                       const allocator_info& b) noexcept\n            {\n                return a.allocator != b.allocator;\n            }\n            /// @}\n        };\n\n        /// The exception class thrown when a low level allocator runs out of memory.\n        /// It is derived from \\c std::bad_alloc.\n        /// This can happen if a low level allocation function like \\c std::malloc() runs out of memory.\n        /// Throwing can be prohibited by the handler function.\n        /// \\ingroup memory core\n        class out_of_memory : public std::bad_alloc\n        {\n        public:\n            /// The type of the handler called in the constructor of \\ref out_of_memory.\n            /// When an out of memory situation is encountered and the exception class created,\n            /// this handler gets called.\n            /// It is especially useful if exception support is disabled.\n            /// It gets the \\ref allocator_info and the amount of memory that was tried to be allocated.\n            /// \\requiredbe It can log the error, throw a different exception derived from \\c std::bad_alloc or abort the program.\n            /// If it returns, this exception object will be created and thrown.\n            /// \\defaultbe On a hosted implementation it logs the error on \\c stderr and continues execution,\n            /// leading to this exception being thrown.\n            /// On a freestanding implementation it does nothing.\n            /// \\note It is different from \\c std::new_handler; it will not be called in a loop trying to allocate memory\n            /// or something like that. Its only job is to report the error.\n            using handler = void (*)(const allocator_info& info, std::size_t amount);\n\n            /// \\effects Sets \\c h as the new \\ref handler in an atomic operation.\n            /// A \\c nullptr sets the default \\ref handler.\n            /// \\returns The previous \\ref handler. This is never \\c nullptr.\n            static handler set_handler(handler h);\n\n            /// \\returns The current \\ref handler. This is never \\c nullptr.\n            static handler get_handler();\n\n            /// \\effects Creates it by passing it the \\ref allocator_info and the amount of memory failed to be allocated.\n            /// It also calls the \\ref handler to control whether or not it will be thrown.\n            out_of_memory(const allocator_info& info, std::size_t amount);\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n\n            /// \\returns The \\ref allocator_info passed to it in the constructor.\n            const allocator_info& allocator() const noexcept\n            {\n                return info_;\n            }\n\n            /// \\returns The amount of memory that was tried to be allocated.\n            /// This is the value passed in the constructor.\n            std::size_t failed_allocation_size() const noexcept\n            {\n                return amount_;\n            }\n\n        private:\n            allocator_info info_;\n            std::size_t    amount_;\n        };\n\n        /// A special case of \\ref out_of_memory errors\n        /// thrown when a low-level allocator with a fixed size runs out of memory.\n        /// For example, thrown by \\ref fixed_block_allocator or \\ref static_allocator.<br>\n        /// It is derived from \\ref out_of_memory but does not provide its own handler.\n        /// \\ingroup memory core\n        class out_of_fixed_memory : public out_of_memory\n        {\n        public:\n            /// \\effects Just forwards to \\ref out_of_memory.\n            out_of_fixed_memory(const allocator_info& info, std::size_t amount)\n            : out_of_memory(info, amount)\n            {\n            }\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n        };\n\n        /// The exception class thrown when an allocation size is bigger than the supported maximum.\n        /// This size is either the node, array or alignment parameter in a call to an allocation function.\n        /// If those exceed the supported maximum returned by \\c max_node_size(), \\c max_array_size() or \\c max_alignment(),\n        /// one of its derived classes will be thrown or this class if in a situation where the type is unknown.\n        /// It is derived from \\c std::bad_alloc.\n        /// Throwing can be prohibited by the handler function.\n        /// \\note Even if all parameters are less than the maximum, \\ref out_of_memory or a similar exception can be thrown,\n        /// because the maximum functions return an upper bound and not the actual supported maximum size,\n        /// since it always depends on fence memory, alignment buffer and the like.\n        /// \\note A user should only \\c catch for \\c bad_allocation_size, not the derived classes.\n        /// \\note Most checks will only be done if \\ref TRTLAB_MEMORY_CHECK_ALLOCATION_SIZE is \\c true.\n        /// \\ingroup memory core\n        class bad_allocation_size : public std::bad_alloc\n        {\n        public:\n            /// The type of the handler called in the constructor of \\ref bad_allocation_size.\n            /// When a bad allocation size is detected and the exception object created,\n            /// this handler gets called.\n            /// It is especially useful if exception support is disabled.\n            /// It gets the \\ref allocator_info, the size passed to the function and the supported size\n            /// (the latter is still an upper bound).\n            /// \\requiredbe It can log the error, throw a different exception derived from \\c std::bad_alloc or abort the program.\n            /// If it returns, this exception object will be created and thrown.\n            /// \\defaultbe On a hosted implementation it logs the error on \\c stderr and continues execution,\n            /// leading to this exception being thrown.\n            /// On a freestanding implementation it does nothing.\n            using handler = void (*)(const allocator_info& info, std::size_t passed,\n                                     std::size_t supported);\n\n            /// \\effects Sets \\c h as the new \\ref handler in an atomic operation.\n            /// A \\c nullptr sets the default \\ref handler.\n            /// \\returns The previous \\ref handler. This is never \\c nullptr.\n            static handler set_handler(handler h);\n\n            /// \\returns The current \\ref handler. This is never \\c nullptr.\n            static handler get_handler();\n\n            /// \\effects Creates it by passing it the \\ref allocator_info, the size passed to the allocation function\n            /// and an upper bound on the supported size.\n            /// It also calls the \\ref handler to control whether or not it will be thrown.\n            bad_allocation_size(const allocator_info& info, std::size_t passed,\n                                std::size_t supported);\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n\n            /// \\returns The \\ref allocator_info passed to it in the constructor.\n            const allocator_info& allocator() const noexcept\n            {\n                return info_;\n            }\n\n            /// \\returns The size or alignment value that was passed to the allocation function\n            /// which was too big. This is the same value passed to the constructor.\n            std::size_t passed_value() const noexcept\n            {\n                return passed_;\n            }\n\n            /// \\returns An upper bound on the maximum supported size/alignment.\n            /// It is only an upper bound, values below can fail, but values above will always fail.\n            std::size_t supported_value() const noexcept\n            {\n                return supported_;\n            }\n\n        private:\n            allocator_info info_;\n            std::size_t    passed_, supported_;\n        };\n\n        /// The exception class thrown when the node size exceeds the supported maximum,\n        /// i.e. it is bigger than \\c max_node_size().\n        /// It is derived from \\ref bad_allocation_size but does not override the handler.\n        /// \\ingroup memory core\n        class bad_node_size : public bad_allocation_size\n        {\n        public:\n            /// \\effects Just forwards to \\ref bad_allocation_size.\n            bad_node_size(const allocator_info& info, std::size_t passed, std::size_t supported)\n            : bad_allocation_size(info, passed, supported)\n            {\n            }\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n        };\n\n        /// The exception class thrown when the array size exceeds the supported maximum,\n        /// i.e. it is bigger than \\c max_array_size().\n        /// It is derived from \\ref bad_allocation_size but does not override the handler.\n        /// \\ingroup memory core\n        class bad_array_size : public bad_allocation_size\n        {\n        public:\n            /// \\effects Just forwards to \\ref bad_allocation_size.\n            bad_array_size(const allocator_info& info, std::size_t passed, std::size_t supported)\n            : bad_allocation_size(info, passed, supported)\n            {\n            }\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n        };\n\n        /// The exception class thrown when the alignment exceeds the supported maximum,\n        /// i.e. it is bigger than \\c max_alignment().\n        /// It is derived from \\ref bad_allocation_size but does not override the handler.\n        /// \\ingroup memory core\n        class bad_alignment : public bad_allocation_size\n        {\n        public:\n            /// \\effects Just forwards to \\ref bad_allocation_size.\n            /// \\c passed is <tt>count * size</tt>, \\c supported the size in bytes.\n            bad_alignment(const allocator_info& info, std::size_t passed, std::size_t supported)\n            : bad_allocation_size(info, passed, supported)\n            {\n            }\n\n            /// \\returns A static NTBS that describes the error.\n            /// It does not contain any specific information since there is no memory for formatting.\n            const char* what() const noexcept override;\n        };\n\n        namespace detail\n        {\n            template <class Ex, typename Func>\n            void check_allocation_size(std::size_t passed, Func f, const allocator_info& info)\n            {\n#if TRTLAB_MEMORY_CHECK_ALLOCATION_SIZE\n                auto supported = f();\n                if (passed > supported)\n                    throw Ex(info, passed, supported);\n#else\n                (void)passed;\n                (void)f;\n                (void)info;\n#endif\n            }\n\n            template <class Ex>\n            void check_allocation_size(std::size_t passed, std::size_t supported,\n                                       const allocator_info& info)\n            {\n                check_allocation_size<Ex>(passed, [&] { return supported; }, info);\n            }\n        } // namespace detail\n    }\n} // namespace trtlab::memory\n\n#endif // TRTLAB_MEMORY_ERROR_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/huge_page_allocator.h",
    "content": "#pragma once\n\n#include \"posix_aligned_allocator.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        template <std::size_t HugePageSize>\n        struct transparent_huge_page_allocator : public posix_aligned_allocator<HugePageSize>\n        {\n            static_assert(is_valid_alignment(HugePageSize), \"must be a power of 2\");\n\n            static void* allocate_node(std::size_t size, std::size_t)\n            {\n                // ensure complete pages are allocated\n                auto addl_bytes_for_complete_page = size % HugePageSize;\n                DLOG_IF(WARNING, addl_bytes_for_complete_page)\n                    << \"transparent_huge_page_allocator allocates complete pages; \" << addl_bytes_for_complete_page\n                    << \" additional bytes were added to allocation\";\n                size += addl_bytes_for_complete_page;\n\n                // allocate and advise\n                void* ptr = posix_aligned_allocator<HugePageSize>::allocate_node(size, HugePageSize);\n                auto ret = madvise(ptr, size, MADV_HUGEPAGE);\n                if (ret)\n                {\n                    LOG(WARNING) << \"madvise returned an error: \" << std::strerror(errno);\n                }\n                return ptr;\n            }\n\n            constexpr static std::size_t page_size()\n            {\n                return HugePageSize;\n            }\n        };\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/literals.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// MODIFICATION MESSAGE\n\n// Modification Notes:\n// - added TiB and TB\n// - taken from foonathan/memory (memory_arena.hpp)\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#pragma once\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace literals\n        {\n            constexpr std::size_t operator\"\" _KiB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1024);\n            }\n\n            constexpr std::size_t operator\"\" _KB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1000);\n            }\n\n            constexpr std::size_t operator\"\" _MiB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1024 * 1024);\n            }\n\n            constexpr std::size_t operator\"\" _MB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1000 * 1000);\n            }\n\n            constexpr std::size_t operator\"\" _GiB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1024 * 1024 * 1024);\n            }\n\n            constexpr std::size_t operator\"\" _GB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1000 * 1000 * 1000);\n            }\n\n            constexpr std::size_t operator\"\" _TiB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1024 * 1024 * 1024 * 1024);\n            }\n\n            constexpr std::size_t operator\"\" _TB(unsigned long long value) noexcept\n            {\n                return std::size_t(value * 1000 * 1000 * 1000 * 1000);\n            }\n        } // namespace literals\n    }     // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/malloc_allocator.h",
    "content": "/* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstdlib>\n#include <unistd.h>\n\n#include \"memory_type.h\"\n\n#include <glog/logging.h>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        struct malloc_allocator\n        {\n            using memory_type = host_memory;\n            using is_stateful = std::false_type;\n\n            static void* allocate_node(std::size_t size, std::size_t)\n            {\n                void* mem = std::malloc(size);\n                VLOG(10) << \"malloc: \" << mem << \"; size=\" << size;\n                return mem;\n            }\n\n            static void deallocate_node(void* ptr, std::size_t, std::size_t) noexcept\n            {\n                free(ptr);\n            }\n\n            static std::size_t page_size()\n            {\n                return sysconf(_SC_PAGE_SIZE);\n            }\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/memory_block.h",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#pragma once\n#include <stdexcept>\n\n#include \"config.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        /// A memory block.\n        /// It is defined by its starting address and size.\n        /// \\ingroup memory core\n        struct memory_block\n        {\n            void*       memory; ///< The address of the memory block (might be \\c nullptr).\n            std::size_t size;   ///< The size of the memory block (might be \\c 0).\n\n            /// \\effects Creates an invalid memory block with starting address \\c nullptr and size \\c 0.\n            memory_block() noexcept : memory_block(nullptr, std::size_t(0)) {}\n\n            /// \\effects Creates a memory block from a given starting address and size.\n            memory_block(void* mem, std::size_t s) noexcept : memory(mem), size(s) {}\n\n            /// \\effects Creates a memory block from a [begin,end) range.\n            memory_block(void* begin, void* end) noexcept\n            : memory_block(begin, static_cast<std::size_t>(static_cast<char*>(end) - static_cast<char*>(begin)))\n            {\n            }\n\n            memory_block(memory_block&& other) noexcept : memory(std::exchange(other.memory, nullptr)), size(std::exchange(other.size, 0u))\n            {\n            }\n\n            memory_block& operator=(memory_block&& other) noexcept\n            {\n                memory = std::exchange(other.memory, nullptr);\n                size   = std::exchange(other.size, 0u);\n                return *this;\n            }\n\n            memory_block(const memory_block&) = default;\n            memory_block& operator=(const memory_block&) = default;\n\n            /// \\returns Whether or not a pointer is inside the memory.\n            bool contains(const void* address) const noexcept\n            {\n                auto mem  = static_cast<const char*>(memory);\n                auto addr = static_cast<const char*>(address);\n                return addr >= mem && addr < mem + size;\n            }\n\n            std::uintptr_t distance(void* ptr)\n            {\n                if (!contains(ptr))\n                    throw std::runtime_error(\"cannot compute distance - ptr not owned by block\");\n                auto s = reinterpret_cast<std::uintptr_t>(memory);\n                auto e = reinterpret_cast<std::uintptr_t>(ptr);\n                return e - s;\n            }\n\n            void* offset(std::size_t distance)\n            {\n                if (distance > size)\n                    return nullptr;\n                auto mem = static_cast<char*>(memory);\n                return mem + distance;\n            }\n        };\n\n        template <typename Compare = std::less<>>\n        struct memory_block_compare_size\n        {\n            using is_transparent = void;\n\n            constexpr bool operator()(std::size_t size, const memory_block& block, Compare compare = Compare()) const\n            {\n                return compare(size, block.size);\n            }\n\n            constexpr bool operator()(const memory_block& block, std::size_t size, Compare compare = Compare()) const\n            {\n                return compare(block.size, size);\n            }\n\n            constexpr bool operator()(const memory_block& lhs, const memory_block& rhs, Compare compare = Compare()) const\n            {\n                if (compare(lhs.size, rhs.size))\n                    return true;\n                else if (lhs.size == rhs.size && compare(reinterpret_cast<addr_t>(lhs.memory), reinterpret_cast<addr_t>(rhs.memory)))\n                    return true;\n                return false;\n            }\n        };\n\n        template <typename Compare = std::less<>>\n        struct memory_block_compare_addr\n        {\n            using is_transparent = void;\n\n            constexpr bool operator()(void* addr, const memory_block& block, Compare compare = Compare()) const\n            {\n                return compare(reinterpret_cast<addr_t>(addr), reinterpret_cast<addr_t>(block.memory));\n            }\n\n            constexpr bool operator()(const memory_block& block, void* addr, Compare compare = Compare()) const\n            {\n                return compare(reinterpret_cast<addr_t>(block.memory), reinterpret_cast<addr_t>(addr));\n            }\n\n            constexpr bool operator()(const memory_block& lhs, const memory_block& rhs, Compare compare = Compare()) const\n            {\n                return compare(reinterpret_cast<addr_t>(lhs.memory), reinterpret_cast<addr_t>(rhs.memory));\n            }\n        };\n\n    } // namespace memory\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/memory_pool.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_MEMORY_POOL_H_INCLUDED\n#define TRTLAB_MEMORY_MEMORY_POOL_H_INCLUDED\n\n/// \\file\n/// Class \\ref foonathan::memory::memory_pool and its \\ref foonathan::memory::allocator_traits specialization.\n\n#include <type_traits>\n\n#include \"align.h\"\n#include \"detail/assert.h\"\n#include \"detail/debug_helpers.h\"\n#include \"detail/free_list.h\"\n#include \"config.h\"\n#include \"error.h\"\n#include \"block_stack.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            struct memory_pool_leak_handler\n            {\n                void operator()(std::ptrdiff_t amount);\n            };\n        } // namespace detail\n\n        /// Tag type defining a memory pool optimized for nodes.\n        /// It does not support array allocations that great and may trigger a growth even if there is enough memory.\n        /// But it is the fastest pool type.\n        /// \\ingroup memory allocator\n        struct node_pool : TRTLAB_EBO(std::true_type)\n        {\n            using type = detail::node_free_memory_list;\n        };\n\n        /// Tag type defining a memory pool optimized for arrays.\n        /// It keeps the nodes oredered inside the free list and searches the list for an appropriate memory block.\n        /// Array allocations are still pretty slow, if the array gets big enough it can get slower than \\c new.\n        /// Node allocations are still fast, unless there is deallocation in random order.\n        /// \\note Use this tag type only if you really need to have a memory pool!\n        /// \\ingroup memory allocator\n        struct array_pool : TRTLAB_EBO(std::true_type)\n        {\n            using type = detail::array_free_memory_list;\n        };\n\n        /// A stateful \\concept{concept_rawallocator,RawAllocator} that manages \\concept{concept_node,nodes} of fixed size.\n        /// It uses a \\ref block_stack with a given \\c BlockOrRawAllocator defaulting to \\ref growing_block_allocator,\n        /// subdivides them in small nodes of given size and puts them onto a free list.\n        /// Allocation and deallocation simply remove or add nodes from this list and are thus fast.\n        /// The way the list is maintained can be controlled via the \\c PoolType\n        /// which is either \\ref node_pool, \\ref array_pool or \\ref small_node_pool.<br>\n        /// This kind of allocator is ideal for fixed size allocations and deallocations in any order,\n        /// for example in a node based container like \\c std::list.\n        /// It is not so good for different allocation sizes and has some drawbacks for arrays\n        /// as described in \\ref memory_pool_type.hpp.\n        /// \\ingroup memory allocator\n        template <class BlockAllocator, typename PoolType = node_pool>\n        class memory_pool : TRTLAB_EBO(detail::default_leak_checker<detail::memory_pool_leak_handler>)\n        {\n            using free_list    = typename PoolType::type;\n            using leak_checker = detail::default_leak_checker<detail::memory_pool_leak_handler>;\n\n        public:\n            using allocator_type = BlockAllocator;\n            using memory_type    = typename BlockAllocator::memory_type;\n            using pool_type      = PoolType;\n\n            static constexpr std::size_t min_node_size = TRTLAB_IMPL_DEFINED(free_list::min_element_size);\n\n            /// \\effects Creates it by specifying the size each \\concept{concept_node,node} will have,\n            /// the initial block size for the arena and other constructor arguments for the \\concept{concept_blockallocator,BlockAllocator}.\n            /// If the \\c node_size is less than the \\c min_node_size, the \\c min_node_size will be the actual node size.\n            /// It will allocate an initial memory block with given size from the \\concept{concept_blockallocator,BlockAllocator}\n            /// and puts it onto the free list.\n            /// \\requires \\c node_size must be a valid \\concept{concept_node,node size}\n            /// and \\c block_size must be a non-zero value.\n            template <typename... Args>\n            memory_pool(std::size_t node_size, std::size_t block_size, Args&&... args)\n            : stack_(block_size, detail::forward<Args>(args)...), free_list_(node_size)\n            {\n                allocate_block();\n            }\n\n            memory_pool(std::size_t node_size, uncached_block_stack<allocator_type>&& stack)\n            : stack_(std::move(stack)), free_list_(node_size)\n            {\n                allocate_block();\n            }\n\n            /// \\effects Destroys the \\ref memory_pool by returning all memory blocks,\n            /// regardless of properly deallocated back to the \\concept{concept_blockallocator,BlockAllocator}.\n            ~memory_pool() noexcept {}\n\n            /// @{\n            /// \\effects Moving a \\ref memory_pool object transfers ownership over the free list,\n            /// i.e. the moved from pool is completely empty and the new one has all its memory.\n            /// That means that it is not allowed to call \\ref deallocate_node() on a moved-from allocator\n            /// even when passing it memory that was previously allocated by this object.\n            memory_pool(memory_pool&& other) noexcept\n            : leak_checker(detail::move(other)), stack_(detail::move(other.stack_)), free_list_(detail::move(other.free_list_))\n            {\n            }\n\n            memory_pool& operator=(memory_pool&& other) noexcept\n            {\n                leak_checker::operator=(detail::move(other));\n                stack_                = detail::move(other.stack_);\n                free_list_            = detail::move(other.free_list_);\n                return *this;\n            }\n            /// @}\n\n            /// \\effects Allocates a single \\concept{concept_node,node} by removing it from the free list.\n            /// If the free list is empty, a new memory block will be allocated from the arena and put onto it.\n            /// The new block size will be \\ref next_capacity() big.\n            /// \\returns A node of size \\ref node_size() suitable aligned,\n            /// i.e. suitable for any type where <tt>sizeof(T) < node_size()</tt>.\n            /// \\throws Anything thrown by the used \\concept{concept_blockallocator,BlockAllocator}'s allocation function if a growth is needed.\n            void* allocate_node()\n            {\n                if (free_list_.empty())\n                    allocate_block();\n                TRTLAB_MEMORY_ASSERT(!free_list_.empty());\n                return free_list_.allocate();\n            }\n\n            /// \\effects Allocates a single \\concept{concept_node,node} similar to \\ref allocate_node().\n            /// But if the free list is empty, a new block will *not* be allocated.\n            /// \\returns A suitable aligned node of size \\ref node_size() or `nullptr`.\n            void* try_allocate_node() noexcept\n            {\n                return free_list_.empty() ? nullptr : free_list_.allocate();\n            }\n\n            /// \\effects Allocates an \\concept{concept_array,array} of nodes by searching for \\c n continuous nodes on the list and removing them.\n            /// Depending on the \\c PoolType this can be a slow operation or not allowed at all.\n            /// This can sometimes lead to a growth, even if technically there is enough continuous memory on the free list.\n            /// \\returns An array of \\c n nodes of size \\ref node_size() suitable aligned.\n            /// \\throws Anything thrown by the used \\concept{concept_blockallocator,BlockAllocator}'s allocation function if a growth is needed,\n            /// or \\ref bad_array_size if <tt>n * node_size()</tt> is too big.\n            /// \\requires \\c n must be valid \\concept{concept_array,array count}.\n            void* allocate_array(std::size_t n)\n            {\n                detail::check_allocation_size<bad_array_size>(n * node_size(), [&] { return pool_type::value ? next_capacity() : 0; },\n                                                              info());\n                return allocate_array(n, node_size());\n            }\n\n            /// \\effects Allocates an \\concept{concept_array,array| of nodes similar to \\ref allocate_array().\n            /// But it will never allocate a new memory block.\n            /// \\returns An array of \\c n nodes of size \\ref node_size() suitable aligned\n            /// or `nullptr`.\n            void* try_allocate_array(std::size_t n) noexcept\n            {\n                return try_allocate_array(n, node_size());\n            }\n\n            /// \\effects Deallocates a single \\concept{concept_node,node} by putting it back onto the free list.\n            /// \\requires \\c ptr must be a result from a previous call to \\ref allocate_node() on the same free list,\n            /// i.e. either this allocator object or a new object created by moving this to it.\n            void deallocate_node(void* ptr) noexcept\n            {\n                free_list_.deallocate(ptr);\n            }\n\n            /// \\effects Deallocates a single \\concept{concept_node,node} but it does not be a result of a previous call to \\ref allocate_node().\n            /// \\returns `true` if the node could be deallocated, `false` otherwise.\n            /// \\note Some free list implementations can deallocate any memory,\n            /// doesn't matter where it is coming from.\n            bool try_deallocate_node(void* ptr) noexcept\n            {\n                if (!stack_.owns(ptr))\n                    return false;\n                free_list_.deallocate(ptr);\n                return true;\n            }\n\n            /// \\effects Deallocates an \\concept{concept_array,array} by putting it back onto the free list.\n            /// \\requires \\c ptr must be a result from a previous call to \\ref allocate_array() with the same \\c n on the same free list,\n            /// i.e. either this allocator object or a new object created by moving this to it.\n            void deallocate_array(void* ptr, std::size_t n) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT_MSG(pool_type::value, \"does not support array allocations\");\n                free_list_.deallocate(ptr, n * node_size());\n            }\n\n            /// \\effects Deallocates an \\concept{concept_array,array} but it does not be a result of a previous call to \\ref allocate_array().\n            /// \\returns `true` if the node could be deallocated, `false` otherwise.\n            /// \\note Some free list implementations can deallocate any memory,\n            /// doesn't matter where it is coming from.\n            bool try_deallocate_array(void* ptr, std::size_t n) noexcept\n            {\n                return try_deallocate_array(ptr, n, node_size());\n            }\n\n            /// \\returns The size of each \\concept{concept_node,node} in the pool,\n            /// this is either the same value as in the constructor or \\c min_node_size if the value was too small.\n            std::size_t node_size() const noexcept\n            {\n                return free_list_.node_size();\n            }\n\n            /// \\effects Returns the total amount of bytes remaining on the free list.\n            /// Divide it by \\ref node_size() to get the number of nodes that can be allocated without growing the arena.\n            /// \\note Array allocations may lead to a growth even if the capacity_left left is big enough.\n            std::size_t capacity_left() const noexcept\n            {\n                return free_list_.capacity() * node_size();\n            }\n\n            /// \\returns The size of the next memory block after the free list gets empty and the arena grows.\n            /// \\ref capacity_left() will increase by this amount.\n            /// \\note Due to fence memory in debug mode this cannot be just divided by the \\ref node_size() to get the number of nodes.\n            std::size_t next_capacity() const noexcept\n            {\n                return free_list_.usable_size(stack_.next_block_size());\n            }\n\n            /// \\returns A reference to the \\concept{concept_blockallocator,BlockAllocator} used for managing the arena.\n            /// \\requires It is undefined behavior to move this allocator out into another object.\n            allocator_type& get_allocator() noexcept\n            {\n                return stack_.get_allocator();\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return stack_.get_allocator();\n            }\n\n            DLContext device_context() const\n            {\n                return stack_.device_context();\n            }\n\n        private:\n            allocator_info info() const noexcept\n            {\n                return {TRTLAB_MEMORY_LOG_PREFIX \"::memory_pool\", this};\n            }\n\n            void allocate_block()\n            {\n                auto mem = stack_.allocate_block();\n                free_list_.insert(static_cast<char*>(mem.memory), mem.size);\n            }\n\n            void* allocate_array(std::size_t n, std::size_t node_size)\n            {\n                auto mem = free_list_.empty() ? nullptr : free_list_.allocate(n * node_size);\n                if (!mem)\n                {\n                    allocate_block();\n                    mem = free_list_.allocate(n * node_size);\n                    if (!mem)\n                        throw bad_array_size(info(), n * node_size, capacity_left());\n                }\n                return mem;\n            }\n\n            void* try_allocate_array(std::size_t n, std::size_t node_size) noexcept\n            {\n                return !pool_type::value || free_list_.empty() ? nullptr : free_list_.allocate(n * node_size);\n            }\n\n            bool try_deallocate_array(void* ptr, std::size_t n, std::size_t node_size) noexcept\n            {\n                if (!pool_type::value || !stack_.owns(ptr))\n                    return false;\n                free_list_.deallocate(ptr, n * node_size);\n                return true;\n            }\n\n            uncached_block_stack<allocator_type> stack_;\n            free_list                            free_list_;\n\n            friend allocator_traits<memory_pool<BlockAllocator, PoolType>>;\n            friend composable_allocator_traits<memory_pool<BlockAllocator, PoolType>>;\n        };\n\n        template <class Alloc, class Type>\n        constexpr std::size_t memory_pool<Alloc, Type>::min_node_size;\n\n        /// Specialization of the \\ref allocator_traits for \\ref memory_pool classes.\n        /// \\note It is not allowed to mix calls through the specialization and through the member functions,\n        /// i.e. \\ref memory_pool::allocate_node() and this \\c allocate_node().\n        /// \\ingroup memory allocator\n        template <typename ImplRawAllocator, class PoolType>\n        class allocator_traits<memory_pool<ImplRawAllocator, PoolType>>\n        {\n        public:\n            using allocator_type = memory_pool<ImplRawAllocator, PoolType>;\n            using memory_type    = typename ImplRawAllocator::memory_type;\n            using is_stateful    = std::true_type;\n\n            /// \\returns The result of \\ref memory_pool::allocate_node().\n            /// \\throws Anything thrown by the pool allocation function\n            /// or a \\ref bad_allocation_size exception.\n            static void* allocate_node(allocator_type& state, std::size_t size, std::size_t alignment)\n            {\n                detail::check_allocation_size<bad_node_size>(size, max_node_size(state), state.info());\n                detail::check_allocation_size<bad_alignment>(alignment, [&] { return max_alignment(state); }, state.info());\n                auto mem = state.allocate_node();\n                state.on_allocate(size);\n                return mem;\n            }\n\n            /// \\effects Forwards to \\ref memory_pool::allocate_array()\n            /// with the number of nodes adjusted to be the minimum,\n            /// i.e. when the \\c size is less than the \\ref memory_pool::node_size().\n            /// \\returns A \\concept{concept_array,array} with specified properties.\n            /// \\requires The \\ref memory_pool has to support array allocations.\n            /// \\throws Anything thrown by the pool allocation function.\n            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                detail::check_allocation_size<bad_node_size>(size, max_node_size(state), state.info());\n                detail::check_allocation_size<bad_alignment>(alignment, [&] { return max_alignment(state); }, state.info());\n                detail::check_allocation_size<bad_array_size>(count * size, max_array_size(state), state.info());\n                auto mem = state.allocate_array(count, size);\n                state.on_allocate(count * size);\n                return mem;\n            }\n\n            /// \\effects Just forwards to \\ref memory_pool::deallocate_node().\n            static void deallocate_node(allocator_type& state, void* node, std::size_t size, std::size_t) noexcept\n            {\n                state.deallocate_node(node);\n                state.on_deallocate(size);\n            }\n\n            /// \\effects Forwards to \\ref memory_pool::deallocate_array() with the same size adjustment.\n            static void deallocate_array(allocator_type& state, void* array, std::size_t count, std::size_t size, std::size_t) noexcept\n            {\n                state.free_list_.deallocate(array, count * size);\n                state.on_deallocate(count * size);\n            }\n\n            /// \\returns The maximum size of each node which is \\ref memory_pool::node_size().\n            static std::size_t max_node_size(const allocator_type& state) noexcept\n            {\n                return state.node_size();\n            }\n\n            /// \\returns An upper bound on the maximum array size which is \\ref memory_pool::next_capacity().\n            static std::size_t max_array_size(const allocator_type& state) noexcept\n            {\n                return state.next_capacity();\n            }\n\n            /// \\returns The maximum alignment which is the next bigger power of two if less than \\c alignof(std::max_align_t)\n            /// or the maximum alignment itself otherwise.\n            static std::size_t min_alignment(const allocator_type& state) noexcept\n            {\n                return state.free_list_.alignment();\n            }\n\n            /// \\returns The maximum alignment which is the next bigger power of two if less than \\c alignof(std::max_align_t)\n            /// or the maximum alignment itself otherwise.\n            static std::size_t max_alignment(const allocator_type& state) noexcept\n            {\n                return state.free_list_.alignment();\n            }\n\n            static DLContext device_context(const allocator_type& state) noexcept\n            {\n                return state.stack_.device_context();\n            }\n        };\n\n        /// Specialization of the \\ref composable_allocator_traits for \\ref memory_pool classes.\n        /// \\ingroup memory allocator\n        template <typename BlockOrRawAllocator, typename PoolType>\n        class composable_allocator_traits<memory_pool<BlockOrRawAllocator, PoolType>>\n        {\n            using traits = allocator_traits<memory_pool<BlockOrRawAllocator, PoolType>>;\n\n        public:\n            using allocator_type = memory_pool<BlockOrRawAllocator, PoolType>;\n\n            /// \\returns The result of \\ref memory_pool::try_allocate_node()\n            /// or `nullptr` if the allocation size was too big.\n            static void* try_allocate_node(allocator_type& state, std::size_t size, std::size_t alignment) noexcept\n            {\n                if (size > traits::max_node_size(state) || alignment > traits::max_alignment(state))\n                    return nullptr;\n                return state.try_allocate_node();\n            }\n\n            /// \\effects Forwards to \\ref memory_pool::try_allocate_array()\n            /// with the number of nodes adjusted to be the minimum,\n            /// if the \\c size is less than the \\ref memory_pool::node_size().\n            /// \\returns A \\concept{concept_array,array} with specified properties\n            /// or `nullptr` if it was unable to allocate.\n            static void* try_allocate_array(allocator_type& state, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                if (size > traits::max_node_size(state) || count * size > traits::max_array_size(state)\n                    || alignment > traits::max_alignment(state))\n                    return nullptr;\n                return state.try_allocate_array(count, size);\n            }\n\n            /// \\effects Just forwards to \\ref memory_pool::try_deallocate_node().\n            /// \\returns Whether the deallocation was successful.\n            static bool try_deallocate_node(allocator_type& state, void* node, std::size_t size, std::size_t alignment) noexcept\n            {\n                if (size > traits::max_node_size(state) || alignment > traits::max_alignment(state))\n                    return false;\n                return state.try_deallocate_node(node);\n            }\n\n            /// \\effects Forwards to \\ref memory_pool::deallocate_array() with the same size adjustment.\n            /// \\returns Whether the deallocation was successful.\n            static bool try_deallocate_array(allocator_type& state, void* array, std::size_t count, std::size_t size,\n                                             std::size_t alignment) noexcept\n            {\n                if (size > traits::max_node_size(state) || count * size > traits::max_array_size(state)\n                    || alignment > traits::max_alignment(state))\n                    return false;\n                return state.try_deallocate_array(array, count, size);\n            }\n        };\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_MEMORY_POOL_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/memory_resource.h",
    "content": "\n#pragma once\n\n#include <cstddef>\n#include <utility>\n\n#include \"descriptor.h\"\n\nnamespace trtlab {\nnamespace memory {\n/**---------------------------------------------------------------------------*\n * @brief Base class for host memory allocation.\n *\n * This is based on `std::pmr::memory_resource`:\n * https://en.cppreference.com/w/cpp/memory/memory_resource\n *\n * When C++17 is available for use in RMM, `rmm::memory_resource` should\n * inherit from `std::pmr::memory_resource`.\n *\n * This class serves as the interface that all host memory resource\n * implementations must satisfy.\n *\n * There are two private, pure virtual functions that all derived classes must\n * implement: `do_allocate` and `do_deallocate`. Optionally, derived classes may\n * also override `is_equal`. By default, `is_equal` simply performs an identity\n * comparison.\n *\n * The public, non-virtual functions `allocate`, `deallocate`, and `is_equal`\n * simply call the private virtual functions. The reason for this is to allow\n * implementing shared, default behavior in the base class. For example, the\n * base class' `allocate` function may log every allocation, no matter what\n * derived class implementation is used.\n *\n *---------------------------------------------------------------------------**/\nclass memory_resource {\n public:\n  memory_resource() = default;\n  virtual ~memory_resource() = default;\n\n  /**---------------------------------------------------------------------------*\n   * @brief Allocates memory on the host of size at least `bytes` bytes.\n   *\n   * The returned storage is aligned to the specified `alignment` if supported,\n   * and to `alignof(std::max_align_t)` otherwise.\n   *\n   * @throws std::bad_alloc When the requested `bytes` and `alignment` cannot be\n   * allocated.\n   *\n   * @param bytes The size of the allocation\n   * @param alignment Alignment of the allocation\n   * @return void* Pointer to the newly allocated memory\n   *---------------------------------------------------------------------------**/\n  void* allocate(std::size_t bytes,\n                 std::size_t alignment = alignof(std::max_align_t)) {\n    return do_allocate(bytes, alignment);\n  }\n\n  /**---------------------------------------------------------------------------*\n   * @brief Deallocate memory pointed to by `p`.\n   *\n   * `p` must have been returned by a prior call to `allocate(bytes,alignment)`\n   * on a `memory_resource` that compares equal to `*this`, and the storage\n   * it points to must not yet have been deallocated, otherwise behavior is\n   * undefined.\n   *\n   * @throws Nothing.\n   *\n   * @param p Pointer to be deallocated\n   * @param bytes The size in bytes of the allocation. This must be equal to the\n   * value of `bytes` that was passed to the `allocate` call that returned `p`.\n   * @param alignment Alignment of the allocation. This must be equal to the\n   *value of `alignment` that was passed to the `allocate` call that returned\n   *`p`.\n   * @param stream Stream on which to perform deallocation\n   *---------------------------------------------------------------------------**/\n  void deallocate(void* p, std::size_t bytes,\n                  std::size_t alignment = alignof(std::max_align_t)) {\n    do_deallocate(p, bytes, alignment);\n  }\n\n  /**---------------------------------------------------------------------------*\n   * @brief Compare this resource to another.\n   *\n   * Two `memory_resource`s compare equal if and only if memory allocated\n   * from one `memory_resource` can be deallocated from the other and vice\n   * versa.\n   *\n   * By default, simply checks if \\p *this and \\p other refer to the same\n   * object, i.e., does not check if they are two objects of the same class.\n   *\n   * @param other The other resource to compare to\n   * @returns If the two resources are equivalent\n   *---------------------------------------------------------------------------**/\n  bool is_equal(memory_resource const& other) const noexcept {\n    return do_is_equal(other);\n  }\n\n private:\n  /**---------------------------------------------------------------------------*\n   * @brief Allocates memory on the host of size at least `bytes` bytes.\n   *\n   * The returned storage is aligned to the specified `alignment` if supported,\n   * and to `alignof(std::max_align_t)` otherwise.\n   *\n   * @throws std::bad_alloc When the requested `bytes` and `alignment` cannot be\n   * allocated.\n   *\n   * @param bytes The size of the allocation\n   * @param alignment Alignment of the allocation\n   * @return void* Pointer to the newly allocated memory\n   *---------------------------------------------------------------------------**/\n  virtual void* do_allocate(\n      std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) = 0;\n\n  /**---------------------------------------------------------------------------*\n   * @brief Deallocate memory pointed to by `p`.\n   *\n   * `p` must have been returned by a prior call to `allocate(bytes,alignment)`\n   * on a `memory_resource` that compares equal to `*this`, and the storage\n   * it points to must not yet have been deallocated, otherwise behavior is\n   * undefined.\n   *\n   * @throws Nothing.\n   *\n   * @param p Pointer to be deallocated\n   * @param bytes The size in bytes of the allocation. This must be equal to the\n   * value of `bytes` that was passed to the `allocate` call that returned `p`.\n   * @param alignment Alignment of the allocation. This must be equal to the\n   *value of `alignment` that was passed to the `allocate` call that returned\n   *`p`.\n   * @param stream Stream on which to perform deallocation\n   *---------------------------------------------------------------------------**/\n  virtual void do_deallocate(\n      void* p, std::size_t bytes,\n      std::size_t alignment = alignof(std::max_align_t)) = 0;\n\n  /**---------------------------------------------------------------------------*\n   * @brief Compare this resource to another.\n   *\n   * Two host_memory_resources compare equal if and only if memory allocated\n   * from one memory_resource can be deallocated from the other and vice\n   * versa.\n   *\n   * By default, simply checks if \\p *this and \\p other refer to the same\n   * object, i.e., does not check if they are two objects of the same class.\n   *\n   * @param other The other resource to compare to\n   * @return true If the two resources are equivalent\n   * @return false If the two resources are not equal\n   *---------------------------------------------------------------------------**/\n  virtual bool do_is_equal(memory_resource const& other) const noexcept {\n    return this == &other;\n  }\n};\n\nclass raii_memory_resource\n{\npublic:\n  raii_memory_resource() = default;\n  virtual ~raii_memory_resource() = default;\n\n  virtual descriptor allocate_descriptor(std::size_t size) = 0;\n  virtual descriptor allocate_descriptor(std::size_t size, std::size_t alignment) = 0;\n};\n\nclass device_context_interface\n{\npublic:\n  device_context_interface() = default;\n  virtual ~device_context_interface() = default;\n\n  virtual DLContext  device_context() const = 0;\n};\n\n}  // namespace memory\n}  // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/memory_type.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <type_traits>\n#include <cstdlib>\n\n#include <dlpack/dlpack.h>\n\n#include \"detail/utility.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            struct any_memory;\n\n            template <class MemoryType>\n            std::true_type is_memory_type_impl(\n                int, TRTLAB_SFINAE(std::declval<DLDeviceType&>() = std::declval<MemoryType&>().device_type()),\n                TRTLAB_SFINAE(std::declval<std::size_t&>() = std::declval<MemoryType&>().min_allocation_alignment()),\n                TRTLAB_SFINAE(std::declval<std::size_t&>() = std::declval<MemoryType&>().max_access_alignment()),\n                TRTLAB_SFINAE(std::declval<std::size_t&>() = std::declval<MemoryType&>().access_alignment_for(0UL)));\n\n            template <typename T>\n            std::false_type is_memory_type_impl(short);\n\n            template <typename T>\n            struct check_memory_type\n            {\n                using has_base = typename std::is_base_of<any_memory, T>::type;\n                using has_impl = decltype(is_memory_type_impl<T>(0));\n\n                using valid = std::integral_constant<bool, has_base::value && has_impl::value>;\n            };\n\n        }\n\n        template <typename T>\n        struct is_memory_type : detail::check_memory_type<T>::valid\n        {\n        };\n\n        namespace detail\n        {\n            class any_memory\n            {\n              protected:\n                template <typename MemoryType>\n                std::size_t static alignment_for(std::size_t size)\n                {\n                    static_assert(is_memory_type<MemoryType>::value, \"\");\n                    auto max_alignment = MemoryType::max_access_alignment();\n                    return (size >= max_alignment ? max_alignment : (std::size_t(1) << ilog2(size)));\n                }\n\n              private:\n                static std::size_t ilog2(std::size_t) noexcept;\n            };\n\n        } // namespace detail\n\n\n\n        // we can define a policy memory_type\n        // this can hold methods to fill memory, etc.\n        struct host_memory : detail::any_memory\n        {\n            constexpr static DLDeviceType device_type() noexcept\n            {\n                return kDLCPU;\n            }\n            constexpr static std::size_t min_allocation_alignment() noexcept\n            {\n                return 8UL;\n            }\n            constexpr static std::size_t max_access_alignment() noexcept\n            {\n                return 8UL;\n            }\n            static std::size_t access_alignment_for(std::size_t size)\n            {\n                using impl = detail::any_memory;\n                return impl::alignment_for<host_memory>(size);\n            }\n        };\n\n        namespace detail\n        {\n            template <typename T>\n            struct check_host_memory\n            {\n                using has_base = typename std::is_base_of<host_memory, T>::type;\n                using has_impl = decltype(is_memory_type_impl<T>(0));\n\n                using valid = std::integral_constant<bool, has_base::value && has_impl::value>;\n            };            \n        }\n\n        template <typename T>\n        struct is_host_memory : detail::check_memory_type<T>::valid\n        {\n        };\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/memory_typed_allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <memory>\n\n#include <glog/logging.h>\n\n#include \"trtlab/memory/allocator_storage.h\"\n#include \"trtlab/memory/descriptor.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        template <typename MemoryType, DLDeviceType DeviceType>\n        class memory_typed_allocator final\n        {\n            std::shared_ptr<iallocator> m_allocator;\n            using allocator_type = memory_typed_allocator<MemoryType, DeviceType>;\n\n        public:\n            using memory_type = MemoryType;\n\n            memory_typed_allocator(std::shared_ptr<iallocator> alloc) : m_allocator(alloc)\n            {\n                CHECK_EQ(m_allocator->device_context().device_type, DeviceType);\n            }\n            ~memory_typed_allocator() = default;\n\n            memory_typed_allocator(const allocator_type&) = default;\n            memory_typed_allocator& operator=(const allocator_type&) = default;\n\n            memory_typed_allocator(allocator_type&&) = default;\n            memory_typed_allocator& operator=(allocator_type&&) = default;\n\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                DCHECK(m_allocator);\n                return m_allocator->allocate(size, alignment);\n            }\n\n            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment)\n            {\n                DCHECK(m_allocator);\n                return m_allocator->deallocate(ptr, size, alignment);\n            }\n\n            std::size_t max_node_size() const\n            {\n                DCHECK(m_allocator);\n                return m_allocator->max_size();\n            }\n\n            std::size_t max_alignment() const\n            {\n                DCHECK(m_allocator);\n                return m_allocator->max_alignment();\n            }\n            \n            std::size_t min_alignment() const\n            {\n                DCHECK(m_allocator);\n                return m_allocator->min_alignment();\n            }\n\n            DLContext device_context() const\n            {\n                DCHECK(m_allocator);\n                return m_allocator->device_context();\n            }\n\n            std::shared_ptr<iallocator> shared() const\n            {\n                return m_allocator;\n            }\n        };\n\n        using host_allocator = memory_typed_allocator<host_memory, kDLCPU>;\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/posix_aligned_allocator.h",
    "content": "#pragma once\n\n#include <cerrno>\n#include <stdlib.h>\n#include <sys/mman.h>\n\n#include \"align.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        template <std::size_t Alignment>\n        struct posix_aligned_allocator\n        {\n            static_assert(is_valid_alignment(Alignment), \"must be a power of 2\");\n\n            using memory_type = host_memory;\n            using is_stateful = std::false_type;\n\n            static void* allocate_node(std::size_t size, std::size_t)\n            {\n                void* ptr = NULL;\n                int   ret = posix_memalign(&ptr, Alignment, size);\n                if (ret)\n                {\n                    throw std::bad_alloc();\n                }\n                return ptr;\n            }\n\n            static void deallocate_node(void* ptr, std::size_t, std::size_t) noexcept\n            {\n                free(ptr);\n            }\n\n            constexpr static std::size_t max_alignment()\n            {\n                return Alignment;\n            }\n\n            constexpr static std::size_t min_alignment()\n            {\n                return Alignment;\n            }\n        };\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/raii_allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <memory>\n#include <set>\n\n#include <glog/logging.h>\n\n#include \"trtlab/memory/allocator.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace raii_detail\n        {\n            template <typename Compare = std::less<>>\n            struct compare_descriptor\n            {\n                using is_transparent = void;\n\n                constexpr bool operator()(void* addr, const descriptor& md, Compare compare = Compare()) const\n                {\n                    return compare(reinterpret_cast<const addr_t>(addr), reinterpret_cast<const addr_t>(const_cast<void*>(md.data())));\n                }\n\n                constexpr bool operator()(const descriptor& md, void* addr, Compare compare = Compare()) const\n                {\n                    return compare(reinterpret_cast<const addr_t>(const_cast<void*>(md.data())), reinterpret_cast<const addr_t>(addr));\n                }\n\n                constexpr bool operator()(const descriptor& lhs, const descriptor& rhs, Compare compare = Compare()) const\n                {\n                    return compare(reinterpret_cast<const addr_t>(const_cast<void*>(lhs.data())),\n                                   reinterpret_cast<const addr_t>(const_cast<void*>(rhs.data())));\n                }\n            };\n\n            template <typename RawAllocator, typename Mutex>\n            class raii_storage : public iallocator\n            {\n            public:\n                using allocator_type = allocator<RawAllocator, Mutex>;\n                using memory_type    = typename allocator_type::memory_type;\n                using mutex          = typename allocator_type::mutex;\n                using is_stateful    = std::true_type;\n\n                raii_storage(const allocator_type& alloc) : m_allocator(alloc) {}\n                ~raii_storage() = default;\n\n                raii_storage(const raii_storage&) = delete;\n                raii_storage& operator=(const raii_storage&) = delete;\n\n                raii_storage(raii_storage&&) noexcept = default;\n                raii_storage& operator=(raii_storage&&) noexcept = default;\n\n                allocator_type& get_allocator()\n                {\n                    return m_allocator;\n                }\n\n                const allocator_type& get_allocator() const\n                {\n                    return m_allocator;\n                }\n\n            private:\n                void* do_allocate(std::size_t size, std::size_t alignment) final override\n                {\n                    alignment = std::min(std::max(alignment, m_allocator.min_alignment()), m_allocator.max_alignment());\n                    auto md = m_allocator.allocate_descriptor(size, alignment);\n\n                    std::lock_guard<mutex> lock(m_mutex);\n                    auto [it, rc] = m_descriptors.insert(std::move(md));\n                    if (!rc)\n                    {\n                        LOG(FATAL) << \"unable to hold internal descriptor\";\n                    }\n                    return const_cast<void*>(it->data());\n                }\n\n                void do_deallocate(void* ptr, std::size_t size, std::size_t alignment) noexcept final override\n                {\n                    std::lock_guard<mutex> lock(m_mutex);\n\n                    auto md = m_descriptors.find(ptr);\n                    if (md == m_descriptors.end())\n                    {\n                        LOG(FATAL) << \"cannot find matching internal descriptor\";\n                    }\n                    m_descriptors.erase(md);\n                }\n\n                descriptor do_allocate_descriptor(std::size_t size, std::size_t alignment) final override\n                {\n                    return m_allocator.allocate_descriptor(size, alignment);\n                }\n\n                std::size_t do_max_alignment() const final override\n                {\n                    return m_allocator.max_alignment();\n                }\n\n                std::size_t do_min_alignment() const final override\n                {\n                    return m_allocator.min_alignment();\n                }\n\n                std::size_t do_max_size() const final override\n                {\n                    return m_allocator.max_node_size();\n                }\n\n                DLContext do_device_context() const final override\n                {\n                    return m_allocator.device_context();\n                }\n\n            private:\n                mutable mutex                              m_mutex;\n                allocator_type                             m_allocator;\n                std::set<descriptor, compare_descriptor<>> m_descriptors;\n            };\n\n        } // namespace raii_detail\n\n        template <typename RawAllocator, typename Mutex>\n        using raii_allocator = allocator_detail::allocator_impl<raii_detail::raii_storage<RawAllocator, Mutex>>;\n\n        template <typename RawAllocator, typename Mutex>\n        auto make_raii_allocator(const allocator<RawAllocator, Mutex>& alloc)\n        {\n            auto storage = std::make_shared<raii_detail::raii_storage<RawAllocator, Mutex>>(alloc);\n            return raii_allocator<RawAllocator, Mutex>(std::move(storage));\n        }\n\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/smart_ptr.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_SMART_PTR_H_INCLUDED\n#define TRTLAB_MEMORY_SMART_PTR_H_INCLUDED\n\n/// \\file\n/// \\c std::make_unique() / \\c std::make_shared() replacement allocating memory through a \\concept{concept_rawallocator,RawAllocator}.\n/// \\note Only available on a hosted implementation.\n\n#include \"config.h\"\n\n#include <memory>\n#include <type_traits>\n\n#include \"detail/utility.h\"\n#include \"deleter.h\"\n#include \"std_allocator.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            template <typename T, class RawAllocator, typename... Args>\n            auto allocate_unique(allocator_reference<RawAllocator> alloc, Args&&... args)\n                -> std::unique_ptr<T, allocator_deleter<T, RawAllocator>>\n            {\n                using raw_ptr = std::unique_ptr<T, allocator_deallocator<T, RawAllocator>>;\n\n                auto memory = alloc.allocate_node(sizeof(T), alignof(T));\n                // raw_ptr deallocates memory in case of constructor exception\n                raw_ptr result(static_cast<T*>(memory), {alloc});\n                // call constructor\n                ::new (memory) T(detail::forward<Args>(args)...);\n                // pass ownership to return value using a deleter that calls destructor\n                return {result.release(), {alloc}};\n            }\n\n            template <typename T, typename... Args>\n            void construct(std::true_type, T* cur, T* end, Args&&... args)\n            {\n                for (; cur != end; ++cur)\n                    ::new (static_cast<void*>(cur)) T(detail::forward<Args>(args)...);\n            }\n\n            template <typename T, typename... Args>\n            void construct(std::false_type, T* begin, T* end, Args&&... args)\n            {\n#if TRTLAB_HAS_EXCEPTION_SUPPORT\n                auto cur = begin;\n                try\n                {\n                    for (; cur != end; ++cur)\n                        ::new (static_cast<void*>(cur)) T(detail::forward<Args>(args)...);\n                }\n                catch (...)\n                {\n                    for (auto el = begin; el != cur; ++el)\n                        el->~T();\n                    throw;\n                }\n#else\n                construct(std::true_type{}, begin, end, detail::forward<Args>(args)...);\n#endif\n            }\n\n            template <typename T, class RawAllocator>\n            auto allocate_array_unique(std::size_t size,\n                                       allocator_reference<RawAllocator> alloc)\n                -> std::unique_ptr<T[], allocator_deleter<T[], RawAllocator>>\n            {\n                using raw_ptr = std::unique_ptr<T[], allocator_deallocator<T[], RawAllocator>>;\n\n                auto memory = alloc.allocate_array(size, sizeof(T), alignof(T));\n                // raw_ptr deallocates memory in case of constructor exception\n                raw_ptr result(static_cast<T*>(memory), {alloc, size});\n                construct(std::integral_constant<bool, noexcept(T())>{}, result.get(),\n                          result.get() + size);\n                // pass ownership to return value using a deleter that calls destructor\n                return {result.release(), {alloc, size}};\n            }\n        } // namespace detail\n\n        /// A \\c std::unique_ptr that deletes using a \\concept{concept_rawallocator,RawAllocator}.\n        ///\n        /// It is an alias template using \\ref allocator_deleter as \\c Deleter class.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator>\n        TRTLAB_ALIAS_TEMPLATE(unique_ptr,\n                                 std::unique_ptr<T, allocator_deleter<T, RawAllocator>>);\n\n        /// A \\c std::unique_ptr that deletes using a \\concept{concept_rawallocator,RawAllocator} and allows polymorphic types.\n        ///\n        /// It can only be created by converting a regular unique pointer to a pointer to a derived class,\n        /// and is meant to be used inside containers.\n        /// It is an alias template using \\ref allocator_polymorphic_deleter as \\c Deleter class.\n        /// \\note It has a relatively high overhead, so only use it if you have to.\n        /// \\ingroup memory adapter\n        template <class BaseType, class RawAllocator>\n        TRTLAB_ALIAS_TEMPLATE(\n            unique_base_ptr,\n            std::unique_ptr<BaseType,\n                            allocator_polymorphic_deleter<BaseType, RawAllocator>>);\n\n        /// Creates a \\c std::unique_ptr using a \\concept{concept_rawallocator,RawAllocator} for the allocation.\n        /// \\effects Allocates memory for the given type using the allocator\n        /// and creates a new object inside it passing the given arguments to its constructor.\n        /// \\returns A \\c std::unique_ptr owning that memory.\n        /// \\note If the allocator is stateful a reference to the \\c RawAllocator will be stored inside the deleter,\n        /// the caller has to ensure that the object lives as long as the smart pointer.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator, typename... Args>\n        auto allocate_unique(RawAllocator&& alloc, Args&&... args) -> TRTLAB_REQUIRES_RET(\n            !std::is_array<T>::value,\n            std::unique_ptr<T, allocator_deleter<T, typename std::decay<RawAllocator>::type>>)\n        {\n            return detail::allocate_unique<T>(make_allocator_reference(\n                                                  detail::forward<RawAllocator>(alloc)),\n                                              detail::forward<Args>(args)...);\n        }\n\n        /// Creates a \\c std::unique_ptr using a type-erased \\concept{concept_rawallocator,RawAllocator} for the allocation.\n        /// It is the same as the other overload but stores the reference to the allocator type-erased inside the \\c std::unique_ptr.\n        /// \\effects Allocates memory for the given type using the allocator\n        /// and creates a new object inside it passing the given arguments to its constructor.\n        /// \\returns A \\c std::unique_ptr with a type-erased allocator reference owning that memory.\n        /// \\note If the allocator is stateful a reference to the \\c RawAllocator will be stored inside the deleter,\n        /// the caller has to ensure that the object lives as long as the smart pointer.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator, typename... Args>\n        auto allocate_unique(any_allocator, RawAllocator&& alloc, Args&&... args)\n            -> TRTLAB_REQUIRES_RET(!std::is_array<T>::value,\n                                      std::unique_ptr<T, allocator_deleter<T, any_allocator>>)\n        {\n            return detail::allocate_unique<T, any_allocator>(make_allocator_reference(\n                                                                 detail::forward<RawAllocator>(\n                                                                     alloc)),\n                                                             detail::forward<Args>(args)...);\n        }\n\n\n        /// Creates a \\c std::unique_ptr owning an array using a \\concept{concept_rawallocator,RawAllocator} for the allocation.\n        /// \\effects Allocates memory for an array of given size and value initializes each element inside of it.\n        /// \\returns A \\c std::unique_ptr owning that array.\n        /// \\note If the allocator is stateful a reference to the \\c RawAllocator will be stored inside the deleter,\n        /// the caller has to ensure that the object lives as long as the smart pointer.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator>\n        auto allocate_unique(RawAllocator&& alloc, std::size_t size) -> TRTLAB_REQUIRES_RET(\n            std::is_array<T>::value,\n            std::unique_ptr<T, allocator_deleter<T, typename std::decay<RawAllocator>::type>>)\n        {\n            return detail::allocate_array_unique<\n                typename std::remove_extent<T>::type>(size,\n                                                      make_allocator_reference(\n                                                          detail::forward<RawAllocator>(alloc)));\n        }\n\n        /// Creates a \\c std::unique_ptr owning an array using a type-erased \\concept{concept_rawallocator,RawAllocator} for the allocation.\n        /// It is the same as the other overload but stores the reference to the allocator type-erased inside the \\c std::unique_ptr.\n        /// \\effects Allocates memory for an array of given size and value initializes each element inside of it.\n        /// \\returns A \\c std::unique_ptr with a type-erased allocator reference owning that array.\n        /// \\note If the allocator is stateful a reference to the \\c RawAllocator will be stored inside the deleter,\n        /// the caller has to ensure that the object lives as long as the smart pointer.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator>\n        auto allocate_unique(any_allocator, RawAllocator&& alloc, std::size_t size)\n            -> TRTLAB_REQUIRES_RET(std::is_array<T>::value,\n                                      std::unique_ptr<T, allocator_deleter<T, any_allocator>>)\n        {\n            return detail::allocate_array_unique<typename std::remove_extent<T>::type,\n                                                 any_allocator>(size,\n                                                                make_allocator_reference(\n                                                                    detail::forward<RawAllocator>(\n                                                                        alloc)));\n        }\n\n        /// Creates a \\c std::shared_ptr using a \\concept{concept_rawallocator,RawAllocator} for the allocation.\n        /// It is similar to \\c std::allocate_shared but uses a \\c RawAllocator (and thus also supports any \\c Allocator).\n        /// \\effects Calls \\ref std_allocator::make_std_allocator to wrap the allocator and forwards to \\c std::allocate_shared.\n        /// \\returns A \\c std::shared_ptr created using \\c std::allocate_shared.\n        /// \\note If the allocator is stateful a reference to the \\c RawAllocator will be stored inside the shared pointer,\n        /// the caller has to ensure that the object lives as long as the smart pointer.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator, typename... Args>\n        std::shared_ptr<T> allocate_shared(RawAllocator&& alloc, Args&&... args)\n        {\n            return std::allocate_shared<T>(make_std_allocator<T>(\n                                               detail::forward<RawAllocator>(alloc)),\n                                           detail::forward<Args>(args)...);\n        }\n\n\n#if !defined(DOXYGEN)\n#include \"detail/container_node_sizes.h\"\n#else\n        /// Contains the node size needed for a `std::shared_ptr`.\n        /// These classes are auto-generated and only available if the tools are build and without cross-compiling.\n        /// \\ingroup memory adapter\n        template <typename T>\n        struct shared_ptr_node_size : std::integral_constant<std::size_t, implementation_defined>\n        {\n        };\n#endif\n\n    } // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_SMART_PTR_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/std_allocator.h",
    "content": "// MODIFICATION MESSAGE\n\n// Modification Notes:\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_STD_ALLOCATOR_H_INCLUDED\n#define TRTLAB_MEMORY_STD_ALLOCATOR_H_INCLUDED\n\n/// \\file\n/// Class \\ref foonathan::memory::std_allocator and related classes and functions.\n\n#include <new>\n#include <type_traits>\n\n#include \"detail/utility.h\"\n#include \"config.h\"\n#include \"allocator_storage.h\"\n#include \"threading.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace traits_detail\n        {\n            template <class RawAllocator>\n            auto propagate_on_container_swap(std_concept) ->\n                typename RawAllocator::propagate_on_container_swap;\n\n            template <class RawAllocator>\n            auto propagate_on_container_swap(min_concept) -> std::true_type;\n\n            template <class RawAllocator>\n            auto propagate_on_container_move_assignment(std_concept) ->\n                typename RawAllocator::propagate_on_container_move_assignment;\n\n            template <class RawAllocator>\n            auto propagate_on_container_move_assignment(min_concept) -> std::true_type;\n\n            template <class RawAllocator>\n            auto propagate_on_container_copy_assignment(std_concept) ->\n                typename RawAllocator::propagate_on_container_copy_assignment;\n\n            template <class RawAllocator>\n            auto propagate_on_container_copy_assignment(min_concept) -> std::true_type;\n        } // namespace traits_detail\n\n        /// Controls the propagation of a \\ref std_allocator for a certain \\concept{concept_rawallocator,RawAllocator}.\n        /// \\ingroup memory adapter\n        template <class RawAllocator>\n        struct propagation_traits\n        {\n            using propagate_on_container_swap =\n                decltype(traits_detail::propagate_on_container_swap<RawAllocator>(\n                    traits_detail::full_concept{}));\n\n            using propagate_on_container_move_assignment =\n                decltype(traits_detail::propagate_on_container_move_assignment<RawAllocator>(\n                    traits_detail::full_concept{}));\n\n            using propagate_on_container_copy_assignment =\n                decltype(traits_detail::propagate_on_container_copy_assignment<RawAllocator>(\n                    traits_detail::full_concept{}));\n\n            template <class AllocReference>\n            static AllocReference select_on_container_copy_construction(const AllocReference& alloc)\n            {\n                return alloc;\n            }\n        };\n\n        /// Wraps a \\concept{concept_rawallocator,RawAllocator} and makes it a \"normal\" \\c Allocator.\n        /// It allows using a \\c RawAllocator anywhere a \\c Allocator is required.\n        /// \\ingroup memory adapter\n        template <typename T, class RawAllocator>\n        class std_allocator :\n#if defined _MSC_VER && defined __clang__\n        TRTLAB_EBO(protected allocator_reference<RawAllocator>)\n#else\n        TRTLAB_EBO(allocator_reference<RawAllocator>)\n#endif\n        {\n            using alloc_reference = allocator_reference<RawAllocator>;\n            // if it is any_allocator_reference an optimized implementation can be used\n            using is_any = std::is_same<alloc_reference, any_allocator_reference>;\n\n            using prop_traits = propagation_traits<RawAllocator>;\n\n        public:\n            //=== typedefs ===//\n            using value_type      = T;\n            using pointer         = T*;\n            using const_pointer   = const T*;\n            using reference       = T&;\n            using const_reference = const T&;\n            using size_type       = std::size_t;\n            using difference_type = std::ptrdiff_t;\n\n            using propagate_on_container_swap = typename prop_traits::propagate_on_container_swap;\n            using propagate_on_container_move_assignment =\n                typename prop_traits::propagate_on_container_move_assignment;\n            using propagate_on_container_copy_assignment =\n                typename prop_traits::propagate_on_container_copy_assignment;\n\n            template <typename U>\n            struct rebind\n            {\n                using other = std_allocator<U, RawAllocator>;\n            };\n\n            using allocator_type = typename alloc_reference::allocator_type;\n\n            //=== constructor ===//\n            /// \\effects Default constructs it by storing a default constructed, stateless \\c RawAllocator inside the reference.\n            /// \\requires The \\c RawAllocator type is stateless, otherwise the body of this function will not compile.\n            std_allocator() noexcept : alloc_reference(allocator_type{})\n            {\n#if !defined(__GNUC__) || (defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI != 0)\n                // std::string requires default constructor for the small string optimization when using gcc's old ABI\n                // so don't assert then to allow joint allocator\n                static_assert(!alloc_reference::is_stateful::value,\n                              \"default constructor must not be used for stateful allocators\");\n#endif\n            }\n\n            /// \\effects Creates it from a reference to a \\c RawAllocator.\n            /// It will store an \\ref allocator_reference to it.\n            /// \\requires The expression <tt>allocator_reference<RawAllocator>(alloc)</tt> is well-formed,\n            /// that is either \\c RawAlloc is the same as \\c RawAllocator or \\c RawAllocator is the tag type \\ref any_allocator.\n            /// If the requirement is not fulfilled this function does not participate in overload resolution.\n            /// \\note The caller has to ensure that the lifetime of the \\c RawAllocator is at least as long as the lifetime\n            /// of this \\ref std_allocator object.\n            template <\n                class RawAlloc,\n                // MSVC seems to ignore access rights in decltype SFINAE below\n                // use this to prevent this constructor being chosen instead of move/copy for types inheriting from it\n                TRTLAB_REQUIRES((!std::is_base_of<std_allocator, RawAlloc>::value))>\n            std_allocator(RawAlloc& alloc,\n                          TRTLAB_SFINAE(alloc_reference(alloc))) noexcept\n            : alloc_reference(alloc)\n            {\n            }\n\n            /// \\effects Creates it from a stateless, temporary \\c RawAllocator object.\n            /// It will not store a reference but create it on the fly.\n            /// \\requires The \\c RawAllocator is stateless\n            /// and the expression <tt>allocator_reference<RawAllocator>(alloc)</tt> is well-formed as above,\n            /// otherwise this function does not participate in overload resolution.\n            template <\n                class RawAlloc,\n                // MSVC seems to ignore access rights in decltype SFINAE below\n                // use this to prevent this constructor being chosen instead of move/copy for types inheriting from it\n                TRTLAB_REQUIRES((!std::is_base_of<std_allocator, RawAlloc>::value))>\n            std_allocator(const RawAlloc& alloc,\n                          TRTLAB_SFINAE(alloc_reference(alloc))) noexcept\n            : alloc_reference(alloc)\n            {\n            }\n\n            /// \\effects Creates it from another \\ref allocator_reference using the same allocator type and mutex.\n            std_allocator(const alloc_reference& alloc) noexcept : alloc_reference(alloc)\n            {\n            }\n\n            /// \\details Implicit conversion from any other \\ref allocator_storage is forbidden\n            /// to prevent accidentally wrapping another \\ref allocator_storage inside a \\ref allocator_reference.\n            template <class StoragePolicy, class OtherMut>\n            std_allocator(const allocator_storage<StoragePolicy, OtherMut>&) = delete;\n\n            /// @{\n            /// \\effects Creates it from another \\ref std_allocator allocating a different type.\n            /// This is required by the \\c Allcoator concept and simply takes the same \\ref allocator_reference.\n            template <typename U>\n            std_allocator(const std_allocator<U, RawAllocator>& alloc) noexcept\n            : alloc_reference(alloc)\n            {\n            }\n\n            template <typename U>\n            std_allocator(std_allocator<U, RawAllocator>& alloc) noexcept\n            : alloc_reference(alloc)\n            {\n            }\n            /// @}\n\n            /// \\returns A copy of the allocator.\n            /// This is required by the \\c Allocator concept and forwards to the \\ref propagation_traits.\n            std_allocator<T, RawAllocator> select_on_container_copy_construction() const\n            {\n                return prop_traits::select_on_container_copy_construction(*this);\n            }\n\n            //=== allocation/deallocation ===//\n            /// \\effects Allocates memory using the underlying \\concept{concept_rawallocator,RawAllocator}.\n            /// If \\c n is \\c 1, it will call <tt>allocate_node(sizeof(T), alignof(T))</tt>,\n            /// otherwise <tt>allocate_array(n, sizeof(T), alignof(T))</tt>.\n            /// \\returns A pointer to a memory block suitable for \\c n objects of type \\c T.\n            /// \\throws Anything thrown by the \\c RawAllocator.\n            pointer allocate(size_type n, void* = nullptr)\n            {\n                return static_cast<pointer>(allocate_impl(is_any{}, n));\n            }\n\n            /// \\effects Deallcoates memory using the underlying \\concept{concept_rawallocator,RawAllocator}.\n            /// It will forward to the deallocation function in the same way as in \\ref allocate().\n            /// \\requires The pointer must come from a previous call to \\ref allocate() with the same \\c n on this object or any copy of it.\n            void deallocate(pointer p, size_type n) noexcept\n            {\n                deallocate_impl(is_any{}, p, n);\n            }\n\n            //=== construction/destruction ===//\n            /// \\effects Creates an object of type \\c U at given address using the passed arguments.\n            template <typename U, typename... Args>\n            void construct(U* p, Args&&... args)\n            {\n                void* mem = p;\n                ::new (mem) U(detail::forward<Args>(args)...);\n            }\n\n            /// \\effects Calls the destructor for an object of type \\c U at given address.\n            template <typename U>\n            void destroy(U* p) noexcept\n            {\n                // This is to avoid a MSVS 2015 'unreferenced formal parameter' warning\n                (void)p;\n                p->~U();\n            }\n\n            //=== getter ===//\n            /// \\returns The maximum size for an allocation which is <tt>max_array_size() / sizeof(value_type)</tt>.\n            /// This is only an upper bound, not the exact maximum.\n            size_type max_size() const noexcept\n            {\n                return this->max_array_size() / sizeof(value_type);\n            }\n\n            /// @{\n            /// \\effects Returns a reference to the referenced allocator.\n            /// \\returns For stateful allocators: A (\\c const) reference to the stored allocator.\n            /// For stateless allocators: A temporary constructed allocator.\n            auto get_allocator() noexcept\n                -> decltype(std::declval<alloc_reference>().get_allocator())\n            {\n                return alloc_reference::get_allocator();\n            }\n\n            auto get_allocator() const noexcept\n                -> decltype(std::declval<const alloc_reference>().get_allocator())\n            {\n                return alloc_reference::get_allocator();\n            }\n            /// @}\n\n        private:\n            // any_allocator_reference: use virtual function which already does a dispatch on node/array\n            void* allocate_impl(std::true_type, size_type n)\n            {\n                return get_allocator()->allocate_impl(n, sizeof(T), alignof(T));\n            }\n\n            void deallocate_impl(std::true_type, void* ptr, size_type n)\n            {\n                get_allocator()->deallocate_impl(ptr, n, sizeof(T), alignof(T));\n            }\n\n            // alloc_reference: decide between node/array\n            void* allocate_impl(std::false_type, size_type n)\n            {\n                if (n == 1)\n                    return this->allocate_node(sizeof(T), alignof(T));\n                else\n                    return this->allocate_array(n, sizeof(T), alignof(T));\n            }\n\n            void deallocate_impl(std::false_type, void* ptr, size_type n)\n            {\n                if (n == 1)\n                    this->deallocate_node(ptr, sizeof(T), alignof(T));\n                else\n                    this->deallocate_array(ptr, n, sizeof(T), alignof(T));\n            }\n\n            template <typename U> // stateful\n            bool equal_to_impl(std::true_type, const std_allocator<U, RawAllocator>& other) const noexcept\n            {\n                return &get_allocator() == &other.get_allocator();\n            }\n\n            template <typename U> // non-stateful\n            bool equal_to_impl(std::false_type, const std_allocator<U, RawAllocator>&) const noexcept\n            {\n                return true;\n            }\n\n            template <typename U> // shared\n            bool equal_to(std::true_type, const std_allocator<U, RawAllocator>& other) const noexcept\n            {\n                return get_allocator() == other.get_allocator();\n            }\n\n            template <typename U> // not shared\n            bool equal_to(std::false_type, const std_allocator<U, RawAllocator>& other) const\n                noexcept\n            {\n                return equal_to_impl(typename allocator_traits<RawAllocator>::is_stateful{}, other);\n            }\n\n            template <typename T1, typename T2, class Impl>\n            friend bool operator==(const std_allocator<T1, Impl>& lhs,\n                                   const std_allocator<T2, Impl>& rhs) noexcept;\n\n            template <typename U, class OtherRawAllocator>\n            friend class std_allocator;\n        };\n\n        /// \\effects Compares two \\ref std_allocator object, they are equal if either stateless or reference the same allocator.\n        /// \\returns The result of the comparision for equality.\n        /// \\relates std_allocator\n        template <typename T, typename U, class Impl>\n        bool operator==(const std_allocator<T, Impl>& lhs,\n                        const std_allocator<U, Impl>& rhs) noexcept\n        {\n            return lhs.equal_to(is_shared_allocator<Impl>{}, rhs);\n        }\n\n        /// \\effects Compares two \\ref std_allocator object, they are equal if either stateless or reference the same allocator.\n        /// \\returns The result of the comparision for inequality.\n        /// \\relates std_allocator\n        template <typename T, typename U, class Impl>\n        bool operator!=(const std_allocator<T, Impl>& lhs,\n                        const std_allocator<U, Impl>& rhs) noexcept\n        {\n            return !(lhs == rhs);\n        }\n\n        /// \\returns A new \\ref std_allocator for a given type using a certain allocator object.\n        /// \\relates std_allocator\n        template <typename T, class RawAllocator>\n        auto make_std_allocator(RawAllocator&& allocator) noexcept\n            -> std_allocator<T, typename std::decay<RawAllocator>::type>\n        {\n            return {detail::forward<RawAllocator>(allocator)};\n        }\n\n        /// An alias template for \\ref std_allocator using a type-erased \\concept{concept_rawallocator,RawAllocator}.\n        /// This is the same as using a \\ref std_allocator with the tag type \\ref any_allocator.\n        /// The implementation is optimized to call fewer virtual functions.\n        /// \\ingroup memory adapter\n        template <typename T>\n        TRTLAB_ALIAS_TEMPLATE(any_std_allocator, std_allocator<T, any_allocator>);\n\n        /// \\returns A new \\ref any_std_allocator for a given type using a certain allocator object.\n        /// \\relates any_std_allocator\n        template <typename T, class RawAllocator>\n        any_std_allocator<T> make_any_std_allocator(RawAllocator&& allocator) noexcept\n        {\n            return {detail::forward<RawAllocator>(allocator)};\n        }\n    }\n} // namespace trtlab::memory\n\n#endif // TRTLAB_MEMORY_STD_ALLOCATOR_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/threading.h",
    "content": "// MODIFICATION_MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_THREADING_H_INCLUDED\n#define TRTLAB_MEMORY_THREADING_H_INCLUDED\n\n/// \\file\n/// The \\ref foonathan::memory::default_mutex.\n\n#include <type_traits>\n\n#include \"allocator_traits.h\"\n#include \"config.h\"\n\n#include <mutex>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        /// A dummy \\c Mutex class that does not lock anything.\n        /// It is a valid \\c Mutex and can be used to disable locking anywhere a \\c Mutex is requested.\n        /// \\ingroup memory core\n        struct no_mutex\n        {\n            void lock() noexcept {}\n\n            bool try_lock() noexcept\n            {\n                return true;\n            }\n\n            void unlock() noexcept {}\n        };\n\n#if TRTLAB_MEMORY_THREAD_SAFE_REFERENCE\n        using default_mutex = std::mutex;\n#else\n        /// The default \\c Mutex type used as default template paremeter in, e.g. \\ref allocator_reference.\n        /// If the CMake option \\ref TRTLAB_MEMORY_THREAD_SAFE_REFERENCE is \\c true and there is threading support,\n        /// it is \\c std::mutex, else \\ref no_mutex.\n        /// \\ingroup memory core\n        using default_mutex = no_mutex;\n#endif\n\n        /// Specifies whether or not a \\concept{concept_rawallocator,RawAllocator} is thread safe as-is.\n        /// This allows to use \\ref no_mutex as an optimization.\n        /// Note that stateless allocators are implictly thread-safe.\n        /// Specialize it only for your own stateful allocators.\n        /// \\ingroup memory core\n        template <class RawAllocator>\n        struct is_thread_safe_allocator : std::integral_constant<bool, !allocator_traits<RawAllocator>::is_stateful::value>\n        {\n        };\n\n        namespace detail\n        {\n            // selects a mutex for an Allocator\n            // stateless allocators don't need locking\n            template <class RawAllocator, class Mutex>\n            using mutex_for = typename std::conditional<is_thread_safe_allocator<RawAllocator>::value, no_mutex, Mutex>::type;\n\n            // storage for mutexes to use EBO\n            // it provides const lock/unlock function, inherit from it\n            template <class Mutex>\n            class mutex_storage\n            {\n            public:\n                mutex_storage() noexcept = default;\n                mutex_storage(const mutex_storage&) noexcept {}\n\n                mutex_storage& operator=(const mutex_storage&) noexcept\n                {\n                    return *this;\n                }\n\n                void lock() const\n                {\n                    mutex_.lock();\n                }\n\n                void unlock() const noexcept\n                {\n                    mutex_.unlock();\n                }\n\n            protected:\n                ~mutex_storage() noexcept = default;\n\n            private:\n                mutable Mutex mutex_;\n            };\n\n            template <>\n            class mutex_storage<no_mutex>\n            {\n            public:\n                mutex_storage() noexcept = default;\n\n                void lock() const noexcept {}\n                void unlock() const noexcept {}\n\n            protected:\n                ~mutex_storage() noexcept = default;\n            };\n\n            // non changeable pointer to an Allocator that keeps a lock\n            // I don't think EBO is necessary here...\n            template <class Alloc, class Mutex>\n            class locked_allocator\n            {\n            public:\n                locked_allocator(Alloc& alloc, Mutex& m) noexcept : mutex_(&m), alloc_(&alloc)\n                {\n                    mutex_->lock();\n                }\n\n                locked_allocator(locked_allocator&& other) noexcept : mutex_(other.mutex_), alloc_(other.alloc_)\n                {\n                    other.mutex_ = nullptr;\n                    other.alloc_ = nullptr;\n                }\n\n                ~locked_allocator() noexcept\n                {\n                    if (mutex_)\n                        mutex_->unlock();\n                }\n\n                locked_allocator& operator=(locked_allocator&& other) noexcept = delete;\n\n                Alloc& operator*() const noexcept\n                {\n                    TRTLAB_MEMORY_ASSERT(alloc_);\n                    return *alloc_;\n                }\n\n                Alloc* operator->() const noexcept\n                {\n                    TRTLAB_MEMORY_ASSERT(alloc_);\n                    return alloc_;\n                }\n\n            private:\n                Mutex* mutex_; // don't use unqiue_lock to avoid dependency\n                Alloc* alloc_;\n            };\n\n            template <class Alloc, class Mutex>\n            locked_allocator<Alloc, Mutex> lock_allocator(Alloc& a, Mutex& m)\n            {\n                return {a, m};\n            }\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_THREADING_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/trackers.h",
    "content": "#pragma once\n#include <cstdlib>\n#include <memory>\n#include <experimental/propagate_const>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        struct size_tracker\n        {\n            size_tracker();\n            ~size_tracker();\n\n            size_tracker(const size_tracker&) = delete;\n            size_tracker& operator=(const size_tracker&) = delete;\n\n            size_tracker(size_tracker&&) noexcept;\n            size_tracker& operator=(size_tracker&&) noexcept;\n\n            void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept;\n            void on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept;\n            void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n            void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n\n            std::size_t bytes() const noexcept;\n\n        private:\n            struct impl;\n            std::experimental::propagate_const<std::unique_ptr<impl>> pimpl;\n        };\n\n        /*\n\n// todo\n\nstruct histogram_tracker\n{\n    histogram_tracker();\n    ~histogram_tracker();\n\n    histogram_tracker(const histogram_tracker&) = delete;\n    histogram_tracker& operator=(const histogram_tracker&) = delete;\n\n    histogram_tracker(histogram_tracker&&) noexcept;\n    histogram_tracker& operator=(histogram_tracker&&) noexcept;\n\n    void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept;\n    void on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept;\n    void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n    void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept;\n\n    std::size_t bytes() const noexcept;\n\nprivate:\n    struct impl;\n    std::experimental::propagate_const<std::unique_ptr<impl>> pimpl;\n};\n\n*/\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/tracking.h",
    "content": "// MODIFiCATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_TRACKING_H_INCLUDED\n#define TRTLAB_MEMORY_TRACKING_H_INCLUDED\n\n/// \\file\n/// Class \\ref foonathan::memory::tracked_allocator and related classes and functions.\n\n#include \"detail/utility.h\"\n#include \"allocator_traits.h\"\n#include \"memory_block.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            template <class Tracker, class BlockAllocator>\n            class deeply_tracked_block_allocator;\n\n            template <class Tracker, class BlockAllocator>\n            void set_tracker(deeply_tracked_block_allocator<Tracker, BlockAllocator>& alloc, Tracker* t) noexcept\n            {\n                alloc.tracker_ = t;\n            }\n\n            template <class Allocator, class Tracker>\n            void set_tracker(Allocator&, Tracker*)\n            {\n            }\n\n            // used with deeply_tracked_allocator\n            template <class Tracker, class BlockAllocator>\n            class deeply_tracked_block_allocator : TRTLAB_EBO(BlockAllocator)\n            {\n            public:\n                template <typename... Args>\n                deeply_tracked_block_allocator(std::size_t block_size, Args&&... args)\n                : BlockAllocator(block_size, detail::forward<Args>(args)...), tracker_(nullptr)\n                {\n                }\n\n                memory_block allocate_block()\n                {\n                    auto block = BlockAllocator::allocate_block();\n                    if (tracker_) // on first call tracker_ is nullptr\n                        tracker_->on_allocator_growth(block.memory, block.size);\n                    return block;\n                }\n\n                void deallocate_block(memory_block block) noexcept\n                {\n                    if (tracker_) // on last call tracker_ is nullptr again\n                        tracker_->on_allocator_shrinking(block.memory, block.size);\n                    BlockAllocator::deallocate_block(block);\n                }\n\n                std::size_t next_block_size() const noexcept\n                {\n                    return BlockAllocator::next_block_size();\n                }\n\n            private:\n                Tracker* tracker_;\n\n                friend void set_tracker<>(deeply_tracked_block_allocator&, Tracker*) noexcept;\n            };\n\n        } // namespace detail\n\n        /*\n\n        /// A \\concept{concept_blockallocator,BlockAllocator} adapter that tracks another allocator using a \\concept{concept_tracker,tracker}.\n        /// It wraps another \\concept{concept_blockallocator,BlockAllocator} and calls the tracker function before forwarding to it.\n        /// The class can then be used anywhere a \\concept{concept_blockallocator,BlockAllocator} is required and the memory usage will be tracked.<br>\n        /// It will only call the <tt>on_allocator_growth()</tt> and <tt>on_allocator_shrinking()</tt> tracking functions,\n        /// since a \\concept{concept_blockallocator,BlockAllocator} is normally used inside higher allocators only.\n        /// \\ingroup memory adapter\n        template <class Tracker, class BlockOrRawAllocator>\n        class tracked_block_allocator\n            : TRTLAB_EBO(Tracker, make_block_allocator_t<BlockOrRawAllocator>)\n        {\n        public:\n            using allocator_type = make_block_allocator_t<BlockOrRawAllocator>;\n            using tracker        = Tracker;\n\n            /// @{\n            /// \\effects Creates it by giving it a \\concept{concept_tracker,tracker} and the tracked \\concept{concept_rawallocator,RawAllocator}.\n            /// It will embed both objects.\n            explicit tracked_block_allocator(tracker t = {}) noexcept\n                : tracker(detail::move(t))\n            {\n            }\n\n            tracked_block_allocator(tracker t, allocator_type&& alloc) noexcept\n                : tracker(detail::move(t)),\n                  allocator_type(detail::move(alloc))\n            {\n            }\n            /// @}\n\n            /// \\effects Creates it in the form required by the concept.\n            /// The allocator will be constructed using \\c block_size and \\c args.\n            template <typename... Args>\n            tracked_block_allocator(std::size_t block_size, tracker t, Args&&... args)\n            : tracker(detail::move(t)), allocator_type(block_size, detail::forward<Args>(args)...)\n            {\n            }\n\n            /// \\effects Calls <tt>Tracker::on_allocator_growth()</tt> after forwarding to the allocator.\n            /// \\returns The block as the returned by the allocator.\n            memory_block allocate_block()\n            {\n                auto block = allocator_type::allocate_block();\n                this->on_allocator_growth(block.memory, block.size);\n                return block;\n            }\n\n            /// \\effects Calls <tt>Tracker::on_allocator_shrinking()</tt> and forwards to the allocator.\n            void deallocate_block(memory_block block) noexcept\n            {\n                this->on_allocator_shrinking(block.memory, block.size);\n                allocator_type::deallocate_block(block);\n            }\n\n            /// \\returns The next block size as returned by the allocator.\n            std::size_t next_block_size() const noexcept\n            {\n                return allocator_type::next_block_size();\n            }\n\n            /// @{\n            /// \\returns A (const) reference to the used allocator.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n\n            /// @{\n            /// \\returns A (const) reference to the tracker.\n            tracker& get_tracker() noexcept\n            {\n                return *this;\n            }\n\n            const tracker& get_tracker() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n        };\n\n        /// Similar to \\ref tracked_block_allocator, but shares the tracker with the higher level allocator.\n        /// This allows tracking both (de-)allocations and growth with one tracker.\n        /// \\note Due to implementation reasons, it cannot track growth and shrinking in the constructor/destructor of the higher level allocator.\n        /// \\ingroup memory adapter\n        template <class Tracker, class BlockOrRawAllocator>\n        using deeply_tracked_block_allocator = TRTLAB_IMPL_DEFINED(\n            detail::deeply_tracked_block_allocator<Tracker,\n                                                   make_block_allocator_t<BlockOrRawAllocator>>);\n\n\n        */\n\n        /// A \\concept{concept_rawallocator,RawAllocator} adapter that tracks another allocator using a \\concept{concept_tracker,tracker}.\n        /// It wraps another \\concept{concept_rawallocator,RawAllocator} and calls the tracker function before forwarding to it.\n        /// The class can then be used anywhere a \\concept{concept_rawallocator,RawAllocator} is required and the memory usage will be tracked.<br>\n        /// If the \\concept{concept_rawallocator,RawAllocator} uses \\ref deeply_tracked_block_allocator as \\concept{concept_blockallocator,BlockAllocator},\n        /// it will also track growth and shrinking of the allocator.\n        /// \\ingroup memory adapter\n        template <class Tracker, class RawAllocator>\n        class tracked_allocator : TRTLAB_EBO(Tracker, allocator_traits<RawAllocator>::allocator_type)\n        {\n            using traits            = allocator_traits<RawAllocator>;\n            using composable_traits = composable_allocator_traits<RawAllocator>;\n\n        public:\n            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;\n            using tracker        = Tracker;\n\n            using is_stateful = std::integral_constant<bool, traits::is_stateful::value || !std::is_empty<Tracker>::value>;\n            using memory_type = typename traits::memory_type;\n\n            /// @{\n            /// \\effects Creates it by giving it a \\concept{concept_tracker,tracker} and the tracked \\concept{concept_rawallocator,RawAllocator}.\n            /// It will embed both objects.\n            /// \\note This will never call the <tt>Tracker::on_allocator_growth()</tt> function.\n            explicit tracked_allocator(tracker t = {}) noexcept : tracked_allocator(detail::move(t), allocator_type{}) {}\n\n            tracked_allocator(tracker t, allocator_type&& allocator) noexcept\n            : tracker(detail::move(t)), allocator_type(detail::move(allocator))\n            {\n                //detail::set_tracker(get_allocator().get_allocator(), &get_tracker());\n            }\n            /// @}\n\n            /// \\effects Destroys both tracker and allocator.\n            /// \\note This will never call the <tt>Tracker::on_allocator_shrinking()</tt> function.\n            ~tracked_allocator() noexcept\n            {\n                //detail::set_tracker(get_allocator().get_allocator(), static_cast<tracker*>(nullptr));\n            }\n\n            /// @{\n            /// \\effects Moving moves both the tracker and the allocator.\n            tracked_allocator(tracked_allocator&& other) noexcept : tracker(detail::move(other)), allocator_type(detail::move(other))\n            {\n                //detail::set_tracker(get_allocator().get_allocator(), &get_tracker());\n            }\n\n            tracked_allocator& operator=(tracked_allocator&& other) noexcept\n            {\n                tracker::       operator=(detail::move(other));\n                allocator_type::operator=(detail::move(other));\n                //detail::set_tracker(get_allocator().get_allocator(), &get_tracker());\n                return *this;\n            }\n            /// @}\n\n            /// \\effects Calls <tt>Tracker::on_node_allocation()</tt> and forwards to the allocator.\n            /// If a growth occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_growth()</tt>.\n            /// \\returns The result of <tt>allocate_node()</tt>\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                auto mem = traits::allocate_node(get_allocator(), size, alignment);\n                this->on_node_allocation(mem, size, alignment);\n                return mem;\n            }\n\n            /// \\effects Calls the composable node allocation function.\n            /// If allocation was successful, also calls `Tracker::on_node_allocation()`.\n            /// \\returns The result of `try_allocate_node()`.\n            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept\n            {\n                auto mem = composable_traits::try_allocate_node(get_allocator(), size, alignment);\n                if (mem)\n                    this->on_node_allocation(mem, size, alignment);\n                return mem;\n            }\n\n            /// \\effects Calls <tt>Tracker::on_array_allocation()</tt> and forwards to the allocator.\n            /// If a growth occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_growth()</tt>.\n            /// \\returns The result of <tt>allocate_array()</tt>\n            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)\n            {\n                auto mem = traits::allocate_array(get_allocator(), count, size, alignment);\n                this->on_array_allocation(mem, count, size, alignment);\n                return mem;\n            }\n\n            /// \\effects Calls the composable array allocation function.\n            /// If allocation was succesful, also calls `Tracker::on_array_allocation()`.\n            /// \\returns The result of `try_allocate_array()`.\n            void* try_allocate_array(std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                auto mem = composable_traits::try_allocate_array(get_allocator(), count, size, alignment);\n                if (mem)\n                    this->on_array_allocation(mem, count, size, alignment);\n                return mem;\n            }\n\n            /// \\effects Calls <tt>Tracker::on_node_deallocation()</tt> and forwards to the allocator's <tt>deallocate_node()</tt>.\n            /// If shrinking occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_shrinking()</tt>.\n            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                this->on_node_deallocation(ptr, size, alignment);\n                traits::deallocate_node(get_allocator(), ptr, size, alignment);\n            }\n\n            /// \\effects Calls the composable node deallocation function.\n            /// If it was succesful, also calls `Tracker::on_node_deallocation()`.\n            /// \\returns The result of `try_deallocate_node()`.\n            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                auto res = composable_traits::try_deallocate_node(get_allocator(), ptr, size, alignment);\n                if (res)\n                    this->on_node_deallocation(ptr, size, alignment);\n                return res;\n            }\n\n            /// \\effects Calls <tt>Tracker::on_array_deallocation()</tt> and forwards to the allocator's <tt>deallocate_array()</tt>.\n            /// If shrinking occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_shrinking()</tt>.\n            void deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                this->on_array_deallocation(ptr, count, size, alignment);\n                traits::deallocate_array(get_allocator(), ptr, count, size, alignment);\n            }\n\n            /// \\effects Calls the composable array deallocation function.\n            /// If it was succesful, also calls `Tracker::on_array_deallocation()`.\n            /// \\returns The result of `try_deallocate_array()`.\n            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n            {\n                auto res = composable_traits::try_deallocate_array(ptr, count, size, alignment);\n                if (res)\n                    this->on_array_deallocation(ptr, count, size, alignment);\n                return res;\n            }\n\n            /// @{\n            /// \\returns The result of the corresponding function on the wrapped allocator.\n            std::size_t max_node_size() const\n            {\n                return traits::max_node_size(get_allocator());\n            }\n\n            std::size_t max_array_size() const\n            {\n                return traits::max_array_size(get_allocator());\n            }\n\n            std::size_t max_alignment() const\n            {\n                return traits::max_alignment(get_allocator());\n            }\n\n            std::size_t min_alignment() const\n            {\n                return traits::min_alignment(get_allocator());\n            }\n\n            DLContext device_context() const\n            {\n                return traits::device_context(get_allocator());\n            }\n            /// @}\n\n            /// @{\n            /// \\returns A (\\c const) reference to the wrapped allocator.\n            allocator_type& get_allocator() noexcept\n            {\n                return *this;\n            }\n\n            const allocator_type& get_allocator() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n\n            /// @{\n            /// \\returns A (\\c const) reference to the tracker.\n            tracker& get_tracker() noexcept\n            {\n                return *this;\n            }\n\n            const tracker& get_tracker() const noexcept\n            {\n                return *this;\n            }\n            /// @}\n        };\n\n        /// \\effects Takes a \\concept{concept_rawallocator,RawAllocator} and wraps it with a \\concept{concept_tracker,tracker}.\n        /// \\returns A \\ref tracked_allocator with the corresponding parameters forwarded to the constructor.\n        /// \\relates tracked_allocator\n        template <class Tracker, class RawAllocator>\n        auto make_tracked_allocator(Tracker t, RawAllocator&& alloc) -> tracked_allocator<Tracker, typename std::decay<RawAllocator>::type>\n        {\n            return tracked_allocator<Tracker, typename std::decay<RawAllocator>::type>{detail::move(t), detail::move(alloc)};\n        }\n\n        /*\n        namespace detail\n        {\n            template <typename T, bool Block>\n            struct is_block_or_raw_allocator_impl : std::true_type\n            {\n            };\n\n            template <typename T>\n            struct is_block_or_raw_allocator_impl<T, false> : memory::is_raw_allocator<T>\n            {\n            };\n\n            template <typename T>\n            struct is_block_or_raw_allocator\n                : is_block_or_raw_allocator_impl<T, memory::is_block_allocator<T>::value>\n            {\n            };\n\n            template <class RawAllocator, class BlockAllocator>\n            struct rebind_block_allocator;\n\n            template <template <typename...> class RawAllocator, typename... Args,\n                      class OtherBlockAllocator>\n            struct rebind_block_allocator<RawAllocator<Args...>, OtherBlockAllocator>\n            {\n                using type =\n                    RawAllocator<typename std::conditional<is_block_or_raw_allocator<Args>::value,\n                                                           OtherBlockAllocator, Args>::type...>;\n            };\n\n            template <class Tracker, class RawAllocator>\n            using deeply_tracked_block_allocator_for =\n                memory::deeply_tracked_block_allocator<Tracker,\n                                                       typename RawAllocator::allocator_type>;\n\n            template <class Tracker, class RawAllocator>\n            using rebound_allocator =\n                typename rebind_block_allocator<RawAllocator,\n                                                deeply_tracked_block_allocator_for<Tracker,\n                                                                                   RawAllocator>>::\n                    type;\n        } // namespace detail\n\n        /// A \\ref tracked_allocator that has rebound any \\concept{concept_blockallocator,BlockAllocator} to the corresponding \\ref deeply_tracked_block_allocator.\n        /// This makes it a deeply tracked allocator.<br>\n        /// It replaces each template argument of the given \\concept{concept_rawallocator,RawAllocator} for which \\ref is_block_allocator or \\ref is_raw_allocator is \\c true with a \\ref deeply_tracked_block_allocator.\n        /// \\ingroup memory adapter\n        template <class Tracker, class RawAllocator>\n        TRTLAB_ALIAS_TEMPLATE(\n            deeply_tracked_allocator,\n            tracked_allocator<Tracker, detail::rebound_allocator<Tracker, RawAllocator>>);\n\n        /// \\effects Takes a \\concept{concept_rawallocator,RawAllocator} and deeply wraps it with a \\concept{concept_tracker,tracker}.\n        /// \\returns A \\ref deeply_tracked_allocator with the corresponding parameters forwarded to the constructor.\n        /// \\relates deeply_tracked_allocator\n        template <class RawAllocator, class Tracker, typename... Args>\n        auto make_deeply_tracked_allocator(Tracker t, Args&&... args)\n            -> deeply_tracked_allocator<Tracker, RawAllocator>\n        {\n            return deeply_tracked_allocator<Tracker, RawAllocator>(detail::move(t),\n                                                                   {detail::forward<Args>(\n                                                                       args)...});\n        }\n        */\n    } // namespace memory\n\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_TRACKING_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/transactional_allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <cstddef>\n#include <map>\n#include <queue>\n#include <utility>\n\n#include <glog/logging.h>\n\n#include \"block_allocators.h\"\n#include \"block_arena.h\"\n#include \"block_manager.h\"\n#include \"error.h\"\n\n#include \"detail/memory_stack.h\"\n//#include <foonathan/memory/allocator_storage.hpp>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace transactional_detail\n        {\n            class basic_stack : public memory_block, private detail::fixed_memory_stack\n            {\n                using stack = detail::fixed_memory_stack;\n\n            public:\n                basic_stack() noexcept : memory_block(), fixed_memory_stack(nullptr), m_end(nullptr) {}\n\n                basic_stack(void* ptr, std::size_t size) noexcept : memory_block(ptr, size), fixed_memory_stack(ptr), m_end(top() + size) {}\n\n                basic_stack(basic_stack&& other) noexcept\n                : memory_block(std::move(other)), fixed_memory_stack(std::move(other)), m_end(std::exchange(other.m_end, nullptr))\n                {\n                }\n\n                basic_stack& operator=(basic_stack&& other) noexcept\n                {\n                    m_end                               = std::exchange(other.m_end, nullptr);\n                    detail::fixed_memory_stack::operator=(std::move(other));\n                    memory_block::              operator=(std::move(other));\n                    return *this;\n                }\n\n                void* allocate(std::size_t size_, std::size_t alignment) noexcept\n                {\n                    return detail::fixed_memory_stack::allocate(m_end, size_, alignment);\n                }\n\n                std::size_t available() const noexcept\n                {\n                    return std::size_t(m_end - top());\n                }\n\n                std::size_t capacity() const noexcept\n                {\n                    return size;\n                };\n\n                bool contains(const void* ptr) const noexcept\n                {\n                    if (!ptr && !m_end)\n                    {\n                        return true;\n                    }\n                    return memory_block::contains(ptr);\n                }\n\n                const memory_block& get_memory_block() const noexcept\n                {\n                    return *this;\n                }\n\n            private:\n                char* m_end;\n            };\n\n            class ref_counted_stack : public basic_stack\n            {\n            public:\n                ref_counted_stack() noexcept : basic_stack(nullptr, 0u), m_count(0u) {}\n                explicit ref_counted_stack(const memory_block& block) noexcept : basic_stack(block.memory, block.size), m_count(0u) {}\n                explicit ref_counted_stack(void* ptr, std::size_t size) noexcept : basic_stack(ptr, size), m_count(0u) {}\n\n                ref_counted_stack(ref_counted_stack&& other) noexcept\n                : basic_stack(std::move(other)), m_count(std::exchange(other.m_count, 0u))\n                {\n                }\n\n                ref_counted_stack& operator=(ref_counted_stack&& other) noexcept\n                {\n                    basic_stack::operator=(std::move(other));\n                    m_count              = std::exchange(other.m_count, 0u);\n                    return *this;\n                }\n\n                void* allocate(std::size_t size, std::size_t alignment) noexcept\n                {\n                    auto ptr = basic_stack::allocate(size, alignment);\n                    if (ptr)\n                    {\n                        m_count++;\n                    }\n                    return ptr;\n                }\n\n                bool should_release_after_deallocate(void* ptr) noexcept\n                {\n                    DCHECK(contains(ptr));\n                    DCHECK(m_count) << \"Caught more deallocates than allocates\";\n                    if (m_count && --m_count)\n                    {\n                        return false;\n                    }\n                    return true;\n                }\n\n                std::size_t use_count() const noexcept\n                {\n                    return m_count;\n                }\n\n            private:\n                std::size_t m_count;\n            };\n\n        } // namespace transactional_detail\n\n        template <typename BlockAllocator, typename ListType>\n        class transactional_allocator\n        : TRTLAB_EBO(block_arena<BlockAllocator, cached_arena, ListType>)\n        {\n            static_assert(is_block_allocator<BlockAllocator>::value, \"BlockAllocator is not a BlockAllocator!\");\n\n            using list_type  = ListType;\n            using stack_type = transactional_detail::ref_counted_stack;\n            using arena_type = block_arena<BlockAllocator, cached_arena, list_type>;\n\n            stack_type                m_current_stack;\n            block_manager<stack_type> m_in_use_stacks;\n            std::size_t               m_max_node_size;\n\n        public:\n            using allocator_type       = typename arena_type::allocator_type;\n            using block_allocator_type = typename arena_type::block_allocator_type;\n            using memory_type          = typename arena_type::memory_type;\n            using is_stateful          = std::true_type;\n\n            explicit transactional_allocator(arena_type&& arena) : arena_type(std::move(arena))\n            {\n                DVLOG(1) << \"allocate initial block/stack\";\n                m_current_stack = allocate_stack();\n            }\n\n            ~transactional_allocator() noexcept\n            {\n                release_current_stack();\n                release_in_use_stacks();\n                shrink_to_fit();\n            }\n\n            transactional_allocator(transactional_allocator&& other) noexcept\n            : arena_type(std::move(other)),\n              m_current_stack(std::move(other.m_current_stack)),\n              m_in_use_stacks(std::move(other.m_in_use_stacks)),\n              m_max_node_size(std::exchange(other.m_max_node_size, 0u))\n            {\n            }\n\n            transactional_allocator& operator=(transactional_allocator&& other) noexcept\n            {\n                arena_type::operator=(std::move(other));\n                m_in_use_stacks     = std::move(other.m_in_use_stacks);\n                m_current_stack     = std::move(other.m_current_stack);\n                m_max_node_size     = std::exchange(other.m_max_node_size, 0u);\n            }\n\n            transactional_allocator(const transactional_allocator&) = delete;\n            transactional_allocator& operator=(const transactional_allocator&) = delete;\n\n            void* allocate_node(std::size_t size, std::size_t alignment)\n            {\n                // allocate off current stack if possible\n                // otherwise, allocate a new stack\n                DVLOG(2) << this << \": allocate_node \" << size << \"; \" << alignment;\n\n                // check size\n                // todo: check alignment\n                if (size > m_max_node_size)\n                {\n                    throw bad_allocation_size(info(), size, m_max_node_size);\n                }\n\n                void* ptr = m_current_stack.allocate(size, alignment);\n                if (__builtin_expect((!ptr), 0)) // unlikely macro\n                {\n                    DVLOG(3) << \"current stack exhaused - rotate stacks\";\n                    release_current_stack();\n                    m_current_stack = allocate_stack();\n                    ptr             = m_current_stack.allocate(size, alignment);\n                }\n                if (__builtin_expect((!ptr), 0))\n                {\n                    throw bad_node_size(info(), size, m_max_node_size);\n                }\n                DVLOG(1) << this << \": allocated \" << ptr << \"; size=\" << size;\n                return ptr;\n            }\n\n            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept\n            {\n                // deallocate stack if its not the current stack\n                // and the reference count goes to 0\n                DVLOG(1) << this << \": deallocate_node \" << ptr << \"; \" << size << \"; \" << alignment;\n                auto stack = find_stack(ptr);\n                DCHECK(stack);\n                if (stack->should_release_after_deallocate(ptr) && !m_current_stack.contains(ptr))\n                {\n                    DVLOG(3) << \"deallocate dropping block\";\n                    drop_stack_containing_address(ptr);\n                }\n            }\n\n            std::size_t max_node_size() const noexcept\n            {\n                return m_max_node_size;\n            }\n\n            DLContext device_context() const noexcept\n            {\n                return arena_type::device_context();\n            }\n\n            // access the arena\n\n            void shrink_to_fit() noexcept\n            {\n                arena_type::shrink_to_fit();\n            }\n\n            void reserve_blocks(std::size_t block_count) noexcept\n            {\n                DVLOG(2) << \"reserve blocks: \" << block_count;\n                auto count = block_count - m_in_use_stacks.size() - 1 /* m_current_stack */;\n                DVLOG(3) << \"reserve blocks: \" << block_count << \"; needed: \" << count;\n                arena_type::reserve_blocks(count);\n            }\n\n            allocator_type& get_allocator() noexcept\n            {\n                return arena_type::get_allocator();\n            }\n\n            block_allocator_type& get_block_allocator() noexcept\n            {\n                return arena_type::get_block_allocator();\n            }\n\n        private:\n            allocator_info info() noexcept\n            {\n                return {\"trtlab::transactional_allocator\", this};\n            }\n\n            stack_type allocate_stack()\n            {\n                auto block      = arena_type::allocate_block();\n                m_max_node_size = std::max(m_max_node_size, block.size);\n                DVLOG(3) << \"allocated new stack\";\n                return stack_type(block);\n            }\n\n            void PushStack(stack_type&& stack)\n            {\n                DVLOG(3) << \"pushing stack to block_manager\";\n                m_in_use_stacks.add_block(std::move(stack));\n            }\n\n            void drop_stack_containing_address(void* ptr) noexcept\n            {\n                // find_stack search both the in-use block pool and teh current stack\n                // We only drop in-use stacks\n                auto stack = m_in_use_stacks.find_block(ptr);\n                if (stack)\n                {\n                    DVLOG(3) << \"dropping stack \" << stack << \" from in-use stack\";\n                    arena_type::deallocate_block(std::move(*stack));\n                    m_in_use_stacks.drop_block(ptr);\n                }\n            }\n\n            void release_current_stack() noexcept\n            {\n                if (m_current_stack.use_count())\n                {\n                    DVLOG(3) << \"current stack is in-use; move to block_manager\";\n                    PushStack(std::move(m_current_stack));\n                }\n                else\n                {\n                    DVLOG(3) << \"current stack is dereferences; deallocating\";\n                    auto block = m_current_stack.get_memory_block();\n                    if (block.memory)\n                    {\n                        arena_type::deallocate_block(std::move(block));\n                    }\n                }\n                m_current_stack = stack_type();\n            }\n\n            void release_in_use_stacks() noexcept\n            {\n                //if(!m_Map.empty())\n                if (m_in_use_stacks.size())\n                {\n                    DLOG(WARNING) << \"transactional_allocator being released with unreleased allocations\";\n                    for (void* ptr : m_in_use_stacks.blocks())\n                    {\n                        DVLOG(3) << \"force dropping stack \" << ptr;\n                        drop_stack_containing_address(ptr);\n                    }\n                    m_in_use_stacks.clear();\n                }\n                DCHECK_EQ(m_in_use_stacks.size(), 0);\n            }\n\n            stack_type* find_stack(const void* ptr) noexcept\n            {\n                if (m_current_stack.contains(ptr))\n                {\n                    return &m_current_stack;\n                }\n                return m_in_use_stacks.find_block(ptr);\n            }\n        };\n\n        template <typename BlockAllocator, typename BlockList>\n        auto make_transactional_allocator(block_arena<BlockAllocator, cached_arena, BlockList>&& arena)\n        {\n            return transactional_allocator<BlockAllocator, BlockList>(std::move(arena));\n        }\n\n    } // namespace memory\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/memory/include/trtlab/memory/utils.h",
    "content": "\n\n#pragma once\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        std::string bytes_to_string(std::size_t bytes);\n        std::size_t string_to_bytes(const std::string);\n    }\n}"
  },
  {
    "path": "trtlab/memory/src/CMakeLists.txt",
    "content": "# MODIFICATION MESSAGE\n\n# Modification Notes:\n\n# Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n# This file is subject to the license terms in the LICENSE file\n# found in the top-level directory of this distribution\n\n\n#find_package(Threads)\nfind_package(dlpack)\nfind_package(glog REQUIRED)\nfind_package(gflags REQUIRED)\nif( CMAKE_BUILD_TYPE STREQUAL \"Debug\" )\n  find_package(gflags COMPONENTS nothreads_shared)\n  set(trtlab_gflags \"gflags_nothreads_shared\")\n  message(STATUS \"gflags: ${trtlab_gflags}\")\nelse()\n  find_package(gflags COMPONENTS nothreads_static)\n  set(trtlab_gflags \"gflags_nothreads_static\")\n  message(STATUS \"gflags: ${trtlab_gflags}\")\nendif()\n\nset(header_path ${TRTLAB_MEMORY_SOURCE_DIR}/include/trtlab/memory)\n\nset(detail_header\n        ${header_path}/detail/assert.h\n#       ${header_path}/detail/container_node_sizes.hpp\n#       ${header_path}/detail/debug_helpers.hpp\n#       ${header_path}/detail/ebo_storage.hpp\n#       ${header_path}/detail/free_list.hpp\n#       ${header_path}/detail/free_list_array.hpp\n#       ${header_path}/detail/lowlevel_allocator.hpp\n#       ${header_path}/detail/memory_stack.hpp\n#       ${header_path}/detail/small_free_list.hpp\n        ${header_path}/detail/utility.h\n)\n\nset(header\n        ${header_path}/align.h\n#       ${header_path}/aligned_allocator.hpp\n        ${header_path}/allocator_storage.h\n        ${header_path}/allocator_traits.h\n        ${header_path}/block_allocators.h\n        ${header_path}/block_arena.h\n        ${header_path}/block_manager.h\n        ${header_path}/block_stack.h\n        ${header_path}/config.h\n#       ${header_path}/container.hpp\n        ${header_path}/debugging.h\n#       ${header_path}/default_allocator.hpp\n        ${header_path}/deleter.h\n        ${header_path}/descriptor.h\n        ${header_path}/error.h\n        ${header_path}/huge_page_allocator.h\n        ${header_path}/literals.h\n        ${header_path}/memory_block.h\n        ${header_path}/memory_pool.h\n#       ${header_path}/fallback_allocator.hpp\n#       ${header_path}/malloc_allocator.hpp\n#       ${header_path}/heap_allocator.hpp\n#       ${header_path}/iteration_allocator.hpp\n#       ${header_path}/joint_allocator.hpp\n#       ${header_path}/memory_arena.hpp\n#       ${header_path}/memory_pool.hpp\n#       ${header_path}/memory_pool_collection.hpp\n#       ${header_path}/memory_pool_type.hpp\n#       ${header_path}/memory_resource_adapter.hpp\n#       ${header_path}/memory_stack.hpp\n#       ${header_path}/namespace_alias.hpp\n#       ${header_path}/new_allocator.hpp\n#       ${header_path}/segregator.hpp\n#       ${header_path}/smart_ptr.hpp\n#       ${header_path}/static_allocator.hpp\n#       ${header_path}/std_allocator.hpp\n#       ${header_path}/temporary_allocator.hpp\n#       ${header_path}/threading.hpp\n        ${header_path}/tracking.h\n        ${header_path}/trackers.h\n#       ${header_path}/virtual_memory.hpp\n        ${header_path}/utils.h\n        ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.h\n)\n\nset(src\n        align.cc\n        block_stack.cc\n        detail/page_info.c\n#       detail/debug_helpers.cpp\n#       detail/assert.cpp\n        detail/block_list.cc\n        detail/free_list.cc\n#       detail/free_list_array.cpp\n#       detail/free_list_utils.hpp\n#       detail/ilog2.hpp\n#       detail/small_free_list.cpp\n#       debugging.cpp\n        descriptor.cc\n        error.cc\n#       heap_allocator.cpp\n#       iteration_allocator.cpp\n#       malloc_allocator.cpp\n#       memory_pool.cpp\n#       memory_pool_collection.cpp\n#       memory_stack.cpp\n        memory_type.cc\n#       new_allocator.cpp\n#       static_allocator.cpp\n#       temporary_allocator.cpp\n        trackers.cc\n        utils.cc\n#       virtual_memory.cpp)\n)\n\n# configure config file\nconfigure_file(\"config.h.in\" \"${CMAKE_CURRENT_BINARY_DIR}/config_impl.h\")\n\n# generate container_node_sizes.hpp\nif(TRTLAB_MEMORY_BUILD_TOOLS AND (NOT CMAKE_CROSSCOMPILING))\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.h\n            COMMAND memory_node_size_debugger --code --alignof \"alignof(T)\" ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.h\n            DEPENDS memory_node_size_debugger\n            VERBATIM)\nelse()\n    message(WARNING \"cannot generate container_node_sizes_impl.h, node size information will be unavailable\")\n    file(WRITE  ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.h \"#define TRTLAB_MEMORY_NO_NODE_SIZE\")\nendif()\n\n# trtlab_memory library\nadd_library(trtlab_memory ${detail_header} ${header} ${src})\n\ntarget_include_directories(trtlab_memory PUBLIC $<BUILD_INTERFACE:${TRTLAB_MEMORY_SOURCE_DIR}/include/> # for client in subdirectory\n                                                $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for generated files in build mode\n                                                $<INSTALL_INTERFACE:${TRTLAB_MEMORY_INC_INSTALL_DIR}> # for client in install mode\n                                         PRIVATE ${header_path})\ntarget_compile_definitions(trtlab_memory PUBLIC\n                           TRTLAB_MEMORY=1\n                           TRTLAB_MEMORY_VERSION_MAJOR=${TRTLAB_MEMORY_VERSION_MAJOR}\n                           TRTLAB_MEMORY_VERSION_MINOR=${TRTLAB_MEMORY_VERSION_MINOR}\n                           TRTLAB_MEMORY_VERSION_PATCH=${TRTLAB_MEMORY_VERSION_PATCH})\n\ntarget_link_libraries(trtlab_memory\n  PUBLIC\n#   Threads::Threads\n    glog::glog\n    ${trtlab_gflags}\n    dlpack::dlpack\n)\n\n#set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} \"-pg\")\n\nset_target_properties(trtlab_memory PROPERTIES\n                      OUTPUT_NAME \"trtlab_memory-${TRTLAB_MEMORY_VERSION}\"\n                      POSITION_INDEPENDENT_CODE ON)\n\ninstall(TARGETS trtlab_memory EXPORT trtlab_memoryTargets\n        RUNTIME       DESTINATION ${TRTLAB_MEMORY_RUNTIME_INSTALL_DIR}\n        LIBRARY       DESTINATION ${TRTLAB_MEMORY_LIBRARY_INSTALL_DIR}\n        ARCHIVE       DESTINATION ${TRTLAB_MEMORY_ARCHIVE_INSTALL_DIR}\n        FRAMEWORK     DESTINATION ${TRTLAB_MEMORY_FRAMEWORK_INSTALL_DIR})\n\n# Write/install version file\ninclude(CMakePackageConfigHelpers)\nset(version_file \"${CMAKE_CURRENT_BINARY_DIR}/cmake/trtlab_memory-config-version.cmake\")\nwrite_basic_package_version_file(${version_file}\n                                 VERSION ${TRTLAB_MEMORY_VERSION}\n                                 COMPATIBILITY AnyNewerVersion)\n\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/config_impl.hpp DESTINATION ${TRTLAB_MEMORY_INC_INSTALL_DIR})\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.hpp DESTINATION ${TRTLAB_MEMORY_INC_INSTALL_DIR}/foonathan/memory/detail)\ninstall(FILES ${header}                                   DESTINATION ${TRTLAB_MEMORY_INC_INSTALL_DIR}/foonathan/memory)\ninstall(FILES ${detail_header}                            DESTINATION ${TRTLAB_MEMORY_INC_INSTALL_DIR}/foonathan/memory/detail)\ninstall(FILES ${version_file}                             DESTINATION ${TRTLAB_MEMORY_CMAKE_CONFIG_INSTALL_DIR})"
  },
  {
    "path": "trtlab/memory/src/align.cc",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#include \"align.h\"\n#include \"detail/assert.h\"\n\n#include \"ilog2.h\"\n\nusing namespace trtlab::memory;\nusing namespace detail;\n\nbool trtlab::memory::is_aligned(void* ptr, std::size_t alignment) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(is_valid_alignment(alignment));\n    auto address = reinterpret_cast<std::uintptr_t>(ptr);\n    return address % alignment == 0u;\n}\n\nstd::size_t trtlab::memory::alignment_for(std::size_t size) noexcept\n{\n    return (size >= 8UL ? 8UL : (std::size_t(1) << ilog2(size)));\n}\n\nstd::size_t trtlab::memory::ilog2(std::size_t x)\n{\n    return ilog2_base(x) - 1;\n}\n\n// ceiling ilog2() implementation, adds one if part after comma\n// e.g. 1 -> 0, 2 -> 1, 3 -> 2, 4 -> 2, 5 -> 3\nstd::size_t trtlab::memory::ilog2_ceil(std::size_t x)\n{\n    // only subtract one if power of two\n    return ilog2_base(x) - std::size_t(is_power_of_two(x));\n}"
  },
  {
    "path": "trtlab/memory/src/block_stack.cc",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#include \"block_stack.h\"\n\n#include <new>\n\n#include \"align.h\"\n\nusing namespace trtlab::memory;\nusing namespace detail;\n\n// TODO: template memory_block_stack on MemoryType\n\nconst std::size_t memory_block_stack::node::div_alignment =\n    sizeof(memory_block_stack::node) / host_memory::max_access_alignment();\nconst std::size_t memory_block_stack::node::mod_offset =\n    sizeof(memory_block_stack::node) % host_memory::max_access_alignment() != 0u;\nconst std::size_t memory_block_stack::node::offset = (div_alignment + mod_offset) * host_memory::max_access_alignment();\n\nconst std::size_t memory_block_stack::implementation_offset = memory_block_stack::node::offset;\n\nvoid memory_block_stack::push(allocated_mb block) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(is_aligned(block.memory, max_alignment));\n    auto next = ::new (block.memory) node(head_, block.size - node::offset);\n    head_     = next;\n}\n\nmemory_block_stack::allocated_mb memory_block_stack::pop() noexcept\n{\n    TRTLAB_MEMORY_ASSERT(head_);\n    auto to_pop = head_;\n    head_       = head_->prev;\n    return {to_pop, to_pop->usable_size + node::offset};\n}\n\nvoid memory_block_stack::steal_top(memory_block_stack& other) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(other.head_);\n    auto to_steal = other.head_;\n    other.head_   = other.head_->prev;\n\n    to_steal->prev = head_;\n    head_          = to_steal;\n}\n\nbool memory_block_stack::owns(const void* ptr) const noexcept\n{\n    auto address = static_cast<const char*>(ptr);\n    for (auto cur = head_; cur; cur = cur->prev)\n    {\n        auto mem = static_cast<char*>(static_cast<void*>(cur));\n        if (address >= mem && address < mem + cur->usable_size)\n            return true;\n    }\n    return false;\n}\n\nstd::size_t memory_block_stack::size() const noexcept\n{\n    std::size_t res = 0u;\n    for (auto cur = head_; cur; cur = cur->prev)\n        ++res;\n    return res;\n}\n"
  },
  {
    "path": "trtlab/memory/src/config.h.in",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_IMPL_IN_CONFIG_H\n    #error \"do not include this file directly, use config.h\"\n#endif\n\n#include <cstddef>\n\n//=== options ===//\n// clang-format off\n#cmakedefine01 TRTLAB_MEMORY_CHECK_ALLOCATION_SIZE\n#define TRTLAB_MEMORY_IMPL_DEFAULT_ALLOCATOR ${TRTLAB_MEMORY_DEFAULT_ALLOCATOR}\n#cmakedefine01 TRTLAB_MEMORY_THREAD_SAFE_REFERENCE\n#cmakedefine01 TRTLAB_MEMORY_DEBUG_ASSERT\n#cmakedefine01 TRTLAB_MEMORY_DEBUG_FILL\n#define TRTLAB_MEMORY_DEBUG_FENCE ${TRTLAB_MEMORY_DEBUG_FENCE}\n#cmakedefine01 TRTLAB_MEMORY_DEBUG_LEAK_CHECK\n#cmakedefine01 TRTLAB_MEMORY_DEBUG_POINTER_CHECK\n#cmakedefine01 TRTLAB_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK\n#define TRTLAB_MEMORY_IMPL_MEMORY_RESOURCE_HEADER ${TRTLAB_MEMORY_MEMORY_RESOURCE_HEADER}\n#define TRTLAB_MEMORY_IMPL_MEMORY_RESOURCE ${TRTLAB_MEMORY_MEMORY_RESOURCE}\n#cmakedefine01 TRTLAB_MEMORY_EXTERN_TEMPLATE\n#define TRTLAB_MEMORY_TEMPORARY_STACK_MODE ${TRTLAB_MEMORY_TEMPORARY_STACK_MODE}\n// clang-format on"
  },
  {
    "path": "trtlab/memory/src/descriptor.cc",
    "content": "#include \"descriptor.h\"\n#include \"utils.h\"\n\nusing namespace trtlab;\nusing namespace memory;\n\ndescriptor::descriptor() : m_storage(nullptr), m_size(0), m_alignment(0), m_data(nullptr) {}\n\ndescriptor::descriptor(std::shared_ptr<iallocator> alloc, std::size_t size, std::size_t alignment)\n: m_storage(std::move(alloc)), m_size(size), m_alignment(alignment), m_data(m_storage->allocate(size, alignment))\n{\n}\n\nvoid descriptor::release()\n{\n    if(m_storage && m_data)\n    {\n        m_storage->deallocate(m_data, m_size, m_alignment);\n    }\n}\n\nDLContext descriptor::device_context() const\n{\n    DCHECK(m_storage);\n    return m_storage->device_context();\n}\n\nstd::shared_ptr<descriptor> descriptor::make_shared()\n{\n    return std::make_shared<descriptor>(std::move(*this));\n}\n\nstd::ostream& trtlab::memory::operator<<(std::ostream& os, const descriptor& md)\n{\n    os << \"[descriptor - addr: \" << md.m_data << \"; size: \" << bytes_to_string(md.m_size) << \"; alignment: \" << md.m_alignment << \"]\";\n    return os;\n}"
  },
  {
    "path": "trtlab/memory/src/detail/block_list.cc",
    "content": "#include \"detail/block_list.h\"\n\n#include \"align.h\"\n#include \"detail/assert.h\"\n#include \"error.h\"\n\n#include \"free_list_utils.h\"\n\nusing namespace trtlab::memory;\nusing namespace detail;\n\n\nconstexpr std::size_t block_list::min_element_size;\nconstexpr std::size_t block_list::min_element_alignment;\n\nblock_list::block_list() noexcept\n: first_(nullptr), capacity_(0u)\n{\n}\n\nblock_list::block_list(block_list&& other) noexcept\n: first_(std::exchange(other.first_, nullptr)), capacity_(std::exchange(other.capacity_, 0u))\n{\n}\n\nblock_list& block_list::operator=(block_list&& other) noexcept\n{\n    block_list tmp(detail::move(other));\n    swap(*this, tmp);\n    return *this;\n}\n\nvoid trtlab::memory::detail::swap(block_list& a, block_list& b) noexcept\n{\n    detail::adl_swap(a.first_, b.first_);\n    detail::adl_swap(a.capacity_, b.capacity_);\n}\n\nvoid block_list::insert(memory_block&& block) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(block.memory);\n    TRTLAB_MEMORY_ASSERT(block.size > sizeof(node));\n    DVLOG(4) << \"block_list::insert \" << block.memory;\n    \n    auto n = static_cast<node*>(block.memory);\n    n->size = block.size;\n    n->next = first_;\n    first_ = n;\n    capacity_++;\n}\n\nmemory_block block_list::allocate() noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n    --capacity_;\n\n    memory_block block;\n    block.memory = static_cast<void*>(first_);\n    block.size = first_->size;\n    first_ = first_->next;\n    return block;\n}\n\nvoid block_list::deallocate(memory_block&& block) noexcept\n{\n    insert(std::move(block));\n}\n\n\nblock_list_oob::block_list_oob() noexcept\n{\n}\n\nblock_list_oob::block_list_oob(block_list_oob&& other) noexcept\n: nodes(std::move(other.nodes))\n{\n}\n\nblock_list_oob& block_list_oob::operator=(block_list_oob&& other) noexcept\n{\n    block_list_oob tmp(detail::move(other));\n    swap(*this, tmp);\n    return *this;\n}\n\nvoid trtlab::memory::detail::swap(block_list_oob& a, block_list_oob& b) noexcept\n{\n    detail::adl_swap(a.nodes, b.nodes);\n}\n\nvoid block_list_oob::insert(memory_block&& block) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(block.memory);\n    TRTLAB_MEMORY_ASSERT(block.size > sizeof(node));\n    DVLOG(4) << \"block_list_oob::insert \" << block.memory;\n    nodes.push_front(std::move(block));\n}\n\nmemory_block block_list_oob::allocate() noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n    memory_block block = nodes.front();\n    nodes.pop_front();\n    return block;\n}\n\nvoid block_list_oob::deallocate(memory_block&& block) noexcept\n{\n    insert(std::move(block));\n}"
  },
  {
    "path": "trtlab/memory/src/detail/free_list.cc",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#include \"detail/free_list.h\"\n\n#include \"align.h\"\n#include \"detail/debug_helpers.h\"\n#include \"detail/assert.h\"\n#include \"debugging.h\"\n#include \"error.h\"\n\n#include \"free_list_utils.h\"\n\nusing namespace trtlab::memory;\nusing namespace detail;\n\nnamespace\n{\n    // i.e. array\n    struct interval\n    {\n        char* prev;  // last before\n        char* first; // first in\n        char* last;  // last in\n        char* next;  // first after\n\n        // number of nodes in the interval\n        std::size_t size(std::size_t node_size) const noexcept\n        {\n            // last is inclusive, so add actual_size to it\n            // note: cannot use next, might not be directly after\n            auto end = last + node_size;\n            TRTLAB_MEMORY_ASSERT((end - first) % node_size == 0u);\n            return (end - first) / node_size;\n        }\n    };\n\n    // searches for n consecutive bytes\n    // begin and end are the proxy nodes\n    // assumes list is not empty\n    // similar to list_search_array()\n    interval list_search_array(char* first, std::size_t bytes_needed, std::size_t node_size) noexcept\n    {\n        interval i;\n        i.prev  = nullptr;\n        i.first = first;\n        // i.last/next are used as iterator for the end of the interval\n        i.last = first;\n        i.next = list_get_next(first);\n\n        auto bytes_so_far = node_size;\n        while (i.next)\n        {\n            if (i.last + node_size != i.next) // not continous\n            {\n                // restart at next\n                i.prev  = i.last;\n                i.first = i.next;\n                i.last  = i.next;\n                i.next  = list_get_next(i.last);\n\n                bytes_so_far = node_size;\n            }\n            else\n            {\n                // extend interval\n                auto new_next = list_get_next(i.next);\n                i.last        = i.next;\n                i.next        = new_next;\n\n                bytes_so_far += node_size;\n                if (bytes_so_far >= bytes_needed)\n                    return i;\n            }\n        }\n        // not enough continuous space\n        return {nullptr, nullptr, nullptr, nullptr};\n    }\n\n    // similar to list_search_array()\n    // begin/end are proxy nodes\n    interval xor_list_search_array(char* begin, char* end, std::size_t bytes_needed, std::size_t node_size) noexcept\n    {\n        interval i;\n        i.prev  = begin;\n        i.first = xor_list_get_other(begin, nullptr);\n        // i.last/next are used as iterator for the end of the interval\n        i.last = i.first;\n        i.next = xor_list_get_other(i.last, i.prev);\n\n        auto bytes_so_far = node_size;\n        while (i.next != end)\n        {\n            if (i.last + node_size != i.next) // not continous\n            {\n                // restart at i.next\n                i.prev  = i.last;\n                i.first = i.next;\n                i.last  = i.next;\n                i.next  = xor_list_get_other(i.first, i.prev);\n\n                bytes_so_far = node_size;\n            }\n            else\n            {\n                // extend interval\n                auto new_next = xor_list_get_other(i.next, i.last);\n                i.last        = i.next;\n                i.next        = new_next;\n\n                bytes_so_far += node_size;\n                if (bytes_so_far >= bytes_needed)\n                    return i;\n            }\n        }\n        // not enough continuous space\n        return {nullptr, nullptr, nullptr, nullptr};\n    }\n} // namespace\n\nconstexpr std::size_t free_memory_list::min_element_size;\nconstexpr std::size_t free_memory_list::min_element_alignment;\n\nfree_memory_list::free_memory_list(std::size_t node_size) noexcept\n: first_(nullptr),\n  node_size_(node_size > min_element_size ? node_size : min_element_size),\n  capacity_(0u),\n  alignment_(alignment_for(node_size))\n{\n}\n\nfree_memory_list::free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept : free_memory_list(node_size)\n{\n    insert(mem, size);\n}\n\nfree_memory_list::free_memory_list(free_memory_list&& other) noexcept\n: first_(other.first_), node_size_(other.node_size_), capacity_(other.capacity_)\n{\n    other.first_    = nullptr;\n    other.capacity_ = 0u;\n}\n\nfree_memory_list& free_memory_list::operator=(free_memory_list&& other) noexcept\n{\n    free_memory_list tmp(detail::move(other));\n    swap(*this, tmp);\n    return *this;\n}\n\nvoid trtlab::memory::detail::swap(free_memory_list& a, free_memory_list& b) noexcept\n{\n    detail::adl_swap(a.first_, b.first_);\n    detail::adl_swap(a.node_size_, b.node_size_);\n    detail::adl_swap(a.capacity_, b.capacity_);\n}\n\nvoid free_memory_list::insert(void* mem, std::size_t size) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(mem);\n    TRTLAB_MEMORY_ASSERT(is_aligned(mem, alignment()));\n    detail::debug_fill_internal(mem, size, false);\n\n    insert_impl(mem, size);\n}\n\nvoid* free_memory_list::allocate() noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n    --capacity_;\n\n    auto mem = first_;\n    first_   = list_get_next(first_);\n    return debug_fill_new(mem, node_size_, fence_size());\n}\n\n#include <glog/logging.h>\n\nvoid* free_memory_list::allocate(std::size_t n) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n    if (n <= node_size_)\n        return allocate();\n\n    auto actual_size = node_size_ + 2 * fence_size();\n\n    auto i = list_search_array(first_, n + 2 * fence_size(), actual_size);\n    if (i.first == nullptr)\n        return nullptr;\n\n    if (i.prev)\n        list_set_next(i.prev, i.next); // change next from previous to first after\n    else\n        first_ = i.next;\n    capacity_ -= i.size(actual_size);\n\n    return debug_fill_new(i.first, n, fence_size());\n}\n\nvoid free_memory_list::deallocate(void* ptr) noexcept\n{\n    ++capacity_;\n\n    auto node = static_cast<char*>(debug_fill_free(ptr, node_size_, fence_size()));\n    list_set_next(node, first_);\n    first_ = node;\n}\n\nvoid free_memory_list::deallocate(void* ptr, std::size_t n) noexcept\n{\n    if (n <= node_size_)\n    {\n        deallocate(ptr);\n    }\n    else\n    {\n        auto mem = debug_fill_free(ptr, n, fence_size());\n        insert_impl(mem, n + 2 * fence_size());\n    }\n}\n\nvoid free_memory_list::insert_impl(void* mem, std::size_t size) noexcept\n{\n    auto actual_size = node_size_ + 2 * fence_size();\n    auto no_nodes    = size / actual_size;\n    TRTLAB_MEMORY_ASSERT(no_nodes > 0);\n\n    auto cur = static_cast<char*>(mem);\n    for (std::size_t i = 0u; i != no_nodes - 1; ++i)\n    {\n        list_set_next(cur, cur + actual_size);\n        cur += actual_size;\n    }\n    list_set_next(cur, first_);\n    first_ = static_cast<char*>(mem);\n\n    capacity_ += no_nodes;\n}\n\nnamespace\n{\n    // converts a block into a linked list\n    void xor_link_block(void* memory, std::size_t node_size, std::size_t no_nodes, char* prev, char* next) noexcept\n    {\n        auto cur = static_cast<char*>(memory);\n        xor_list_change(prev, next, cur); // change next pointer of prev\n\n        auto last_cur = prev;\n        for (std::size_t i = 0u; i != no_nodes - 1; ++i)\n        {\n            xor_list_set(cur, last_cur,\n                         cur + node_size); // cur gets last_cur and next node in continous memory\n            last_cur = cur;\n            cur += node_size;\n        }\n        xor_list_set(cur, last_cur, next); // last memory node gets next as next\n        xor_list_change(next, prev, cur);  // change prev pointer of next\n    }\n\n    struct pos\n    {\n        char *prev, *next;\n    };\n\n    // finds position to insert memory to keep list ordered\n    // first_prev -> first -> ... (memory somewhere here) ... -> last -> last_next\n    pos find_pos_interval(const allocator_info& info, char* memory, char* first_prev, char* first, char* last, char* last_next) noexcept\n    {\n        // note: first_prev/last_next can be the proxy nodes, then first_prev isn't necessarily less than first!\n        TRTLAB_MEMORY_ASSERT(less(first, memory) && less(memory, last));\n\n        // need to insert somewhere in the middle\n        // search through the entire list\n        // search from both ends at once\n        auto cur_forward  = first;\n        auto prev_forward = first_prev;\n\n        auto cur_backward  = last;\n        auto prev_backward = last_next;\n\n        do\n        {\n            if (greater(cur_forward, memory))\n                return {prev_forward, cur_forward};\n            else if (less(cur_backward, memory))\n                // the next position is the previous backwards pointer\n                return {cur_backward, prev_backward};\n            debug_check_double_dealloc([&] { return cur_forward != memory && cur_backward != memory; }, info, memory);\n            xor_list_iter_next(cur_forward, prev_forward);\n            xor_list_iter_next(cur_backward, prev_backward);\n        } while (less(prev_forward, prev_backward));\n\n        // ran outside of list\n        debug_check_double_dealloc([] { return false; }, info, memory);\n        return {nullptr, nullptr};\n    }\n\n    // finds the position in the entire list\n    pos find_pos(const allocator_info& info, char* memory, char* begin_node, char* end_node, char* last_dealloc,\n                 char* last_dealloc_prev) noexcept\n    {\n        auto first = xor_list_get_other(begin_node, nullptr);\n        auto last  = xor_list_get_other(end_node, nullptr);\n\n        if (greater(first, memory))\n            // insert at front\n            return {begin_node, first};\n        else if (less(last, memory))\n            // insert at the end\n            return {last, end_node};\n        else if (less(last_dealloc_prev, memory) && less(memory, last_dealloc))\n            // insert before last_dealloc\n            return {last_dealloc_prev, last_dealloc};\n        else if (less(memory, last_dealloc))\n            // insert into [first, last_dealloc_prev]\n            return find_pos_interval(info, memory, begin_node, first, last_dealloc_prev, last_dealloc);\n        else if (greater(memory, last_dealloc))\n            // insert into (last_dealloc, last]\n            return find_pos_interval(info, memory, last_dealloc_prev, last_dealloc, last, end_node);\n\n        TRTLAB_MEMORY_UNREACHABLE(\"memory must be in some half or outside\");\n        return {nullptr, nullptr};\n    }\n} // namespace\n\nconstexpr std::size_t ordered_free_memory_list::min_element_size;\nconstexpr std::size_t ordered_free_memory_list::min_element_alignment;\n\nordered_free_memory_list::ordered_free_memory_list(std::size_t node_size) noexcept\n: node_size_(node_size > min_element_size ? node_size : min_element_size),\n  capacity_(0u),\n  last_dealloc_(end_node()),\n  last_dealloc_prev_(begin_node())\n{\n    xor_list_set(begin_node(), nullptr, end_node());\n    xor_list_set(end_node(), begin_node(), nullptr);\n}\n\nordered_free_memory_list::ordered_free_memory_list(ordered_free_memory_list&& other) noexcept\n: node_size_(other.node_size_), capacity_(other.capacity_)\n{\n    if (!other.empty())\n    {\n        auto first = xor_list_get_other(other.begin_node(), nullptr);\n        auto last  = xor_list_get_other(other.end_node(), nullptr);\n\n        xor_list_set(begin_node(), nullptr, first);\n        xor_list_change(first, other.begin_node(), begin_node());\n        xor_list_change(last, other.end_node(), end_node());\n        xor_list_set(end_node(), last, nullptr);\n\n        other.capacity_ = 0u;\n        xor_list_set(other.begin_node(), nullptr, other.end_node());\n        xor_list_set(other.end_node(), other.begin_node(), nullptr);\n    }\n    else\n    {\n        xor_list_set(begin_node(), nullptr, end_node());\n        xor_list_set(end_node(), begin_node(), nullptr);\n    }\n\n    // for programming convenience, last_dealloc is reset\n    last_dealloc_prev_ = begin_node();\n    last_dealloc_      = xor_list_get_other(last_dealloc_prev_, nullptr);\n}\n\nvoid trtlab::memory::detail::swap(ordered_free_memory_list& a, ordered_free_memory_list& b) noexcept\n{\n    auto a_first = xor_list_get_other(a.begin_node(), nullptr);\n    auto a_last  = xor_list_get_other(a.end_node(), nullptr);\n\n    auto b_first = xor_list_get_other(b.begin_node(), nullptr);\n    auto b_last  = xor_list_get_other(b.end_node(), nullptr);\n\n    if (!a.empty())\n    {\n        xor_list_set(b.begin_node(), nullptr, a_first);\n        xor_list_change(a_first, a.begin_node(), b.begin_node());\n        xor_list_change(a_last, a.end_node(), b.end_node());\n        xor_list_set(b.end_node(), a_last, nullptr);\n    }\n    else\n    {\n        xor_list_set(b.begin_node(), nullptr, b.end_node());\n        xor_list_set(b.end_node(), b.begin_node(), nullptr);\n    }\n\n    if (!b.empty())\n    {\n        xor_list_set(a.begin_node(), nullptr, b_first);\n        xor_list_change(b_first, b.begin_node(), a.begin_node());\n        xor_list_change(b_last, b.end_node(), a.end_node());\n        xor_list_set(a.end_node(), b_last, nullptr);\n    }\n    else\n    {\n        xor_list_set(a.begin_node(), nullptr, a.end_node());\n        xor_list_set(a.end_node(), a.begin_node(), nullptr);\n    }\n\n    detail::adl_swap(a.node_size_, b.node_size_);\n    detail::adl_swap(a.capacity_, b.capacity_);\n\n    // for programming convenience, last_dealloc is reset\n    a.last_dealloc_prev_ = a.begin_node();\n    a.last_dealloc_      = xor_list_get_other(a.last_dealloc_prev_, nullptr);\n\n    b.last_dealloc_prev_ = b.begin_node();\n    b.last_dealloc_      = xor_list_get_other(b.last_dealloc_prev_, nullptr);\n}\n\nvoid ordered_free_memory_list::insert(void* mem, std::size_t size) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(mem);\n    TRTLAB_MEMORY_ASSERT(is_aligned(mem, alignment()));\n    debug_fill_internal(mem, size, false);\n\n    insert_impl(mem, size);\n}\n\nvoid* ordered_free_memory_list::allocate() noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n\n    // remove first node\n    auto prev = begin_node();\n    auto node = xor_list_get_other(prev, nullptr);\n    auto next = xor_list_get_other(node, prev);\n\n    xor_list_set(prev, nullptr, next); // link prev to next\n    xor_list_change(next, node, prev); // change prev of next\n    --capacity_;\n\n    if (node == last_dealloc_)\n    {\n        // move last_dealloc_ one further in\n        last_dealloc_ = next;\n        TRTLAB_MEMORY_ASSERT(last_dealloc_prev_ == prev);\n    }\n\n    return debug_fill_new(node, node_size_, fence_size());\n}\n\nvoid* ordered_free_memory_list::allocate(std::size_t n) noexcept\n{\n    TRTLAB_MEMORY_ASSERT(!empty());\n\n    if (n <= node_size_)\n        return allocate();\n\n    auto actual_size = node_size_ + 2 * fence_size();\n\n    auto i = xor_list_search_array(begin_node(), end_node(), n + 2 * fence_size(), actual_size);\n    if (i.first == nullptr)\n        return nullptr;\n\n    xor_list_change(i.prev, i.first, i.next); // change next pointer from i.prev to i.next\n    xor_list_change(i.next, i.last, i.prev);  // change prev pointer from i.next to i.prev\n    capacity_ -= i.size(actual_size);\n\n    // if last_dealloc_ points into the array being removed\n    if (less_equal(i.first, last_dealloc_) && less_equal(last_dealloc_, i.last))\n    {\n        // move last_dealloc just outside range\n        last_dealloc_      = i.next;\n        last_dealloc_prev_ = i.prev;\n    }\n\n    return debug_fill_new(i.first, n, fence_size());\n}\n\nvoid ordered_free_memory_list::deallocate(void* ptr) noexcept\n{\n    auto node = static_cast<char*>(debug_fill_free(ptr, node_size_, fence_size()));\n\n    auto p = find_pos(allocator_info(TRTLAB_MEMORY_LOG_PREFIX \"::detail::ordered_free_memory_list\", this), node, begin_node(), end_node(),\n                      last_dealloc_, last_dealloc_prev_);\n\n    xor_list_insert(node, p.prev, p.next);\n    ++capacity_;\n\n    last_dealloc_      = node;\n    last_dealloc_prev_ = p.prev;\n}\n\nvoid ordered_free_memory_list::deallocate(void* ptr, std::size_t n) noexcept\n{\n    if (n <= node_size_)\n        deallocate(ptr);\n    else\n    {\n        auto mem  = debug_fill_free(ptr, n, fence_size());\n        auto prev = insert_impl(mem, n + 2 * fence_size());\n\n        last_dealloc_      = static_cast<char*>(mem);\n        last_dealloc_prev_ = prev;\n    }\n}\n\nstd::size_t ordered_free_memory_list::alignment() const noexcept\n{\n    return alignment_for(node_size_);\n}\n\nstd::size_t ordered_free_memory_list::fence_size() const noexcept\n{\n    // node size is fence size\n    return debug_fence_size ? node_size_ : 0u;\n}\n\nchar* ordered_free_memory_list::insert_impl(void* mem, std::size_t size) noexcept\n{\n    auto actual_size = node_size_ + 2 * fence_size();\n    auto no_nodes    = size / actual_size;\n    TRTLAB_MEMORY_ASSERT(no_nodes > 0);\n\n    auto p = find_pos(allocator_info(TRTLAB_MEMORY_LOG_PREFIX \"::detail::ordered_free_memory_list\", this), static_cast<char*>(mem),\n                      begin_node(), end_node(), last_dealloc_, last_dealloc_prev_);\n\n    xor_link_block(mem, actual_size, no_nodes, p.prev, p.next);\n    capacity_ += no_nodes;\n\n    if (p.prev == last_dealloc_prev_)\n    {\n        last_dealloc_ = static_cast<char*>(mem);\n    }\n\n    return p.prev;\n}\n\nchar* ordered_free_memory_list::begin_node() noexcept\n{\n    void* mem = &begin_proxy_;\n    return static_cast<char*>(mem);\n}\n\nchar* ordered_free_memory_list::end_node() noexcept\n{\n    void* mem = &end_proxy_;\n    return static_cast<char*>(mem);\n}\n"
  },
  {
    "path": "trtlab/memory/src/detail/free_list_utils.h",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_H_INCLUDED\n#define TRTLAB_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_H_INCLUDED\n\n#include <cstdint>\n\n#include \"config.h\"\n#include \"align.h\"\n#include \"detail/assert.h\"\n\n#include <cstring>\n#include <functional>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            //=== storage ===///\n            // reads stored integer value\n            inline std::uintptr_t get_int(void* address) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(address);\n                std::uintptr_t res;\n                std::memcpy(&res, address, sizeof(std::uintptr_t));\n                return res;\n            }\n\n            // sets stored integer value\n            inline void set_int(void* address, std::uintptr_t i) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(address);\n                std::memcpy(address, &i, sizeof(std::uintptr_t));\n            }\n\n            // pointer to integer\n            inline std::uintptr_t to_int(char* ptr) noexcept\n            {\n                return reinterpret_cast<std::uintptr_t>(ptr);\n            }\n\n            // integer to pointer\n            inline char* from_int(std::uintptr_t i) noexcept\n            {\n                return reinterpret_cast<char*>(i);\n            }\n\n            //=== intrusive linked list ===//\n            // reads a stored pointer value\n            inline char* list_get_next(void* address) noexcept\n            {\n                return from_int(get_int(address));\n            }\n\n            // stores a pointer value\n            inline void list_set_next(void* address, char* ptr) noexcept\n            {\n                set_int(address, to_int(ptr));\n            }\n\n            //=== intrusive xor linked list ===//\n            // returns the other pointer given one pointer\n            inline char* xor_list_get_other(void* address, char* prev_or_next) noexcept\n            {\n                return from_int(get_int(address) ^ to_int(prev_or_next));\n            }\n\n            // sets the next and previous pointer (order actually does not matter)\n            inline void xor_list_set(void* address, char* prev, char* next) noexcept\n            {\n                set_int(address, to_int(prev) ^ to_int(next));\n            }\n\n            // changes other pointer given one pointer\n            inline void xor_list_change(void* address, char* old_ptr,\n                                        char* new_ptr) noexcept\n            {\n                TRTLAB_MEMORY_ASSERT(address);\n                auto other = xor_list_get_other(address, old_ptr);\n                xor_list_set(address, other, new_ptr);\n            }\n\n            // advances a pointer pair forward/backward\n            inline void xor_list_iter_next(char*& cur, char*& prev) noexcept\n            {\n                auto next = xor_list_get_other(cur, prev);\n                prev      = cur;\n                cur       = next;\n            }\n\n            // links new node between prev and next\n            inline void xor_list_insert(char* new_node, char* prev, char* next) noexcept\n            {\n                xor_list_set(new_node, prev, next);\n                xor_list_change(prev, next, new_node); // change prev's next to new_node\n                xor_list_change(next, prev, new_node); // change next's prev to new_node\n            }\n\n            //=== sorted list utils ===//\n            // if std::less/std::greater not available compare integer representation and hope it works\n            inline bool less(void* a, void* b) noexcept\n            {\n                return std::less<void*>()(a, b);\n            }\n\n            inline bool less_equal(void* a, void* b) noexcept\n            {\n                return a == b || less(a, b);\n            }\n\n            inline bool greater(void* a, void* b) noexcept\n            {\n                return std::greater<void*>()(a, b);\n            }\n\n            inline bool greater_equal(void* a, void* b) noexcept\n            {\n                return a == b || greater(a, b);\n            }\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab\n\n#endif // TRTLAB_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_H_INCLUDED\n"
  },
  {
    "path": "trtlab/memory/src/detail/page_info.c",
    "content": "/*\n * smaps.c\n *\n *  Created on: Jan 31, 2017\n *      Author: tdowns\n *\n\nextracted from: https://github.com/travisdowns/page-info\n \nMIT License\n\nCopyright (c) 2017 travisdowns\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n \n*/\n\n#include \"detail/page_info.h\"\n\n#include <stdio.h>\n#include <sys/types.h>\n#include <linux/kernel-page-flags.h>\n#include <unistd.h>\n#include <string.h>\n#include <strings.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <err.h>\n#include <assert.h>\n#include <limits.h>\n\n\n#define PM_PFRAME_MASK         ((1ULL << 55) - 1)\n#define PM_SOFT_DIRTY           (1ULL << 55)\n#define PM_MMAP_EXCLUSIVE       (1ULL << 56)\n#define PM_FILE                 (1ULL << 61)\n#define PM_SWAP                 (1ULL << 62)\n#define PM_PRESENT              (1ULL << 63)\n\n\n/** bundles a flag with its description */\ntypedef struct {\n    int flag_num;\n    char const *name;\n    bool show_default;\n} flag;\n\n#define FLAG_SHOW(name) { KPF_ ## name, # name, true },\n#define FLAG_HIDE(name) { KPF_ ## name, # name, false },\n\nconst flag kpageflag_defs[] = {\n        FLAG_SHOW(LOCKED       )\n        FLAG_HIDE(ERROR        )\n        FLAG_HIDE(REFERENCED   )\n        FLAG_HIDE(UPTODATE     )\n        FLAG_HIDE(DIRTY        )\n        FLAG_HIDE(LRU          )\n        FLAG_SHOW(ACTIVE       )\n        FLAG_SHOW(SLAB         )\n        FLAG_HIDE(WRITEBACK    )\n        FLAG_HIDE(RECLAIM      )\n        FLAG_SHOW(BUDDY        )\n        FLAG_SHOW(MMAP         )\n        FLAG_SHOW(ANON         )\n        FLAG_SHOW(SWAPCACHE    )\n        FLAG_SHOW(SWAPBACKED   )\n        FLAG_SHOW(COMPOUND_HEAD)\n        FLAG_SHOW(COMPOUND_TAIL)\n        FLAG_SHOW(HUGE         )\n        FLAG_SHOW(UNEVICTABLE  )\n        FLAG_SHOW(HWPOISON     )\n        FLAG_SHOW(NOPAGE       )\n        FLAG_SHOW(KSM          )\n        FLAG_SHOW(THP          )\n        /* older kernels won't have these new flags, so conditionally compile in support for them */\n#ifdef KPF_BALLOON\n        FLAG_SHOW(BALLOON      )\n#endif\n#ifdef KPF_ZERO_PAGE\n        FLAG_SHOW(ZERO_PAGE    )\n#endif\n#ifdef KPF_IDLE\n        FLAG_SHOW(IDLE         )\n#endif\n\n        { -1, 0, false }  // sentinel\n};\n\n#define kpageflag_count (sizeof(kpageflag_defs)/sizeof(kpageflag_defs[0]) - 1)\n\n#define ITERATE_FLAGS for (flag const *f = kpageflag_defs; f->flag_num != -1; f++)\n\n\n// x-macro for doing some operation on all the pagemap flags\n#define PAGEMAP_X(fn) \\\n    fn(softdirty ) \\\n    fn(exclusive ) \\\n    fn(file      ) \\\n    fn(swapped   ) \\\n    fn(present   )\n\nstatic unsigned get_page_size() {\n    long psize = sysconf(_SC_PAGESIZE);\n    assert(psize >= 1 && psize <= UINT_MAX);\n    return (unsigned)psize;\n}\n\n/* round the given pointer down to the page boundary (i.e,. return a pointer to the page it lives in) */\nstatic inline void *pagedown(void *p, unsigned psize) {\n    return (void *)(((uintptr_t)p) & -(uintptr_t)psize);\n}\n\n/**\n * Extract the interesting info from a 64-bit pagemap value, and return it as a page_info.\n */\npage_info extract_info(uint64_t bits) {\n    page_info ret = {};\n    ret.pfn         = bits & PM_PFRAME_MASK;\n    ret.softdirty   = bits & PM_SOFT_DIRTY;\n    ret.exclusive   = bits & PM_MMAP_EXCLUSIVE;\n    ret.file        = bits & PM_FILE;\n    ret.swapped     = bits & PM_SWAP;\n    ret.present     = bits & PM_PRESENT;\n    return ret;\n}\n\n/* print page_info to the given file */\nvoid fprint_info(FILE* f, page_info info) {\n    fprintf(f,\n            \"PFN: %p\\n\"\n            \"softdirty = %d\\n\"\n            \"exclusive = %d\\n\"\n            \"file      = %d\\n\"\n            \"swapped   = %d\\n\"\n            \"present   = %d\\n\",\n            (void*)info.pfn,\n            info.softdirty,\n            info.exclusive,\n            info.file,\n            info.swapped,\n            info.present);\n}\n\nvoid print_info(page_info info) {\n    fprint_info(stdout, info);\n}\n\nflag_count get_flag_count(page_info_array infos, int flag_num) {\n    flag_count ret = {};\n\n    if (flag_num < 0 || flag_num > 63) {\n        return ret;\n    }\n\n    uint64_t flag = (1ULL << flag_num);\n\n    ret.flag = flag_num;\n    ret.pages_total = infos.num_pages;\n\n    for (size_t i = 0; i < infos.num_pages; i++) {\n        page_info info = infos.info[i];\n        if (info.kpageflags_ok) {\n            ret.pages_set += (info.kpageflags & flag) == flag;\n            ret.pages_available++;\n        }\n    }\n    return ret;\n}\n\n/**\n * Print the table header that lines up with the tabluar format used by the \"table\" printing\n * functions. Called by fprint_ratios, or you can call it yourself if you want to prefix the\n * output with your own columns.\n */\nvoid fprint_info_header(FILE *file) {\n    fprintf(file,  \"         PFN  sdirty   excl   file swappd presnt \");\n    ITERATE_FLAGS { if (f->show_default) fprintf(file, \"%4.4s \", f->name); }\n    fprintf(file, \"\\n\");\n}\n\n/* print one info in a tabular format (as a single row) */\nvoid fprint_info_row(FILE *file, page_info info) {\n    fprintf(file, \"%12p %7d%7d%7d%7d%7d \",\n            (void*)info.pfn,\n            info.softdirty,\n            info.exclusive,\n            info.file,\n            info.swapped,\n            info.present);\n\n    if (info.kpageflags_ok) {\n        ITERATE_FLAGS { if (f->show_default) fprintf(file, \"%4d \", !!(info.kpageflags & (1ULL << f->flag_num))); }\n    }\n    fprintf(file, \"\\n\");\n}\n\n#define DECLARE_ACCUM(name) size_t name ## _accum = 0;\n#define INCR_ACCUM(name)    name ## _accum += info->name;\n#define PRINT_ACCUM(name)   fprintf(file, \"%7.4f\", (double)name ## _accum / infos.num_pages);\n\n\nvoid fprint_ratios_noheader(FILE *file, page_info_array infos) {\n    PAGEMAP_X(DECLARE_ACCUM);\n    size_t total_kpage_ok = 0;\n    size_t flag_totals[kpageflag_count] = {};\n    for (size_t p = 0; p < infos.num_pages; p++) {\n        page_info *info = &infos.info[p];\n        PAGEMAP_X(INCR_ACCUM);\n        if (info->kpageflags_ok) {\n            total_kpage_ok++;\n            int i = 0;\n            ITERATE_FLAGS {\n                flag_totals[i++] += !!(info->kpageflags & (1ULL << f->flag_num));\n            }\n        }\n    }\n\n    printf(\"%12s \", \"----------\");\n    PAGEMAP_X(PRINT_ACCUM)\n\n    int i = 0;\n    if (total_kpage_ok > 0) {\n        ITERATE_FLAGS {\n            if (f->show_default) fprintf(file, \" %4.2f\", (double)flag_totals[i] / total_kpage_ok);\n            i++;\n        }\n    }\n    fprintf(file, \"\\n\");\n}\n\n/*\n * Print a table with one row per page from the given infos.\n */\nvoid fprint_ratios(FILE *file, page_info_array infos) {\n    fprint_info_header(file);\n    fprint_ratios_noheader(file, infos);\n}\n\n/*\n * Prints a summary of all the pages in the given array as ratios: the fraction of the time the given\n * flag was set.\n */\nvoid fprint_table(FILE *f, page_info_array infos) {\n    fprintf(f, \"%zu total pages\\n\", infos.num_pages);\n    fprint_info_header(f);\n    for (size_t p = 0; p < infos.num_pages; p++) {\n        fprint_info_row(f, infos.info[p]);\n    }\n}\n\n\n\n/**\n * Get info for a single page indicated by the given pointer (which may point anywhere in the page)\n */\npage_info get_page_info(void *p) {\n    // just get the info array for a single page\n    page_info_array onepage = get_info_for_range(p, (char *)p + 1);\n    assert(onepage.num_pages == 1);\n    page_info ret = onepage.info[0];\n    free_info_array(onepage);\n    return ret;\n}\n\n/**\n * Get information for each page in the range from start (inclusive) to end (exclusive).\n */\npage_info_array get_info_for_range(void *start, void *end) {\n    unsigned psize = get_page_size();\n    void *start_page = pagedown(start, psize);\n    void *end_page   = pagedown(end - 1, psize) + psize;\n    size_t page_count = start < end ? (end_page - start_page) / psize : 0;\n    assert(page_count == 0 || start_page < end_page);\n\n    if (page_count == 0) {\n        return (page_info_array){ 0, NULL };\n    }\n\n    page_info *infos = malloc((page_count + 1) * sizeof(page_info));\n\n    // open the pagemap file\n    FILE *pagemap_file = fopen(\"/proc/self/pagemap\", \"rb\");\n    if (!pagemap_file) err(EXIT_FAILURE, \"failed to open pagemap\");\n\n    // seek to the first page\n    if (fseek(pagemap_file, (uintptr_t)start_page / psize * sizeof(uint64_t), SEEK_SET)) err(EXIT_FAILURE, \"pagemap seek failed\");\n\n    size_t bitmap_bytes = page_count * sizeof(uint64_t);\n    uint64_t* bitmap = malloc(bitmap_bytes);\n    assert(bitmap);\n    size_t readc = fread(bitmap, bitmap_bytes, 1, pagemap_file);\n    if (readc != 1) err(EXIT_FAILURE, \"unexpected fread(pagemap) return: %zu\", readc);\n\n    fclose(pagemap_file);\n\n    FILE *kpageflags_file = NULL;\n    enum { INIT, OPEN, FAILED  } file_state = INIT;\n\n    for (size_t page_idx = 0; page_idx < page_count; page_idx++) {\n        page_info info = extract_info(bitmap[page_idx]);\n\n        if (info.pfn) {\n            // we got a pfn, try to read /proc/kpageflags\n\n            // open file if not open\n            if (file_state == INIT) {\n                kpageflags_file = fopen(\"/proc/kpageflags\", \"rb\");\n                if (!kpageflags_file) {\n                    warn(\"failed to open kpageflags\");\n                    file_state = FAILED;\n                } else {\n                    file_state = OPEN;\n                }\n            }\n\n            if (file_state == OPEN) {\n                uint64_t bits;\n                if (fseek(kpageflags_file, info.pfn * sizeof(bits), SEEK_SET)) err(EXIT_FAILURE, \"kpageflags seek failed\");\n                if ((readc = fread(&bits, sizeof(bits), 1, kpageflags_file)) != 1) err(EXIT_FAILURE, \"unexpected fread(kpageflags) return: %zu\", readc);\n                info.kpageflags_ok = true;\n                info.kpageflags = bits;\n            }\n        }\n\n        infos[page_idx] = info;\n    }\n\n    if (kpageflags_file)\n        fclose(kpageflags_file);\n\n    free(bitmap);\n\n    return (page_info_array){ page_count, infos };\n}\n\nvoid free_info_array(page_info_array infos) {\n    free(infos.info);\n}\n\nint flag_from_name(char const *name) {\n    ITERATE_FLAGS {\n        if (strcasecmp(f->name, name) == 0) {\n            return f->flag_num;\n        }\n    }\n    return -1;\n}"
  },
  {
    "path": "trtlab/memory/src/error.cc",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#include \"error.h\"\n\n#include <atomic>\n#include <cstdio>\n\n// #include <foonathan/get_new_handler.hpp>\n\nusing namespace trtlab::memory;\n\nnamespace\n{\n    void default_out_of_memory_handler(const allocator_info& info, std::size_t amount) noexcept\n    {\n#if TRTLAB_HOSTED_IMPLEMENTATION\n        std::fprintf(stderr,\n                     \"[%s] Allocator %s (at %p) ran out of memory trying to allocate %zu bytes.\\n\",\n                     TRTLAB_MEMORY_LOG_PREFIX, info.name, info.allocator, amount);\n#endif\n    }\n\n    std::atomic<out_of_memory::handler> out_of_memory_h(default_out_of_memory_handler);\n}\n\nout_of_memory::handler out_of_memory::set_handler(out_of_memory::handler h)\n{\n    return out_of_memory_h.exchange(h ? h : default_out_of_memory_handler);\n}\n\nout_of_memory::handler out_of_memory::get_handler()\n{\n    return out_of_memory_h;\n}\n\nout_of_memory::out_of_memory(const allocator_info& info, std::size_t amount)\n: info_(info), amount_(amount)\n{\n    out_of_memory_h.load()(info, amount);\n}\n\nconst char* out_of_memory::what() const noexcept\n{\n    return \"low-level allocator is out of memory\";\n}\n\nconst char* out_of_fixed_memory::what() const noexcept\n{\n    return \"fixed size allocator is out of memory\";\n}\n\nnamespace\n{\n    void default_bad_alloc_size_handler(const allocator_info& info, std::size_t passed,\n                                        std::size_t supported) noexcept\n    {\n#if TRTLAB_HOSTED_IMPLEMENTATION\n        std::fprintf(stderr, \"[%s] Allocator %s (at %p) received invalid size/alignment %zu, \"\n                             \"max supported is %zu\\n\",\n                     TRTLAB_MEMORY_LOG_PREFIX, info.name, info.allocator, passed, supported);\n#endif\n    }\n\n    std::atomic<bad_allocation_size::handler> bad_alloc_size_h(default_bad_alloc_size_handler);\n}\n\nbad_allocation_size::handler bad_allocation_size::set_handler(bad_allocation_size::handler h)\n{\n    return bad_alloc_size_h.exchange(h ? h : default_bad_alloc_size_handler);\n}\n\nbad_allocation_size::handler bad_allocation_size::get_handler()\n{\n    return bad_alloc_size_h;\n}\n\nbad_allocation_size::bad_allocation_size(const allocator_info& info, std::size_t passed,\n                                         std::size_t supported)\n: info_(info), passed_(passed), supported_(supported)\n{\n    bad_alloc_size_h.load()(info_, passed_, supported_);\n}\n\nconst char* bad_allocation_size::what() const noexcept\n{\n    return \"allocation node size exceeds supported maximum of allocator\";\n}\n\nconst char* bad_node_size::what() const noexcept\n{\n    return \"allocation node size exceeds supported maximum of allocator\";\n}\n\nconst char* bad_array_size::what() const noexcept\n{\n    return \"allocation array size exceeds supported maximum of allocator\";\n}\n\nconst char* bad_alignment::what() const noexcept\n{\n    return \"allocation alignment exceeds supported maximum of allocator\";\n}\n"
  },
  {
    "path": "trtlab/memory/src/ilog2.h",
    "content": "// MODIFICATION MESSAGE\n\n// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef TRTLAB_MEMORY_SRC_DETAIL_ILOG2_HPP_INCLUDED\n#define TRTLAB_MEMORY_SRC_DETAIL_ILOG2_HPP_INCLUDED\n\n#include \"config.h\"\n\n#include <cstddef>\n#include <climits>\n#include <cstdint>\n#include <type_traits>\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        namespace detail\n        {\n            // prioritized tag dispatching to choose smallest integer that fits\n            struct clzll_tag\n            {\n            };\n            struct clzl_tag : clzll_tag\n            {\n            };\n            struct clz_tag : clzl_tag\n            {\n            };\n\n            // also subtracts the number of addtional 0s that occur because the target type is smaller\n            template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned int)>::type>\n            constexpr unsigned clz(clz_tag, T x)\n            {\n                return __builtin_clz(x) - (sizeof(unsigned int) * CHAR_BIT - sizeof(T) * CHAR_BIT);\n            }\n\n            template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned long)>::type>\n            constexpr unsigned clz(clzl_tag, T x)\n            {\n                return __builtin_clzl(x) - (sizeof(unsigned long) * CHAR_BIT - sizeof(T) * CHAR_BIT);\n            }\n\n            template <typename T, typename = typename std::enable_if<sizeof(T) <= sizeof(unsigned long long)>::type>\n            constexpr unsigned clz(clzll_tag, T x)\n            {\n                return __builtin_clzll(x) - (sizeof(unsigned long long) * CHAR_BIT - sizeof(T) * CHAR_BIT);\n            }\n            constexpr unsigned clz(std::uint8_t x)\n            {\n                return detail::clz(detail::clz_tag{}, x);\n            }\n\n            constexpr unsigned clz(std::uint16_t x)\n            {\n                return detail::clz(detail::clz_tag{}, x);\n                ;\n            }\n\n            constexpr unsigned clz(std::uint32_t x)\n            {\n                return detail::clz(detail::clz_tag{}, x);\n            }\n\n            constexpr unsigned clz(std::uint64_t x)\n            {\n                return detail::clz(detail::clz_tag{}, x);\n            }\n\n            // undefined for 0\n            template <typename UInt>\n            constexpr bool is_power_of_two(UInt x)\n            {\n                return (x & (x - 1)) == 0;\n            }\n\n            constexpr std::size_t ilog2_base(std::uint64_t x)\n            {\n                return sizeof(x) * CHAR_BIT - clz(x);\n            }\n\n            // ilog2() implementation, cuts part after the comma\n            // e.g. 1 -> 0, 2 -> 1, 3 -> 1, 4 -> 2, 5 -> 2\n            constexpr std::size_t ilog2(std::size_t x)\n            {\n                return ilog2_base(x) - 1;\n            }\n\n            // ceiling ilog2() implementation, adds one if part after comma\n            // e.g. 1 -> 0, 2 -> 1, 3 -> 2, 4 -> 2, 5 -> 3\n            constexpr std::size_t ilog2_ceil(std::size_t x)\n            {\n                // only subtract one if power of two\n                return ilog2_base(x) - std::size_t(is_power_of_two(x));\n            }\n        } // namespace detail\n    }     // namespace memory\n} // namespace trtlab\n\n#endif\n"
  },
  {
    "path": "trtlab/memory/src/memory_type.cc",
    "content": "\n#include \"memory_type.h\"\n#include \"ilog2.h\"\n\nusing namespace trtlab::memory;\n\nstd::size_t detail::any_memory::ilog2(std::size_t size) noexcept\n{\n    return ::trtlab::memory::detail::ilog2(size);\n}\n"
  },
  {
    "path": "trtlab/memory/src/trackers.cc",
    "content": "\n#include \"trackers.h\"\n#include <atomic>\n\nusing namespace trtlab;\nusing namespace memory;\n\nstruct size_tracker::impl\n{\n    std::atomic<std::size_t> bytes = 0;\n};\n\nsize_tracker::size_tracker() : pimpl(std::make_unique<size_tracker::impl>()) {}\nsize_tracker::~size_tracker() = default;\n\nsize_tracker::size_tracker(size_tracker&&) noexcept = default;\nsize_tracker& size_tracker::operator=(size_tracker&&) noexcept = default;\n\nstd::size_t size_tracker::bytes() const noexcept\n{\n    return pimpl->bytes.load();\n}\n\nvoid size_tracker::on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n{\n    pimpl->bytes += size;\n}\n\nvoid size_tracker::on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n{\n    pimpl->bytes -= size;\n}\n\nvoid size_tracker::on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n{\n    pimpl->bytes += (count * size);\n}\n\nvoid size_tracker::on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n{\n    pimpl->bytes -= (count * size);\n}"
  },
  {
    "path": "trtlab/memory/src/utils.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <math.h>\n#include <stdio.h>\n\n#include <cmath>\n#include <regex>\n\n#include <glog/logging.h>\n\n#include \"utils.h\"\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        std::string bytes_to_string(size_t bytes)\n        {\n            char       buffer[50];\n            int        unit       = 1024;\n            const char prefixes[] = \"KMGTPE\";\n            if (bytes < unit)\n            {\n                sprintf(buffer, \"%ld B\", bytes);\n                return std::string(buffer);\n            }\n            int exp = (int)(std::log(bytes) / std::log(unit));\n            sprintf(buffer, \"%.1f %ciB\", bytes / std::pow(unit, exp), prefixes[exp - 1]);\n            return std::string(buffer);\n        }\n\n        std::uint64_t string_to_bytes(const std::string str)\n        {\n            // https://regex101.com/r/UVm5wT/1\n            std::smatch         m;\n            std::regex          r(\"(\\\\d+[.\\\\d+]*)([KMGTkmgt]*)([i]*)[bB]\");\n            std::map<char, int> prefix = {\n                {'k', 1}, {'m', 2}, {'g', 3}, {'t', 4}, {'K', 1}, {'M', 2}, {'G', 3}, {'T', 4},\n            };\n\n            if (!std::regex_search(str, m, r))\n                LOG(FATAL) << \"Unable to convert \\\"\" << str << \"\\\" to bytes. \"\n                           << \"Expected format: 10b, 1024B, 1KiB, 10MB, 2.4gb, etc.\";\n\n            const std::uint64_t base     = m.empty() || (m.size() > 3 && m[3] == \"\") ? 1000 : 1024;\n            auto                exponent = prefix[m[2].str()[0]];\n            auto                scalar   = std::stod(m[1]);\n            return (std::uint64_t)(scalar * std::pow(base, exponent));\n        }\n    } // namespace memory\n} // namespace trtlab"
  },
  {
    "path": "trtlab/memory/tests/CMakeLists.txt",
    "content": "# MODIFICATION MESSAGE\n\n# Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n# This file is subject to the license terms in the LICENSE file\n# found in the top-level directory of this distribution.\n\n# builds test\n\nfind_package(GTest)\nenable_testing()\n\nset(tests\n#   test_simple.cc\n    test_memory.cc\n    test_main.cc\n)\n\nadd_executable(test_memory ${tests})\ntarget_link_libraries(test_memory trtlab_memory GTest::gtest)\ntarget_include_directories(test_memory PRIVATE\n                           ${CMAKE_CURRENT_BINARY_DIR}\n                           ${TRTLAB_MEMORY_SOURCE_DIR}/include/trtlab/memory)\n\nadd_test(NAME memory COMMAND test_memory)\n"
  },
  {
    "path": "trtlab/memory/tests/test_main.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <glog/logging.h>\n#include <gtest/gtest.h>\n\nint main(int argc, char **argv) {\n    FLAGS_alsologtostderr = 1; // Log to console\n    ::google::InitGoogleLogging(\"trtlab::test_memory\");\n    ::testing::InitGoogleTest(&argc, argv);\n    ::google::ParseCommandLineFlags(&argc, &argv, true);\n    return RUN_ALL_TESTS();\n}"
  },
  {
    "path": "trtlab/memory/tests/test_memory.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <gtest/gtest.h>\n\n#include <cstring>\n#include <mutex>\n#include <vector>\n\n#include \"trtlab/memory/allocator.h\"\n#include \"trtlab/memory/block_allocators.h\"\n#include \"trtlab/memory/block_arena.h\"\n#include \"trtlab/memory/std_allocator.h\"\n#include \"trtlab/memory/tracking.h\"\n#include \"trtlab/memory/literals.h\"\n#include \"trtlab/memory/smart_ptr.h\"\n\n#include \"trtlab/memory/detail/memory_stack.h\"\n#include \"trtlab/memory/transactional_allocator.h\"\n\nusing namespace trtlab::memory;\nusing namespace trtlab::memory::literals;\n\nclass TestMemory : public ::testing::Test\n{\n};\n\n#define ALIAS_TEMPLATE(Name, ...) using Name = __VA_ARGS__\n\nnamespace trtlab\n{\n    namespace memory\n    {\n        template <typename T, class RawAllocator>\n        ALIAS_TEMPLATE(vector, std::vector<T, std_allocator<T, RawAllocator>>);\n    }\n} // namespace trtlab\n\ntemplate <typename T, typename RawAllocator>\nauto make_vector(RawAllocator&& alloc)\n{\n    return vector<T, RawAllocator>(alloc);\n}\n\ntemplate <typename T, typename RawAllocator, typename Mutex>\nauto make_vector(allocator<RawAllocator, Mutex> alloc)\n{\n    return vector<T, trtlab::memory::allocator<RawAllocator, Mutex>>(alloc);\n}\n\nstruct log_tracker\n{\n    void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << name << \": node allocated: \" << ptr << \"; size: \" << size << \"; alignment: \" << alignment;\n    }\n\n    void on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << name << \": node deallocated: \" << ptr << \"; \" << size << \"; \" << alignment;\n    }\n\n    void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << name << \": array allocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    }\n\n    void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << name << \": array deallocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    }\n\n    const char* name;\n};\n\nstruct empty_tracker\n{\n    void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << \": node allocated: \" << ptr << \"; size: \" << size << \"; alignment: \" << alignment;\n    }\n\n    void on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << \": node deallocated: \" << ptr << \"; \" << size << \"; \" << alignment;\n    }\n\n    void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << \": array allocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    }\n\n    void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        LOG(INFO) << \": array deallocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n    }\n};\n\nstruct counting_tracker\n{\n    counting_tracker(std::string n) : name(n), m_node_count(0), m_node_bytes(0), m_array_count(0), m_array_bytes(0) {}\n    ~counting_tracker() {}\n\n    counting_tracker(const counting_tracker&) = default;\n    counting_tracker& operator=(const counting_tracker&) = default;\n\n    counting_tracker(counting_tracker&&) noexcept = default;\n    counting_tracker& operator=(counting_tracker&&) noexcept = default;\n\n    void on_node_allocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        DLOG(INFO) << name << \": node allocated: \" << ptr << \"; size: \" << size << \"; alignment: \" << alignment;\n        m_node_count++;\n        m_node_bytes += size;\n        DLOG(INFO) << name << \": node allocations: \" << m_node_count << \"; node bytes: \" << m_node_bytes;\n    }\n\n    void on_node_deallocation(void* ptr, std::size_t size, std::size_t alignment) noexcept\n    {\n        DLOG(INFO) << name << \": node deallocated: \" << ptr << \"; \" << size << \"; \" << alignment;\n        m_node_count--;\n        m_node_bytes -= size;\n        DLOG(INFO) << name << \": node allocations: \" << m_node_count << \"; node bytes: \" << m_node_bytes;\n    }\n\n    void on_array_allocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        DLOG(INFO) << name << \": array allocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n        m_array_count++;\n        m_array_bytes += count * size;\n        DLOG(INFO) << name << \": array allocations: \" << m_array_count << \"; array bytes: \" << m_array_bytes;\n    }\n\n    void on_array_deallocation(void* ptr, std::size_t count, std::size_t size, std::size_t alignment) noexcept\n    {\n        DLOG(INFO) << name << \": array deallocated: \" << ptr << \" ( \" << count << \" * \" << size << \"; \" << alignment << \" )\";\n        m_array_count--;\n        m_array_bytes -= count * size;\n        DLOG(INFO) << name << \": array allocations: \" << m_array_count << \"; array bytes: \" << m_array_bytes;\n    }\n\n    std::size_t count() const noexcept\n    {\n        return m_node_count + m_array_count;\n    }\n\n    std::size_t bytes() const noexcept\n    {\n        return m_node_bytes + m_array_bytes;\n    }\n\n    std::size_t node_count() const noexcept\n    {\n        return m_node_count;\n    }\n    std::size_t node_bytes() const noexcept\n    {\n        return m_node_bytes;\n    }\n    std::size_t array_count() const noexcept\n    {\n        return m_array_count;\n    }\n    std::size_t array_bytes() const noexcept\n    {\n        return m_array_bytes;\n    }\n\nprivate:\n    std::string name;\n    std::size_t m_node_count;\n    std::size_t m_node_bytes;\n    std::size_t m_array_count;\n    std::size_t m_array_bytes;\n};\n\ntemplate <typename Allocator>\nstatic void test_alloc_x10(Allocator& alloc)\n{\n    auto p0 = alloc.allocate_node(33_MiB, 8UL);\n    auto p1 = alloc.allocate_node(44_MiB, 8UL);\n    auto p2 = alloc.allocate_node(78_MiB, 8UL);\n    auto p3 = alloc.allocate_node(12_MiB, 8UL);\n    auto p4 = alloc.allocate_node(32_MiB, 8UL);\n    auto p5 = alloc.allocate_node(100_MiB, 8UL);\n    auto p6 = alloc.allocate_node(18_MiB, 8UL);\n    auto p7 = alloc.allocate_node(21_MiB, 8UL);\n    auto p8 = alloc.allocate_node(15_MiB, 8UL);\n    auto p9 = alloc.allocate_node(71_MiB, 8UL);\n\n    alloc.deallocate_node(p3, 12_MiB, 8UL);\n    alloc.deallocate_node(p1, 44_MiB, 8UL);\n    alloc.deallocate_node(p7, 21_MiB, 8UL);\n    alloc.deallocate_node(p8, 15_MiB, 8UL);\n    alloc.deallocate_node(p0, 33_MiB, 8UL);\n    alloc.deallocate_node(p4, 32_MiB, 8UL);\n    alloc.deallocate_node(p6, 18_MiB, 8UL);\n    alloc.deallocate_node(p5, 100_MiB, 8UL);\n    alloc.deallocate_node(p9, 71_MiB, 8UL);\n    alloc.deallocate_node(p2, 78_MiB, 8UL);\n}\n\nstruct TestRawMalloc\n{\n    using memory_type = host_memory;\n    using is_stateful = std::false_type;\n\n    static void* allocate_node(std::size_t size, std::size_t)\n    {\n        return std::malloc(size);\n    }\n\n    static void deallocate_node(void* ptr, std::size_t, std::size_t) noexcept\n    {\n        return std::free(ptr);\n    }\n};\n\nTEST_F(TestMemory, BasicTraits)\n{\n    auto raw = TestRawMalloc();\n    static_assert(std::is_same<typename decltype(raw)::is_stateful, std::false_type>::value, \"\");\n    auto alloc = make_allocator(std::move(raw));\n    //static_assert(std::is_same<typename decltype(alloc)::is_stateful, std::false_type>::value, \"\");\n\n    void* p0 = alloc.allocate(1_MiB);\n    ASSERT_NE(p0, nullptr);\n    std::memset(p0, 1, 1_MiB);\n    alloc.deallocate(p0, 1_MiB);\n}\n\nTEST_F(TestMemory, ReferenceStorage)\n{\n    auto raw = TestRawMalloc();\n    static_assert(std::is_same<typename decltype(raw)::is_stateful, std::false_type>::value, \"\");\n\n    auto alloc = make_allocator(std::move(raw));\n\n    ASSERT_EQ(alloc.use_count(), 1);\n    auto ref = make_allocator_reference(alloc);\n    ASSERT_EQ(alloc.use_count(), 2);\n}\n\n#include \"malloc_allocator.h\"\n\nTEST_F(TestMemory, VectorWithTracking)\n{\n    auto raw     = malloc_allocator();\n    auto adpt    = make_allocator_adapter(std::move(raw));\n    ASSERT_EQ(adpt.device_context().device_type, kDLCPU);\n\n    auto tracked = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(adpt));\n    ASSERT_EQ(tracked.device_context().device_type, kDLCPU);\n\n    auto alloc   = make_allocator(std::move(tracked));\n\n    ASSERT_EQ(alloc.device_context().device_type, kDLCPU);\n\n    ASSERT_EQ(alloc.use_count(), 1);\n    auto vec1 = make_vector<int>(alloc);\n    ASSERT_EQ(alloc.use_count(), 2);\n\n    vec1.reserve(128);\n\n    LOG(INFO) << vec1.get_allocator().get_allocator().min_alignment();\n    LOG(INFO) << vec1.get_allocator().get_allocator().max_alignment();\n\n    for (int i = 0; i < 10; i++)\n    {\n        vec1.push_back(i);\n    }\n\n    auto vec2 = vec1;\n\n    for (int i = 0; i < 10; i++)\n    {\n        vec2[i] += 2;\n    }\n\n    ASSERT_EQ(alloc.use_count(), 3);\n}\n\n// block_allocator from raw type\nTEST_F(TestMemory, SingleBlockAllocatorFromType)\n{\n    auto block_alloc = make_block_allocator<single_block_allocator, TestRawMalloc>(1_MiB);\n    auto block       = block_alloc.allocate_block();\n    ASSERT_EQ(block_alloc.next_block_size(), 0);\n    block_alloc.deallocate_block(block);\n    ASSERT_EQ(block_alloc.next_block_size(), 1_MiB);\n}\n\nTEST_F(TestMemory, SingleBlockAllocatorFromObj)\n{\n    auto raw         = TestRawMalloc();\n    auto tracked     = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(raw));\n    auto block_alloc = make_block_allocator<single_block_allocator>(std::move(tracked), 1_MiB);\n\n    auto block = block_alloc.allocate_block();\n    block_alloc.deallocate_block(block);\n\n    block = block_alloc.allocate_block();\n    EXPECT_ANY_THROW(block_alloc.allocate_block());\n    block_alloc.deallocate_block(block);\n}\n\nTEST_F(TestMemory, FixedSizedBlockAllocatorFromType)\n{\n    auto block_alloc = make_block_allocator<fixed_size_block_allocator, TestRawMalloc>(1_MiB);\n    auto block       = block_alloc.allocate_block();\n    ASSERT_EQ(block_alloc.next_block_size(), 1_MiB);\n    block_alloc.deallocate_block(block);\n}\n\nTEST_F(TestMemory, FixedSizedBlockAllocatorFromObj)\n{\n    auto raw         = TestRawMalloc();\n    auto tracked     = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(raw));\n    auto block_alloc = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n\n    auto block0 = block_alloc.allocate_block();\n    auto block1 = block_alloc.allocate_block();\n    ASSERT_EQ(block0.size, 1_MiB);\n    ASSERT_EQ(block1.size, 1_MiB);\n    block_alloc.deallocate_block(block0);\n    block_alloc.deallocate_block(block1);\n}\n\nTEST_F(TestMemory, GrowingdBlockAllocatorFromType)\n{\n    auto block_alloc = make_block_allocator<growing_block_allocator, TestRawMalloc>(1_MiB);\n    auto block       = block_alloc.allocate_block();\n    ASSERT_EQ(block_alloc.next_block_size(), 2_MiB);\n    block_alloc.deallocate_block(block);\n}\n\nTEST_F(TestMemory, GrowingdBlockAllocatorFromObj)\n{\n    auto raw         = TestRawMalloc();\n    auto tracked     = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(raw));\n    auto block_alloc = make_block_allocator<growing_block_allocator>(std::move(tracked), 1_MiB, 2_MiB, 2.0);\n\n    auto block0 = block_alloc.allocate_block();\n    auto block1 = block_alloc.allocate_block();\n    ASSERT_EQ(block0.size, 1_MiB);\n    ASSERT_EQ(block1.size, 2_MiB);\n    ASSERT_EQ(block_alloc.next_block_size(), 2_MiB);\n    block_alloc.deallocate_block(block0);\n    block_alloc.deallocate_block(block1);\n}\n\nTEST_F(TestMemory, CountLimitedFixedSizeBlockAllocatorFromType)\n{\n    auto block_alloc = make_block_allocator<fixed_size_block_allocator, TestRawMalloc>(1_MiB);\n    auto block       = block_alloc.allocate_block();\n    ASSERT_EQ(block_alloc.next_block_size(), 1_MiB);\n    block_alloc.deallocate_block(block);\n}\n\nTEST_F(TestMemory, CountLimitedFixedSizeBlockAllocatorFromObj)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n    auto alloc   = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 2UL);\n\n    auto block0 = alloc.allocate_block();\n    auto block1 = alloc.allocate_block();\n    ASSERT_EQ(block0.size, 1_MiB);\n    ASSERT_EQ(block1.size, 1_MiB);\n    ASSERT_EQ(alloc.block_count(), 2);\n    ASSERT_ANY_THROW(alloc.allocate_block());\n    alloc.deallocate_block(block0);\n    alloc.deallocate_block(block1);\n}\n\nTEST_F(TestMemory, SizeLimitedFixedSizeBlockAllocatorFromObj)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n    auto alloc   = make_extended_block_allocator<size_limited_block_allocator>(std::move(block), 2_MiB);\n\n    auto block0 = alloc.allocate_block();\n    auto block1 = alloc.allocate_block();\n    ASSERT_EQ(block0.size, 1_MiB);\n    ASSERT_EQ(block1.size, 1_MiB);\n    ASSERT_EQ(alloc.bytes_allocated(), 2_MiB);\n    ASSERT_ANY_THROW(alloc.allocate_block());\n    alloc.deallocate_block(block0);\n    alloc.deallocate_block(block1);\n}\n\nTEST_F(TestMemory, SmartPtrsWithStatelessRawAllocator)\n{\n    auto raw = TestRawMalloc();\n    static_assert(std::is_same<typename decltype(raw)::is_stateful, std::false_type>::value, \"\");\n    static_assert(is_thread_safe_allocator<decltype(raw)>::value, \"should be true\");\n\n    auto tracked = make_tracked_allocator(empty_tracker{}, std::move(raw));\n    static_assert(std::is_same<typename decltype(tracked)::is_stateful, std::false_type>::value, \"\");\n    static_assert(is_thread_safe_allocator<decltype(tracked)>::value, \"should be true\");\n\n    auto alloc = make_allocator(std::move(tracked));\n    static_assert(is_thread_safe_allocator<decltype(alloc)>::value, \"should be true\");\n    static_assert(std::is_same<typename decltype(alloc)::mutex, no_mutex>::value, \"\");\n\n    ASSERT_EQ(alloc.use_count(), 1);\n\n    auto i0 = allocate_unique<int>(alloc, 1);\n    ASSERT_EQ(alloc.use_count(), 2);\n}\n\nTEST_F(TestMemory, SmartPtrsWithStatefulRawAllocator)\n{\n    auto raw = TestRawMalloc();\n    static_assert(std::is_same<typename decltype(raw)::is_stateful, std::false_type>::value, \"\");\n    static_assert(is_thread_safe_allocator<decltype(raw)>::value, \"should be true\");\n\n    auto tracked = make_tracked_allocator(log_tracker{\"** malloc **\"}, std::move(raw));\n    static_assert(std::is_same<typename decltype(tracked)::is_stateful, std::true_type>::value, \"\");\n    static_assert(!is_thread_safe_allocator<decltype(tracked)>::value, \"should be false\");\n\n    auto alloc = make_allocator(std::move(tracked));\n    static_assert(is_thread_safe_allocator<decltype(alloc)>::value, \"should be true\");\n    static_assert(std::is_same<typename decltype(alloc)::mutex, std::mutex>::value, \"\");\n\n    ASSERT_EQ(alloc.use_count(), 1);\n\n    auto i0 = allocate_unique<int>(alloc, 1);\n    ASSERT_EQ(alloc.use_count(), 2);\n}\n\nTEST_F(TestMemory, MemoryDescriptors)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(empty_tracker{}, std::move(raw));\n    auto alloc   = make_allocator(std::move(tracked));\n\n    ASSERT_EQ(alloc.use_count(), 1);\n\n    auto ref = make_allocator_reference(alloc);\n    ASSERT_EQ(alloc.use_count(), 2);\n\n    LOG(INFO) << \"testing any\";\n\n    auto any_ref = make_any_allocator_reference(alloc);\n    ASSERT_EQ(alloc.use_count(), 3);\n\n    auto md = alloc.allocate_descriptor(1_MiB);\n    /*\n    auto md = alloc.allocate_mdesc(1_MiB);\n    ASSERT_EQ(alloc.use_count(), 4);\n\n    auto md3 = alloc.allocate_mdesc_v3(1_MiB);\n    ASSERT_EQ(alloc.use_count(), 5);\n\n    mdesc_v3 v3;\n    v3 = std::move(md3);\n    ASSERT_EQ(alloc.use_count(), 5);\n*/\n    LOG(INFO) << \"finished testing any\";\n}\n\nTEST_F(TestMemory, AllocatorTraits)\n{\n    auto raw   = TestRawMalloc();\n    auto alloc = make_allocator(std::move(raw));\n\n    using traits = allocator_traits<decltype(alloc)>;\n\n    auto min = traits::min_alignment(alloc);\n    auto ctx = traits::device_context(alloc);\n}\n\nTEST_F(TestMemory, CachedBlockArena)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(counting_tracker(\"** tracker: malloc **\"), std::move(raw));\n    // protect the counters by making tracked a thread-safe allocator\n    auto safe  = make_thread_safe_allocator<std::mutex>(std::move(tracked));\n    auto block = make_block_allocator<fixed_size_block_allocator>(std::move(safe), 1_MiB);\n    auto alloc = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 2UL);\n    auto arena = make_cached_block_arena(std::move(alloc));\n\n    /*                          v thread-safe v  v tracked v                */\n    const auto& tracker = arena.get_allocator().get_allocator().get_tracker();\n\n    auto block0 = arena.allocate_block();\n    ASSERT_EQ(tracker.array_count(), 1);\n    ASSERT_EQ(tracker.array_bytes(), 1_MiB);\n\n    auto block1 = arena.allocate_block();\n    ASSERT_EQ(tracker.array_count(), 2);\n    ASSERT_EQ(tracker.array_bytes(), 2_MiB);\n\n    ASSERT_EQ(arena.get_block_allocator().block_count(), 2);\n    ASSERT_ANY_THROW(arena.allocate_block());\n\n    // caching arena will hold the block and not actually deallocate it\n    arena.deallocate_block(std::move(block0));\n    ASSERT_EQ(tracker.array_count(), 2);\n    ASSERT_EQ(tracker.array_bytes(), 2_MiB);\n\n    // deallocate any used cached blocks\n    arena.shrink_to_fit();\n    ASSERT_EQ(tracker.array_count(), 1);\n    ASSERT_EQ(tracker.array_bytes(), 1_MiB);\n\n    // add a block back to the cache\n    arena.deallocate_block(std::move(block1));\n    ASSERT_EQ(tracker.array_count(), 1);\n    ASSERT_EQ(tracker.array_bytes(), 1_MiB);\n\n    // this allocation should pull from the cache\n    block0 = arena.allocate_block();\n    ASSERT_EQ(tracker.array_count(), 1);\n    ASSERT_EQ(tracker.array_bytes(), 1_MiB);\n    arena.deallocate_block(std::move(block0));\n}\n\nTEST_F(TestMemory, DetailStack)\n{\n    detail::fixed_memory_stack stack;\n}\n\nTEST_F(TestMemory, TransactionalAllocator)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(counting_tracker(\"** tracker: malloc **\"), std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n    auto counted = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 3);\n    auto arena   = make_cached_block_arena(std::move(counted));\n    auto txalloc = make_transactional_allocator(std::move(arena));\n    auto alloc   = make_allocator(std::move(txalloc));\n\n    /*                           v txalloc v     v tracked v  */\n    const auto& tracker = alloc.get_allocator().get_allocator().get_tracker();\n\n    // the transactional allocator will allocate one block on instantiate\n    // you can avoid this overhead if you've pre-instantiated the arena by\n    // calling reserve_blocks on the arena allocator prior to moving it into\n    // the transactional allocator\n    ASSERT_EQ(tracker.count(), 1);\n    ASSERT_EQ(tracker.bytes(), 1_MiB);\n\n    {\n        // this is allocated on the initial stack\n        auto md = alloc.allocate_descriptor(1_KiB);\n        ASSERT_EQ(tracker.count(), 1UL);\n        ASSERT_EQ(tracker.bytes(), 1_MiB);\n    }\n\n    {\n        // since the previous memory descriptor is released\n        // the next allocation can force recycling of that block\n        // rather than allocating a new one\n        auto md1 = alloc.allocate_descriptor(1_MiB);\n        ASSERT_EQ(tracker.count(), 1);\n        ASSERT_EQ(tracker.bytes(), 1_MiB);\n    }\n\n    {\n        auto on_block_0 = alloc.allocate_descriptor(1_KiB);\n        ASSERT_EQ(tracker.count(), 1UL);\n        ASSERT_EQ(tracker.bytes(), 1_MiB);\n\n        // not enough room on the original stack\n        // since we have not pre-reserved arena blocks\n        // this will allocate a new block\n\n        auto on_block_1 = alloc.allocate_descriptor(1_MiB);\n        ASSERT_EQ(tracker.count(), 2UL);\n        ASSERT_EQ(tracker.bytes(), 2_MiB);\n    }\n}\n\n#include \"huge_page_allocator.h\"\n#include \"detail/page_info.h\"\n#include \"linux/kernel-page-flags.h\"\n\n#include <thread>\n\nTEST_F(TestMemory, TransparentHugePages)\n{\n    constexpr std::size_t size = 20_MiB;\n\n    auto thp_2m = transparent_huge_page_allocator<2_MiB>();\n\n    auto alloc = make_allocator(std::move(thp_2m));\n\n    ASSERT_EQ(2_MiB, alloc.min_alignment());\n    ASSERT_EQ(2_MiB, alloc.max_alignment());\n\n    auto md = alloc.allocate_descriptor(size);\n    std::memset(md.data(), 0, size);\n\n    // this breaks down the array into system page-sized pages\n    // on linux, 4k pages\n    // in this example, we will test each of those 4k pages to see if they belong\n    // to a larger transparent huge page\n    page_info_array pinfo     = get_info_for_range(md.data(), ((char*)md.data()) + size);\n    flag_count      thp_count = get_flag_count(pinfo, KPF_THP);\n\n    EXPECT_TRUE(thp_count.pages_available) << \"hugepage info not available; probably not running as root\";\n\n    if (thp_count.pages_available)\n    {\n        EXPECT_EQ(thp_count.pages_set, thp_count.pages_total);\n    }\n\n    // DLOG(INFO) << \"grep -e AnonHugePages  /proc/\" << getpid() << \"/smaps\";\n    // std::this_thread::sleep_for(std::chrono::seconds(60));\n}\n\n#include \"detail/free_list.h\"\n\nbool is_equal(void* a, void* b)\n{\n    return reinterpret_cast<std::uintptr_t>(a) == reinterpret_cast<std::uintptr_t>(b);\n}\n\nTEST_F(TestMemory, TestFreeList)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(counting_tracker(\"** tracker: malloc **\"), std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n\n    auto b0 = block.allocate_block();\n    auto b1 = block.allocate_block();\n\n    auto mem0 = b0.memory;\n    auto mem1 = b1.memory;\n\n    ASSERT_FALSE(is_equal(b0.memory, b1.memory));\n\n    auto list = detail::block_list();\n\n    list.insert(std::move(b0));\n    list.insert(std::move(b1));\n    ASSERT_EQ(list.size(), 2);\n\n    auto l0 = list.allocate();\n    ASSERT_EQ(list.size(), 1);\n    EXPECT_TRUE(is_equal(l0.memory, mem1));\n\n    list.deallocate(std::move(l0));\n    ASSERT_EQ(list.size(), 2);\n\n    // a second allocation and deallocation should look similar\n    l0 = list.allocate();\n    ASSERT_EQ(list.size(), 1);\n    EXPECT_TRUE(is_equal(l0.memory, mem1));\n    auto l1 = list.allocate();\n    ASSERT_EQ(list.size(), 0);\n    EXPECT_TRUE(is_equal(l1.memory, mem0));\n\n    block.deallocate_block(std::move(l0));\n    block.deallocate_block(std::move(l1));\n    ASSERT_EQ(list.size(), 0);\n}\n\n#include \"block_stack.h\"\n\nTEST_F(TestMemory, MemoryArenaUncached)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(counting_tracker(\"** tracker: malloc **\"), std::move(raw));\n    auto block   = make_block_allocator<fixed_size_block_allocator>(std::move(tracked), 1_MiB);\n    auto count   = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 2UL);\n    auto stack   = make_block_stack<uncached>(std::move(count));\n\n    /*                            v count v       v tracked v                */\n    const auto& tracker = stack.get_allocator().get_allocator().get_tracker();\n\n    ASSERT_LT(stack.next_block_size(), 1_MiB);\n    auto actual_size = stack.next_block_size();\n\n    // we can only grow memory_arena one block at a time\n    // the memory_arena is a stack of blocks\n    // when we deallocate_block, it pops the stack back\n    // the stack is not necessarily continuous\n\n    stack.allocate_block();\n    auto block0 = stack.current_block().memory;\n    ASSERT_EQ(stack.current_block().size, actual_size);\n    ASSERT_EQ(tracker.count(), 1);\n\n    stack.allocate_block();\n    auto block1 = stack.current_block().memory;\n    ASSERT_FALSE(is_equal(block0, block1));\n    ASSERT_EQ(stack.current_block().size, actual_size);\n    ASSERT_EQ(tracker.count(), 2);\n\n    stack.deallocate_block();\n    ASSERT_TRUE(is_equal(stack.current_block().memory, block0));\n    ASSERT_EQ(tracker.count(), 1);\n\n    stack.deallocate_block();\n    ASSERT_TRUE(stack.empty());\n    ASSERT_EQ(tracker.count(), 0);\n}\n\n#include \"memory_pool.h\"\n#include \"detail/container_node_sizes.h\"\n#include <list>\n\nTEST_F(TestMemory, MemoryPool)\n{\n    auto raw     = TestRawMalloc();\n    auto tracked = make_tracked_allocator(counting_tracker(\"** tracker: malloc **\"), std::move(raw));\n    auto single  = make_block_allocator<single_block_allocator>(std::move(tracked), 1_MiB);\n    auto stack   = make_block_stack<uncached>(std::move(single));\n    auto pool    = memory_pool<decltype(single)>(list_node_size<int>::value, std::move(stack));\n\n    auto node_size  = list_node_size<int>::value;\n    auto node_count = pool.capacity_left() / node_size;\n    LOG(INFO) << \"pool node_size      : \" << node_size;\n    LOG(INFO) << \"pool node capacity  : \" << node_count;\n    auto ctx = pool.device_context();\n\n    auto list  = std::list<int, std_allocator<int, decltype(pool)>>(pool);\n    auto queue = std::queue<int, decltype(list)>(std::move(list));\n\n    for (int i = 0; i < node_count; i++)\n    {\n        queue.push(i);\n    }\n\n    ASSERT_ANY_THROW(queue.push(42));\n}\n\n#include \"memory_type.h\"\n\nTEST_F(TestMemory, IsMemoryType)\n{\n    static_assert(is_memory_type<host_memory>::value, \"\");\n\n    struct empty_memory\n    {\n    };\n    static_assert(!is_memory_type<empty_memory>::value, \"\");\n\n    struct with_valid_impl\n    {\n        constexpr static DLDeviceType device_type()\n        {\n            return kDLCPU;\n        }\n        constexpr static std::size_t min_allocation_alignment()\n        {\n            return 8UL;\n        }\n        constexpr static std::size_t max_access_alignment()\n        {\n            return 8UL;\n        }\n        static std::size_t access_alignment_for(std::size_t)\n        {\n            return with_valid_impl::max_access_alignment();\n        }\n    };\n    static_assert(!is_memory_type<with_valid_impl>::value, \"\");\n    static_assert(decltype(detail::is_memory_type_impl<with_valid_impl>(0))::value, \"\");\n\n    struct with_valid_base : detail::any_memory\n    {\n    };\n    static_assert(!is_memory_type<with_valid_base>::value, \"\");\n\n    struct valid_memory_type : public with_valid_impl, public with_valid_base\n    {\n    };\n\n    //static_assert(std::is_base_of<detail::any_memory, valid_memory_type>::value, \"\");\n    static_assert(decltype(detail::is_memory_type_impl<valid_memory_type>(0))::value, \"\");\n\n    static_assert(is_memory_type<valid_memory_type>::value, \"\");\n\n    struct pinned_host_memory : host_memory\n    {\n        constexpr static DLDeviceType device_type() noexcept\n        {\n            return kDLCPUPinned;\n        }\n    };\n\n    static_assert(is_memory_type<pinned_host_memory>::value, \"\");\n    static_assert(is_host_memory<pinned_host_memory>::value, \"\");\n}\n\nTEST_F(TestMemory, HostMemory)\n{\n    static_assert(is_memory_type<host_memory>::value, \"\");\n    static_assert(is_host_memory<host_memory>::value, \"\");\n    static_assert(host_memory::max_access_alignment() == 8UL, \"\");\n    ASSERT_EQ(host_memory::access_alignment_for(1), 1);\n    ASSERT_EQ(host_memory::access_alignment_for(2), 2);\n    ASSERT_EQ(host_memory::access_alignment_for(3), 2);\n    ASSERT_EQ(host_memory::access_alignment_for(4), 4);\n    ASSERT_EQ(host_memory::access_alignment_for(5), 4);\n    ASSERT_EQ(host_memory::access_alignment_for(6), 4);\n    ASSERT_EQ(host_memory::access_alignment_for(7), 4);\n    ASSERT_EQ(host_memory::access_alignment_for(8), 8);\n    ASSERT_EQ(host_memory::access_alignment_for(9), 8);\n    ASSERT_EQ(host_memory::access_alignment_for(100), 8);\n}\n\n/*\n#include \"affinity.h\"\n\nTEST_F(TestMemory, Topology)\n{\n    auto logical_cpus = [](const cpuaff::cpu& cpu) { return int(cpu.id().get()); };\n\n    auto initial_affinity = affinity::this_thread::get_affinity();\n    LOG(INFO) << \"affinity: this_thread: \" << initial_affinity;\n\n    {\n        affinity_guard guard(cpu_set::from_string(\"0\"));\n        auto           scoped_affinity = affinity::this_thread::get_affinity();\n        EXPECT_EQ(scoped_affinity.size(), 1);\n    }\n\n    auto after_guard_affinity = affinity::this_thread::get_affinity();\n    EXPECT_EQ(initial_affinity, after_guard_affinity);\n\n    auto numa_nodes = affinity::system::topology();\n    for(const auto& n : numa_nodes)\n    {\n        LOG(INFO) << n;\n    }\n}\n*/\n\n#include \"malloc_allocator.h\"\n\nTEST_F(TestMemory, FirstTouchMallocAllocator)\n{\n    constexpr std::size_t size = 20_MiB;\n\n    //auto raw = first_touch_allocator<malloc_allocator>();\n\n    auto alloc = make_allocator(malloc_allocator());\n\n    ASSERT_EQ(8, alloc.min_alignment());\n    ASSERT_EQ(8, alloc.max_alignment());\n\n    auto md = alloc.allocate_descriptor(size);\n\n    // this breaks down the array into system page-sized pages; on linux, 4k pages\n    // in this example, we will test each of those 4k pages to see if they belong\n    // to a larger transparent huge page\n    page_info_array pinfo     = get_info_for_range(md.data(), ((char*)md.data()) + size);\n    flag_count      thp_count = get_flag_count(pinfo, KPF_THP);\n\n    EXPECT_TRUE(thp_count.pages_available) << \"hugepage info not available; probably not running as root\";\n\n    if (thp_count.pages_available)\n    {\n        EXPECT_EQ(thp_count.pages_set, 0);\n    }\n\n    // DLOG(INFO) << \"grep -e AnonHugePages  /proc/\" << getpid() << \"/smaps\";\n    // std::this_thread::sleep_for(std::chrono::seconds(60));\n}\n\n#include \"detail/ranges.h\"\n\nusing detail::find_ranges;\nusing detail::print_ranges;\n\nTEST_F(TestMemory, FindRanges0)\n{\n    std::vector<int>                 a{1};\n    std::vector<std::pair<int, int>> a_ranges{{1, 1}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1\");\n}\n\nTEST_F(TestMemory, FindRanges1)\n{\n    std::vector<int>                 a{1, 2};\n    std::vector<std::pair<int, int>> a_ranges{{1, 2}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-2\");\n}\n\nTEST_F(TestMemory, FindRanges2)\n{\n    std::vector<int>                 a{1, 2, 3};\n    std::vector<std::pair<int, int>> a_ranges{{1, 3}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-3\");\n}\n\nTEST_F(TestMemory, FindRanges3)\n{\n    std::vector<int>                 a{1, 3};\n    std::vector<std::pair<int, int>> a_ranges{{1, 1}, {3, 3}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1,3\");\n}\n\nTEST_F(TestMemory, FindRanges4)\n{\n    std::vector<int>                 a{1, 2, 4, 5, 6, 10};\n    std::vector<std::pair<int, int>> a_ranges{{1, 2}, {4, 6}, {10, 10}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"1-2,4-6,10\");\n}\n\nTEST_F(TestMemory, FindRanges5)\n{\n    std::vector<int>                 a{0, 1, 2, 3, 4, 5, 6};\n    std::vector<std::pair<int, int>> a_ranges{{0, 6}};\n    auto                             ranges = find_ranges(a);\n    ASSERT_EQ(ranges, a_ranges);\n    ASSERT_EQ(print_ranges(ranges), \"0-6\");\n}\n\ntemplate <typename Key, typename Value, typename BlockAllocator>\nauto make_map(BlockAllocator&& block_alloc)\n{\n    static_assert(is_block_allocator<BlockAllocator>::value, \"\");\n\n    using node_type = std::pair<Key, Value>;\n    auto node_size  = alignof(node_type) + sizeof(node_type) + 64;\n\n    auto stack = make_block_stack<uncached>(std::move(block_alloc));\n    auto pool  = memory_pool<BlockAllocator>(node_size, std::move(stack));\n    auto alloc = make_thread_unsafe_allocator(std::move(pool));\n\n    return std::map<Key, Value, std::less<Key>, std_allocator<node_type, decltype(alloc)>>(alloc);\n}\n\nTEST_F(TestMemory, MapWithCustomAllocator)\n{\n    auto huge  = transparent_huge_page_allocator<2_MiB>();\n    auto track = make_tracked_allocator(counting_tracker{\"** tracker: huge **\"}, std::move(huge));\n    auto block = make_block_allocator<fixed_size_block_allocator>(std::move(track), 2_MiB);\n    auto alloc = make_extended_block_allocator<count_limited_block_allocator>(std::move(block), 4);\n    auto arena = make_cached_block_arena(std::move(alloc));\n\n    // populate cache\n    arena.reserve_blocks(4);\n\n    // create map\n    auto m = make_map<int, int>(std::move(arena));\n\n    // unwind the allocator stack to get the tracker\n    //                      v  std_alloc  v v memory_pool v v block_stack v v block_arena v  v tracker v\n    const auto& tracker = m.get_allocator().get_allocator().get_allocator().get_allocator().get_allocator().get_tracker();\n\n    // our system allocator has been used 4 times to populate the block cache\n    EXPECT_EQ(tracker.count(), 4);\n\n    LOG(INFO) << \"Start Using Map\";\n\n    for (int i = 0; i < 10240; i++)\n    {\n        m[i] = i;\n    }\n\n    EXPECT_EQ(tracker.count(), 4);\n    LOG(INFO) << \"total system allocations: \" << tracker.count();\n}\n\nTEST_F(TestMemory, MapWithTracedMalloc)\n{\n    auto track = make_tracked_allocator(counting_tracker{\"** tracker: malloc **\"}, malloc_allocator());\n\n    // create map\n    auto m = std::map<int, int, std::less<int>, std_allocator<std::pair<int, int>, decltype(track)>>(track);\n\n    // get tracker          v  std_alloc  v   v tracker v\n    const auto& tracker = m.get_allocator().get_allocator().get_tracker();\n\n    LOG(INFO) << \"system allocation count on init: \" << tracker.count();\n    LOG(INFO) << \"start using map\";\n\n    for (int i = 0; i < 10240; i++)\n    {\n        m[i] = i;\n    }\n\n    LOG(INFO) << \"finish using map\";\n    LOG(INFO) << \"system allocation count on fini: \" << tracker.count();\n}\n\nbool equiv_ptr(void* lhs, void* rhs)\n{\n    return reinterpret_cast<addr_t>(lhs) == reinterpret_cast<addr_t>(rhs);\n}\n\nTEST_F(TestMemory, RBTree_Set)\n{\n    memory_block b1{reinterpret_cast<void*>(0x00000001), 128};\n    memory_block b2{reinterpret_cast<void*>(0xDEADBEEF), 1024};\n    memory_block b3{reinterpret_cast<void*>(0xFACEBAD1), 1024};\n    memory_block b4{reinterpret_cast<void*>(0xA0000000), 2048};\n\n    std::set<memory_block, memory_block_compare_size<>> blocks(memory_block_compare_size<>{});\n\n    blocks.insert(b1);\n    blocks.insert(b2);\n    blocks.insert(b3);\n    blocks.insert(b4);\n\n    // using is_transparent -> we can find blocks by size\n\n    // we can find blocks by actual block or by size\n    auto search = blocks.find(1024);\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b2.memory));\n\n    // we can find blocks that meet certin size requirements by using lower bound\n    search = blocks.lower_bound(129);\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b2.memory));\n\n    // this is how we woudl have to do it without is_transparent\n    search = blocks.lower_bound(memory_block{nullptr, 127});\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b1.memory));\n\n    search = blocks.lower_bound(memory_block{nullptr, 128});\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b1.memory));\n\n    search = blocks.lower_bound(memory_block{nullptr, 129});\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b2.memory));\n\n    // we can also find blocks directly by content\n    search = blocks.find(b3);\n    ASSERT_NE(search, blocks.end());\n    ASSERT_TRUE(equiv_ptr(search->memory, b3.memory));\n}\n\n#include \"bfit_allocator.h\"\nTEST_F(TestMemory, bfit)\n{\n    auto track = make_tracked_allocator(log_tracker{\"** tracker: malloc **\"}, malloc_allocator());\n    auto alloc = make_bfit_allocator(6 * 128_MiB, std::move(track));\n    //auto alloc = make_allocator(std::move(bfit));\n\n    test_alloc_x10(alloc);\n    ASSERT_EQ(alloc.free_nodes(), 1);\n    ASSERT_EQ(alloc.used_nodes(), 0);\n    test_alloc_x10(alloc);\n    ASSERT_EQ(alloc.free_nodes(), 1);\n    ASSERT_EQ(alloc.used_nodes(), 0);\n    test_alloc_x10(alloc);\n    ASSERT_EQ(alloc.free_nodes(), 1);\n    ASSERT_EQ(alloc.used_nodes(), 0);\n}\n\n#include <boost/histogram.hpp> // make_histogram, regular, weight, indexed\n#include <boost/format.hpp>\n#include \"utils.h\"\n\nTEST_F(TestMemory, histogram)\n{\n    using namespace boost::histogram; // strip the boost::histogram prefix\n    auto h = make_histogram(axis::regular<>(6, 12, 36, \"x\"));\n\n    /*\n    Let's fill a histogram with data, typically this happens in a loop.\n\n    STL algorithms are supported. std::for_each is very convenient to fill a\n    histogram from an iterator range. Use std::ref in the call, if you don't\n    want std::for_each to make a copy of your histogram.\n  */\n    std::vector<std::size_t> data = {1_KiB, 3_MiB, 512, 256, 128};\n\n    auto log_hist = [&h](std::size_t size) { h(ilog2_ceil(size)); };\n\n    std::for_each(data.begin(), data.end(), log_hist);\n    //h(-1.5); // is placed in underflow bin -1\n    //h(-1.0); // is placed in bin 0, bin interval is semi-open\n    //h(2.0);  // is placed in overflow bin 6, bin interval is semi-open\n    //h(20.0); // is placed in overflow bin 6\n\n    /*\n    This does a weighted fill using the `weight` function as an additional\n    argument. It may appear at the beginning or end of the argument list. C++\n    doesn't have keyword arguments like Python, this is the next-best thing.\n  */\n\n    std::ostringstream os;\n    os << std::endl;\n    for (auto&& x : indexed(h, coverage::all))\n    {\n        //os << boost::format(\"bin %2i [%4.1f, %4.1f): %i\\n\") % x.index() % x.bin().lower() % x.bin().upper() % *x;\n        os << boost::format(\"bin %2i [%10s, %10s): %i\\n\") % x.index() % bytes_to_string(std::pow(2, x.bin().lower()))\n                  % bytes_to_string(std::pow(2, x.bin().upper())) % *x;\n    }\n\n    LOG(INFO) << os.str();\n}\n\n#include <trtlab/memory/trackers.h>\n#include <trtlab/memory/raii_allocator.h>\n\nTEST_F(TestMemory, TrackHighLevelAllocator)\n{\n    auto high_lvl = make_allocator(make_bfit_allocator(256_MiB, malloc_allocator()));\n    auto tracker1 = make_tracked_allocator(size_tracker{}, high_lvl.copy());\n    auto tracker2 = make_tracked_allocator(size_tracker{}, high_lvl.copy());\n    auto alloc1 = make_allocator(std::move(tracker1));\n    auto alloc2 = make_allocator(std::move(tracker2));\n\n    const auto& t1 = alloc1.get_allocator().get_tracker();\n    const auto& t2 = alloc2.get_allocator().get_tracker();\n\n    EXPECT_EQ(t1.bytes(), 0);\n    EXPECT_EQ(t2.bytes(), 0);\n\n\n    auto md0 = alloc1.allocate_descriptor(3_MiB);\n    EXPECT_EQ(t1.bytes(), 3_MiB);\n\n    auto md1 = alloc2.allocate_descriptor(128_MiB);\n    EXPECT_EQ(t2.bytes(), 128_MiB);\n\n    descriptor md2;\n    EXPECT_ANY_THROW(md2 = alloc1.allocate_descriptor(128_MiB));\n\n    // the state of the trackers should not change\n    EXPECT_EQ(t1.bytes(), 3_MiB);\n    EXPECT_EQ(t2.bytes(), 128_MiB);\n\n    auto raii = make_raii_allocator(alloc1);\n    auto md3 = raii.allocate_descriptor(45_MiB);\n    EXPECT_EQ(t1.bytes(), 48_MiB);\n\n    void* p0  = raii.allocate(2_MiB);\n    void* p1  = raii.allocate(4_MiB);\n    EXPECT_EQ(t1.bytes(), 54_MiB);\n\n    raii.deallocate(p1);\n    // this would normally be a memory leak,\n    // but because the allocator owns a descriptor for all non-descriptor allocations\n    // this will get cleaned up by the destructor.\n    // todo: add a warning for all\n    // raii.deallocate(p0);\n    EXPECT_EQ(t1.bytes(), 50_MiB);\n\n    auto iraii = raii.shared();\n    auto md4 = iraii->allocate_descriptor(8_MiB);\n    EXPECT_EQ(t1.bytes(), 58_MiB);\n\n}\n\n#include <trtlab/memory/memory_typed_allocator.h>\n\nTEST_F(TestMemory, IAllocator)\n{\n    auto high_lvl = make_allocator(make_bfit_allocator(256_MiB, malloc_allocator()));\n\n    CHECK_EQ(high_lvl.device_context().device_type, kDLCPU);\n\n    auto tracker1 = make_tracked_allocator(log_tracker{\"** tracker: high-level #1 **\"}, high_lvl.copy());\n    auto tracker2 = make_tracked_allocator(log_tracker{\"** tracker: high-level #2 **\"}, high_lvl.copy());\n    auto alloc1 = make_allocator(std::move(tracker1));\n    auto alloc2 = make_allocator(std::move(tracker2));\n\n\n    LOG(INFO) << \"init host_allocator\";\n    auto host = host_allocator(alloc1.shared());\n\n    //auto tracker3 = make_tracked_allocator(log_tracker{\"** tracker: high-level #3 **\"}, std::move(host)););\n\n}"
  },
  {
    "path": "trtlab/memory/tools/CMakeLists.txt",
    "content": "# Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n# This file is subject to the license terms in the LICENSE file\n# found in the top-level directory of this distribution.\n\n# builds tools\n\nadd_executable(memory_node_size_debugger test_types.hpp node_size_debugger.hpp node_size_debugger.cpp)\n#_use_comp(memory_node_size_debugger)\n# comp_target_features(memory_node_size_debugger PUBLIC CPP11)\nif (MSVC)\n    target_compile_options(memory_node_size_debugger PRIVATE \"/bigobj\")\nendif()\ntarget_compile_definitions(memory_node_size_debugger PUBLIC\n                           VERSION=\"${TRTLAB_MEMORY_VERSION_MAJOR}.${TRTLAB_MEMORY_VERSION_MINOR}\")\nset_target_properties(memory_node_size_debugger PROPERTIES OUTPUT_NAME nodesize_dbg)\n\ninstall(TARGETS memory_node_size_debugger EXPORT memoryTargets RUNTIME DESTINATION ${TRTLAB_MEMORY_RUNTIME_INSTALL_DIR})\n"
  },
  {
    "path": "trtlab/memory/tools/node_size_debugger.cpp",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#include <cctype>\n#include <cstring>\n#include <fstream>\n#include <iomanip>\n#include <iostream>\n#include <string>\n\n#include \"node_size_debugger.hpp\"\n\nconst char* const exe_name = \"nodesize_dbg\";\nconst std::string exe_spaces(std::strlen(exe_name), ' ');\n\nstruct simple_serializer\n{\n    std::ostream& out;\n\n    void prefix() const {}\n\n    void operator()(const debug_result& result) const\n    {\n        out << result.container_name << \":\\n\";\n        for (auto pair : result.node_sizes)\n            out << '\\t' << pair.first << '=' << pair.second << '\\n';\n    }\n\n    void suffix() const {}\n};\n\nstruct verbose_serializer\n{\n    std::ostream& out;\n\n    void prefix() const {}\n\n    void operator()(const debug_result& result) const\n    {\n        out << \"For container '\" << result.container_name << \"':\\n\";\n        for (auto pair : result.node_sizes)\n            out << '\\t' << \"With an alignment of \" << std::setw(2) << pair.first\n                << \" is the base node size \" << std::setw(2) << pair.second << \".\\n\";\n    }\n\n    void suffix() const {}\n};\n\nstruct code_serializer\n{\n    std::ostream& out;\n    std::string   alignment;\n    std::size_t   tab_width;\n\n    void prefix() const\n    {\n        out << \"// The following section was autogenerated by \" << exe_name << '\\n';\n        out << \"//=== BEGIN AUTOGENERATED SECTION ===//\\n\\n\";\n    }\n\n    void operator()(const debug_result& result) const\n    {\n        /* namespace detail\n         * {\n         *      template <std::size_t Alignment>\n         *      struct <name>_node_size;\n         *\n         *      template <>\n         *      struct <name>_node_size<I>\n         *      : std::integral_constant<std::size_t, I_base_size>\n         *      {};\n         *\n         *      ...\n         * } // namespace detail\n         *\n         * template <typename T>\n         * struct <name>_node_size\n         * : std::integral_constant<std::size_t,\n         *    detail::<name>_node_size<FOONATHAN_ALIGNOF(T)>::value + sizeof(T)>\n         * {};\n         */\n        auto newline = \"\\n\";\n        out << \"namespace detail\" << newline << '{' << newline << tab()\n            << \"template <std::size_t Alignment>\" << newline << tab() << \"struct \"\n            << struct_name(result.container_name) << ';' << newline;\n        for (auto pair : result.node_sizes)\n            out << newline << tab() << \"template <>\" << newline << tab() << \"struct \"\n                << struct_name(result.container_name) << '<' << pair.first << '>' << newline\n                << tab() << \": std::integral_constant<std::size_t, \" << pair.second << '>'\n                << newline << tab() << \"{};\" << newline;\n        out << \"} // namespace detail\" << newline << newline << \"template <typename T>\" << newline\n            << \"struct \" << struct_name(result.container_name) << newline\n            << \": std::integral_constant<std::size_t,\" << newline\n            << \"       detail::\" << struct_name(result.container_name) << '<' << alignment\n            << \">::value + sizeof(T)>\" << newline << \"{};\" << newline << newline;\n    }\n\n    void suffix() const\n    {\n        out << \"//=== END AUTOGENERATED SECTION ===//\\n\";\n    }\n\n    std::string tab() const\n    {\n        if (tab_width == 0u)\n            return \"\\t\";\n        return std::string(tab_width, ' ');\n    }\n\n    std::string struct_name(const char* container_name) const\n    {\n        return container_name + std::string(\"_node_size\");\n    }\n};\n\nusing debuggers =\n    std::tuple<debug_forward_list, debug_list, debug_set, debug_multiset, debug_unordered_set,\n               debug_unordered_multiset, debug_map, debug_multimap, debug_unordered_map,\n               debug_unordered_multimap, debug_shared_ptr_stateless, debug_shared_ptr_stateful,\n               debug_shared_ptr_stateful_mutex>;\n\ntemplate <class Debugger, class Serializer>\nvoid serialize_single(const Serializer& serializer)\n{\n    serializer.prefix();\n    serializer(debug(Debugger{}));\n    serializer.suffix();\n}\n\ntemplate <class Debugger, class Serializer>\nint serialize_impl(const Serializer& serializer)\n{\n    serializer(debug(Debugger()));\n    return 0;\n}\n\ntemplate <class Serializer, class... Debuggers>\nvoid serialize_impl(const Serializer& serializer, std::tuple<Debuggers...>)\n{\n    int dummy[] = {serialize_impl<Debuggers>(serializer)...};\n    (void)dummy;\n}\n\ntemplate <class Serializer>\nvoid serialize(const Serializer& serializer)\n{\n    serializer.prefix();\n    serialize_impl(serializer, debuggers{});\n    serializer.suffix();\n}\n\nvoid print_help(std::ostream& out)\n{\n    out << \"Usage: \" << exe_name << \" [--version][--help]\\n\";\n    out << \"       \" << exe_spaces << \" [--simple][--verbose]\\n\";\n    out << \"       \" << exe_spaces\n        << \" [--code [--alignof expr] [--append] [--tab digit] [outputfile]]\\n\";\n    out << \"Obtains information about the internal node sizes of the STL containers.\\n\";\n    out << '\\n';\n    out << \"   --simple\\tprints node sizes in the form 'alignment=base-node-size'\\n\";\n    out << \"   --verbose\\tprints node sizes in a more verbose form\\n\";\n    out << \"   --code\\tgenerates C++ code to obtain the node size\\n\";\n    out << \"   --help\\tdisplay this help and exit\\n\";\n    out << \"   --version\\toutput version information and exit\\n\";\n    out << '\\n';\n    out << \"Options for code generation: \\n\";\n    out << \"   --alignof\\tfollowed by an expression that calculates the alignment of a type named \"\n           \"'T', default is 'alignof(T)'\\n\";\n    out << \"   --append\\tappend to the outputfile instead of overwriting it (the default)\\n\";\n    out << \"   --tab\\tfollowed by single digit specifying tab width, 0 uses '\\\\t'\\n\";\n    out << '\\n';\n    out << \"The base node size is the size of the node without the storage for the value type.\\n\"\n        << \"Add 'sizeof(value_type)' to the base node size for the appropriate alignment to get \"\n           \"the whole size.\\n\";\n    out << \"With no options prints base node sizes of all containers in a simple manner.\\n\";\n}\n\nvoid print_version(std::ostream& out)\n{\n    out << exe_name << \" version \" << VERSION << '\\n';\n}\n\nint print_invalid_option(std::ostream& out, const char* option)\n{\n    out << exe_name << \": invalid option -- '\";\n    while (*option == '-')\n        ++option;\n    out << option << \"'\\n\";\n    out << \"Try '\" << exe_name << \" --help' for more information.\\n\";\n    return 2;\n}\n\nint print_invalid_argument(std::ostream& out, const char* option)\n{\n    out << exe_name << \": invalid argument for option -- '\" << option << \"'\\n\";\n    out << \"Try '\" << exe_name << \" --help' for more information.\\n\";\n    return 2;\n}\n\nint main(int argc, char* argv[])\n{\n    if (argc <= 1 || argv[1] == std::string(\"--simple\"))\n        serialize(simple_serializer{std::cout});\n    else if (argv[1] == std::string(\"--verbose\"))\n        serialize(verbose_serializer{std::cout});\n    else if (argv[1] == std::string(\"--code\"))\n    {\n        std::size_t   tab_width = 4u;\n        std::string   alignment = \"alignof(T)\";\n        auto          append    = false;\n        std::ofstream file;\n        std::ostream  out(std::cout.rdbuf());\n\n        for (auto cur = &argv[2]; *cur; ++cur)\n        {\n            if (*cur == std::string(\"--tab\"))\n            {\n                ++cur;\n                if (*cur && std::isdigit(cur[0][0]) && !cur[0][1])\n                    tab_width = std::size_t(cur[0][0] - '0');\n                else\n                    return print_invalid_argument(std::cerr, \"-t\");\n            }\n            else if (*cur == std::string(\"--alignof\"))\n            {\n                ++cur;\n                if (*cur)\n                    alignment = *cur;\n                else\n                    return print_invalid_argument(std::cerr, \"--alignof\");\n            }\n            else if (!file.is_open() && *cur == std::string(\"--append\"))\n            {\n                append = true;\n            }\n            else if (!file.is_open())\n            {\n                file.open(*cur, append ? std::ios_base::app : std::ios_base::out);\n                if (!file.is_open())\n                    return print_invalid_argument(std::cerr, \"outputfile\");\n                out.rdbuf(file.rdbuf());\n            }\n            else\n                return print_invalid_argument(std::cerr, \"--code\");\n        }\n\n        code_serializer serializer{out, alignment, tab_width};\n        serialize(serializer);\n    }\n    else if (argv[1] == std::string(\"--help\"))\n        print_help(std::cout);\n    else if (argv[1] == std::string(\"--version\"))\n        print_version(std::cout);\n    else\n        return print_invalid_option(std::cerr, argv[1]);\n}\n"
  },
  {
    "path": "trtlab/memory/tools/node_size_debugger.hpp",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef FOONATHAN_MEMORY_TOOL_NODE_SIZE_DEBUGGER_HPP\n#define FOONATHAN_MEMORY_TOOL_NODE_SIZE_DEBUGGER_HPP\n\n#include <algorithm>\n#include <memory>\n#include <mutex>\n#include <tuple>\n#include <type_traits>\n\n#include <forward_list>\n#include <list>\n#include <map>\n#include <set>\n#include <unordered_map>\n#include <unordered_set>\n\n// #include <foonathan/alignof.hpp>\n\ntemplate <typename TestType, class Debugger>\nstruct node_size_storage\n{\n    static std::size_t size;\n};\n\ntemplate <typename TT, class Debugger>\nstd::size_t node_size_storage<TT, Debugger>::size = 0;\n\nstruct empty_payload\n{\n};\n\n// Obtains the node size for a container.\n// Since the node type is private to the implementation,\n// it cannot be accessed directly.\n// It is only available to the allocator through rebinding.\n// The allocator simply stores the size of the biggest type, it is rebound to,\n// as long as it is not the TestType, the actual value_type of the container.\ntemplate <typename T, typename TestType, class Debugger, class AdditionalPayload = empty_payload>\nclass node_size_debugger : public std::allocator<T>, private AdditionalPayload\n{\npublic:\n    template <typename Other>\n    struct rebind\n    {\n        using other = node_size_debugger<Other, TestType, Debugger, AdditionalPayload>;\n    };\n\n    node_size_debugger()\n    {\n        if (!std::is_same<T, TestType>::value)\n            node_size() = std::max(node_size(), sizeof(T));\n    }\n\n    template <typename U>\n    node_size_debugger(node_size_debugger<U, TestType, Debugger, AdditionalPayload>)\n    {\n        if (!std::is_same<T, TestType>::value)\n            node_size() = std::max(node_size(), sizeof(T));\n    }\n\n    static std::size_t& node_size()\n    {\n        return node_size_storage<TestType, Debugger>::size;\n    }\n\nprivate:\n    template <typename U, typename TT, class Dbg, class Payload>\n    friend class node_size_debugger;\n};\n\nstruct hash\n{\n    // note: not noexcept! this leads to a cached hash value\n    template <typename T>\n    std::size_t operator()(const T&) const\n    {\n        // quality doesn't matter\n        return 0;\n    }\n};\n\nstruct debug_forward_list\n{\n    const char* name() const\n    {\n        return \"forward_list\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::forward_list<T, node_size_debugger<T, T, debug_forward_list>> list;\n        list.push_front(T());\n        list.push_front(T());\n        list.push_front(T());\n        return list.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_list\n{\n    const char* name() const\n    {\n        return \"list\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::list<T, node_size_debugger<T, T, debug_list>> list;\n        list.push_front(T());\n        list.push_front(T());\n        list.push_front(T());\n        return list.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_set\n{\n    const char* name() const\n    {\n        return \"set\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::set<T, std::less<T>, node_size_debugger<T, T, debug_set>> set;\n        set.insert(T());\n        set.insert(T());\n        set.insert(T());\n        return set.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_multiset\n{\n    const char* name() const\n    {\n        return \"multiset\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::multiset<T, std::less<T>, node_size_debugger<T, T, debug_multiset>> set;\n        set.insert(T());\n        set.insert(T());\n        set.insert(T());\n        return set.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_unordered_set\n{\n    const char* name() const\n    {\n        return \"unordered_set\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::unordered_set<T, hash, std::equal_to<T>, node_size_debugger<T, T, debug_unordered_set>>\n            set;\n        set.insert(T());\n        set.insert(T());\n        set.insert(T());\n        return set.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_unordered_multiset\n{\n    const char* name() const\n    {\n        return \"unordered_multiset\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        std::unordered_multiset<T, hash, std::equal_to<T>,\n                                node_size_debugger<T, T, debug_unordered_multiset>>\n            set;\n        set.insert(T());\n        set.insert(T());\n        set.insert(T());\n        return set.get_allocator().node_size() - sizeof(T);\n    }\n};\n\nstruct debug_map\n{\n    const char* name() const\n    {\n        return \"map\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        using type = std::pair<const T, T>;\n        std::map<T, T, std::less<T>, node_size_debugger<type, type, debug_map>> map;\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        return map.get_allocator().node_size() - sizeof(typename decltype(map)::value_type);\n    }\n};\n\nstruct debug_multimap\n{\n    const char* name() const\n    {\n        return \"multimap\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        using type = std::pair<const T, T>;\n        std::multimap<T, T, std::less<T>, node_size_debugger<type, type, debug_multimap>> map;\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        return map.get_allocator().node_size() - sizeof(typename decltype(map)::value_type);\n    }\n};\n\nstruct debug_unordered_map\n{\n    const char* name() const\n    {\n        return \"unordered_map\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        using type = std::pair<const T, T>;\n        std::unordered_map<T, T, hash, std::equal_to<T>,\n                           node_size_debugger<type, type, debug_unordered_map>>\n            map;\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        return map.get_allocator().node_size() - sizeof(typename decltype(map)::value_type);\n    }\n};\n\nstruct debug_unordered_multimap\n{\n    const char* name() const\n    {\n        return \"unordered_multimap\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        using type = std::pair<const T, T>;\n        std::unordered_multimap<T, T, hash, std::equal_to<T>,\n                                node_size_debugger<type, type, debug_unordered_multimap>>\n            map;\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        map.insert(std::make_pair(T(), T()));\n        return map.get_allocator().node_size() - sizeof(typename decltype(map)::value_type);\n    }\n};\n\nstruct debug_shared_ptr_stateless\n{\n    const char* name() const\n    {\n        return \"shared_ptr_stateless\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        struct allocator_reference_payload\n        {\n        };\n\n        auto ptr = std::allocate_shared<T>(\n            node_size_debugger<T, T, debug_shared_ptr_stateless, allocator_reference_payload>());\n        auto ptr2 = std::allocate_shared<T>(\n            node_size_debugger<T, T, debug_shared_ptr_stateless, allocator_reference_payload>());\n        return node_size_debugger<T, T, debug_shared_ptr_stateless>::node_size();\n    }\n};\n\nstruct debug_shared_ptr_stateful\n{\n    const char* name() const\n    {\n        return \"shared_ptr_stateful\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        struct allocator_reference_payload\n        {\n            void* ptr;\n        };\n\n        auto ptr = std::allocate_shared<T>(\n            node_size_debugger<T, T, debug_shared_ptr_stateful, allocator_reference_payload>());\n        auto ptr2 = std::allocate_shared<T>(\n            node_size_debugger<T, T, debug_shared_ptr_stateful, allocator_reference_payload>());\n        return node_size_debugger<T, T, debug_shared_ptr_stateful>::node_size();\n    }\n};\n\nstruct debug_shared_ptr_stateful_mutex\n{\n    const char* name() const\n    {\n        return \"shared_ptr_stateful_mutex\";\n    }\n\n    template <typename T>\n    std::size_t debug()\n    {\n        struct allocator_reference_payload\n        {\n            typename std::aligned_storage<sizeof(std::mutex)>::type mutex;\n            void*                                                   ptr;\n        };\n\n        auto ptr = std::allocate_shared<T>(node_size_debugger<T, T, debug_shared_ptr_stateful_mutex,\n                                                              allocator_reference_payload>());\n        auto ptr2 =\n            std::allocate_shared<T>(node_size_debugger<T, T, debug_shared_ptr_stateful_mutex,\n                                                       allocator_reference_payload>());\n        return node_size_debugger<T, T, debug_shared_ptr_stateful_mutex>::node_size();\n    }\n};\n\ntemplate <typename T, class Debugger>\nstd::size_t debug_single(Debugger debugger)\n{\n    return debugger.template debug<T>();\n}\n\n#include \"test_types.hpp\"\n\n// Maps the alignment of the test types to the base size of the node.\n// The base size of the node is the node size obtained via the allocator\n// but without the storage for the value type.\n// It is only dependent on the alignment of the value type.\nusing node_size_map = std::map<std::size_t, std::size_t>;\n\nstruct debug_result\n{\n    const char*   container_name;\n    node_size_map node_sizes;\n};\n\ntemplate <class Debugger, typename... Types>\nnode_size_map debug_impl(Debugger debugger, std::tuple<Types...>)\n{\n    node_size_map result;\n    int dummy[] = {(result[alignof(Types)] = debug_single<Types>(debugger), 0)...};\n    (void)dummy;\n    return result;\n}\n\ntemplate <class Debugger>\ndebug_result debug(Debugger debugger)\n{\n    return {debugger.name(), debug_impl(debugger, test_types{})};\n}\n\n#endif //FOONATHAN_MEMORY_TOOL_NODE_SIZE_DEBUGGER_HPP\n"
  },
  {
    "path": "trtlab/memory/tools/test_types.hpp",
    "content": "// Copyright (C) 2015-2016 Jonathan Müller <jonathanmueller.dev@gmail.com>\n// This file is subject to the license terms in the LICENSE file\n// found in the top-level directory of this distribution.\n\n#ifndef FOONATHAN_MEMORY_TOOL_TEST_TYPES_HPP_INCLUDED\n#define FOONATHAN_MEMORY_TOOL_TEST_TYPES_HPP_INCLUDED\n\n#include <cstddef>\n#include <tuple>\n\n#if !defined(_MSC_VER)\n//#include <foonathan/alignof.hpp>\n//#include <foonathan/constexpr.hpp>\n\n// erases duplicate alignments\n// adopted from https://github.com/irrequietus/clause/blob/alignutil/clause/ample/storage/alignutil.hh\n// Copyright (C) 2013 - 2016 George Makrydakis <george@irrequietus.eu>\nnamespace detail\n{\n    template <typename T>\n    using M0 = typename T::type;\n\n    /*~\n     * @note Forward declarations for several utility templates that are to be used\n     *       for emulating high order functions over a pack without using the rest\n     *       of the clause::ample library for two reasons: (1) alignof allows for\n     *       special optimizations when applied over a pack of types range for the\n     *       \"sorting by alignof\" step; (2) a single header solution was required\n     *       and depending on other parts would mean bring increasing compoments\n     *       of full-fledged metaprogramming library features. This header is to\n     *       provide utilities for aligned storage and it came up when a challenge\n     *       was thrown to me during a discussion with my fellow C++ programmers\n     *       Jonathan Müller and Manu Sánchez. Purpose of inclusion to `clause is\n     *       simple: it can be of use when analyzing boilerplate generation for\n     *       runtime containers and memory allocators by template metaprogramming.\n     *\n     *       tl;dr: fully standalone header for getting a duplicate-free, sorted by\n     *       alignment list of types unique by alignment.\n     */\n    template <typename...>\n    struct M1; // Insert by alignof (map)\n    template <typename, typename>\n    struct M2; // Remove by alignof (M1 map)\n    template <typename...>\n    struct M3; // A pack wrap instead of M1\n    template <typename, typename, typename>\n    struct M4; // 'foldl,fmap' dups to M1<>\n    template <typename, typename...>\n    struct M5; // Remove M1<>\n    template <typename, std::size_t, std::size_t, std::size_t...>\n    struct M6; // Sort by alignof\n\n    /*~\n     * @note Both `M1,`M2 are used as a mutable compile-time \"map\"; `M1 inheritance\n     *       of function signature of the kind:\n     *\n     *          static auto C(int(*)[alignof(X)]) -> X\n     *\n     *       is used as a key/value store in the first \"fold\", while `M2 is used for\n     *       a lookup removing occurences of duplicates in the second \"fold\" by\n     *       substituting each with `M1<>; this is orchestrated by `M4 while cleanup\n     *       is handled by `M5 (removal of those `M1<> markers).\n     */\n    template <typename X, typename... T>\n    struct M1<X, T...> : M1<T...>\n    {\n        using M1<T...>::C;\n\n        static auto C(int (*)[alignof(X)]) -> X;\n\n        static std::size_t constexpr min_val =\n            alignof(X) < M1<T...>::min_val ? alignof(X) : M1<T...>::min_val;\n\n        static std::size_t constexpr max_val =\n            alignof(X) > M1<T...>::max_val ? alignof(X) : M1<T...>::max_val;\n\n        template <template <typename...> class W>\n        using rebind = W<X, T...>;\n    };\n\n    template <>\n    struct M1<>\n    {\n        static M1<>        C(...);\n        static std::size_t constexpr min_val = 1;\n        static std::size_t constexpr max_val = 1;\n\n        template <template <typename...> class W>\n        using rebind = W<>;\n    };\n\n    template <typename W, typename X>\n    struct M2 : W\n    {\n        using W::C;\n        static auto C(int (*)[alignof(X)]) -> M1<>;\n    };\n\n    template <typename...>\n    struct M3\n    { /* one could use M1 instead, but it renders the code more cryptic */\n    };\n\n    /*~\n     * @note Scanning for duplicates while removing them at the same time.\n     */\n    template <typename S, typename A, template <typename...> class W, typename... X, typename... Y>\n    struct M4<S, W<A, X...>, W<Y...>>\n        : M4<M2<S, A>, W<X...>, W<Y..., decltype(S::C((int (*)[alignof(A)])(nullptr)))>>\n    {\n    };\n\n    template <typename S, template <typename...> class W, typename... Y>\n    struct M4<S, W<>, W<Y...>>\n    {\n        using type = W<Y...>;\n    };\n\n    template <typename A, typename...>\n    struct M5\n    {\n        using type = A;\n    };\n\n    /*~\n     * @note Cleaning up random empty `M1<> types after `M4.\n     */\n    template <template <typename...> class W, typename... A, typename... B, typename X>\n    struct M5<W<A...>, W<X, B...>> : M5<W<A..., X>, W<B...>>\n    {\n    };\n\n    template <template <typename...> class W, typename... A, typename... B>\n    struct M5<W<A...>, W<M1<>, B...>> : M5<W<A...>, W<B...>>\n    {\n    };\n\n    template <template <typename...> class W, typename... A>\n    struct M5<W<A...>, W<>> : M5<M1<A...>>\n    {\n    }; // ::type instantiates to M1<A...> !\n\n    /*~\n     * @note Sorting step; because of alignof(X) being a power of 2 and the way\n     *       our \"map\" in M1/M2 works, it is extremely simple to optimize using\n     *       linear expansion of a sequence of powers of two, then use intrinsic\n     *       \"fmap\" properties of  the triple-dot operator for pack expansion to\n     *       yield the types remaining in the M1/M2 \"map\" (here, it is the S type\n     *       parameter). Iterates through min/max values (parameters A, B) by\n     *       creating that sequence then deploying it upon the ::C(int(*)[Z])\n     *       function signature doing the lookup for M1/M2.\n     */\n    template <typename S, std::size_t A, std::size_t B, std::size_t... Z>\n    struct M6 : M6<S, A * 2, B, Z..., A>\n    {\n    };\n\n    template <typename S, std::size_t A, std::size_t... Z>\n    struct M6<S, A, A, Z...>\n    {\n        using type =\n            M1<decltype(S::C((int (*)[Z])(nullptr)))..., decltype(S::C((int (*)[A])(nullptr)))>;\n    };\n\n    /*~\n     * @note Assembling everything together; `M0 is just for convenience purposes\n     *       in order to avoid writing typename Type::type where applicable; while\n     *       the `M4 cleans up duplicates by replacement through `M1 and `M2 lookup\n     *       in combination with triple-dot expansion (\"fmap\"...). Notice that `M1\n     *       is re-used many times as a plain linear container itself, upon which\n     *       `M4 partial specializations match through ordering.\n     */\n    template <typename... X>\n    using M7 =\n        M0<M5<M3<>, M0<M4<M1<decltype(M1<X...>::C((int (*)[alignof(X)])(nullptr)))...>,\n                          M3<X...>, M3<>>>>>;\n\n    /*~\n     * @note The final result is given by this template alias, instantiating to a\n     *       `M1 wrapped pack containing everything that is used afterwards via\n     *       a ::template rebind instantiation to wrap to an end user defined\n     *       template template parameter type. Through this, `M6 will run only\n     *       through the necessary range of powers of 2 for the sorting to occur.\n     */\n    template <typename... X>\n    using unisorted_aligned_ = M0<M6<M7<X...>, M1<X...>::min_val, M1<X...>::max_val>>;\n\n    /*~\n     * @desc Given a sequence of types that may contain duplicates of both quality\n     *       (the kind of type X) and of alignment (result of alignedof(X)) provide\n     *       the equivalent sorted list of unique types by alignment. Semantics are\n     *       eager.\n     * @parm W   : template template parameter type wrapping a sequence of types.\n     * @parm X...: parameter pack containing the aforementioned types.\n     */\n    template <template <typename...> class W, typename... X>\n    using unisorted_aligned_wrap = typename unisorted_aligned_<X...>::template rebind<W>;\n}\n\n// All fundamental types that don't guarantee to have the same alignment (like int and unsigned int).\n// It thus covers all fundamental alignments and all possible node sizes.\n// Does not support extended alignments!\n// The cryptic template stuff above erases duplicate alignments\nusing test_types = detail::unisorted_aligned_wrap<std::tuple, char, bool, short, int, long,\n                                                  long long, float, double, long double>;\n#else\nusing test_types = std::tuple<char, bool, short, int, long, long long, float, double, long double>;\n#endif\n\n#endif // FOONATHAN_MEMORY_TOOL_TEST_TYPES_HPP_INCLUDED\n"
  },
  {
    "path": "trtlab/nvrpc/BUILD.bazel",
    "content": "\ncc_library(\n    name = \"nvrpc\",\n    srcs = glob([\n        \"src/**/*.cc\",\n        \"src/**/*.h\",\n    ]),\n    hdrs = glob([\n        \"include/**/*.h\",\n    ]),\n    deps = [\n        \"//trtlab/core\",\n        \"@com_github_grpc_grpc//:grpc++\",\n#       \"@com_github_grpc_grpc//:grpc++_unsecure\",\n    ],\n    strip_include_prefix = \"include\",\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "trtlab/nvrpc/CMakeLists.txt",
    "content": "#project(nvrpc VERSION 0.1 LANGUAGES CXX)\n\n# Build options\n#set(CMAKE_CXX_STANDARD 17)\n#set(default_build_type \"Release\")\n#set(CMAKE_DEBUG_POSTFIX \"-d\")\n#set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\n\n#add_subdirectory(tests)\n\n# Find Protobuf installation\n# Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.\nset(protobuf_MODULE_COMPATIBLE TRUE)\nfind_package(Protobuf CONFIG REQUIRED)\nmessage(STATUS \"Using protobuf ${protobuf_VERSION}\")\nset(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)\nset(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)\n\n# Find gRPC installation\n# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.\nfind_package(gRPC CONFIG REQUIRED)\nmessage(STATUS \"Using gRPC ${gRPC_VERSION}\")\n\nset(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure)\nset(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)\n\nadd_library(nvrpc\n  src/server.cc\n  src/executor.cc\n)\n\nadd_library(nvrpc-client\n  src/client/client_executor.cc\n)\n\nadd_library(${PROJECT_NAME}::nvrpc ALIAS nvrpc)\nadd_library(${PROJECT_NAME}::nvrpc-client ALIAS nvrpc-client)\n\ntarget_link_libraries(nvrpc\n  PUBLIC\n    core\n    ${_GRPC_GRPCPP_UNSECURE}\n    gRPC::gpr\n)\n\ntarget_link_libraries(nvrpc-client\n  PUBLIC\n    core\n    ${_GRPC_GRPCPP_UNSECURE}\n)\n\ntarget_include_directories(nvrpc\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n)\n\ntarget_include_directories(nvrpc-client\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n)\n\nset_target_properties(nvrpc PROPERTIES OUTPUT_NAME nvrpc)\nset_target_properties(nvrpc-client PROPERTIES OUTPUT_NAME nvrpc-client)\n\ninstall(\n  TARGETS nvrpc\n  EXPORT ${PROJECT_NAME}-targets\n  RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\ninstall(\n  TARGETS nvrpc-client\n  EXPORT ${PROJECT_NAME}-targets\n  RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\n\ninstall(\n  DIRECTORY include/\n  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\n#if(ENABLE_TESTING)\n   add_subdirectory(tests)\n#endif()\n\n#if(benchmark_FOUND)\n#  add_subdirectory(benchmarks)\n#endif()\n\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/base_context.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\nnamespace nvrpc {\nnamespace client {\n\nclass BaseContext\n{\n  public:\n    BaseContext() : m_MasterContext(this) {}\n    BaseContext(BaseContext* master) : m_MasterContext(master) {}\n\n    virtual ~BaseContext() {}\n    virtual bool RunNextState(bool ok) = 0;\n\n    virtual bool ExecutorShouldDeleteContext() const = 0;\n\n    void* Tag() { return static_cast<void*>(this); }\n\n    static BaseContext* Detag(void* tag) { return static_cast<BaseContext*>(tag); }\n\n  protected:\n    BaseContext* m_MasterContext;\n};\n\n} // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_single_up_multiple_down.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n#include <future>\n\n#include <glog/logging.h>\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\nnamespace nvrpc {\nnamespace client {\n\ntemplate<typename Request, typename Response>\nstruct ClientSingleUpMultipleDown : public BaseContext\n{\n    using Client = ClientSingleUpMultipleDown<Request, Response>;\n\n  public:\n    using PrepareFn = std::function<std::unique_ptr<::grpc_impl::ClientAsyncReader<Response>>(\n        ::grpc::ClientContext*, const Request&, ::grpc::CompletionQueue*)>;\n\n    ClientSingleUpMultipleDown(PrepareFn prepare_fn, std::shared_ptr<Executor> executor)\n        : m_PrepareFn(prepare_fn), m_Executor(executor)\n    {\n        m_NextState = &Client::StateInvalid;\n    }\n\n    ~ClientSingleUpMultipleDown() {}\n\n    void Write(Request&&);\n    void Cancel()\n    {\n        m_Context.TryCancel();\n    }\n\n    bool ExecutorShouldDeleteContext() const final override { return false; }\n\n  protected:\n    ::grpc::ClientContext& GetClientContext() { return m_Context; }\n\n  private:\n    virtual void CallbackOnRequestSent(Request&&) {}\n    virtual void CallbackOnResponseReceived(Response&&) = 0;\n    virtual void CallbackOnComplete(const ::grpc::Status&) = 0;\n\n    PrepareFn m_PrepareFn;\n    std::shared_ptr<Executor> m_Executor;\n\n    ::grpc::Status m_Status;\n    ::grpc::ClientContext m_Context;\n    std::unique_ptr<::grpc_impl::ClientAsyncReader<Response>> m_Stream;\n\n\n    Request m_Request;\n    Response m_Response;\n\n    bool RunNextState(bool ok) final override { return (this->*m_NextState)(ok); }\n\n    bool StateStreamInitialized(bool);\n    bool StateReadDone(bool);\n    bool StateFinishDone(bool);\n    bool StateInvalid(bool);\n\n    bool (Client::*m_NextState)(bool);\n\n};\n\ntemplate<typename Request, typename Response>\nvoid ClientSingleUpMultipleDown<Request, Response>::Write(Request&& request)\n{\n    CHECK(m_Stream == nullptr);\n\n    m_Request = std::move(request);\n    m_NextState = &Client::StateStreamInitialized;\n\n    m_Stream = m_PrepareFn(&m_Context, m_Request, m_Executor->GetNextCQ());\n    m_Stream->StartCall(this->Tag());\n}\n\ntemplate<typename Request, typename Response>\nbool ClientSingleUpMultipleDown<Request, Response>::StateStreamInitialized(bool ok)\n{\n    if(!ok)\n    {\n        DVLOG(1) << \"stream failed to initialize\";\n        return false;\n    }\n\n    DVLOG(1) << \"executing callback after initial write to server finished\";\n    CallbackOnRequestSent(std::move(m_Request));\n\n    m_NextState = &Client::StateReadDone;\n    m_Stream->Read(&m_Response, this->Tag());\n}\n\ntemplate<typename Request, typename Response>\nbool ClientSingleUpMultipleDown<Request, Response>::StateReadDone(bool ok)\n{\n    if(!ok)\n    {\n        DVLOG(1) << \"server closed the read/download portion of the stream\";\n        m_NextState = &Client::StateFinishDone;\n        m_Stream->Finish(&m_Status, this->Tag());\n        return true;\n    }\n\n    DVLOG(1) << \"issuing callback on received message\";\n    CallbackOnResponseReceived(std::move(m_Response));\n\n    DVLOG(2) << \"issuing next read from stream\";\n    m_NextState = &Client::StateReadDone;\n    m_Stream->Read(&m_Response, this->Tag());\n}\n\ntemplate<typename Request, typename Response>\nbool ClientSingleUpMultipleDown<Request, Response>::StateFinishDone(bool ok)\n{\n    if(!ok)\n    {\n        DVLOG(1) << \"failed to close the read/download portion of the stream\";\n        m_Context.TryCancel();\n        return false;\n        m_NextState = &Client::StateInvalid;\n    }\n\n    DVLOG(1) << \"calling on complete callback\";\n    CallbackOnComplete(m_Status);\n\n    m_NextState = &Client::StateInvalid;\n    return false;\n}\n\ntemplate<typename Request, typename Response>\nbool ClientSingleUpMultipleDown<Request, Response>::StateInvalid(bool ok)\n{\n    LOG(FATAL) << \"logic error in ClientSingleUpMultipleDown state management\";\n    return false;\n}\n\n\ntemplate<typename Request, typename Response>\nclass ClientSUMD : ClientSingleUpMultipleDown<Request, Response>\n{\n    using Client = ClientSingleUpMultipleDown<Request, Response>;\n\npublic:\n    using PrepareFn = typename Client::PrepareFn;\n    using MetaData = std::multimap<::grpc::string_ref, ::grpc::string_ref>;\n    using CallbackOnResponseFn = std::function<void(Response&&)>;\n    using CallbackOnCompleteFn = std::function<void(const ::grpc::Status&, MetaData&)>;\n\n    ClientSUMD(PrepareFn prepare_fn, std::shared_ptr<Executor> executor, CallbackOnResponseFn callback, CallbackOnCompleteFn completer)\n    : Client(prepare_fn, executor), m_Callback(callback), m_Completer(completer)\n    {\n\n    }\n\n    std::shared_future<::grpc::Status> Write(Request&& request)\n    {\n        Client::Write(std::move(request));\n        return Status();\n    }\n\n    std::shared_future<::grpc::Status> Status() { return m_Promise.get_future().share(); }\n\nprivate:\n    std::promise<::grpc::Status> m_Promise;\n    CallbackOnResponseFn m_Callback;\n    CallbackOnCompleteFn m_Completer;\n\n    void CallbackOnResponseReceived(Response&& response) final override\n    {\n        m_Callback(std::move(response));\n    }\n\n    void CallbackOnComplete(const ::grpc::Status& status) final override\n    {\n        m_Promise.set_value(status);\n        auto metadata = this->GetClientContext().GetServerTrailingMetadata();\n        m_Completer(status, metadata);\n    }\n\n};\n\n} // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_streaming.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\n#include <glog/logging.h>\n\nnamespace nvrpc {\nnamespace client {\n\ntemplate<typename Request, typename Response>\nstruct ClientStreaming : public BaseContext\n{\n  public:\n    using PrepareFn =\n        std::function<std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>>(\n            ::grpc::ClientContext*, ::grpc::CompletionQueue*)>;\n\n    using ReadCallback = std::function<void(Response&&)>;\n    using WriteCallback = std::function<void(Request&&)>;\n\n    ClientStreaming(PrepareFn, std::shared_ptr<Executor>, WriteCallback, ReadCallback);\n    ~ClientStreaming() { DVLOG(1) << \"ClientStreaming dtor\"; }\n\n    // void Write(Request*);\n    bool Write(Request&&);\n\n    std::shared_future<::grpc::Status> Status();\n    std::shared_future<::grpc::Status> Done();\n\n    bool SetCorked(bool true_or_false) { m_Corked = true_or_false; }\n\n    bool IsCorked() const { return m_Corked; }\n\n    bool ExecutorShouldDeleteContext() const override { return false; }\n\n    void ExecutorShouldDeleteContext(bool true_or_false) { m_ShouldDelete = true_or_false; }\n\n  private:\n    bool RunNextState(bool ok) final override { return (this->*m_NextState)(ok); }\n\n    bool RunNextState(bool (ClientStreaming<Request, Response>::*state_fn)(bool), bool ok)\n    {\n        return (this->*state_fn)(ok);\n    }\n\n    class Context : public BaseContext\n    {\n      public:\n        Context(BaseContext* master) : BaseContext(master) {}\n        ~Context() override {}\n\n      private:\n        bool RunNextState(bool ok) final override\n        {\n            // DVLOG(1) << \"Event for Tag: \" << Tag();\n            return static_cast<ClientStreaming*>(m_MasterContext)->RunNextState(m_NextState, ok);\n        }\n\n        bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n        bool ExecutorShouldDeleteContext() const override { return false; }\n\n        friend class ClientStreaming<Request, Response>;\n    };\n\n    ::grpc::Status m_Status;\n    ::grpc::ClientContext m_Context;\n    std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>> m_Stream;\n    std::promise<::grpc::Status> m_Promise;\n\n    PrepareFn m_PrepareFn;\n\n    ReadCallback m_ReadCallback;\n    WriteCallback m_WriteCallback;\n\n    // Context<Request, Response> m_ReadState;\n    // Context<Request, Response> m_WriteState;\n\n    Context m_ReadState;\n    Context m_WriteState;\n\n    std::mutex m_Mutex;\n    std::queue<Response> m_ReadQueue;\n    std::queue<Request> m_WriteQueue;\n\n    std::shared_ptr<Executor> m_Executor;\n\n    bool m_Corked;\n    bool m_ShouldDelete;\n\n    using ReadHandle = bool;\n    using WriteHandle = bool;\n    using ExecuteHandle = std::function<void()>;\n    using CloseHandle = bool;\n    using FinishHandle = bool;\n    using CompleteHandle = bool;\n    using Actions = std::tuple<ReadHandle, WriteHandle, ExecuteHandle, CloseHandle, FinishHandle,\n                               CompleteHandle>;\n\n    bool m_Reading, m_Writing, m_Finishing, m_Closing, m_ReadsDone, m_WritesDone, m_FinishDone;\n\n    bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n    Actions EvaluateState();\n    void ForwardProgress(Actions& actions);\n\n    bool StateStreamInitialized(bool);\n    bool StateReadDone(bool);\n    bool StateWriteDone(bool);\n    bool StateWritesDoneDone(bool);\n    bool StateFinishDone(bool);\n    bool StateInvalid(bool);\n    bool StateIdle(bool);\n};\n\ntemplate<typename Request, typename Response>\nClientStreaming<Request, Response>::ClientStreaming(PrepareFn prepare_fn,\n                                                    std::shared_ptr<Executor> executor,\n                                                    WriteCallback OnWrite, ReadCallback OnRead)\n    : m_Executor(executor), m_PrepareFn(prepare_fn), m_ReadState(this), m_WriteState(this),\n      m_ReadCallback(OnRead), m_WriteCallback(OnWrite), m_Reading(false), m_Writing(false),\n      m_Finishing(false), m_Closing(false), m_ReadsDone(false), m_WritesDone(false),\n      m_FinishDone(false), m_ShouldDelete(false), m_Corked(false)\n{\n    m_NextState = &ClientStreaming<Request, Response>::StateStreamInitialized;\n    m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n    m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n    m_Stream = m_PrepareFn(&m_Context, m_Executor->GetNextCQ());\n    m_Stream->StartCall(this->Tag());\n}\n\n/*\ntemplate<typename Request, typename Response>\nvoid ClientStreaming<Request, Response>::Write(Request* request)\n{\n    // TODO: fixes this so it queues up a lambda\n    Write(std::move(*request));\n}\n*/\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::Write(Request&& request)\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"Writing Request\";\n\n        if(m_WritesDone)\n        {\n            LOG(WARNING) << \"Attempting to Write on a Stream that is closed\";\n            return false;\n        }\n\n        m_WriteQueue.push(std::move(request));\n        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWriteDone;\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return true;\n}\n\ntemplate<typename Request, typename Response>\nstd::shared_future<::grpc::Status> ClientStreaming<Request, Response>::Done()\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"Sending WritesDone - Closing Client -> Server side of the stream\";\n\n        m_WritesDone = true;\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return m_Promise.get_future();\n}\n\ntemplate<typename Request, typename Response>\nstd::shared_future<::grpc::Status> ClientStreaming<Request, Response>::Status()\n{\n    return m_Promise.get_future();\n}\n\ntemplate<typename Request, typename Response>\ntypename ClientStreaming<Request, Response>::Actions\n    ClientStreaming<Request, Response>::EvaluateState()\n{\n    ReadHandle should_read = false;\n    WriteHandle should_write = nullptr;\n    ExecuteHandle should_execute = nullptr;\n    CloseHandle should_close = false;\n    FinishHandle should_finish = false;\n    CompleteHandle should_complete = false;\n\n    if(m_NextState == &ClientStreaming<Request, Response>::StateStreamInitialized)\n    {\n        DVLOG(1) << \"Action Queued: Stream Initializing\";\n    }\n    else\n    {\n        if(!m_Reading && !m_ReadsDone)\n        {\n            should_read = true;\n            m_Reading = true;\n            m_ReadQueue.emplace();\n            m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateReadDone;\n\n            should_execute = [this, response = std::move(m_ReadQueue.front())]() mutable {\n                m_ReadCallback(std::move(response));\n            };\n            m_ReadQueue.pop();\n        }\n        if(!m_Writing && !m_WriteQueue.empty())\n        {\n            should_write = true;\n            m_Writing = true;\n            m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWriteDone;\n        }\n        if(!m_Closing && !m_Writing && m_WritesDone)\n        {\n            should_close = true;\n            m_Closing = true;\n            m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWritesDoneDone;\n        }\n        if(!m_Reading && !m_Writing && !m_Finishing && m_ReadsDone && m_WritesDone && !m_FinishDone)\n        {\n            should_finish = true;\n            m_Finishing = true;\n            m_NextState = &ClientStreaming<Request, Response>::StateFinishDone;\n        }\n        if(m_ReadsDone && m_WritesDone && m_FinishDone)\n        {\n            should_complete = true;\n        }\n    }\n\n    // clang-format off\n    DVLOG(1) << (should_read ? 1 : 0) << (should_write ? 1 : 0) << (should_execute ? 1 : 0)\n               << (should_finish ? 1 : 0)\n               << \" -- \" << m_Reading << m_Writing << m_Finishing\n               << \" -- \" << m_ReadsDone << m_WritesDone\n               << \" -- \" << m_Finishing;\n    // clang-format on\n\n    return std::make_tuple(should_read, should_write, should_execute, should_close, should_finish,\n                           should_complete);\n}\n\ntemplate<class Request, class Response>\nvoid ClientStreaming<Request, Response>::ForwardProgress(Actions& actions)\n{\n    ReadHandle should_read = std::get<0>(actions);\n    WriteHandle should_write = std::get<1>(actions);\n    ExecuteHandle should_execute = std::get<2>(actions);\n    CloseHandle should_close = std::get<3>(actions);\n    FinishHandle should_finish = std::get<4>(actions);\n    CompleteHandle should_complete = std::get<5>(actions);\n\n    if(should_read)\n    {\n        DVLOG(1) << \"Posting Read/Recv\";\n        m_Stream->Read(&m_ReadQueue.back(), m_ReadState.Tag());\n    }\n    if(should_write)\n    {\n        DVLOG(1) << \"Writing/Sending Request\";\n        if(m_Corked)\n        {\n            ::grpc::WriteOptions options;\n            options.set_corked();\n            m_Stream->Write(m_WriteQueue.front(), options, m_WriteState.Tag());\n        }\n        else\n        {\n            m_Stream->Write(m_WriteQueue.front(), m_WriteState.Tag());\n        }\n    }\n    if(should_close)\n    {\n        DVLOG(1) << \"Sending WritesDone to Server\";\n        m_Stream->WritesDone(m_WriteState.Tag());\n    }\n    if(should_execute)\n    {\n        DVLOG(1) << \"Kicking off Execution of Received Request\";\n        should_execute();\n    }\n    if(should_finish)\n    {\n        DVLOG(1) << \"Closing Stream - Finish\";\n        m_Stream->Finish(&m_Status, Tag());\n    }\n    if(should_complete)\n    {\n        DVLOG(1) << \"Completing Promise\";\n        m_Promise.set_value(std::move(m_Status));\n    }\n}\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateStreamInitialized(bool ok)\n{\n    if(!ok)\n    {\n        DVLOG(1) << \"Stream Failed to Initialize\";\n        return false;\n    }\n\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"StreamInitialized\";\n\n        m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n        m_Reading = true;\n        m_ReadQueue.emplace();\n        m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateReadDone;\n\n        actions = EvaluateState();\n    }\n    DVLOG(1) << \"Posting Initial Read/Recv\";\n    m_Stream->Read(&m_ReadQueue.back(), m_ReadState.Tag());\n    ForwardProgress(actions);\n    return true;\n}\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateReadDone(bool ok)\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"ReadDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n        m_Reading = false;\n        m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n        if(!ok)\n        {\n            DVLOG(1) << \"Server is closing the read/download portion of the stream\";\n            m_ReadsDone = true;\n            m_WritesDone = true;\n            m_Closing = true;\n            if(m_Writing)\n            {\n                m_Context.TryCancel();\n            }\n        }\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return true;\n}\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateWriteDone(bool ok)\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"WriteDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n        m_Writing = false;\n        m_WriteQueue.pop();\n        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n        if(!ok)\n        {\n            // Invalidate any outstanding reads on stream\n            DLOG(ERROR) << \"Failed to Write to Stream - shutting down\";\n            m_WritesDone = true;\n            if(!m_ReadsDone)\n            {\n                m_Context.TryCancel();\n            }\n            return false;\n        }\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return true;\n}\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateWritesDoneDone(bool ok)\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"WritesDoneDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n        // m_Closing = false;  // keep m_Closing true\n        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n        if(!ok)\n        {\n            LOG(ERROR) << \"Failed to close write/upload portion of stream\";\n            if(!m_ReadsDone)\n            {\n                m_Context.TryCancel();\n            }\n            return true;\n        }\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return true;\n}\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateFinishDone(bool ok)\n{\n    Actions actions;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DVLOG(1) << \"FinishedDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n        m_Finishing = false;\n        m_FinishDone = true;\n\n        if(!ok)\n        {\n            LOG(ERROR) << \"Failed to close read/download portion of the stream\";\n            m_Context.TryCancel();\n            return false;\n        }\n\n        actions = EvaluateState();\n    }\n    ForwardProgress(actions);\n    return true;\n}\n/*\n        DVLOG(1) << \"Read/Download portion of the stream has closed\";\n\n        std::lock_guard<std::mutex> lock(m_Mutex);\n\n        if(m_WriteState.m_NextState == &ClientStreaming<Request, Response>::StateInvalid)\n        {\n            DVLOG(1) << \"Write/Upload has already finished - completing future\";\n\n            m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n        }\n        else\n        {\n            DVLOG(1) << \"Received Finished from Server before Client has sent Done writing\";\n            m_Context.TryCancel();\n        }\n        return true;\n*/\n\ntemplate<typename Request, typename Response>\nbool ClientStreaming<Request, Response>::StateInvalid(bool ok)\n{\n    LOG(FATAL) << \"Your logic is bad - you should never have come here\";\n}\n\n} // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_streaming_v2.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\n#include <glog/logging.h>\n\nnamespace nvrpc\n{\n    namespace client\n    {\n        namespace v2\n        {\n            template <typename Request, typename Response>\n            struct ClientStreaming : public BaseContext\n            {\n            public:\n                using PrepareFn =\n                    std::function<std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>>(::grpc::ClientContext*,\n                                                                                                           ::grpc::CompletionQueue*)>;\n\n                ClientStreaming(PrepareFn, std::shared_ptr<Executor>, bool initialize = true);\n                ~ClientStreaming() override {}\n\n                // void Write(Request*);\n                bool Write(Request&&);\n\n                std::shared_future<::grpc::Status> Status();\n                std::shared_future<::grpc::Status> Done();\n                std::shared_future<::grpc::Status> Cancel();\n\n                bool SetCorked(bool true_or_false)\n                {\n                    m_Corked = true_or_false;\n                }\n\n                bool IsCorked() const\n                {\n                    return m_Corked;\n                }\n\n                bool ExecutorShouldDeleteContext() const override\n                {\n                    return false;\n                }\n\n                void ExecutorShouldDeleteContext(bool true_or_false)\n                {\n                    m_ShouldDelete = true_or_false;\n                }\n\n            protected:\n                void Initialize();\n\n                ::grpc::ClientContext& GetClientContext()\n                {\n                    return m_Context;\n                }\n\n            private:\n                bool RunNextState(bool ok) final override\n                {\n                    return (this->*m_NextState)(ok);\n                }\n\n                bool RunNextState(bool (ClientStreaming<Request, Response>::*state_fn)(bool), bool ok)\n                {\n                    return (this->*state_fn)(ok);\n                }\n\n                class Context : public BaseContext\n                {\n                public:\n                    Context(BaseContext* master) : BaseContext(master) {}\n                    ~Context() override {}\n\n                private:\n                    bool RunNextState(bool ok) final override\n                    {\n                        // DVLOG(1) << this << \": \" << \"Event for Tag: \" << Tag();\n                        return static_cast<ClientStreaming*>(m_MasterContext)->RunNextState(m_NextState, ok);\n                    }\n\n                    bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n                    bool ExecutorShouldDeleteContext() const override\n                    {\n                        return false;\n                    }\n\n                    friend class ClientStreaming<Request, Response>;\n                };\n\n                ::grpc::Status                                                           m_Status;\n                ::grpc::ClientContext                                                    m_Context;\n                std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>> m_Stream;\n                std::promise<::grpc::Status>                                             m_Promise;\n                std::shared_future<::grpc::Status>                                       m_SharedFuture;\n\n                PrepareFn m_PrepareFn;\n\n                virtual void CallbackOnInitialized() {}\n                virtual void CallbackOnRequestSent(Request&&) {}\n                virtual void CallbackOnResponseReceived(Response&&) = 0;\n                virtual void CallbackOnComplete(const ::grpc::Status&) {}\n\n                Context m_ReadState;\n                Context m_WriteState;\n\n                std::mutex           m_Mutex;\n                std::queue<Response> m_ReadQueue;\n                std::queue<Request>  m_WriteQueue;\n\n                std::shared_ptr<Executor> m_Executor;\n\n                bool m_Corked;\n                bool m_ShouldDelete;\n                bool m_Initialized;\n\n                using ReadHandle     = bool;\n                using WriteHandle    = bool;\n                using CloseHandle    = bool;\n                using FinishHandle   = bool;\n                using CompleteHandle = bool;\n                using Actions        = std::tuple<ReadHandle, WriteHandle, CloseHandle, FinishHandle, CompleteHandle>;\n\n                bool m_Reading, m_Writing, m_Finishing, m_Closing, m_ReadsDone, m_WritesDone, m_ClosedDone, m_FinishDone, m_Complete;\n\n                bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n                Actions EvaluateState();\n                void    ForwardProgress(Actions& actions);\n\n                bool StateStreamInitialized(bool);\n                bool StateReadDone(bool);\n                bool StateWriteDone(bool);\n                bool StateWritesDoneDone(bool);\n                bool StateFinishDone(bool);\n                bool StateInvalid(bool);\n                bool StateIdle(bool);\n            };\n\n            template <typename Request, typename Response>\n            ClientStreaming<Request, Response>::ClientStreaming(PrepareFn prepare_fn, std::shared_ptr<Executor> executor, bool initialize)\n            : m_Executor(executor),\n              m_PrepareFn(prepare_fn),\n              m_ReadState(this),\n              m_WriteState(this),\n              m_Reading(false),\n              m_Writing(false),\n              m_Finishing(false),\n              m_Closing(false),\n              m_ReadsDone(false),\n              m_WritesDone(false),\n              m_ClosedDone(false),\n              m_FinishDone(false),\n              m_Complete(false),\n              m_ShouldDelete(false),\n              m_Corked(false),\n              m_Initialized(false)\n            {\n                m_NextState              = &ClientStreaming<Request, Response>::StateInvalid;\n                m_ReadState.m_NextState  = &ClientStreaming<Request, Response>::StateInvalid;\n                m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                Initialize();\n\n                m_SharedFuture = m_Promise.get_future().share();\n            }\n\n            template <typename Request, typename Response>\n            void ClientStreaming<Request, Response>::Initialize()\n            {\n                std::lock_guard<std::mutex> lock(m_Mutex);\n\n                m_Initialized = true;\n\n                m_NextState = &ClientStreaming<Request, Response>::StateStreamInitialized;\n                m_Stream    = m_PrepareFn(&m_Context, m_Executor->GetNextCQ());\n                m_Stream->StartCall(this->Tag());\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::Write(Request&& request)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    CHECK(m_Initialized);\n\n                    if (m_WritesDone)\n                    {\n                        LOG(WARNING) << this << \": Attempting to Write on a Stream that is already closed\";\n                        return false;\n                    }\n\n                    DVLOG(1) << this << \": Queuing Write Request\";\n                    DVLOG(3) << this << \": On Queuing Write, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    m_WriteQueue.push(std::move(request));\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            std::shared_future<::grpc::Status> ClientStreaming<Request, Response>::Done()\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    CHECK(m_Initialized);\n\n                    if (m_WritesDone)\n                    {\n                        LOG(WARNING) << this << \": Attempting to Close (issue WritesDone) to a Stream that is already closed\";\n                        return m_SharedFuture;\n                    }\n\n                    DVLOG(1) << this << \": Queuing WritesDone - no more Writes can be queued\";\n                    DVLOG(3) << this << \": On Queuing WritesDone, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    m_WritesDone = true;\n                    actions      = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return m_SharedFuture;\n            }\n\n            template <typename Request, typename Response>\n            std::shared_future<::grpc::Status> ClientStreaming<Request, Response>::Cancel()\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": Client Cancelling Stream\";\n                    DVLOG(3) << this << \": On Cancel, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    CHECK(m_Initialized);\n\n                    m_WritesDone = true;\n                    m_Context.TryCancel();\n                }\n                return m_SharedFuture;\n            }\n\n            template <typename Request, typename Response>\n            std::shared_future<::grpc::Status> ClientStreaming<Request, Response>::Status()\n            {\n                return m_SharedFuture;\n            }\n\n            template <typename Request, typename Response>\n            typename ClientStreaming<Request, Response>::Actions ClientStreaming<Request, Response>::EvaluateState()\n            {\n                ReadHandle     should_read     = false;\n                WriteHandle    should_write    = nullptr;\n                CloseHandle    should_close    = false;\n                FinishHandle   should_finish   = false;\n                CompleteHandle should_complete = false;\n\n                if (m_NextState == &ClientStreaming<Request, Response>::StateStreamInitialized)\n                {\n                    DVLOG(1) << this << \": Action Queued: Stream Initializing\";\n                }\n                else\n                {\n                    if (!m_Reading && !m_ReadsDone)\n                    {\n                        should_read = true;\n                        m_Reading   = true;\n                        m_ReadQueue.emplace();\n                        m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateReadDone;\n                    }\n                    if (!m_Writing && !m_WriteQueue.empty())\n                    {\n                        should_write             = true;\n                        m_Writing                = true;\n                        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWriteDone;\n                        DVLOG(3) << this << \": WriteQueue has \" << m_WriteQueue.size() << \" outstanding messages\";\n                    }\n                    if (!m_Closing && !m_Writing && m_WritesDone)\n                    {\n                        should_close             = true;\n                        m_Closing                = true;\n                        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWritesDoneDone;\n                    }\n                    if (!m_Reading && !m_Writing && !m_Finishing && m_ReadsDone && m_WritesDone && m_ClosedDone && !m_FinishDone)\n                    {\n                        should_finish = true;\n                        m_Finishing   = true;\n                        m_NextState   = &ClientStreaming<Request, Response>::StateFinishDone;\n                        DCHECK((m_ReadState.m_NextState == &ClientStreaming<Request, Response>::StateInvalid));\n                        DCHECK((m_WriteState.m_NextState == &ClientStreaming<Request, Response>::StateInvalid));\n                    }\n                    if (m_ReadsDone && m_WritesDone && m_ClosedDone && m_FinishDone && !m_Complete)\n                    {\n                        m_Complete      = true;\n                        should_complete = true;\n                    }\n                }\n\n                // clang-format off\n                DVLOG(1) << this << \": \" << (should_read ? 1 : 0) << (should_write ? 1 : 0) << (should_finish ? 1 : 0)\n                    << \" -- \" << m_Reading << m_Writing << m_Finishing\n                    << \" -- \" << m_ReadsDone << m_WritesDone\n                    << \" -- \" << m_Finishing;\n                // clang-format on\n\n                return std::make_tuple(should_read, should_write, should_close, should_finish, should_complete);\n            }\n\n            template <class Request, class Response>\n            void ClientStreaming<Request, Response>::ForwardProgress(Actions& actions)\n            {\n                ReadHandle     should_read     = std::get<0>(actions);\n                WriteHandle    should_write    = std::get<1>(actions);\n                CloseHandle    should_close    = std::get<2>(actions);\n                FinishHandle   should_finish   = std::get<3>(actions);\n                CompleteHandle should_complete = std::get<4>(actions);\n\n                if (should_read)\n                {\n                    DVLOG(1) << this << \": Posting Read/Recv\";\n                    m_Stream->Read(&m_ReadQueue.back(), m_ReadState.Tag());\n                }\n                if (should_write)\n                {\n                    DVLOG(1) << this << \": Writing/Sending Request\";\n                    if (m_Corked)\n                    {\n                        ::grpc::WriteOptions options;\n                        options.set_corked();\n                        m_Stream->Write(m_WriteQueue.front(), options, m_WriteState.Tag());\n                    }\n                    else\n                    {\n                        m_Stream->Write(m_WriteQueue.front(), m_WriteState.Tag());\n                    }\n                }\n                if (should_close)\n                {\n                    DVLOG(1) << this << \": Sending WritesDone to Server\";\n                    m_Stream->WritesDone(m_WriteState.Tag());\n                }\n                if (should_finish)\n                {\n                    DVLOG(1) << this << \": Closing Stream - Finish\";\n                    m_Stream->Finish(&m_Status, Tag());\n                }\n                if (should_complete)\n                {\n                    DVLOG(1) << this << \": Completing Promise\";\n                    CallbackOnComplete(m_Status);\n                    m_Promise.set_value(std::move(m_Status));\n                }\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateStreamInitialized(bool ok)\n            {\n                if (!ok)\n                {\n                    LOG(ERROR) << this << \": Stream Failed to Initialize\";\n                    m_Status    = ::grpc::Status::CANCELLED;\n                    m_ReadsDone = m_WritesDone = m_ClosedDone = m_FinishDone = m_Complete = true;\n                    m_Promise.set_value(::grpc::Status::CANCELLED);\n                    CallbackOnComplete(m_Status);\n                    return false;\n                }\n\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": StreamInitialized\";\n\n                    m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n                    actions     = EvaluateState();\n                }\n\n                CallbackOnInitialized();\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateReadDone(bool ok)\n            {\n                Actions               actions;\n                std::function<void()> callback = nullptr;\n\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": ReadDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Reading               = false;\n                    m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        DVLOG(1) << this << \": Server is closing the read/download portion of the stream\";\n                        m_ReadsDone  = true;\n                        m_WritesDone = true;\n                        if (m_Writing)\n                        {\n                            DLOG(WARNING) << \"ReadDone with NOT OK; however, there is still an outstanding Write\";\n                            m_Context.TryCancel();\n                        }\n                    }\n                    else\n                    {\n                        callback = [this, response = std::move(m_ReadQueue.front())]() mutable {\n                            CallbackOnResponseReceived(std::move(response));\n                        };\n                        m_ReadQueue.pop();\n                    }\n                    actions = EvaluateState();\n                }\n\n                // drop mutex and perform actions\n                if (callback)\n                {\n                    callback();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateWriteDone(bool ok)\n            {\n                Actions               actions;\n                std::function<void()> callback = nullptr;\n\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": WriteDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Writing                = false;\n                    m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        // Invalidate any outstanding reads on stream\n                        DLOG(ERROR) << \"Failed to Write to Stream - shutting down\";\n                        m_WritesDone = true;\n                        m_WriteQueue = std::queue<Request>();\n                        if (!m_ReadsDone)\n                        {\n                            m_Context.TryCancel();\n                        }\n                    }\n                    else\n                    {\n                        callback = [this, request = std::move(m_WriteQueue.front())]() mutable {\n                            CallbackOnRequestSent(std::move(request));\n                        };\n                        m_WriteQueue.pop();\n                    }\n\n                    actions = EvaluateState();\n                }\n\n                // drop mutex and perform any actions\n                if (callback)\n                {\n                    callback();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateWritesDoneDone(bool ok)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": WritesDoneDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_ClosedDone             = true;\n                    m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        LOG(ERROR) << \"Failed to close write/upload portion of stream\";\n                        if (!m_ReadsDone)\n                        {\n                            m_Context.TryCancel();\n                        }\n                    }\n\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateFinishDone(bool ok)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": FinishedDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Finishing  = false;\n                    m_FinishDone = true;\n\n                    if (!ok)\n                    {\n                        LOG(ERROR) << \"Request to Finish the stream failed\";\n                        m_Context.TryCancel();\n                    }\n\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return false;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateInvalid(bool ok)\n            {\n                LOG(FATAL) << \"Your logic is bad - you should never have come here\";\n            }\n\n        } // namespace v2\n    }     // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_streaming_v3.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\n#include <glog/logging.h>\n\nnamespace nvrpc\n{\n    namespace client\n    {\n        namespace v3\n        {\n            template <typename Request, typename Response>\n            struct ClientStreaming : public BaseContext\n            {\n                using Stream = std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>>;\n\n            public:\n                using PrepareFn =\n                    std::function<std::unique_ptr<::grpc_impl::ClientAsyncReaderWriter<Request, Response>>(::grpc::ClientContext*,\n                                                                                                           ::grpc::CompletionQueue*)>;\n\n                ClientStreaming(PrepareFn, std::shared_ptr<Executor>);\n                ~ClientStreaming() override {}\n\n                bool Write(Request&&);\n                bool CloseWrites();\n                bool IsComplete();\n\n                void Cancel();\n\n                bool SetCorked(bool true_or_false)\n                {\n                    m_Corked = true_or_false;\n                }\n\n                bool IsCorked() const\n                {\n                    return m_Corked;\n                }\n\n                bool ExecutorShouldDeleteContext() const override\n                {\n                    return false;\n                }\n\n                void ExecutorShouldDeleteContext(bool true_or_false)\n                {\n                    m_ShouldDelete = true_or_false;\n                }\n\n            protected:\n                void Initialize();\n\n                ::grpc::ClientContext& GetClientContext()\n                {\n                    return m_Context;\n                }\n\n            private:\n                bool RunNextState(bool ok) final override\n                {\n                    return (this->*m_NextState)(ok);\n                }\n\n                bool RunNextState(bool (ClientStreaming<Request, Response>::*state_fn)(bool), bool ok)\n                {\n                    return (this->*state_fn)(ok);\n                }\n\n                class Context : public BaseContext\n                {\n                public:\n                    Context(BaseContext* master) : BaseContext(master) {}\n                    ~Context() override {}\n\n                private:\n                    bool RunNextState(bool ok) final override\n                    {\n                        // DVLOG(1) << this << \": \" << \"Event for Tag: \" << Tag();\n                        return static_cast<ClientStreaming*>(m_MasterContext)->RunNextState(m_NextState, ok);\n                    }\n\n                    bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n                    bool ExecutorShouldDeleteContext() const override\n                    {\n                        return false;\n                    }\n\n                    friend class ClientStreaming<Request, Response>;\n                };\n\n                ::grpc::Status        m_Status;\n                ::grpc::ClientContext m_Context;\n                Stream                m_Stream;\n\n                PrepareFn m_PrepareFn;\n\n                virtual void CallbackOnInitialized() {}\n                virtual void CallbackOnRequestSent(Request&&) {}\n                virtual void CallbackOnResponseReceived(Response&&) = 0;\n                virtual void CallbackOnComplete(const ::grpc::Status&) {}\n\n                Context m_ReadState;\n                Context m_WriteState;\n\n                std::mutex           m_Mutex;\n                std::queue<Response> m_ReadQueue;\n                std::queue<Request>  m_WriteQueue;\n\n                std::shared_ptr<Executor> m_Executor;\n\n                bool m_Corked;\n                bool m_ShouldDelete;\n                bool m_Initialized;\n\n                using ReadHandle   = bool;\n                using WriteHandle  = bool;\n                using CloseHandle  = bool;\n                using FinishHandle = bool;\n                using Actions      = std::tuple<ReadHandle, WriteHandle, CloseHandle, FinishHandle>;\n\n                bool m_Reading, m_Writing, m_Finishing, m_Closing, m_ReadsDone, m_WritesDone, m_ClosedDone, m_FinishDone, m_Complete;\n\n                bool (ClientStreaming<Request, Response>::*m_NextState)(bool);\n\n                Actions EvaluateState();\n                void    ForwardProgress(Actions& actions);\n\n                bool StateStreamInitialized(bool);\n                bool StateReadDone(bool);\n                bool StateWriteDone(bool);\n                bool StateWritesDoneDone(bool);\n                bool StateFinishDone(bool);\n                bool StateInvalid(bool);\n                bool StateIdle(bool);\n            };\n\n            template <typename Request, typename Response>\n            ClientStreaming<Request, Response>::ClientStreaming(PrepareFn prepare_fn, std::shared_ptr<Executor> executor)\n            : m_Executor(executor),\n              m_PrepareFn(prepare_fn),\n              m_ReadState(this),\n              m_WriteState(this),\n              m_Reading(false),\n              m_Writing(false),\n              m_Finishing(false),\n              m_Closing(false),\n              m_ReadsDone(false),\n              m_WritesDone(false),\n              m_ClosedDone(false),\n              m_FinishDone(false),\n              m_Complete(false),\n              m_ShouldDelete(false),\n              m_Corked(false),\n              m_Initialized(false)\n            {\n                m_NextState              = &ClientStreaming<Request, Response>::StateInvalid;\n                m_ReadState.m_NextState  = &ClientStreaming<Request, Response>::StateInvalid;\n                m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                Initialize();\n            }\n\n            template <typename Request, typename Response>\n            void ClientStreaming<Request, Response>::Initialize()\n            {\n                std::lock_guard<std::mutex> lock(m_Mutex);\n\n                m_Initialized = true;\n\n                m_NextState = &ClientStreaming<Request, Response>::StateStreamInitialized;\n                m_Stream    = m_PrepareFn(&m_Context, m_Executor->GetNextCQ());\n                m_Stream->StartCall(this->Tag());\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::Write(Request&& request)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    CHECK(m_Initialized);\n\n                    if (m_WritesDone)\n                    {\n                        LOG(WARNING) << this << \": Attempting to Write on a Stream that is already closed\";\n                        return false;\n                    }\n\n                    DVLOG(1) << this << \": Queuing Write Request\";\n                    DVLOG(3) << this << \": On Queuing Write, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    m_WriteQueue.push(std::move(request));\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::CloseWrites()\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    CHECK(m_Initialized);\n\n                    if (m_WritesDone)\n                    {\n                        LOG(WARNING) << this << \": Attempting to Close (issue WritesDone) to a Stream that is already closed\";\n                        return false;\n                    }\n\n                    DVLOG(1) << this << \": Queuing WritesDone - no more Writes can be queued\";\n                    DVLOG(3) << this << \": On Queuing WritesDone, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    m_WritesDone = true;\n                    actions      = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            void ClientStreaming<Request, Response>::Cancel()\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": Client Cancelling Stream\";\n                    DVLOG(3) << this << \": On Cancel, there are \" << m_WriteQueue.size() << \" outstanding writes\";\n\n                    CHECK(m_Initialized);\n\n                    m_WritesDone = true;\n                    m_Context.TryCancel();\n                }\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::IsComplete()\n            {\n                std::lock_guard<std::mutex> lock(m_Mutex);\n                return m_Complete;\n            }\n\n            template <typename Request, typename Response>\n            typename ClientStreaming<Request, Response>::Actions ClientStreaming<Request, Response>::EvaluateState()\n            {\n                ReadHandle   should_read   = false;\n                WriteHandle  should_write  = nullptr;\n                CloseHandle  should_close  = false;\n                FinishHandle should_finish = false;\n\n                if (m_NextState == &ClientStreaming<Request, Response>::StateStreamInitialized)\n                {\n                    DVLOG(1) << this << \": Action Queued: Stream Initializing\";\n                }\n                else\n                {\n                    if (!m_Reading && !m_ReadsDone)\n                    {\n                        should_read = true;\n                        m_Reading   = true;\n                        m_ReadQueue.emplace();\n                        m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateReadDone;\n                    }\n                    if (!m_Writing && !m_WriteQueue.empty())\n                    {\n                        should_write             = true;\n                        m_Writing                = true;\n                        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWriteDone;\n                        DVLOG(3) << this << \": WriteQueue has \" << m_WriteQueue.size() << \" outstanding messages\";\n                    }\n                    if (!m_Closing && !m_Writing && m_WritesDone)\n                    {\n                        should_close             = true;\n                        m_Closing                = true;\n                        m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateWritesDoneDone;\n                    }\n                    if (!m_Reading && !m_Writing && !m_Finishing && m_ReadsDone && m_WritesDone && m_ClosedDone && !m_FinishDone)\n                    {\n                        should_finish = true;\n                        m_Finishing   = true;\n                        m_NextState   = &ClientStreaming<Request, Response>::StateFinishDone;\n                        DCHECK((m_ReadState.m_NextState == &ClientStreaming<Request, Response>::StateInvalid));\n                        DCHECK((m_WriteState.m_NextState == &ClientStreaming<Request, Response>::StateInvalid));\n                    }\n                    if (m_ReadsDone && m_WritesDone && m_ClosedDone && m_FinishDone && !m_Complete)\n                    {\n                        CallbackOnComplete(m_Status);\n                        m_Complete = true;\n                    }\n                }\n\n                // clang-format off\n                DVLOG(1) << this << \": \" << (should_read ? 1 : 0) << (should_write ? 1 : 0) << (should_finish ? 1 : 0)\n                    << \" -- \" << m_Reading << m_Writing << m_Finishing\n                    << \" -- \" << m_ReadsDone << m_WritesDone\n                    << \" -- \" << m_Finishing;\n                // clang-format on\n\n                return std::make_tuple(should_read, should_write, should_close, should_finish);\n            }\n\n            template <class Request, class Response>\n            void ClientStreaming<Request, Response>::ForwardProgress(Actions& actions)\n            {\n                ReadHandle   should_read   = std::get<0>(actions);\n                WriteHandle  should_write  = std::get<1>(actions);\n                CloseHandle  should_close  = std::get<2>(actions);\n                FinishHandle should_finish = std::get<3>(actions);\n\n                if (should_read)\n                {\n                    DVLOG(1) << this << \": Posting Read/Recv\";\n                    m_Stream->Read(&m_ReadQueue.back(), m_ReadState.Tag());\n                }\n                if (should_write)\n                {\n                    DVLOG(1) << this << \": Writing/Sending Request\";\n                    if (m_Corked)\n                    {\n                        ::grpc::WriteOptions options;\n                        options.set_corked();\n                        m_Stream->Write(m_WriteQueue.front(), options, m_WriteState.Tag());\n                    }\n                    else\n                    {\n                        m_Stream->Write(m_WriteQueue.front(), m_WriteState.Tag());\n                    }\n                }\n                if (should_close)\n                {\n                    DVLOG(1) << this << \": Sending WritesDone to Server\";\n                    m_Stream->WritesDone(m_WriteState.Tag());\n                }\n                if (should_finish)\n                {\n                    DVLOG(1) << this << \": Closing Stream - Finish\";\n                    m_Stream->Finish(&m_Status, Tag());\n                }\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateStreamInitialized(bool ok)\n            {\n                if (!ok)\n                {\n                    LOG(ERROR) << this << \": Stream Failed to Initialize\";\n                    m_Status    = ::grpc::Status::CANCELLED;\n                    m_ReadsDone = m_WritesDone = m_ClosedDone = m_FinishDone = m_Complete = true;\n                    CallbackOnComplete(m_Status);\n                    return false;\n                }\n\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": StreamInitialized\";\n\n                    m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n                    actions     = EvaluateState();\n                }\n\n                CallbackOnInitialized();\n\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateReadDone(bool ok)\n            {\n                Actions               actions;\n                std::function<void()> callback = nullptr;\n\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": ReadDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Reading               = false;\n                    m_ReadState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        DVLOG(1) << this << \": Server is closing the read/download portion of the stream\";\n                        m_ReadsDone  = true;\n                        m_WritesDone = true;\n                        if (m_Writing)\n                        {\n                            DLOG(WARNING) << \"ReadDone with NOT OK; however, there is still an outstanding Write\";\n                            m_Context.TryCancel();\n                        }\n                    }\n                    else\n                    {\n                        callback = [this, response = std::move(m_ReadQueue.front())]() mutable {\n                            CallbackOnResponseReceived(std::move(response));\n                        };\n                        m_ReadQueue.pop();\n                    }\n                    actions = EvaluateState();\n                }\n\n                // drop mutex and perform actions\n                if (callback)\n                {\n                    callback();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateWriteDone(bool ok)\n            {\n                Actions               actions;\n                std::function<void()> callback = nullptr;\n\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": WriteDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Writing                = false;\n                    m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        // Invalidate any outstanding reads on stream\n                        DLOG(ERROR) << \"Failed to Write to Stream - shutting down\";\n                        m_WritesDone = true;\n                        m_WriteQueue = std::queue<Request>();\n                        if (!m_ReadsDone)\n                        {\n                            m_Context.TryCancel();\n                        }\n                    }\n                    else\n                    {\n                        callback = [this, request = std::move(m_WriteQueue.front())]() mutable {\n                            CallbackOnRequestSent(std::move(request));\n                        };\n                        m_WriteQueue.pop();\n                    }\n\n                    actions = EvaluateState();\n                }\n\n                // drop mutex and perform any actions\n                if (callback)\n                {\n                    callback();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateWritesDoneDone(bool ok)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": WritesDoneDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_ClosedDone             = true;\n                    m_WriteState.m_NextState = &ClientStreaming<Request, Response>::StateInvalid;\n\n                    if (!ok)\n                    {\n                        LOG(ERROR) << \"Failed to close write/upload portion of stream\";\n                        if (!m_ReadsDone)\n                        {\n                            m_Context.TryCancel();\n                        }\n                    }\n\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return true;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateFinishDone(bool ok)\n            {\n                Actions actions;\n                {\n                    std::lock_guard<std::mutex> lock(m_Mutex);\n                    DVLOG(1) << this << \": FinishedDone: \" << (ok ? \"OK\" : \"NOT OK\");\n\n                    m_Finishing  = false;\n                    m_FinishDone = true;\n\n                    if (!ok)\n                    {\n                        LOG(ERROR) << \"Request to Finish the stream failed\";\n                        m_Context.TryCancel();\n                    }\n\n                    actions = EvaluateState();\n                }\n                ForwardProgress(actions);\n                return false;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientStreaming<Request, Response>::StateInvalid(bool ok)\n            {\n                LOG(FATAL) << \"Your logic is bad - you should never have come here\";\n            }\n\n        } // namespace v3\n    }     // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_unary.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n\n#include <glog/logging.h>\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\nnamespace nvrpc {\nnamespace client {\n\ntemplate<typename Request, typename Response>\nstruct ClientUnary : public ::trtlab::async_compute<void(Request&, Response&, ::grpc::Status&)>\n{\n  public:\n    using PrepareFn = std::function<std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<Response>>(\n        ::grpc::ClientContext*, const Request&, ::grpc::CompletionQueue*)>;\n\n    ClientUnary(PrepareFn prepare_fn, std::shared_ptr<Executor> executor)\n        : m_PrepareFn(prepare_fn), m_Executor(executor)\n    {\n    }\n\n    ~ClientUnary() {}\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request* request, Response* response, OnReturnFn on_return,\n                 std::map<std::string, std::string>& headers)\n    {\n        auto wrapped = this->wrap(on_return);\n        auto future = wrapped->get_future();\n\n        Context* ctx = new Context;\n        ctx->m_Request = request;\n        ctx->m_Response = response;\n        ctx->m_Callback = [ctx, wrapped]() mutable {\n            (*wrapped)(*ctx->m_Request, *ctx->m_Response, ctx->m_Status);\n        };\n\n        for(auto& header : headers)\n        {\n            ctx->m_Context.AddMetadata(header.first, header.second);\n        }\n\n        ctx->m_Reader = m_PrepareFn(&ctx->m_Context, *ctx->m_Request, m_Executor->GetNextCQ());\n        ctx->m_Reader->StartCall();\n        ctx->m_Reader->Finish(ctx->m_Response, &ctx->m_Status, ctx->Tag());\n\n        return future.share();\n    }\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request&& request, OnReturnFn on_return)\n    {\n        std::map<std::string, std::string> empty_headers;\n        return Enqueue(std::move(request), on_return, empty_headers);\n    }\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request&& request, OnReturnFn on_return,\n                 std::map<std::string, std::string>& headers)\n    {\n        auto req = std::make_shared<Request>(std::move(request));\n        auto resp = std::make_shared<Response>();\n\n        auto extended_on_return = [req, resp, on_return](Request & request, Response & response,\n                                                         ::grpc::Status & status) mutable -> auto\n        {\n            return on_return(request, response, status);\n        };\n\n        return Enqueue(req.get(), resp.get(), extended_on_return, headers);\n    }\n\n  private:\n    PrepareFn m_PrepareFn;\n    std::shared_ptr<Executor> m_Executor;\n\n    class Context : public BaseContext\n    {\n        Context() : m_NextState(&Context::StateFinishedDone) {}\n        ~Context() override {}\n\n        bool RunNextState(bool ok) final override\n        {\n            bool ret = (this->*m_NextState)(ok);\n            // DLOG_IF(INFO, !ret) << \"RunNextState returning false\";\n            return ret;\n        }\n\n        bool ExecutorShouldDeleteContext() const override { return true; }\n\n      protected:\n        bool StateFinishedDone(bool ok)\n        {\n            DVLOG(1) << \"ClientContext: \" << Tag() << \" finished with \"\n                       << (m_Status.ok() ? \"OK\" : \"CANCELLED\");\n            m_Callback();\n            DVLOG(1) << \"ClientContext: \" << Tag() << \" callback completed\";\n            return false;\n        }\n\n      private:\n        Request* m_Request;\n        Response* m_Response;\n        std::function<void()> m_Callback;\n        ::grpc::Status m_Status;\n        ::grpc::ClientContext m_Context;\n        std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<Response>> m_Reader;\n        bool (Context::*m_NextState)(bool);\n\n        friend class ClientUnary;\n    };\n};\n\ntemplate<typename Request, typename Response>\nstruct ClientUnaryWithMetaData : public ::trtlab::async_compute<void(Request&, Response&, ::grpc::Status&)>\n{\n  public:\n    using metadata_t = std::multimap<::grpc::string_ref, ::grpc::string_ref>;\n\n    using PrepareFn = std::function<std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<Response>>(\n        ::grpc::ClientContext*, const Request&, ::grpc::CompletionQueue*)>;\n\n    ClientUnaryWithMetaData(PrepareFn prepare_fn, std::shared_ptr<Executor> executor)\n        : m_PrepareFn(prepare_fn), m_Executor(executor)\n    {\n    }\n\n    ~ClientUnaryWithMetaData() {}\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request* request, Response* response, OnReturnFn on_return,\n                 std::map<std::string, std::string>& headers)\n    {\n        auto wrapped = this->wrap(on_return);\n        auto future = wrapped->get_future();\n\n        Context* ctx = new Context;\n        ctx->m_Request = request;\n        ctx->m_Response = response;\n        ctx->m_Callback = [ctx, wrapped]() mutable {\n            auto metadata = ctx->GetMetaData();\n            (*wrapped)(*ctx->m_Request, *ctx->m_Response, ctx->m_Status, metadata);\n        };\n\n        for(auto& header : headers)\n        {\n            ctx->m_Context.AddMetadata(header.first, header.second);\n        }\n\n        ctx->m_Reader = m_PrepareFn(&ctx->m_Context, *ctx->m_Request, m_Executor->GetNextCQ());\n        ctx->m_Reader->StartCall();\n        ctx->m_Reader->Finish(ctx->m_Response, &ctx->m_Status, ctx->Tag());\n\n        return future.share();\n    }\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request&& request, OnReturnFn on_return)\n    {\n        std::map<std::string, std::string> empty_headers;\n        return Enqueue(std::move(request), on_return, empty_headers);\n    }\n\n    template<typename OnReturnFn>\n    auto Enqueue(Request&& request, OnReturnFn on_return,\n                 std::map<std::string, std::string>& headers)\n    {\n        auto req = std::make_shared<Request>(std::move(request));\n        auto resp = std::make_shared<Response>();\n\n        auto extended_on_return = [req, resp, on_return](Request & request, Response & response,\n                                                         ::grpc::Status & status, metadata_t& metadata) mutable -> auto\n        {\n            return on_return(request, response, status, metadata);\n        };\n\n        return Enqueue(req.get(), resp.get(), extended_on_return, headers);\n    }\n\n  private:\n    PrepareFn m_PrepareFn;\n    std::shared_ptr<Executor> m_Executor;\n\n    class Context : public BaseContext\n    {\n        Context() : m_NextState(&Context::StateFinishedDone) {}\n        ~Context() override {}\n\n        bool RunNextState(bool ok) final override\n        {\n            bool ret = (this->*m_NextState)(ok);\n            // DLOG_IF(INFO, !ret) << \"RunNextState returning false\";\n            return ret;\n        }\n\n        bool ExecutorShouldDeleteContext() const override { return true; }\n\n        metadata_t GetMetaData() { return m_Context.GetServerTrailingMetadata(); }\n\n      protected:\n        bool StateFinishedDone(bool ok)\n        {\n            DVLOG(1) << \"ClientContext: \" << Tag() << \" finished with \"\n                       << (m_Status.ok() ? \"OK\" : \"CANCELLED\");\n            m_Callback();\n            DVLOG(1) << \"ClientContext: \" << Tag() << \" callback completed\";\n            return false;\n        }\n\n      private:\n        Request* m_Request;\n        Response* m_Response;\n        std::function<void()> m_Callback;\n        ::grpc::Status m_Status;\n        ::grpc::ClientContext m_Context;\n        std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<Response>> m_Reader;\n        bool (Context::*m_NextState)(bool);\n\n        friend class ClientUnaryWithMetaData;\n    };\n\n};\n\n} // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/client_unary_v2.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <functional>\n#include <memory>\n#include <future>\n\n#include <glog/logging.h>\n#include <grpc++/grpc++.h>\n\n#include \"nvrpc/client/base_context.h\"\n#include \"nvrpc/client/executor.h\"\n#include \"trtlab/core/async_compute.h\"\n\nnamespace nvrpc\n{\n    namespace client\n    {\n        namespace v2\n        {\n            template <typename Request, typename Response>\n            struct ClientUnary : public BaseContext\n            {\n                using Client = ClientUnary<Request, Response>;\n                using Reader = std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<Response>>;\n\n            public:\n                using PrepareFn = std::function<Reader(::grpc::ClientContext*, const Request&, ::grpc::CompletionQueue*)>;\n\n                ClientUnary(PrepareFn prepare_fn, std::shared_ptr<Executor> executor) : m_PrepareFn(prepare_fn), m_Executor(executor)\n                {\n                    m_NextState = &Client::StateInvalid;\n                }\n\n                ~ClientUnary() {}\n\n                void Write(Request&&);\n\n                virtual void CallbackOnRequestSent(Request&&) {}\n                virtual void CallbackOnResponseReceived(Response&&)    = 0;\n                virtual void CallbackOnComplete(const ::grpc::Status&) = 0;\n\n                bool ExecutorShouldDeleteContext() const override\n                {\n                    return false;\n                }\n\n            protected:\n                ::grpc::ClientContext& GetClientContext()\n                {\n                    return m_Context;\n                }\n\n            private:\n                PrepareFn                 m_PrepareFn;\n                std::shared_ptr<Executor> m_Executor;\n\n                ::grpc::Status        m_Status;\n                ::grpc::ClientContext m_Context;\n                Reader                m_Stream;\n\n                Request  m_Request;\n                Response m_Response;\n\n                bool RunNextState(bool ok) final override\n                {\n                    return (this->*m_NextState)(ok);\n                }\n\n                bool StateFinishDone(bool);\n                bool StateInvalid(bool);\n\n                bool (Client::*m_NextState)(bool);\n            };\n\n            template <typename Request, typename Response>\n            void ClientUnary<Request, Response>::Write(Request&& request)\n            {\n                CHECK(m_Stream == nullptr);\n\n                m_Request   = std::move(request);\n                m_NextState = &Client::StateFinishDone;\n\n                m_Stream = m_PrepareFn(&m_Context, m_Request, m_Executor->GetNextCQ());\n                m_Stream->StartCall();\n                m_Stream->Finish(&m_Response, &m_Status, this->Tag());\n            }\n\n            template <typename Request, typename Response>\n            bool ClientUnary<Request, Response>::StateFinishDone(bool ok)\n            {\n                m_NextState = &Client::StateInvalid;\n\n                if (!ok)\n                {\n                    DVLOG(1) << \"FinishDone handler called with NOT OK\";\n                }\n\n                DVLOG(1) << \"calling on complete callback\";\n                if (m_Status.ok())\n                {\n                    CallbackOnResponseReceived(std::move(m_Response));\n                }\n                CallbackOnComplete(m_Status);\n\n                return false;\n            }\n\n            template <typename Request, typename Response>\n            bool ClientUnary<Request, Response>::StateInvalid(bool ok)\n            {\n                LOG(FATAL) << \"logic error in ClientUnary state management\";\n                return false;\n            }\n\n        } // namespace v2\n    }     // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/client/executor.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <memory>\n#include <mutex>\n#include <vector>\n\n#include <grpc++/grpc++.h>\n\n#include <trtlab/core/thread_pool.h>\n\nnamespace nvrpc {\nnamespace client {\n\nclass Executor : public std::enable_shared_from_this<Executor>\n{\n  public:\n    Executor();\n    Executor(int numThreads);\n    Executor(std::unique_ptr<::trtlab::ThreadPool> threadpool);\n\n    Executor(Executor&& other) noexcept = delete;\n    Executor& operator=(Executor&& other) noexcept = delete;\n\n    Executor(const Executor& other) = delete;\n    Executor& operator=(const Executor& other) = delete;\n\n    virtual ~Executor();\n\n    void ShutdownAndJoin();\n    ::grpc::CompletionQueue* GetNextCQ() const;\n\n  private:\n    void ProgressEngine(::grpc::CompletionQueue&);\n\n    mutable std::size_t m_Counter;\n    std::unique_ptr<::trtlab::ThreadPool> m_ThreadPool;\n    std::vector<std::unique_ptr<::grpc::CompletionQueue>> m_CQs;\n    mutable std::mutex m_Mutex;\n};\n\n} // namespace client\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/context.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/interfaces.h\"\n#include \"nvrpc/life_cycle_batching.h\"\n#include \"nvrpc/life_cycle_bidirectional.h\"\n#include \"nvrpc/life_cycle_streaming.h\"\n#include \"nvrpc/life_cycle_unary.h\"\n\n#ifdef NVRPC_METRICS_ENABLED\n#include \"YAIS/Metrics.h\"\n#endif\n\nnamespace nvrpc {\n\ntemplate<class LifeCycle, class Resources>\nclass BaseContext;\n\ntemplate<class Request, class Response, class Resources>\nusing Context = BaseContext<LifeCycleUnary<Request, Response>, Resources>;\n\ntemplate<class Request, class Response, class Resources>\nusing BatchingContext = BaseContext<LifeCycleBatching<Request, Response>, Resources>;\n\ntemplate<class Request, class Response, class Resources>\nusing BidirectionalContext =\n    BaseContext<BidirectionalLifeCycleStreaming<Request, Response>, Resources>;\n\ntemplate<class Request, class Response, class Resources>\nusing StreamingContext = BaseContext<LifeCycleStreaming<Request, Response>, Resources>;\n\ntemplate<class LifeCycle, class Resources>\nclass BaseContext : public LifeCycle\n{\n  public:\n    using RequestType = typename LifeCycle::RequestType;\n    using ResponseType = typename LifeCycle::ResponseType;\n    using ResourcesType = std::shared_ptr<Resources>;\n    using QueueFuncType = typename LifeCycle::ExecutorQueueFuncType;\n\n    using LifeCycleType = LifeCycle;\n    virtual ~BaseContext() override {}\n\n  protected:\n    const ResourcesType& GetResources() const { return m_Resources; }\n    double Walltime() const;\n\n    virtual void OnContextStart() {}\n    virtual void OnContextReset() {}\n\n  private:\n    virtual void OnLifeCycleStart() final override;\n    virtual void OnLifeCycleReset() final override;\n\n    ResourcesType m_Resources;\n    std::chrono::high_resolution_clock::time_point m_StartTime;\n\n    void FactoryInitializer(QueueFuncType, ResourcesType);\n\n    // Factory function allowed to create unique pointers to context objects\n    template<class ContextType>\n    friend std::unique_ptr<ContextType>\n        ContextFactory(typename ContextType::QueueFuncType q_fn,\n                       typename ContextType::ResourcesType resources);\n\n  public:\n    // Convenience method to acquire the Context base pointer from a derived class\n    BaseContext<LifeCycle, Resources>* GetBase()\n    {\n        return dynamic_cast<BaseContext<LifeCycle, Resources>*>(this);\n    }\n};\n\n// Implementations\n\n/**\n * @brief Method invoked when a request is received and the per-call context lifecycle begins.\n */\ntemplate<class LifeCycle, class Resources>\nvoid BaseContext<LifeCycle, Resources>::OnLifeCycleStart()\n{\n    m_StartTime = std::chrono::high_resolution_clock::now();\n#ifdef NVRPC_METRICS_ENABLED\n    Metrics::ExecutionQueueDepthIncrement();\n#endif\n    OnContextStart();\n}\n\n/**\n * @brief Method invoked at the end of the per-call lifecycle just before the context is reset.\n */\ntemplate<class LifeCycle, class Resources>\nvoid BaseContext<LifeCycle, Resources>::OnLifeCycleReset()\n{\n#ifdef NVRPC_METRICS_ENABLED\n    Metrics::ExecutionQueueDepthDecrement();\n#endif\n    OnContextReset();\n}\n\n/**\n * @brief Number of seconds since the start of the RPC\n */\ntemplate<class LifeCycle, class Resources>\ndouble BaseContext<LifeCycle, Resources>::Walltime() const\n{\n    return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - m_StartTime)\n        .count();\n}\n\n/**\n * @brief Used by ContextFactory to initialize the Context\n */\ntemplate<class LifeCycle, class Resources>\nvoid BaseContext<LifeCycle, Resources>::FactoryInitializer(QueueFuncType queue_fn,\n                                                           ResourcesType resources)\n{\n    this->SetQueueFunc(queue_fn);\n    m_Resources = resources;\n}\n\n/**\n * @brief ContextFactory is the only function in the library allowed to create an IContext object.\n */\ntemplate<class ContextType>\nstd::unique_ptr<ContextType> ContextFactory(typename ContextType::QueueFuncType queue_fn,\n                                            typename ContextType::ResourcesType resources)\n{\n    auto ctx = std::make_unique<ContextType>();\n    auto base = ctx->GetBase();\n    base->FactoryInitializer(queue_fn, resources);\n    return ctx;\n}\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/executor.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/interfaces.h\"\n#include \"trtlab/core/resources.h\"\n#include \"trtlab/core/thread_pool.h\"\n\n#include <thread>\n\n#include <glog/logging.h>\n\nnamespace nvrpc\n{\n    class Executor : public IExecutor\n    {\n    public:\n        Executor();\n        Executor(int numThreads);\n        Executor(std::unique_ptr<::trtlab::ThreadPool> threadpool);\n        ~Executor() override {}\n\n        void Initialize(::grpc::ServerBuilder& builder) final override\n        {\n            for (int i = 0; i < m_ThreadPool->Size(); i++)\n            {\n                m_ServerCompletionQueues.emplace_back(builder.AddCompletionQueue());\n            }\n        }\n\n        void RegisterContexts(IRPC* rpc, std::shared_ptr<::trtlab::Resources> resources, int numContextsPerThread) final override\n        {\n            auto base = dynamic_cast<IExecutor*>(this);\n            CHECK_EQ(m_ThreadPool->Size(), m_ServerCompletionQueues.size()) << \"Incorrect number of CQs\";\n            for (int i = 0; i < m_ThreadPool->Size(); i++)\n            {\n                auto cq = m_ServerCompletionQueues[i].get();\n                for (int j = 0; j < numContextsPerThread; j++)\n                {\n                    DVLOG(3) << \"Creating Context \" << j << \" on thread \" << i;\n                    m_Contexts.emplace_back(this->CreateContext(rpc, cq, resources));\n                }\n            }\n        }\n\n        void Shutdown() final override\n        {\n            for (auto& cq : m_ServerCompletionQueues)\n            {\n                LOG(INFO) << \"Telling CQ to Shutdown: \" << cq.get();\n                cq->Shutdown();\n                m_Running = false;\n            }\n            // exit(911);\n            LOG(INFO) << \"Joining Executor Threads\";\n            m_ThreadPool.reset();\n        }\n\n        void Run() final override\n        {\n            // Launch the threads polling on their CQs\n            for (int i = 0; i < m_ThreadPool->Size(); i++)\n            {\n                m_ThreadPool->enqueue([this, i] { ProgressEngine(i); });\n                // m_Threads.emplace_back(&Executor::ProgressEngine, this, i);\n            }\n            // Queue the Execution Contexts in the recieve queue\n            for (int i = 0; i < m_Contexts.size(); i++)\n            {\n                ResetContext(m_Contexts[i].get());\n                // TODO: add a hooked to allow one to customize some\n                // ContextDidReset(m_Contexts[i].get());\n            }\n        }\n\n    protected:\n        void SetTimeout(time_point, std::function<void()>) final override;\n\n        //private:\n        virtual void ProgressEngine(int thread_id);\n\n        volatile bool                                               m_Running;\n        time_point                                                  m_TimeoutDeadline;\n        std::function<void()>                                       m_TimeoutCallback;\n        std::vector<std::unique_ptr<IContext>>                      m_Contexts;\n        std::vector<std::unique_ptr<::grpc::ServerCompletionQueue>> m_ServerCompletionQueues;\n        // std::vector<std::unique_ptr<PerThreadState>> m_ShutdownState;\n        std::unique_ptr<::trtlab::ThreadPool> m_ThreadPool;\n    };\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/fiber/executor.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/executor.h\"\n#include <boost/fiber/all.hpp>\n\nnamespace nvrpc\n{\n    // todo: the derviation of FiberExecutor required making the variables of Executor protected\n    // instead of private.  work should be to clean up the interface and establish better \n    // inheritance properites\n    class FiberExecutor : public Executor\n    {\n        using Executor::Executor;\n\n        void ProgressEngine(int thread_id) override\n        {\n            //::trtlab::async::shared_work_pool<WorkPoolID>();\n            ::boost::fibers::use_scheduling_algorithm<::boost::fibers::algo::shared_work>();\n            bool  ok;\n            void* tag;\n            auto  myCQ = m_ServerCompletionQueues[thread_id].get();\n            m_Running  = true;\n\n            while (myCQ->Next(&tag, &ok))\n            {\n                ::boost::fibers::fiber([this, tag, ok]() mutable {\n                    DVLOG(3) << \"execution fiber \" << boost::this_fiber::get_id() << \" running on thread \" << std::this_thread::get_id();\n                    auto ctx = IContext::Detag(tag);\n                    if (!RunContext(ctx, ok))\n                    {\n                        if (m_Running)\n                        {\n                            ResetContext(ctx);\n                        }\n                    }\n                }).detach();\n            }\n        }\n    };\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/interfaces.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef NVIS_INTERFACES_H_\n#define NVIS_INTERFACES_H_\n\n#include <grpcpp/grpcpp.h>\n\n#include \"trtlab/core/resources.h\"\n\nnamespace nvrpc {\n\nclass IContext;\nclass IExecutor;\nclass IContextLifeCycle;\nclass IRPC;\nclass IService;\n\n/**\n * The IContext object and it's subsequent derivations are the single more important class\n * in this library. Contexts are responsible for maintaining the state of a message and\n * performing the custom code for an RPC invocation.\n */\nclass IContext\n{\n  public:\n    virtual ~IContext() {}\n    static IContext* Detag(void* tag) { return static_cast<IContext*>(tag); }\n\n  protected:\n    IContext() : m_PrimaryContext(this) {}\n    IContext(IContext* primary_context) : m_PrimaryContext(primary_context) {}\n\n    void* Tag() { return reinterpret_cast<void*>(this); }\n\n  protected:\n    IContext* m_PrimaryContext;\n\n  private:\n    virtual bool RunNextState(bool) = 0;\n    virtual void Reset() = 0;\n\n    friend class IRPC;\n    friend class IExecutor;\n};\n\nclass IContextLifeCycle : public IContext\n{\n  public:\n    ~IContextLifeCycle() override {}\n\n  protected:\n    IContextLifeCycle() = default;\n\n    virtual void OnLifeCycleStart() = 0;\n    virtual void OnLifeCycleReset() = 0;\n\n    virtual void FinishResponse() = 0;\n    virtual void CancelResponse() = 0;\n};\n\nclass IService\n{\n  public:\n    IService() = default;\n    virtual ~IService() {}\n\n    virtual void Initialize(::grpc::ServerBuilder&) = 0;\n};\n\nclass IRPC\n{\n  public:\n    IRPC() = default;\n    virtual ~IRPC() {}\n\n  protected:\n    virtual std::unique_ptr<IContext> CreateContext(::grpc::ServerCompletionQueue*,\n                                                    std::shared_ptr<::trtlab::Resources>) = 0;\n\n    friend class IExecutor;\n};\n\nclass IExecutor\n{\n  public:\n    IExecutor() = default;\n    virtual ~IExecutor() {}\n\n    virtual void Initialize(::grpc::ServerBuilder&) = 0;\n    virtual void Run() = 0;\n    virtual void RegisterContexts(IRPC* rpc, std::shared_ptr<::trtlab::Resources> resources,\n                                  int numContextsPerThread) = 0;\n    virtual void Shutdown() = 0;\n\n  protected:\n    using time_point = std::chrono::system_clock::time_point;\n\n    virtual void SetTimeout(time_point, std::function<void()>) = 0;\n\n    inline bool RunContext(IContext* ctx, bool ok) { return ctx->RunNextState(ok); }\n    inline void ResetContext(IContext* ctx) { ctx->Reset(); }\n    inline std::unique_ptr<IContext> CreateContext(IRPC* rpc, ::grpc::ServerCompletionQueue* cq,\n                                                   std::shared_ptr<::trtlab::Resources> res)\n    {\n        return rpc->CreateContext(cq, res);\n    }\n};\n\n} // namespace nvrpc\n\n#endif // NVIS_INTERFACES_H_\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/life_cycle_batching.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/interfaces.h\"\n#include \"nvrpc/life_cycle_streaming.h\"\n\nnamespace nvrpc {\n\ntemplate<typename Request, typename Response>\nclass LifeCycleBatchingNew : public LifeCycleStreaming<Request, Response>\n{\n  public:\n    using LifeCycleStreaming<Request, Response>::LifeCycleStreaming;\n    using Stream = typename LifeCycleStreaming<Request, Response>::ServerStream;\n\n  protected:\n    virtual void ExecuteRPC(std::vector<Request>&, std::shared_ptr<Stream>) = 0;\n\n  private:\n    void RequestReceived(Request&&, std::shared_ptr<Stream>) final override;\n    void RequestsFinished(std::shared_ptr<Stream>) final override;\n\n    std::vector<Request> m_Requests;\n};\n\ntemplate<class Request, class Response>\nvoid LifeCycleBatchingNew<Request, Response>::RequestReceived(Request&& request,\n                                                              std::shared_ptr<Stream> stream)\n{\n    m_Requests.push_back(std::move(request));\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleBatchingNew<Request, Response>::RequestsFinished(std::shared_ptr<Stream> stream)\n{\n    ExecuteRPC(m_Requests, stream);\n}\n\n/**\n * @brief LifeCycle State Machine All-In, then All-Out BATCHING\n *\n * Client sends message until it says it is done, then execute the RPC\n * on all received items, then for each item, return a response on the\n * stream in the same order the requests were received.\n *\n * @tparam Request\n * @tparam Response\n */\ntemplate<class Request, class Response>\nclass LifeCycleBatching : public IContextLifeCycle\n{\n  public:\n    using RequestType = Request;\n    using ResponseType = Response;\n    using ServiceQueueFuncType = std::function<void(\n        ::grpc::ServerContext*, ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*,\n        ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*)>;\n    using ExecutorQueueFuncType =\n        std::function<void(::grpc::ServerContext*,\n                           ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*, void*)>;\n\n    virtual ~LifeCycleBatching() override {}\n\n  protected:\n    LifeCycleBatching() = default;\n    void SetQueueFunc(ExecutorQueueFuncType q_fn) { m_QueuingFunc = q_fn; }\n\n    virtual void ExecuteRPC(std::vector<RequestType>&, std::vector<ResponseType>&) = 0;\n    virtual void OnRequestReceived(const RequestType&) {}\n\n    void FinishResponse() final override;\n    void CancelResponse() final override;\n\n  private:\n    // IContext Methods\n    bool RunNextState(bool ok) final override;\n    void Reset() final override;\n\n    bool StateRequestDone(bool);\n    bool StateReadDone(bool);\n    bool StateWriteDone(bool);\n    bool StateFinishedDone(bool);\n\n    // Function pointers\n    ExecutorQueueFuncType m_QueuingFunc;\n    bool (LifeCycleBatching<RequestType, ResponseType>::*m_NextState)(bool);\n\n    std::vector<RequestType> m_Requests;\n    std::vector<ResponseType> m_Responses;\n    std::unique_ptr<::grpc::ServerContext> m_Context;\n    std::unique_ptr<::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>> m_Stream;\n    typename std::vector<ResponseType>::const_iterator m_ResponseIterator;\n\n  public:\n    template<class RequestFuncType, class ServiceType>\n    static ServiceQueueFuncType BindServiceQueueFunc(\n        /*\n        std::function<void(\n            ServiceType*, ServerContextType*,\n            ServerAsyncReaderWriter<ResponseType, RequestType>*,\n            CompletionQueue*, ServerCompletionQueue*, void*)>\n        */\n        RequestFuncType request_fn, ServiceType* service_type)\n    {\n        return std::bind(request_fn, service_type,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // AsyncReaderWriter<ResponseType, RequestType>*\n                         std::placeholders::_3, // CQ*\n                         std::placeholders::_4, // ServerCQ*\n                         std::placeholders::_5 // Tag\n        );\n    }\n\n    static ExecutorQueueFuncType BindExecutorQueueFunc(ServiceQueueFuncType service_q_fn,\n                                                       ::grpc::ServerCompletionQueue* cq)\n    {\n        return std::bind(service_q_fn,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // AsyncReaderWriter<ResponseType, RequestType>*\n                         cq, cq,\n                         std::placeholders::_3 // Tag\n        );\n    }\n};\n\n// Implementations\n\ntemplate<class Request, class Response>\nbool LifeCycleBatching<Request, Response>::RunNextState(bool ok)\n{\n    return (this->*m_NextState)(ok);\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleBatching<Request, Response>::Reset()\n{\n    OnLifeCycleReset();\n    m_Requests.clear();\n    m_Responses.clear();\n    m_Context.reset(new ::grpc::ServerContext);\n    m_Stream.reset(new ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>(m_Context.get()));\n    m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateRequestDone;\n    m_QueuingFunc(m_Context.get(), m_Stream.get(), IContext::Tag());\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleBatching<Request, Response>::StateRequestDone(bool ok)\n{\n    if(!ok) return false;\n    OnLifeCycleStart();\n    m_Requests.emplace(m_Requests.end());\n    m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateReadDone;\n    m_Stream->Read(&m_Requests.back(), IContext::Tag());\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleBatching<Request, Response>::StateReadDone(bool ok)\n{\n    if(ok)\n    {\n        // Execute Callback for the Request item received\n        OnRequestReceived(m_Requests.back());\n        // Stream is still open, so pull off another request\n        m_Requests.emplace(m_Requests.end());\n        m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateReadDone;\n        m_Stream->Read(&m_Requests.back(), IContext::Tag());\n    }\n    else\n    {\n        // Client has signaled it will not send any more requests\n        // Remove the Request we didn't actually use\n        m_Requests.pop_back();\n        // Execute Batched RPC on all Requests\n        ExecuteRPC(m_Requests, m_Responses);\n    }\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleBatching<Request, Response>::StateWriteDone(bool ok)\n{\n    if(!ok) return false;\n    if(m_ResponseIterator != m_Responses.cend())\n    {\n        if(m_ResponseIterator + 1 != m_Responses.cend())\n        {\n            m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateWriteDone;\n            m_Stream->Write(*m_ResponseIterator, IContext::Tag());\n            // The following hangs even though the client is guaranteed to have sent WritesDone();\n            // thus, all the response writes from the server should not rely on any of the previous\n            // messages https://grpc.io/grpc/cpp/md_doc_cpp_perf_notes.html\n            // m_Stream->Write(*m_ResponseIterator, ::grpc::WriteOptions().set_buffer_hint(),\n            // IContext::Tag());\n            m_ResponseIterator++;\n        }\n        else\n        {\n            m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateFinishedDone;\n            m_Stream->WriteAndFinish(*m_ResponseIterator, ::grpc::WriteOptions(),\n                                     ::grpc::Status::OK, IContext::Tag());\n        }\n    }\n    else\n    {\n        m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateFinishedDone;\n        m_Stream->Finish(::grpc::Status::OK, IContext::Tag());\n    }\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleBatching<Request, Response>::StateFinishedDone(bool ok)\n{\n    return false;\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleBatching<Request, Response>::FinishResponse()\n{\n    m_ResponseIterator = m_Responses.cbegin();\n    StateWriteDone(true);\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleBatching<Request, Response>::CancelResponse()\n{\n    m_NextState = &LifeCycleBatching<RequestType, ResponseType>::StateFinishedDone;\n    m_Stream->Finish(::grpc::Status::CANCELLED, IContext::Tag());\n}\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/life_cycle_bidirectional.h",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n#pragma once\n\n#include <queue>\n\n#include \"nvrpc/interfaces.h\"\n\n#include <glog/logging.h>\n\nnamespace nvrpc {\n\n// A bidirectional streaming version of LifeCycleUnary class\n// Note that the bidirectional streaming feature in gRPC supports\n// arbitrary call order of ServerReaderWriter::Read() and\n// ServerReaderWriter::Write(), so we are able to handle\n// reading request and writing response seperately.\ntemplate<class Request, class Response>\nclass BidirectionalLifeCycleStreaming : public IContextLifeCycle\n{\n  public:\n    using RequestType = Request;\n    using ResponseType = Response;\n    using ServiceQueueFuncType = std::function<void(\n        ::grpc::ServerContext*, ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*,\n        ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*)>;\n    using ExecutorQueueFuncType =\n        std::function<void(::grpc::ServerContext*,\n                           ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*, void*)>;\n\n    ~BidirectionalLifeCycleStreaming() override {}\n\n  protected:\n    // Class to wrap over the State function pointers to allow the use of\n    // different tags while referencing to the same Context.\n    // Executor Detag() the tag, which points to the StateContext, which contains\n    // a pointer to the actual context (master context).\n    template<class RequestType, class ResponseType>\n    class StateContext : public IContext\n    {\n      public:\n        StateContext(IContext* master) : IContext(master) {}\n\n      private:\n        // IContext Methods\n        bool RunNextState(bool ok) final override\n        {\n            return static_cast<BidirectionalLifeCycleStreaming*>(m_PrimaryContext)\n                ->RunNextState(m_NextState, ok);\n        }\n        void Reset() final override { LOG(FATAL) << \"ooops; call reset on master\"; }\n\n        bool (BidirectionalLifeCycleStreaming<RequestType, ResponseType>::*m_NextState)(bool);\n\n        friend class BidirectionalLifeCycleStreaming<RequestType, ResponseType>;\n    };\n\n    BidirectionalLifeCycleStreaming();\n    void SetQueueFunc(ExecutorQueueFuncType);\n\n    // Function to actually process the request\n    virtual void ExecuteRPC(RequestType& request, ResponseType& response) = 0;\n\n    void FinishResponse() final override;\n    void CancelResponse() final override;\n\n  private:\n    std::tuple<bool, bool, bool> EvaluateState();\n    void ProgressState(bool should_write, bool should_execute, bool should_finish);\n\n    // IContext Methods\n    bool RunNextState(bool ok) final override;\n    bool RunNextState(bool (BidirectionalLifeCycleStreaming<Request, Response>::*state_fn)(bool),\n                      bool ok);\n    void Reset() final override;\n\n    // BidirectionalLifeCycleStreaming Specific Methods\n    bool StateInitializedDone(bool ok);\n    bool StateRequestDone(bool ok);\n    bool StateResponseDone(bool ok);\n    bool StateFinishDone(bool ok);\n    bool StateInvalid(bool ok);\n\n    // Function pointers\n    ExecutorQueueFuncType m_QueuingFunc;\n    bool (BidirectionalLifeCycleStreaming<RequestType, ResponseType>::*m_NextState)(bool);\n\n    // Variables\n    // The mutex will be more useful once we can keep reading requests\n    // without waiting for response to be sent\n    std::mutex m_QueueMutex;\n    std::queue<RequestType> m_RequestQueue;\n    std::queue<ResponseType> m_ResponseQueue;\n    std::queue<ResponseType> m_ResponseWriteBackQueue;\n\n    StateContext<RequestType, ResponseType> m_ReadStateContext;\n    StateContext<RequestType, ResponseType> m_WriteStateContext;\n\n    bool m_Writing;\n    bool m_Executing;\n    bool m_WritesDone;\n    bool m_Finishing;\n\n    std::unique_ptr<::grpc::ServerContext> m_Context;\n    std::unique_ptr<::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>> m_ReaderWriter;\n\n    friend class StateContext<RequestType, ResponseType>;\n\n  public:\n    template<class RequestFuncType, class ServiceType>\n    static ServiceQueueFuncType BindServiceQueueFunc(\n        /*\n        std::function<void(\n            ServiceType *, ::grpc::ServerContext *,\n            ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*,\n            ::grpc::CompletionQueue *, ::grpc::ServerCompletionQueue *, void *)>\n        */\n        RequestFuncType request_fn, ServiceType* service_type)\n    {\n        return std::bind(request_fn, service_type,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // AsyncReaderWriter<OutputType, InputType>\n                         std::placeholders::_3, // CQ\n                         std::placeholders::_4, // ServerCQ\n                         std::placeholders::_5 // Tag\n        );\n    }\n\n    static ExecutorQueueFuncType BindExecutorQueueFunc(ServiceQueueFuncType service_q_fn,\n                                                       ::grpc::ServerCompletionQueue* cq)\n    {\n        return std::bind(service_q_fn,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // AsyncReaderWriter<Response, Request> *\n                         cq, cq,\n                         std::placeholders::_3 // Tag\n        );\n    }\n};\n\n// Implementation\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::RunNextState(bool ok)\n{\n    return (this->*m_NextState)(ok);\n}\n\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::RunNextState(\n    bool (BidirectionalLifeCycleStreaming<Request, Response>::*state_fn)(bool), bool ok)\n{\n    return (this->*state_fn)(ok);\n}\n\ntemplate<class Request, class Response>\nBidirectionalLifeCycleStreaming<Request, Response>::BidirectionalLifeCycleStreaming()\n    : m_ReadStateContext(static_cast<IContext*>(this)),\n      m_WriteStateContext(static_cast<IContext*>(this)), m_WritesDone(false), m_Writing(false),\n      m_Executing(false), m_Finishing(false)\n{\n    m_ReadStateContext.m_NextState =\n        &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateRequestDone;\n    m_WriteStateContext.m_NextState =\n        &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateResponseDone;\n}\n\ntemplate<class Request, class Response>\nvoid BidirectionalLifeCycleStreaming<Request, Response>::Reset()\n{\n    std::queue<RequestType> empty_request_queue;\n    std::queue<ResponseType> empty_response_queue;\n    std::queue<ResponseType> empty_response_write_back_queue;\n    OnLifeCycleReset();\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        m_Writing = false;\n        m_Executing = false;\n        m_WritesDone = false;\n        m_Finishing = false;\n        m_RequestQueue.swap(empty_request_queue);\n        m_ResponseQueue.swap(empty_response_queue);\n        m_ResponseWriteBackQueue.swap(empty_response_write_back_queue);\n        m_Context.reset(new ::grpc::ServerContext);\n        m_ReaderWriter.reset(\n            new ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>(m_Context.get()));\n\n        m_NextState =\n            &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateInitializedDone;\n    }\n    m_QueuingFunc(m_Context.get(), m_ReaderWriter.get(), IContext::Tag());\n}\n\ntemplate<class Request, class Response>\nstd::tuple<bool, bool, bool> BidirectionalLifeCycleStreaming<Request, Response>::EvaluateState()\n{\n    bool should_write = false;\n    bool should_execute = false;\n    bool should_finish = false;\n\n    if(!m_Executing && !m_ResponseQueue.empty())\n    {\n        should_execute = true;\n        m_Executing = true;\n    }\n\n    if(!m_Writing && !m_ResponseWriteBackQueue.empty())\n    {\n        should_write = true;\n        m_Writing = true;\n    }\n\n    if(!should_write && !should_execute && !m_Writing && !m_Executing && !m_Finishing &&\n       m_WritesDone)\n    {\n        should_finish = true;\n        m_Finishing = true;\n        m_NextState = &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateFinishDone;\n    }\n\n    DLOG(INFO) << should_write << \"; \" << should_execute << \"; \" << should_finish << \" -- \"\n               << m_Writing << \"; \" << m_Executing << \"; \" << m_WritesDone;\n\n    return std::make_tuple(should_write, should_execute, should_finish);\n}\n\ntemplate<class Request, class Response>\nvoid BidirectionalLifeCycleStreaming<Request, Response>::ProgressState(bool should_write,\n                                                                       bool should_execute,\n                                                                       bool should_finish)\n{\n    if(should_write)\n    {\n        DLOG(INFO) << \"Writing response\";\n        m_ReaderWriter->Write(m_ResponseWriteBackQueue.front(),\n                              m_WriteStateContext.IContext::Tag());\n    }\n    if(should_execute)\n    {\n        DLOG(INFO) << \"Executing\";\n        ExecuteRPC(m_RequestQueue.front(), m_ResponseQueue.front());\n    }\n    if(should_finish)\n    {\n        DLOG(INFO) << \"Triggering Finish\";\n        m_ReaderWriter->Finish(::grpc::Status::OK, IContext::Tag());\n    }\n}\n\n// The following are a set of functions used as function pointers\n// to keep track of the state of the context.\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::StateInitializedDone(bool ok)\n{\n    if(!ok)\n    {\n        return false;\n    }\n\n    OnLifeCycleStart();\n    // Start reading once connection is created\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        m_RequestQueue.emplace();\n        m_NextState = &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n    }\n    m_ReaderWriter->Read(&m_RequestQueue.back(), m_ReadStateContext.IContext::Tag());\n    return true;\n}\n\n// If the Context.m_NextState is at this state or at StateResponseDone state,\n// it will keep reading requests from the stream until no more requests will\n// be read (Read() brings back status ok==false)\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::StateRequestDone(bool ok)\n{\n    // No more message to be read from this stream, however, if it is executing\n    // a request, then a ServerReaderWriter::Write() will be called. In that case,\n    // let WriteStateContext handle the reset procedure.\n\n    bool should_write, should_execute, should_finish, should_read = true;\n\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        DLOG(INFO) << \"RequestDone Triggered\";\n\n        if(!ok)\n        {\n            {\n                // Client called WritesDone\n                DLOG(INFO) << \"WritesDone received from Client; closing Server Reads\";\n                m_WritesDone = true;\n            }\n        }\n\n        // Successfully receive request\n        should_read = !m_WritesDone;\n        if(should_read)\n        {\n            m_ResponseQueue.emplace(); // add a response object which will be written on execution\n            m_RequestQueue.emplace(); // post a read/recv on a new request object\n        }\n\n        auto should_wef = EvaluateState();\n        should_write = std::get<0>(should_wef);\n        should_execute = std::get<1>(should_wef);\n        should_finish = std::get<2>(should_wef);\n    }\n    if(should_read)\n    {\n        // Post Read/Receive\n        m_ReaderWriter->Read(&m_RequestQueue.back(), m_ReadStateContext.IContext::Tag());\n    }\n    ProgressState(should_write, should_execute, should_finish);\n    return true;\n}\n\n// If the Context.m_NextState is at this state or at StateResponseDone state,\n// it will keep writing completed response to the stream until it is closed\n// (Write() brings back status ok==false)\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::StateResponseDone(bool ok)\n{\n    // If write didn't go through, then the call is dead. Start reseting\n    if(!ok)\n    {\n        // this is likely an unrecoverable error on the client\n        // i think we should return a false without trying to cancel;\n        DLOG(ERROR) << \"not ok in ResponseDone\";\n        CancelResponse();\n        return true;\n    }\n\n    // Done writing back one response\n    bool should_write, should_execute, should_finish;\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        DLOG(ERROR) << \"Finished Writing a Response - ResponseDone\";\n\n        m_Writing = false;\n        m_ResponseWriteBackQueue.pop();\n\n        auto should_wef = EvaluateState();\n        should_write = std::get<0>(should_wef);\n        should_execute = std::get<1>(should_wef);\n        should_finish = std::get<2>(should_wef);\n    }\n    ProgressState(should_write, should_execute, should_finish);\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::StateFinishDone(bool ok)\n{\n    DLOG(INFO) << \"Server closed Write stream - FinishedDone\";\n    return false;\n}\n\ntemplate<class Request, class Response>\nbool BidirectionalLifeCycleStreaming<Request, Response>::StateInvalid(bool ok)\n{\n    throw std::runtime_error(\"invalid state\");\n    return false;\n}\n\ntemplate<class Request, class Response>\nvoid BidirectionalLifeCycleStreaming<Request, Response>::FinishResponse()\n{\n    bool should_write, should_execute, should_finish;\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        DLOG(INFO) << \"InFinishResponse\";\n\n        m_Executing = false;\n        m_ResponseWriteBackQueue.push(std::move(m_ResponseQueue.front()));\n        m_RequestQueue.pop();\n        m_ResponseQueue.pop();\n\n        auto should_wef = EvaluateState();\n        should_write = std::get<0>(should_wef);\n        should_execute = std::get<1>(should_wef);\n        should_finish = std::get<2>(should_wef);\n    }\n    ProgressState(should_write, should_execute, should_finish);\n}\n\ntemplate<class Request, class Response>\nvoid BidirectionalLifeCycleStreaming<Request, Response>::CancelResponse()\n{\n    bool reset_ready = false;\n    {\n        std::lock_guard<std::mutex> lock(m_QueueMutex);\n        m_NextState = &BidirectionalLifeCycleStreaming<RequestType, ResponseType>::StateFinishDone;\n        reset_ready = !m_Executing;\n    }\n    // Only call Finish() when no RPC is being executed to avoid clearing\n    // request and response while they are being referenced in the RPC\n    if(reset_ready)\n    {\n        DLOG(INFO) << \"Closing Server Writes\";\n        m_ReaderWriter->Finish(::grpc::Status::CANCELLED, IContext::Tag());\n    }\n}\n\ntemplate<class Request, class Response>\nvoid BidirectionalLifeCycleStreaming<Request, Response>::SetQueueFunc(\n    ExecutorQueueFuncType queue_fn)\n{\n    m_QueuingFunc = queue_fn;\n}\n\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/life_cycle_streaming.h",
    "content": "// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n//  * Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n//  * Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//  * Neither the name of NVIDIA CORPORATION nor the names of its\n//    contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n#pragma once\n\n#include <queue>\n#include \"nvrpc/interfaces.h\"\n\n#include <glog/logging.h>\n\nnamespace nvrpc\n{\n    /**\n * @brief Base Steaming Life Cycle\n *\n * For every incoming request, `ReceivedRequest` is executed with a shared pointer to a\n * `ServerStream`.  The `ServerStream` is used to write responses back on the stream or\n * optionally cancel the stream.  The life cycle maintains a weak pointer to the `ServerStream`\n * which allows it detect when all external `ServerStream` objects have been dereferenced.\n *\n * The `ServerStream` can be handed off to an external Resource.  If this happens, the external\n * resource can write back responses on the stream until either it decides to release the\n * `ServerStream` object or the stream becomes invalidated.  All `ServerStream` object become\n * invalid when either `CloseStream` or `FinishStream` is called on either a `ServerStream`\n * or by the LifeCycle.\n *\n * The stream is closed when:\n *  1) the client has closed its half of stream, meaning no more Requests will be received,\n *  2) either,\n *     a) all `ServerStream` object have been dereferenced, or\n *     b) `CancelStream` or `FinishStream` is called on either the lifecycle or an external\n *        `ServerStream`.\n *\n * @tparam Request\n * @tparam Response\n */\n    template <class Request, class Response>\n    class LifeCycleStreaming : public IContextLifeCycle\n    {\n    public:\n        using RequestType  = Request;\n        using ResponseType = Response;\n        using ServiceQueueFuncType =\n            std::function<void(::grpc::ServerContext*, ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*,\n                               ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*)>;\n        using ExecutorQueueFuncType =\n            std::function<void(::grpc::ServerContext*, ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*, void*)>;\n\n        ~LifeCycleStreaming() override {}\n\n        class ServerStream;\n\n    protected:\n        LifeCycleStreaming();\n        void SetQueueFunc(ExecutorQueueFuncType);\n\n        // developer must implement RequestsReceived\n        virtual void RequestReceived(Request&&, std::shared_ptr<ServerStream>) = 0;\n\n        // optional hooks to perform actions when the stream is openned/closed\n        virtual void StreamInitialized(std::shared_ptr<ServerStream>) {}\n        virtual void RequestsFinished(std::shared_ptr<ServerStream>) {}\n\n        // TODO: Add an OnInitialized virtual method\n\n    public:\n        // template<typename RequestType, typename ResponseType>\n        class ServerStream\n        {\n        public:\n            // ServerStream(LifeCycleStreaming<RequestType, ResponseType>* master) : m_Stream(master) {}\n            ServerStream(LifeCycleStreaming<Request, Response>* master) : m_Stream(master) {}\n            ~ServerStream()\n            {\n                if (m_Stream)\n                {\n                    LOG(WARNING) << \"ServerStream is still valid on deconstruction; \"\n                                 << \"this means an external handler was the last thing to own the ServerStream, \"\n                                 << \"but Cancel/FinishStream was never called\";\n                    m_Stream->UnblockFinish();\n                    m_Stream->CancelResponse();\n                }\n            }\n\n            bool IsConnected()\n            {\n                return m_Stream;\n            }\n\n            std::uint64_t StreamID()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    DLOG(WARNING) << \"Attempted to get ID of a disconnected stream\";\n                    return 0UL;\n                }\n                return reinterpret_cast<std::uint64_t>(m_Stream->Tag());\n            }\n\n            bool WriteResponse(ResponseType&& response)\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    DLOG(WARNING) << \"Attempted to write to a disconnected stream\";\n                    return false;\n                }\n                m_Stream->WriteResponse(std::move(response));\n                return true;\n            }\n\n            bool CancelStream()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    LOG(WARNING) << \"Attempted to cancel to a disconnected stream\";\n                    return false;\n                }\n                m_Stream->CancelResponse();\n                return false;\n            }\n\n            bool FinishStream()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    LOG(WARNING) << \"Attempted to finish to a disconnected stream\";\n                    return false;\n                }\n                m_Stream->FinishResponse();\n                return false;\n            }\n\n            bool BlockFinish()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    DLOG(WARNING) << \"Attempted to block to a disconnected stream\";\n                    return false;\n                }\n                m_Stream->BlockFinish();\n                return true;\n            }\n\n            bool UnblockFinish()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                if (!IsConnected())\n                {\n                    DLOG(WARNING) << \"Attempted to block to a disconnected stream\";\n                    return false;\n                }\n                m_Stream->UnblockFinish();\n                return true;\n            }\n\n        protected:\n            void Invalidate()\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                m_Stream = nullptr;\n            }\n\n        private:\n            std::recursive_mutex                   m_Mutex;\n            LifeCycleStreaming<Request, Response>* m_Stream;\n\n            friend class LifeCycleStreaming<Request, Response>;\n        };\n\n    protected:\n        template <class RequestType, class ResponseType>\n        class StateContext : public IContext\n        {\n        public:\n            StateContext(IContext* primary_context) : IContext(primary_context) {}\n\n        private:\n            // IContext Methods\n            bool RunNextState(bool ok) final override\n            {\n                return static_cast<LifeCycleStreaming*>(m_PrimaryContext)->RunNextState(m_NextState, ok);\n            }\n            void Reset() final override\n            {\n                static_cast<LifeCycleStreaming*>(m_PrimaryContext)->Reset();\n            }\n\n            bool (LifeCycleStreaming<RequestType, ResponseType>::*m_NextState)(bool);\n\n            friend class LifeCycleStreaming<RequestType, ResponseType>;\n        };\n\n    protected:\n        void BlockFinish();\n        void UnblockFinish();\n\n    private:\n        using ReadHandle    = bool;\n        using WriteHandle   = bool;\n        using ExecuteHandle = std::function<void()>;\n        using FinishHandle  = bool;\n        using Actions       = std::tuple<ReadHandle, WriteHandle, ExecuteHandle, FinishHandle>;\n\n        // IContext Methods\n        void Reset() final override;\n        bool RunNextState(bool ok) final override;\n        bool RunNextState(bool (LifeCycleStreaming<Request, Response>::*state_fn)(bool), bool ok);\n\n        // IContextLifeCycle Methods\n        void FinishResponse() final override;\n        void CancelResponse() final override;\n\n        // LifeCycleStreaming Specific Methods\n        bool StateInitializedDone(bool ok);\n        bool StateReadDone(bool ok);\n        bool StateWriteDone(bool ok);\n        bool StateFinishedDone(bool ok);\n        bool StateInvalid(bool ok);\n\n        // Progress Engine\n        Actions EvaluateState();\n        void    ForwardProgress(Actions&);\n\n        // User Actions\n        void WriteResponse(Response&& response);\n        void CloseStream(::grpc::Status);\n\n        // Function pointers\n        ExecutorQueueFuncType m_QueuingFunc;\n        bool (LifeCycleStreaming<RequestType, ResponseType>::*m_NextState)(bool);\n\n        // Internal State\n        std::recursive_mutex     m_QueueMutex;\n        std::queue<RequestType>  m_RequestQueue;\n        std::queue<ResponseType> m_ResponseQueue;\n\n        std::shared_ptr<ServerStream> m_ServerStream;\n        std::weak_ptr<ServerStream>   m_ExternalStream;\n\n        bool m_Reading, m_Writing, m_Finishing, m_ReadsDone, m_WritesDone, m_ReadsFinished, m_BlockFinish;\n\n        StateContext<RequestType, ResponseType> m_ReadStateContext;\n        StateContext<RequestType, ResponseType> m_WriteStateContext;\n\n        std::unique_ptr<::grpc::Status>                                                  m_Status;\n        std::unique_ptr<::grpc::ServerContext>                                           m_Context;\n        std::unique_ptr<::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>> m_Stream;\n\n        friend class StateContext<RequestType, ResponseType>;\n        // friend class ServerStream<RequestType, ResponseType>;\n        friend class ServerStream;\n\n    public:\n        template <class RequestFuncType, class ServiceType>\n        static ServiceQueueFuncType BindServiceQueueFunc(RequestFuncType request_fn, ServiceType* service_type)\n        {\n            /*\n            RequestFuncType = std::function<void(\n                ServiceType *, ::grpc::ServerContext *,\n                ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>*,\n                ::grpc::CompletionQueue *, ::grpc::ServerCompletionQueue *, void *)>\n        */\n            return std::bind(request_fn, service_type,\n                             std::placeholders::_1, // ServerContext*\n                             std::placeholders::_2, // AsyncReaderWriter<OutputType, InputType>\n                             std::placeholders::_3, // CQ\n                             std::placeholders::_4, // ServerCQ\n                             std::placeholders::_5  // Tag\n            );\n        }\n\n        static ExecutorQueueFuncType BindExecutorQueueFunc(ServiceQueueFuncType service_q_fn, ::grpc::ServerCompletionQueue* cq)\n        {\n            return std::bind(service_q_fn,\n                             std::placeholders::_1, // ServerContext*\n                             std::placeholders::_2, // AsyncReaderWriter<Response, Request> *\n                             cq, cq,\n                             std::placeholders::_3 // Tag\n            );\n        }\n    };\n\n    // Implementation\n    template <class Request, class Response>\n    LifeCycleStreaming<Request, Response>::LifeCycleStreaming()\n    : m_ReadStateContext(static_cast<IContext*>(this)),\n      m_WriteStateContext(static_cast<IContext*>(this)),\n      m_Reading(false),\n      m_Writing(false),\n      m_Finishing(false),\n      m_ReadsDone(false),\n      m_WritesDone(false),\n      m_ReadsFinished(false),\n      m_BlockFinish(false)\n    {\n        m_NextState                     = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n        m_ReadStateContext.m_NextState  = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n        m_WriteStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::Reset()\n    {\n        std::queue<RequestType>  empty_request_queue;\n        std::queue<ResponseType> empty_response_queue;\n        OnLifeCycleReset();\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            m_Reading       = false;\n            m_Writing       = false;\n            m_Finishing     = false;\n            m_ReadsDone     = false;\n            m_WritesDone    = false;\n            m_ReadsFinished = false;\n            m_RequestQueue.swap(empty_request_queue);\n            m_ResponseQueue.swap(empty_response_queue);\n            m_ServerStream.reset();\n            m_ExternalStream.reset();\n\n            m_NextState                     = &LifeCycleStreaming<RequestType, ResponseType>::StateInitializedDone;\n            m_ReadStateContext.m_NextState  = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n            m_WriteStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n\n            m_Status.reset();\n            m_Context.reset(new ::grpc::ServerContext);\n            m_Stream.reset(new ::grpc_impl::ServerAsyncReaderWriter<ResponseType, RequestType>(m_Context.get()));\n        }\n        m_QueuingFunc(m_Context.get(), m_Stream.get(), IContext::Tag());\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::RunNextState(bool ok)\n    {\n        return (this->*m_NextState)(ok);\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::RunNextState(bool (LifeCycleStreaming<Request, Response>::*state_fn)(bool), bool ok)\n    {\n        return (this->*state_fn)(ok);\n    }\n\n    template <class Request, class Response>\n    typename LifeCycleStreaming<Request, Response>::Actions LifeCycleStreaming<Request, Response>::EvaluateState()\n    {\n        ReadHandle    should_read    = false;\n        WriteHandle   should_write   = false;\n        ExecuteHandle should_execute = nullptr;\n        FinishHandle  should_finish  = false;\n\n        if (!m_Reading && !m_ReadsDone)\n        {\n            should_read = true;\n            m_Reading   = true;\n            m_RequestQueue.emplace();\n            m_ReadStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateReadDone;\n\n            should_execute = [this, request = std::move(m_RequestQueue.front()), stream = m_ServerStream]() mutable {\n                RequestReceived(std::move(request), stream);\n            };\n            m_RequestQueue.pop();\n        }\n\n        if (!m_Reading && m_ReadsDone && !m_ReadsFinished && !(m_Status || m_ExternalStream.expired()))\n        {\n            DCHECK_NOTNULL(m_ServerStream);\n            m_ReadsFinished = true;\n            should_execute  = [this, stream = m_ServerStream]() mutable {\n                DVLOG(1) << \"Client sent WritesDone\";\n                RequestsFinished(stream);\n            };\n            // we will never hand m_ServerStream to another handler\n            // it is safe for the context to decrement the refcount\n            // the ServerStream will Cancel the Stream if it is still\n            // valid on deconstruction\n            m_ServerStream.reset();\n        }\n\n        if (m_Status && !m_Status->ok())\n        {\n            DVLOG(1) << \"Stream was CANCELLED by Server - Cancel All Callbacks\";\n            should_execute = nullptr;\n        }\n\n        if (!m_Writing && !m_ResponseQueue.empty())\n        {\n            should_write                    = true;\n            m_Writing                       = true;\n            m_WriteStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateWriteDone;\n        }\n\n        if (!m_Reading && !m_Writing && !m_Finishing && m_Status && !m_BlockFinish)\n        {\n            should_finish = true;\n            m_Finishing   = true;\n            m_NextState   = &LifeCycleStreaming<RequestType, ResponseType>::StateFinishedDone;\n        }\n        // clang-format off\n    DVLOG(1) << (should_read ? 1 : 0) << (should_write ? 1 : 0) << (should_execute ? 1 : 0)\n               << (should_finish ? 1 : 0) \n               << \" -- \" << m_Reading << m_Writing \n               << \" -- \" << m_ReadsDone << m_ReadsFinished << (m_Status ? 1 : 0) << (m_ExternalStream.expired() ? 1 : 0)\n               << \" -- \" << m_Finishing;\n        // clang-format on\n\n        return std::make_tuple(should_read, should_write, should_execute, should_finish);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::ForwardProgress(Actions& actions)\n    {\n        ReadHandle    should_read    = std::get<0>(actions);\n        WriteHandle   should_write   = std::get<1>(actions);\n        ExecuteHandle should_execute = std::get<2>(actions);\n        FinishHandle  should_finish  = std::get<3>(actions);\n\n        if (should_write)\n        {\n            DVLOG(1) << \"Writing Response\";\n            m_Stream->Write(m_ResponseQueue.front(), m_WriteStateContext.IContext::Tag());\n        }\n        if (should_execute)\n        {\n            DVLOG(1) << \"Kicking off Execution\";\n            should_execute();\n        }\n        // moved to after should_execute; this allows the m_ReadCallback method\n        // to update the state of the context without contending with another\n        // potential m_ReadCallback call should the Read have been posted\n        if (should_read)\n        {\n            DVLOG(1) << \"Posting Read/Recv\";\n            m_Stream->Read(&m_RequestQueue.back(), m_ReadStateContext.IContext::Tag());\n        }\n        if (should_finish)\n        {\n            DVLOG(1) << \"Closing Stream - \" << (m_Status->ok() ? \"OK\" : \"CANCELLED\");\n            m_Stream->Finish(*m_Status, IContext::Tag());\n        }\n    }\n\n    // The following are a set of functions used as function pointers\n    // to keep track of the state of the context.\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::StateInitializedDone(bool ok)\n    {\n        if (!ok)\n        {\n            DVLOG(2) << \"Stream Initialization Failed - Server Shutting Down\";\n            return false;\n        }\n\n        OnLifeCycleStart();\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"Initialize Stream\";\n\n            m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n\n            // Object that allows the server to response on the stream\n            // new ServerStream<RequestType, ResponseType>(this), [this](auto ptr) mutable {\n            m_ServerStream   = std::shared_ptr<ServerStream>(new ServerStream(this), [this](auto ptr) mutable {\n                // Custom Deleter - may trigger stream closing\n                Actions actions;\n                {\n                    std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n                    DVLOG(1) << \"All ServerStream objects have been deleted\";\n                    actions = this->EvaluateState();\n                };\n                this->ForwardProgress(actions);\n                delete ptr;\n            });\n            m_ExternalStream = m_ServerStream;\n            StreamInitialized(m_ServerStream);\n\n            // Start reading once connection is created - State\n            m_Reading = true;\n            m_RequestQueue.emplace();\n            m_ReadStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateReadDone;\n        }\n\n        // Start reading once connection is created - Action\n        m_Stream->Read(&m_RequestQueue.back(), m_ReadStateContext.IContext::Tag());\n        return true;\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::StateReadDone(bool ok)\n    {\n        Actions actions;\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"ReadDone Event: \" << (ok ? \"OK\" : \"NOT OK\");\n\n            m_Reading = false;\n\n            if (!ok)\n            {\n                {\n                    // Client called WritesDone\n                    DVLOG(1) << \"WritesDone received from Client; closing Server Reads\";\n                    m_ReadsDone = true;\n                    m_RequestQueue.pop();\n                    m_ReadStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n                }\n            }\n\n            actions = EvaluateState();\n        }\n        ForwardProgress(actions);\n        return true;\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::StateWriteDone(bool ok)\n    {\n        // If write didn't go through, then the call is dead. Start reseting\n        DCHECK(m_ResponseQueue.size());\n\n        Actions actions;\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"WriteDone Event: \" << (ok ? \"OK\" : \"NOT OK\");\n\n            m_Writing = false;\n\n            if (!ok)\n            {\n                DVLOG(1) << \"Write Response failed on Stream; Client may have Cancelled\";\n                CancelResponse();\n            }\n            else\n            {\n                // todo: add a CallbackOnResponseSent\n                m_ResponseQueue.pop();\n                m_WriteStateContext.m_NextState = &LifeCycleStreaming<RequestType, ResponseType>::StateInvalid;\n            }\n\n            actions = EvaluateState();\n        }\n        ForwardProgress(actions);\n        return true;\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::StateFinishedDone(bool ok)\n    {\n        DVLOG(1) << \"Server closed Write stream - FinishedDone - \" << (ok ? \"OK\" : \"CANCELLED\");\n        // Clear the m_ServerStream since we will not be launching any new tasks\n        // m_ExternalStream holds a weak_ptr to the original m_ServerStream so we\n        // can track when the last external reference was released.\n        m_ServerStream.reset();\n        if (!m_ExternalStream.expired())\n        {\n            auto sp = m_ExternalStream.lock();\n            sp->Invalidate();\n        }\n        return false;\n    }\n\n    template <class Request, class Response>\n    bool LifeCycleStreaming<Request, Response>::StateInvalid(bool ok)\n    {\n        throw std::runtime_error(\"invalid state\");\n        return false;\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::FinishResponse()\n    {\n        CloseStream(::grpc::Status::OK);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::CancelResponse()\n    {\n        CloseStream(::grpc::Status::CANCELLED);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::BlockFinish()\n    {\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"Setting BlockFinish to true; UnblockFinish must be called for RPC to complete\";\n            m_BlockFinish = true;\n        }\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::UnblockFinish()\n    {\n        Actions actions;\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"Setting BlockFinish to false - this will also trigger a step thru the progress engine\";\n            m_BlockFinish = false;\n        }\n        ForwardProgress(actions);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::WriteResponse(Response&& response)\n    {\n        Actions actions;\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"Queuing Response\";\n\n            m_ResponseQueue.push(std::move(response));\n            actions = EvaluateState();\n        }\n        ForwardProgress(actions);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::CloseStream(::grpc::Status status)\n    {\n        Actions actions;\n        {\n            std::lock_guard<std::recursive_mutex> lock(m_QueueMutex);\n            DVLOG(1) << \"Queue Close Stream: \" << (status.ok() ? \"OK\" : \"NOT OK\");\n\n            m_WritesDone = true;\n            m_Status     = std::make_unique<::grpc::Status>(status);\n\n            if (!m_ReadsDone)\n            {\n                DVLOG(1) << \"Server Canceling before Client WritesDone; issue TryCancel() to flush Read Tags\";\n                m_ResponseQueue = std::queue<Response>();\n                m_Context->TryCancel();\n            }\n\n            actions = EvaluateState();\n        }\n        ForwardProgress(actions);\n    }\n\n    template <class Request, class Response>\n    void LifeCycleStreaming<Request, Response>::SetQueueFunc(ExecutorQueueFuncType queue_fn)\n    {\n        m_QueuingFunc = queue_fn;\n    }\n\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/life_cycle_unary.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include \"nvrpc/interfaces.h\"\n\nnamespace nvrpc {\n\ntemplate<class Request, class Response>\nclass LifeCycleUnary : public IContextLifeCycle\n{\n  public:\n    using RequestType = Request;\n    using ResponseType = Response;\n    using ServiceQueueFuncType = std::function<void(\n        ::grpc::ServerContext*, RequestType*, ::grpc_impl::ServerAsyncResponseWriter<ResponseType>*,\n        ::grpc::CompletionQueue*, ::grpc::ServerCompletionQueue*, void*)>;\n    using ExecutorQueueFuncType =\n        std::function<void(::grpc::ServerContext*, RequestType*,\n                           ::grpc_impl::ServerAsyncResponseWriter<ResponseType>*, void*)>;\n\n    ~LifeCycleUnary() override {}\n\n  protected:\n    LifeCycleUnary() = default;\n    void SetQueueFunc(ExecutorQueueFuncType);\n\n    virtual void ExecuteRPC(RequestType& request, ResponseType& response) = 0;\n\n    void FinishResponse() final override;\n    void CancelResponse() final override;\n\n    bool CheckDeadlineAndShouldContinue();\n\n    const std::multimap<grpc::string_ref, grpc::string_ref>& ClientMetadata();\n\n  private:\n    // IContext Methods\n    bool RunNextState(bool ok) final override;\n    void Reset() final override;\n\n    // LifeCycleUnary Specific Methods\n    bool StateRequestDone(bool ok);\n    bool StateFinishedDone(bool ok);\n\n    // Function pointers\n    ExecutorQueueFuncType m_QueuingFunc;\n    bool (LifeCycleUnary<RequestType, ResponseType>::*m_NextState)(bool);\n\n    // Variables\n    std::unique_ptr<RequestType> m_Request;\n    std::unique_ptr<ResponseType> m_Response;\n    std::unique_ptr<::grpc::ServerContext> m_Context;\n    std::unique_ptr<::grpc_impl::ServerAsyncResponseWriter<ResponseType>> m_ResponseWriter;\n\n  public:\n    template<class RequestFuncType, class ServiceType>\n    static ServiceQueueFuncType BindServiceQueueFunc(\n        /*\n        std::function<void(\n            ServiceType *, ::grpc::ServerContext *, RequestType *,\n            ::grpc_impl::ServerAsyncResponseWriter<ResponseType> *,\n            ::grpc::CompletionQueue *, ::grpc::ServerCompletionQueue *, void *)>\n        */\n        RequestFuncType request_fn, ServiceType* service_type)\n    {\n        return std::bind(request_fn, service_type,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // InputType\n                         std::placeholders::_3, // AsyncResponseWriter<OutputType>\n                         std::placeholders::_4, // CQ\n                         std::placeholders::_5, // ServerCQ\n                         std::placeholders::_6 // Tag\n        );\n    }\n\n    static ExecutorQueueFuncType BindExecutorQueueFunc(ServiceQueueFuncType service_q_fn,\n                                                       ::grpc::ServerCompletionQueue* cq)\n    {\n        return std::bind(service_q_fn,\n                         std::placeholders::_1, // ServerContext*\n                         std::placeholders::_2, // Request *\n                         std::placeholders::_3, // AsyncResponseWriter<Response> *\n                         cq, cq,\n                         std::placeholders::_4 // Tag\n        );\n    }\n};\n\n// Implementation\n\ntemplate<class Request, class Response>\nbool LifeCycleUnary<Request, Response>::RunNextState(bool ok)\n{\n    return (this->*m_NextState)(ok);\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleUnary<Request, Response>::Reset()\n{\n    OnLifeCycleReset();\n    m_Request.reset(new Request);\n    m_Response.reset(new Response);\n    m_Context.reset(new ::grpc::ServerContext);\n    m_ResponseWriter.reset(new ::grpc_impl::ServerAsyncResponseWriter<ResponseType>(m_Context.get()));\n    m_NextState = &LifeCycleUnary<RequestType, ResponseType>::StateRequestDone;\n    m_QueuingFunc(m_Context.get(), m_Request.get(), m_ResponseWriter.get(), IContext::Tag());\n}\n\ntemplate<class Request, class Response>\nconst std::multimap<grpc::string_ref, grpc::string_ref>&\n    LifeCycleUnary<Request, Response>::ClientMetadata()\n{\n    return m_Context->client_metadata();\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleUnary<Request, Response>::CheckDeadlineAndShouldContinue()\n{\n    // this segfaults\n    // todo: work on the check deadline feature\n    /*\n    if(m_Context->IsCancelled())\n    {\n        CancelResponse();\n        return false;\n    }\n    */\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleUnary<Request, Response>::StateRequestDone(bool ok)\n{\n    if(!ok)\n    {\n        return false;\n    }\n    OnLifeCycleStart();\n    if(CheckDeadlineAndShouldContinue())\n    {\n        ExecuteRPC(*m_Request, *m_Response);\n    }\n    return true;\n}\n\ntemplate<class Request, class Response>\nbool LifeCycleUnary<Request, Response>::StateFinishedDone(bool ok)\n{\n    return false;\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleUnary<Request, Response>::FinishResponse()\n{\n    m_NextState = &LifeCycleUnary<RequestType, ResponseType>::StateFinishedDone;\n    m_ResponseWriter->Finish(*m_Response, ::grpc::Status::OK, IContext::Tag());\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleUnary<Request, Response>::CancelResponse()\n{\n    m_NextState = &LifeCycleUnary<RequestType, ResponseType>::StateFinishedDone;\n    m_ResponseWriter->Finish(*m_Response, ::grpc::Status::CANCELLED, IContext::Tag());\n}\n\ntemplate<class Request, class Response>\nvoid LifeCycleUnary<Request, Response>::SetQueueFunc(ExecutorQueueFuncType queue_fn)\n{\n    m_QueuingFunc = queue_fn;\n}\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/rpc.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef NVIS_RPC_H_\n#define NVIS_RPC_H_\n\n#include \"nvrpc/context.h\"\n#include \"trtlab/core/resources.h\"\n\nnamespace nvrpc {\n\ntemplate<class ContextType, class ServiceType>\nclass AsyncRPC : public IRPC\n{\n  public:\n    using ContextType_t = ContextType;\n    using ServiceQueueFuncType = typename ContextType::LifeCycleType::ServiceQueueFuncType;\n    using ExecutorQueueFuncType = typename ContextType::LifeCycleType::ExecutorQueueFuncType;\n\n    AsyncRPC(ServiceQueueFuncType);\n    ~AsyncRPC() override {}\n\n  protected:\n    std::unique_ptr<IContext> CreateContext(::grpc::ServerCompletionQueue*,\n                                            std::shared_ptr<::trtlab::Resources>) final override;\n\n  private:\n    ServiceQueueFuncType m_RequestFunc;\n};\n\ntemplate<class ContextType, class ServiceType>\nAsyncRPC<ContextType, ServiceType>::AsyncRPC(ServiceQueueFuncType req_fn) : m_RequestFunc(req_fn)\n{\n}\n\ntemplate<class ContextType, class ServiceType>\nstd::unique_ptr<IContext>\n    AsyncRPC<ContextType, ServiceType>::CreateContext(::grpc::ServerCompletionQueue* cq,\n                                                      std::shared_ptr<::trtlab::Resources> r)\n{\n    auto ctx_resources =\n        std::dynamic_pointer_cast<typename ContextType::ResourcesType::element_type>(r);\n    if(!ctx_resources)\n    {\n        throw std::runtime_error(\"Incompatible Resource object\");\n    }\n    auto q_fn = ContextType::LifeCycleType::BindExecutorQueueFunc(m_RequestFunc, cq);\n    std::unique_ptr<IContext> ctx = ContextFactory<ContextType>(q_fn, ctx_resources);\n    return ctx;\n}\n\n} // namespace nvrpc\n\n#endif // NVIS_RPC_H_\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/server.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef NVIS_SERVER_H_\n#define NVIS_SERVER_H_\n#pragma once\n\n#include <chrono>\n#include <condition_variable>\n\n#include \"nvrpc/service.h\"\n\nnamespace nvrpc {\n\nusing std::chrono::milliseconds;\n\nclass Server\n{\n  public:\n    Server(std::string server_address);\n\n    Server() : Server(\"0.0.0.0:50051\") {}\n\n    template<class ServiceType>\n    AsyncService<typename ServiceType::AsyncService>* RegisterAsyncService();\n\n    IExecutor* RegisterExecutor(IExecutor* executor)\n    {\n        m_Executors.emplace_back(executor);\n        executor->Initialize(m_Builder);\n        return executor;\n    }\n\n    void Run();\n    void Run(milliseconds timeout, std::function<void()> control_fn);\n    void AsyncStart();\n    void Shutdown();\n\n    bool Running();\n\n    ::grpc::ServerBuilder& Builder();\n\n  private:\n    bool m_Running;\n    std::mutex m_Mutex;\n    std::condition_variable m_Condition;\n    std::string m_ServerAddress;\n    ::grpc::ServerBuilder m_Builder;\n    std::unique_ptr<::grpc::Server> m_Server;\n    std::vector<std::unique_ptr<IService>> m_Services;\n    std::vector<std::unique_ptr<IExecutor>> m_Executors;\n};\n\ntemplate<class ServiceType>\nAsyncService<typename ServiceType::AsyncService>* Server::RegisterAsyncService()\n{\n    if(m_Running)\n    {\n        throw std::runtime_error(\"Error: cannot register service on a running server\");\n    }\n    auto service = new AsyncService<typename ServiceType::AsyncService>;\n    auto base = static_cast<IService*>(service);\n    m_Services.emplace_back(base);\n    service->Initialize(m_Builder);\n    return service;\n}\n\n} // namespace nvrpc\n\n#endif // NVIS_SERVER_H_\n"
  },
  {
    "path": "trtlab/nvrpc/include/nvrpc/service.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/interfaces.h\"\n#include \"nvrpc/rpc.h\"\n\nnamespace nvrpc {\n\ntemplate<class ServiceType>\nclass AsyncService : public IService\n{\n  public:\n    using ServiceType_t = ServiceType;\n\n    AsyncService() : IService(), m_Service(std::make_unique<ServiceType>()) {}\n    ~AsyncService() override {}\n\n    void Initialize(::grpc::ServerBuilder& builder) final override\n    {\n        builder.RegisterService(m_Service.get());\n    }\n\n    template<typename ContextType, typename RequestFuncType>\n    IRPC* RegisterRPC(RequestFuncType req_fn)\n    {\n        auto q_fn = ContextType::LifeCycleType::BindServiceQueueFunc(req_fn, m_Service.get());\n        auto rpc = new AsyncRPC<ContextType, ServiceType>(q_fn);\n        auto base = static_cast<IRPC*>(rpc);\n        m_RPCs.emplace_back(base);\n        return base;\n    }\n\n  private:\n    std::unique_ptr<ServiceType> m_Service;\n    std::vector<std::unique_ptr<IRPC>> m_RPCs;\n};\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/src/client/client_executor.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"nvrpc/client/executor.h\"\n#include \"nvrpc/client/base_context.h\"\n\n#include <glog/logging.h>\n\nusing trtlab::ThreadPool;\n\nnamespace nvrpc {\nnamespace client {\n\nExecutor::Executor() : Executor(1) {}\n\nExecutor::Executor(int numThreads) : Executor(std::make_unique<ThreadPool>(numThreads)) {}\n\nExecutor::Executor(std::unique_ptr<ThreadPool> threadpool) : m_ThreadPool(std::move(threadpool)), m_Counter(0)\n{\n    // for(decltype(m_ThreadPool->Size()) i = 0; i < m_ThreadPool->Size(); i++)\n    for(auto i = 0; i < m_ThreadPool->Size(); i++)\n    {\n        DVLOG(1) << \"Starting Client Progress Engine #\" << i;\n        m_CQs.emplace_back(new ::grpc::CompletionQueue);\n        auto cq = m_CQs.back().get();\n        m_ThreadPool->enqueue([this, cq] { ProgressEngine(*cq); });\n    }\n}\n\nExecutor::~Executor() { ShutdownAndJoin(); }\n\nvoid Executor::ShutdownAndJoin()\n{\n    for(auto& cq : m_CQs)\n    {\n        cq->Shutdown();\n    }\n    m_ThreadPool.reset();\n}\n\nvoid Executor::ProgressEngine(::grpc::CompletionQueue& cq)\n{\n    void* tag;\n    bool ok = false;\n\n    while(cq.Next(&tag, &ok))\n    {\n        // CHECK(ok);\n        BaseContext* ctx = BaseContext::Detag(tag);\n        DVLOG(3) << \"executor issuing callback\";\n        auto should_delete = ctx->ExecutorShouldDeleteContext();\n        if(!ctx->RunNextState(ok))\n        {\n            if(should_delete)\n            {\n                DVLOG(1) << \"Deleting ClientContext: \" << tag;\n                delete ctx;\n            }\n        }\n        DVLOG(3) << \"executor callback complete\";\n    }\n}\n\n::grpc::CompletionQueue* Executor::GetNextCQ() const\n{\n    std::size_t idx = 0;\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        DCHECK_LT(m_Counter, m_ThreadPool->Size());\n        if(++m_Counter == m_ThreadPool->Size()) { m_Counter = 0; }\n        idx = m_Counter;\n    }\n    return m_CQs[idx].get();\n}\n\n} // namespace client\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/src/executor.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"nvrpc/executor.h\"\n\n#include <glog/logging.h>\n\n#include <grpc/support/time.h>\n#include <grpcpp/support/time.h>\n\nusing trtlab::ThreadPool;\n\nnamespace nvrpc {\n\nExecutor::Executor() : Executor(1) {}\n\nExecutor::Executor(int numThreads) : Executor(std::make_unique<ThreadPool>(numThreads)) {}\n\nExecutor::Executor(std::unique_ptr<ThreadPool> threadpool)\n    : IExecutor(), m_ThreadPool(std::move(threadpool)), m_Running(false)\n{\n    m_TimeoutCallback = [] {};\n}\n\nvoid Executor::ProgressEngine(int thread_id)\n{\n    bool ok;\n    void* tag;\n    auto myCQ = m_ServerCompletionQueues[thread_id].get();\n    using NextStatus = ::grpc::ServerCompletionQueue::NextStatus;\n    m_Running = true;\n\n    while(myCQ->Next(&tag, &ok))\n    {\n        auto ctx = IContext::Detag(tag);\n        if(!RunContext(ctx, ok))\n        {\n            if(m_Running)\n            {\n                ResetContext(ctx);\n            }\n        }\n    }\n}\n\nvoid Executor::SetTimeout(time_point deadline, std::function<void()> callback)\n{\n    m_TimeoutDeadline = deadline;\n    m_TimeoutCallback = callback;\n}\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/src/server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"nvrpc/server.h\"\n\n#include <csignal>\n#include <thread>\n\n#include <glog/logging.h>\n\nnamespace {\nstd::function<void(int)> shutdown_handler;\nvoid signal_handler(int signal) { shutdown_handler(signal); }\n} // namespace\n\nnamespace nvrpc {\n\nServer::Server(std::string server_address) : m_ServerAddress(server_address), m_Running(false)\n{\n    VLOG(1) << \"gRPC will listening on: \" << m_ServerAddress;\n    m_Builder.AddListeningPort(m_ServerAddress, ::grpc::InsecureServerCredentials());\n}\n\n::grpc::ServerBuilder& Server::Builder()\n{\n    LOG_IF(FATAL, m_Running) << \"Unable to access Builder after the Server is running.\";\n    return m_Builder;\n}\n\nvoid Server::Run()\n{\n    Run(std::chrono::milliseconds(1000), [] {});\n}\n\nvoid Server::Run(std::chrono::milliseconds timeout, std::function<void()> control_fn)\n{\n    AsyncStart();\n    while(m_Running)\n    {\n        {\n            std::unique_lock<std::mutex> lock(m_Mutex);\n            if(m_Condition.wait_for(lock, timeout, [this] { return !m_Running; }))\n            {\n                // if not running\n                m_Condition.notify_all();\n                DLOG(INFO) << \"Server::Run exitting\";\n                return;\n            }\n            else\n            {\n                // if running\n                // DLOG(INFO) << \"Server::Run executing user lambda\";\n                control_fn();\n            }\n        }\n    }\n}\n\nvoid Server::AsyncStart()\n{\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        CHECK_EQ(m_Running, false) << \"Server is already running\";\n        m_Server = m_Builder.BuildAndStart();\n\n        shutdown_handler = [this](int signal) {\n            LOG(INFO) << \"Trapped Signal: \" << signal;\n            Shutdown();\n        };\n        std::signal(SIGINT, signal_handler);\n\n        for(int i = 0; i < m_Executors.size(); i++)\n        {\n            m_Executors[i]->Run();\n        }\n        m_Running = true;\n    }\n    m_Condition.notify_all();\n    LOG(INFO) << \"grpc server and event loop initialized and accepting connections\";\n}\n\nvoid Server::Shutdown()\n{\n    LOG(INFO) << \"Shutdown Requested\";\n    CHECK(m_Server);\n    {\n        std::lock_guard<std::mutex> lock(m_Mutex);\n        m_Server->Shutdown();\n        for(auto& executor : m_Executors)\n        {\n            executor->Shutdown();\n        }\n        m_Running = false;\n    }\n    m_Condition.notify_all();\n}\n\nbool Server::Running()\n{\n    std::lock_guard<std::mutex> lock(m_Mutex);\n    return m_Running;\n}\n\n} // namespace nvrpc\n"
  },
  {
    "path": "trtlab/nvrpc/tests/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfind_package(GTest)\nset(protobuf_MODULE_COMPATIBLE TRUE)\nfind_package(Protobuf CONFIG REQUIRED)\nmessage(STATUS \"Using protobuf ${protobuf_VERSION}\")\nset(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)\nset(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)\n\nINCLUDE(GRPCGenerateCPP)\n\nPROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS \n    testing.proto\n)\n\nPROTOBUF_GENERATE_GRPC_CPP(PROTO_GRPC_SRCS PROTO_GRPC_HDRS \n    testing.proto\n)\n\nadd_library(nvrpc-testing-protos\n    ${PROTO_SRCS}\n    ${PROTO_GRPC_SRCS}\n)\n\ntarget_link_libraries(nvrpc-testing-protos\n  PUBLIC\n  ${_PROTOBUF_LIBPROTOBUF}\n)\n\ntarget_include_directories(nvrpc-testing-protos PUBLIC\n    ${CMAKE_CURRENT_BINARY_DIR}\n)\n\nset(LIBS nvrpc nvrpc-testing-protos)\n\nadd_executable(test_nvrpc\n  test_resources.cc\n  test_pingpong.cc\n  test_server.cc\n)\n\ntarget_link_libraries(test_nvrpc\n  PRIVATE \n    ${PROJECT_NAME}::core\n    nvrpc\n    nvrpc-client\n    nvrpc-testing-protos\n    GTest::gtest_main\n)\n\nadd_test(\n  NAME nvrpc\n  COMMAND $<TARGET_FILE:test_nvrpc\n)"
  },
  {
    "path": "trtlab/nvrpc/tests/test_build_client.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n\n#include \"nvrpc/client/client_streaming.h\"\n#include \"nvrpc/client/client_unary.h\"\n\n#include \"test_resources.h\"\n\n#include \"testing.grpc.pb.h\"\n#include \"testing.pb.h\"\n\nnamespace nvrpc {\nnamespace testing {\n\nstd::unique_ptr<client::ClientUnary<Input, Output>> BuildUnaryClient()\n{\n    auto executor = std::make_shared<client::Executor>(1);\n\n    auto channel = grpc::CreateChannel(\"localhost:13377\", grpc::InsecureChannelCredentials());\n    std::shared_ptr<TestService::Stub> stub = TestService::NewStub(channel);\n\n    auto infer_prepare_fn = [stub](::grpc::ClientContext * context, const Input& request,\n                                   ::grpc::CompletionQueue* cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncUnary(context, request, cq));\n    };\n\n    return std::make_unique<client::ClientUnary<Input, Output>>(infer_prepare_fn, executor);\n}\n\nstd::unique_ptr<client::ClientStreaming<Input, Output>>\n    BuildStreamingClient(std::function<void(Input&&)> on_sent,\n                         std::function<void(Output&&)> on_recv)\n{\n    auto executor = std::make_shared<client::Executor>(1);\n\n    auto channel = grpc::CreateChannel(\"localhost:13377\", grpc::InsecureChannelCredentials());\n    std::shared_ptr<TestService::Stub> stub = TestService::NewStub(channel);\n\n    auto infer_prepare_fn = [stub](::grpc::ClientContext * context,\n                                   ::grpc::CompletionQueue * cq) -> auto\n    {\n        return std::move(stub->PrepareAsyncStreaming(context, cq));\n    };\n\n    return std::make_unique<client::ClientStreaming<Input, Output>>(infer_prepare_fn, executor,\n                                                                    on_sent, on_recv);\n}\n\n} // namespace testing\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/tests/test_build_server.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n\n#include \"test_resources.h\"\n\n#include \"testing.grpc.pb.h\"\n#include \"testing.pb.h\"\n\nnamespace nvrpc {\nnamespace testing {\n\ntemplate<typename Context>\nstd::unique_ptr<Server> BuildServer();\n\ntemplate<typename T, typename ExecutorType = Executor>\nstd::unique_ptr<Server> BuildStreamingServer()\n{\n    auto server = std::make_unique<Server>(\"0.0.0.0:13377\");\n    auto resources = std::make_shared<TestResources>(3);\n    auto executor = server->RegisterExecutor(new ExecutorType(1));\n    auto service = server->RegisterAsyncService<TestService>();\n    auto rpc_streaming = service->RegisterRPC<T>(&TestService::AsyncService::RequestStreaming);\n    executor->RegisterContexts(rpc_streaming, resources, 10);\n    return std::move(server);\n}\n\ntemplate<typename UnaryContext, typename StreamingContext, typename ExecutorType = Executor>\nstd::unique_ptr<Server> BuildServer()\n{\n    auto server = std::make_unique<Server>(\"0.0.0.0:13377\");\n    auto resources = std::make_shared<TestResources>(3);\n    auto executor = server->RegisterExecutor(new ExecutorType(1));\n    auto service = server->RegisterAsyncService<TestService>();\n    auto rpc_unary = service->RegisterRPC<UnaryContext>(&TestService::AsyncService::RequestUnary);\n    auto rpc_streaming =\n        service->RegisterRPC<StreamingContext>(&TestService::AsyncService::RequestStreaming);\n    executor->RegisterContexts(rpc_unary, resources, 10);\n    executor->RegisterContexts(rpc_streaming, resources, 10);\n    return std::move(server);\n}\n\n} // namespace testing\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/tests/test_pingpong.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"test_pingpong.h\"\n\n#include \"nvrpc/server.h\"\n\n#include \"test_build_client.h\"\n#include \"test_build_server.h\"\n\n#include <nvrpc/fiber/executor.h>\n\n#include <gtest/gtest.h>\n\n#define PINGPONG_SEND_COUNT 10\n\nusing namespace nvrpc;\nusing namespace nvrpc::testing;\n\nvoid PingPongUnaryContext::ExecuteRPC(Input& input, Output& output)\n{\n    auto headers    = ClientMetadata();\n    auto model_name = headers.find(\"x-content-model\");\n    EXPECT_NE(model_name, headers.end());\n    EXPECT_EQ(model_name->second, \"flowers-152\");\n    output.set_batch_id(input.batch_id());\n    FinishResponse();\n}\n\nvoid PingPongStreamingContext::RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream)\n{\n    EXPECT_EQ(++m_Counter, input.batch_id());\n\n    EXPECT_NE(stream, nullptr);\n    Output output;\n    output.set_batch_id(input.batch_id());\n    stream->WriteResponse(std::move(output));\n}\n\nvoid PingPongStreamingContext::StreamInitialized(std::shared_ptr<ServerStream> stream)\n{\n    m_Counter = 0;\n}\n\n\n/**\n * @brief Server->Client stream closes with OK before Client->Server stream\n *\n * In this test, the Server closes its server->client stream with a call to FinishStream.  This\n * essentially says, \"me the server is happy with what it has gotten and this call was a success\".\n *\n * The server will continue to process incoming requests from the client, but will not be able to\n * send back responses.\n *\n * In the EarlyCancel test, we call CancelStream, which will also immediately stop and drain the\n * processing of incoming requests.\n */\nvoid PingPongStreamingEarlyFinishContext::RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream)\n{\n    //static size_t counter = 0;\n    //m_Counter             = ++counter;\n    m_Counter++;\n    EXPECT_EQ(m_Counter, input.batch_id());\n\n    if (stream && m_Counter > PINGPONG_SEND_COUNT / 2)\n    {\n        // We are closing the server->client portion of the stream early\n        EXPECT_NE(stream, nullptr);\n        stream->FinishStream();\n    }\n    if (!stream || !stream->IsConnected())\n    {\n        // Stream was closed\n        EXPECT_GT(m_Counter, PINGPONG_SEND_COUNT / 2);\n        return;\n    }\n\n    EXPECT_NE(stream, nullptr);\n    Output output;\n    output.set_batch_id(input.batch_id());\n    stream->WriteResponse(std::move(output));\n}\n\nvoid PingPongStreamingEarlyFinishContext::StreamInitialized(std::shared_ptr<ServerStream> stream)\n{\n    m_Counter = 0;\n}\n\nvoid PingPongStreamingEarlyFinishContext::RequestsFinished(std::shared_ptr<ServerStream> stream)\n{\n    // The Server should still receive all incoming requests until the client sends WritesDone\n    EXPECT_EQ(m_Counter, PINGPONG_SEND_COUNT);\n}\n\n/**\n * @brief Server->Client stream closes with CANCELLED before Client->Server stream\n *\n * In this test, the Server closes its server->client stream with a call to CancelStream.  This\n * essentially says, \"me the server is unhappy with what it has gotten and its time to shut down\"\n *\n * The server will stop processing incoming requests from the client and will not be able to\n * send back responses.\n */\nvoid PingPongStreamingEarlyCancelContext::RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream)\n{\n    // static size_t counter = 0;\n    // m_Counter             = ++counter;\n    m_Counter++;\n    EXPECT_EQ(m_Counter, input.batch_id());\n\n    if (stream && m_Counter > PINGPONG_SEND_COUNT / 2)\n    {\n        // We are closing the server->client portion of the stream early\n        EXPECT_NE(stream, nullptr);\n        stream->CancelStream();\n    }\n    if (!stream || !stream->IsConnected())\n    {\n        // Stream was closed\n        EXPECT_EQ(m_Counter, PINGPONG_SEND_COUNT / 2 + 1);\n        return;\n    }\n\n    EXPECT_NE(stream, nullptr);\n    Output output;\n    output.set_batch_id(input.batch_id());\n    stream->WriteResponse(std::move(output));\n}\n\nvoid PingPongStreamingEarlyCancelContext::StreamInitialized(std::shared_ptr<ServerStream> stream)\n{\n    m_Counter = 0;\n}\n\nvoid PingPongStreamingEarlyCancelContext::RequestsFinished(std::shared_ptr<ServerStream> stream)\n{\n    // The Server should still receive all incoming requests until the client sends WritesDone\n    EXPECT_EQ(m_Counter, PINGPONG_SEND_COUNT / 2);\n}\n\nclass PingPongTest : public ::testing::Test\n{\n    void SetUp() override {}\n\n    void TearDown() override\n    {\n        if (m_Server)\n        {\n            m_Server->Shutdown();\n            m_Server.reset();\n        }\n    }\n\nprotected:\n    std::unique_ptr<Server> m_Server;\n};\n\nTEST_F(PingPongTest, UnaryTest)\n{\n    m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingContext>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto client = BuildUnaryClient();\n\n    std::vector<std::shared_future<void>> futures;\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        std::map<std::string, std::string> headers = {{\"x-content-model\", \"flowers-152\"}};\n        futures.push_back(client->Enqueue(std::move(input),\n                                          [&mutex, &count, &recv_count, i](Input& input, Output& output, ::grpc::Status& status) {\n                                              EXPECT_EQ(output.batch_id(), i);\n                                              EXPECT_TRUE(status.ok());\n                                              std::lock_guard<std::mutex> lock(mutex);\n                                              --count;\n                                              ++recv_count;\n                                          },\n                                          headers));\n    }\n\n    for (auto& future : futures)\n    {\n        future.wait();\n    }\n\n    EXPECT_EQ(count, 0UL);\n    EXPECT_EQ(send_count, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}\n\nTEST_F(PingPongTest, FibersUnaryTest)\n{\n    // set up worker fiber pool\n    trtlab::ThreadPool                    workers(1);\n    bool                                  workers_running = true;\n    std::mutex                            workers_mutex;\n    boost::fibers::condition_variable_any workers_cv;\n    for (int i = 0; i < workers.Size(); i++)\n    {\n        workers.enqueue([&workers_mutex, &workers_cv, &workers_running] {\n            // start the fiber scheduler and put the main to deferred sleep\n            LOG(INFO) << \"fiber runner thread id: \" << std::this_thread::get_id();\n            boost::fibers::use_scheduling_algorithm<boost::fibers::algo::shared_work>();\n            std::unique_lock<std::mutex> lock(workers_mutex);\n            workers_cv.wait(lock, [&workers_running]() { return !workers_running; });\n        });\n    }\n\n    m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingContext, FiberExecutor>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto client = BuildUnaryClient();\n\n    std::vector<std::shared_future<void>> futures;\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        std::map<std::string, std::string> headers = {{\"x-content-model\", \"flowers-152\"}};\n        futures.push_back(client->Enqueue(std::move(input),\n                                          [&mutex, &count, &recv_count, i](Input& input, Output& output, ::grpc::Status& status) {\n                                              EXPECT_EQ(output.batch_id(), i);\n                                              EXPECT_TRUE(status.ok());\n                                              std::lock_guard<std::mutex> lock(mutex);\n                                              --count;\n                                              ++recv_count;\n                                          },\n                                          headers));\n    }\n\n    for (auto& future : futures)\n    {\n        future.wait();\n    }\n\n    EXPECT_EQ(count, 0UL);\n    EXPECT_EQ(send_count, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n\n    // shutdown worker fibers\n    std::unique_lock<std::mutex> lock(workers_mutex);\n    workers_running = false;\n    lock.unlock();\n    workers_cv.notify_all();\n}\n\nTEST_F(PingPongTest, StreamingTest)\n{\n    m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingContext>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto on_recv = [&mutex, &count, &recv_count](Output&& response) {\n        static size_t last = 0;\n        EXPECT_EQ(++last, response.batch_id());\n        std::lock_guard<std::mutex> lock(mutex);\n        --count;\n        ++recv_count;\n    };\n\n    auto stream = BuildStreamingClient([](Input&&) {}, on_recv);\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        EXPECT_TRUE(stream->Write(std::move(input)));\n    }\n\n    auto future = stream->Done();\n    auto status = future.get();\n\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(count, 0UL);\n    EXPECT_EQ(send_count, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}\n\nTEST_F(PingPongTest, FibersStreamingTest)\n{\n\n    // set up worker fiber pool\n    trtlab::ThreadPool                    workers(4);\n    bool                                  workers_running = true;\n    std::mutex                            workers_mutex;\n    boost::fibers::condition_variable_any workers_cv;\n    for (int i = 0; i < workers.Size(); i++)\n    {\n        workers.enqueue([&workers_mutex, &workers_cv, &workers_running] {\n            // start the fiber scheduler and put the main to deferred sleep\n            LOG(INFO) << \"fiber runner thread id: \" << std::this_thread::get_id();\n            boost::fibers::use_scheduling_algorithm<boost::fibers::algo::shared_work>();\n            std::unique_lock<std::mutex> lock(workers_mutex);\n            workers_cv.wait(lock, [&workers_running]() { return !workers_running; });\n        });\n    }\n\n    m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingContext, FiberExecutor>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto on_recv = [&mutex, &count, &recv_count](Output&& response) {\n        static size_t last = 0;\n        EXPECT_EQ(++last, response.batch_id());\n        std::lock_guard<std::mutex> lock(mutex);\n        --count;\n        ++recv_count;\n    };\n\n    auto stream = BuildStreamingClient([](Input&&) {}, on_recv);\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        EXPECT_TRUE(stream->Write(std::move(input)));\n    }\n\n    auto future = stream->Done();\n    auto status = future.get();\n\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(count, 0UL);\n    EXPECT_EQ(send_count, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n\n    // shutdown worker fibers\n    std::unique_lock<std::mutex> lock(workers_mutex);\n    workers_running = false;\n    lock.unlock();\n    workers_cv.notify_all();\n}\n\nTEST_F(PingPongTest, ServerEarlyFinish)\n{\n    m_Server = BuildStreamingServer<PingPongStreamingEarlyFinishContext>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto on_recv = [&mutex, &count, &recv_count](Output&& response) {\n        static size_t last = 0;\n        EXPECT_EQ(++last, response.batch_id());\n        std::lock_guard<std::mutex> lock(mutex);\n        --count;\n        ++recv_count;\n    };\n\n    auto stream = BuildStreamingClient([](Input&&) {}, on_recv);\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        EXPECT_TRUE(stream->Write(std::move(input)));\n    }\n\n    auto future = stream->Done();\n    auto status = future.get();\n\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(send_count / 2, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}\n\nTEST_F(PingPongTest, ServerEarlyCancel)\n{\n    m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingEarlyCancelContext>();\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n\n    std::mutex  mutex;\n    std::size_t count      = 0;\n    std::size_t recv_count = 0;\n    std::size_t send_count = PINGPONG_SEND_COUNT;\n\n    auto on_recv = [&mutex, &count, &recv_count](Output&& response) {\n        static size_t last = 0;\n        EXPECT_EQ(++last, response.batch_id());\n        std::lock_guard<std::mutex> lock(mutex);\n        --count;\n        ++recv_count;\n    };\n\n    auto stream = BuildStreamingClient([](Input&&) {}, on_recv);\n\n    for (int i = 1; i <= send_count; i++)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            ++count;\n        }\n        Input input;\n        input.set_batch_id(i);\n        EXPECT_TRUE(stream->Write(std::move(input)));\n    }\n\n    auto future = stream->Done();\n    auto status = future.get();\n\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(send_count / 2, recv_count);\n    EXPECT_TRUE(m_Server->Running());\n\n    // We need a sleep here - The Server's TryCancel() seems to\n    // issue an OOB CANCELLED such that the Client receives the\n    // status before the server actually flushes and shuts down.\n    // This is expected behavior on gRPC cancelling.\n    // The wait allows the server to complete it's testing\n    // Since Client and Server are in the same process, we could\n    // use a mutex+condition to synchronize this event. Anyone?\n    std::this_thread::sleep_for(std::chrono::seconds(1));\n\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}\n"
  },
  {
    "path": "trtlab/nvrpc/tests/test_pingpong.h",
    "content": "\n\n/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"nvrpc/context.h\"\n\n#include \"test_resources.h\"\n\n#include \"testing.grpc.pb.h\"\n#include \"testing.pb.h\"\n\nnamespace nvrpc {\nnamespace testing {\n\nclass PingPongUnaryContext final : public Context<Input, Output, TestResources>\n{\n    void ExecuteRPC(Input& input, Output& output) final override;\n};\n\nclass PingPongStreamingContext final : public StreamingContext<Input, Output, TestResources>\n{\n    void RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream) final override;\n    void StreamInitialized(std::shared_ptr<ServerStream>) final override;\n\n    std::size_t m_Counter;\n};\n\nclass PingPongStreamingEarlyFinishContext final\n    : public StreamingContext<Input, Output, TestResources>\n{\n    void RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream) final override;\n    void RequestsFinished(std::shared_ptr<ServerStream>) final override;\n    void StreamInitialized(std::shared_ptr<ServerStream>) final override;\n\n    std::size_t m_Counter;\n};\n\nclass PingPongStreamingEarlyCancelContext final\n    : public StreamingContext<Input, Output, TestResources>\n{\n    void RequestReceived(Input&& input, std::shared_ptr<ServerStream> stream) final override;\n    void RequestsFinished(std::shared_ptr<ServerStream>) final override;\n    void StreamInitialized(std::shared_ptr<ServerStream>) final override;\n\n    std::size_t m_Counter;\n};\n} // namespace testing\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/tests/test_resources.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"test_resources.h\"\n\nnamespace nvrpc {\nnamespace testing {\n\nTestResources::TestResources(int numThreadsInPool) : m_ThreadPool(numThreadsInPool) {}\n\n::trtlab::ThreadPool& TestResources::AcquireThreadPool() { return m_ThreadPool; }\n\nvoid TestResources::StreamManagerInit()\n{\n    std::lock_guard<std::mutex> lock(m_MessageMutex);\n    m_Running = true;\n    m_ThreadPool.enqueue([this]() mutable { StreamManagerWorker(); });\n}\n\nvoid TestResources::StreamManagerFini()\n{\n    std::lock_guard<std::mutex> lock(m_MessageMutex);\n    m_Running = false;\n}\n\nvoid TestResources::StreamManagerWorker()\n{\n    while(m_Running)\n    {\n        {\n            std::lock_guard<std::mutex> lock(m_MessageMutex);\n            for(auto& item : m_Streams)\n            {\n                LOG_FIRST_N(INFO, 10) << \"Progress Engine\";\n                auto stream_id = item.first;\n                auto& stream = item.second;\n\n                for(size_t i = m_MessagesSent[stream_id] + 1; i <= m_MessagesRecv[stream_id]; i++)\n                {\n                    DLOG(INFO) << \"Writing: \" << i;\n                    Output output;\n                    output.set_batch_id(i);\n                    stream->WriteResponse(std::move(output));\n                }\n\n                m_MessagesSent[stream_id] = m_MessagesRecv[stream_id];\n            }\n        }\n        std::this_thread::sleep_for(std::chrono::microseconds(100));\n    }\n}\n\nvoid TestResources::CloseStream(Stream stream)\n{\n    std::lock_guard<std::mutex> lock(m_MessageMutex);\n    auto stream_id = stream->StreamID();\n\n    m_Streams.erase(stream_id);\n    m_MessagesRecv.erase(stream_id);\n    m_MessagesSent.erase(stream_id);\n\n    DLOG(INFO) << \"****** Client Closed ****** \";\n    stream->FinishStream();\n}\n\nvoid TestResources::IncrementStreamCount(Stream stream)\n{\n    std::lock_guard<std::mutex> lock(m_MessageMutex);\n    auto stream_id = stream->StreamID();\n    auto search = m_Streams.find(stream_id);\n    if(search == m_Streams.end())\n    {\n        m_Streams[stream_id] = stream;\n        m_MessagesRecv[stream_id] = 1;\n    }\n    else\n    {\n        m_MessagesRecv[stream_id]++;\n    }\n}\n\n} // namespace testing\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/tests/test_resources.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"trtlab/core/resources.h\"\n#include \"trtlab/core/thread_pool.h\"\n\n#include \"nvrpc/life_cycle_streaming.h\"\n\n#include \"testing.grpc.pb.h\"\n#include \"testing.pb.h\"\n\nnamespace nvrpc {\nnamespace testing {\n\nstruct TestResources : public ::trtlab::Resources\n{\n    TestResources(int numThreadsInPool = 3);\n\n    using Stream = std::shared_ptr<LifeCycleStreaming<Input, Output>::ServerStream>;\n    using StreamID = std::size_t;\n    using Counter = std::size_t;\n\n    ::trtlab::ThreadPool& AcquireThreadPool();\n\n    void StreamManagerInit();\n    void StreamManagerFini();\n    void StreamManagerWorker();\n\n    void IncrementStreamCount(Stream);\n    void CloseStream(Stream);\n\n  private:\n    ::trtlab::ThreadPool m_ThreadPool;\n\n    bool m_Running;\n    std::mutex m_MessageMutex;\n    std::map<StreamID, Stream> m_Streams;\n    std::map<StreamID, Counter> m_MessagesRecv;\n    std::map<StreamID, Counter> m_MessagesSent;\n\n    std::mutex m_ShutdownMutex;\n    bool m_ClientRunning;\n    bool m_ServerRunning;\n};\n\n} // namespace testing\n} // namespace nvrpc"
  },
  {
    "path": "trtlab/nvrpc/tests/test_server.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"test_build_server.h\"\n#include \"test_pingpong.h\"\n#include \"test_resources.h\"\n\n#include <gtest/gtest.h>\n\nusing namespace nvrpc;\nusing namespace nvrpc::testing;\n\nclass ServerTest : public ::testing::Test\n{\n    void SetUp() override\n    {\n        m_BackgroundThreads = std::make_unique<::trtlab::ThreadPool>(1);\n        m_Server = BuildServer<PingPongUnaryContext, PingPongStreamingContext>();\n    }\n\n    void TearDown() override\n    {\n        if(m_Server)\n        {\n            m_Server->Shutdown();\n            m_Server.reset();\n        }\n        m_BackgroundThreads.reset();\n    }\n\n  protected:\n    std::unique_ptr<Server> m_Server;\n    std::unique_ptr<::trtlab::ThreadPool> m_BackgroundThreads;\n};\n\nTEST_F(ServerTest, AsyncStartAndShutdown)\n{\n    EXPECT_FALSE(m_Server->Running());\n    m_Server->AsyncStart();\n    EXPECT_TRUE(m_Server->Running());\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}\n\nTEST_F(ServerTest, RunAndShutdown)\n{\n    bool running = false;\n    std::mutex mutex;\n    std::condition_variable condition;\n\n    EXPECT_FALSE(m_Server->Running());\n    m_BackgroundThreads->enqueue([&, this] {\n        m_Server->Run(std::chrono::milliseconds(1), [&] {\n            {\n                std::lock_guard<std::mutex> lock(mutex);\n                running = true;\n            }\n            condition.notify_all();\n        });\n    });\n    {\n        std::unique_lock<std::mutex> lock(mutex);\n        condition.wait(lock, [&running] { return running; });\n    }\n    EXPECT_TRUE(m_Server->Running());\n    m_Server->Shutdown();\n    EXPECT_FALSE(m_Server->Running());\n}"
  },
  {
    "path": "trtlab/nvrpc/tests/testing.proto",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n syntax = \"proto3\";\n\n package nvrpc.testing;\n \n service TestService {\n    rpc Unary (Input) returns (Output) {}\n    rpc Streaming (stream Input) returns (stream Output) {}\n }\n \n message SystemV {\n     uint64 shm_id = 1;\n     uint64 offset = 2;\n     uint64 size = 3;\n }\n \n message Input {\n     uint64 batch_id = 1;\n     oneof data {\n         bytes raw_bytes = 2;\n         SystemV sysv = 3;\n     }\n }\n \n message Output {\n     uint64 batch_id = 1;\n }\n \n "
  },
  {
    "path": "trtlab/pybind/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nadd_subdirectory(trtlab)\n"
  },
  {
    "path": "trtlab/pybind/trtlab/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\npybind11_add_module(trtlab \n  infer.cc\n  utils.cc\n)\n\ntarget_link_libraries(trtlab\n  PUBLIC\n    core\n    cuda\n    nvrpc\n    nvrpc-client\n    tensorrt\n    nv-inference-protos\n)\n\ntarget_include_directories(trtlab\n  PRIVATE\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>\n)\n\n##find_program(PYTHON \"python)\n##\n##if (PYTHON)\n##    set(SETUP_PY_IN \"${CMAKE_CURRENT_SOURCE_DIR}/setup.py\")\n##    set(SETUP_PY    \"${CMAKE_CURRENT_BINARY_DIR}/setup.py\")\n##    set(DEPS        \"${CMAKE_CURRENT_SOURCE_DIR}/trtlab/__init__.py\")\n##    set(OUTPUT      \"${CMAKE_CURRENT_BINARY_DIR}/build\")\n##\n##    configure_file(${SETUP_PY_IN} ${SETUP_PY})\n##\n##    add_custom_command(OUTPUT ${OUTPUT}\n##                       COMMAND ${PYTHON} ${SETUP_PY} build\n##                       DEPENDS ${DEPS} _trtlab_cpp)\n##\n##    add_custom_target(target ALL DEPENDS ${OUTPUT})\n##\n##    install(CODE \"execute_process(COMMAND ${PYTHON} ${SETUP_PY} bdist_wheel)\")\n##endif()\n"
  },
  {
    "path": "trtlab/pybind/trtlab/infer.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <pybind11/numpy.h>\n#include <pybind11/pybind11.h>\n#include <pybind11/stl.h>\n#include <pybind11/stl_bind.h>\n\nnamespace py = pybind11;\n\n#include <future>\n#include <memory>\n#include <string>\n\n#include <gflags/gflags.h>\n#include <glog/logging.h>\n\n#include \"tensorrt/laboratory/bindings.h\"\n#include \"tensorrt/laboratory/core/async_compute.h\"\n#include \"tensorrt/laboratory/core/thread_pool.h\"\n#include \"tensorrt/laboratory/infer_bench.h\"\n#include \"tensorrt/laboratory/infer_runner.h\"\n#include \"tensorrt/laboratory/inference_manager.h\"\n#include \"tensorrt/laboratory/model.h\"\n#include \"tensorrt/laboratory/runtime.h\"\n#include \"tensorrt/laboratory/utils.h\"\n\n#include \"utils.h\"\n\nusing namespace trtlab;\nusing namespace trtlab;\nusing namespace trtlab::TensorRT;\n\n#include \"nvrpc/context.h\"\n#include \"nvrpc/executor.h\"\n#include \"nvrpc/server.h\"\n#include \"nvrpc/service.h\"\n\n#include \"nvrpc/client/client_unary.h\"\n#include \"nvrpc/client/executor.h\"\n\nusing nvrpc::AsyncService;\nusing nvrpc::Context;\nusing nvrpc::Executor;\nusing nvrpc::Server;\n\n// NVIDIA Inference Server Protos\n#include \"nvidia_inference.grpc.pb.h\"\n#include \"nvidia_inference.pb.h\"\n\nnamespace trtis = ::nvidia::inferenceserver;\n\nvoid BasicInferService(std::shared_ptr<InferenceManager> resources, int port = 50052,\n                       const std::string& max_recv_msg_size = \"100MiB\");\n\nclass TrtisModel;\nclass PyInferRunner;\nclass PyInferRemoteRunner;\n\nclass PyInferenceManager final : public InferenceManager\n{\n  public:\n    PyInferenceManager(int max_executions, int max_buffers, int pre_threads, int cuda_threads,\n                       int post_threads)\n        : InferenceManager(max_executions, max_buffers)\n    {\n        RegisterThreadPool(\"pre\", std::make_unique<ThreadPool>(pre_threads));\n        RegisterThreadPool(\"cuda\", std::make_unique<ThreadPool>(cuda_threads));\n        RegisterThreadPool(\"post\", std::make_unique<ThreadPool>(post_threads));\n        RegisterRuntime(\"default\", std::make_shared<StandardRuntime>());\n        RegisterRuntime(\"unified\", std::make_shared<ManagedRuntime>());\n        SetActiveRuntime(\"default\");\n    }\n\n    ~PyInferenceManager() override {}\n\n    std::shared_ptr<PyInferRunner> RegisterModelByPath(const std::string& name,\n                                                       const std::string& path)\n    {\n        auto model = ActiveRuntime().DeserializeEngine(path);\n        RegisterModel(name, model);\n        return this->InferRunner(name);\n    }\n\n    std::shared_ptr<PyInferRunner> InferRunner(std::string name)\n    {\n        return std::make_shared<PyInferRunner>(GetModel(name),\n                                               casted_shared_from_this<PyInferenceManager>());\n    }\n\n    void Serve(int port) { BasicInferService(casted_shared_from_this<PyInferenceManager>(), port); }\n\n    std::vector<std::string> Models()\n    {\n        std::vector<std::string> model_names;\n        ForEachModel([&model_names](const Model& model) { model_names.push_back(model.Name()); });\n        return model_names;\n    }\n};\n\nclass PyRemoteInferenceManager\n{\n  public:\n    PyRemoteInferenceManager(py::kwargs kwargs)\n    {\n        m_Hostname = \"localhost:50052\";\n        int client_threads = 1;\n        for(const auto& item : kwargs)\n        {\n            auto key = py::cast<std::string>(item.first);\n            if(key == \"hostname\")\n            {\n                m_Hostname = py::cast<std::string>(item.second);\n            }\n        }\n\n        ::grpc::ChannelArguments ch_args;\n        ch_args.SetMaxReceiveMessageSize(-1);\n        m_Channel =\n            grpc::CreateCustomChannel(m_Hostname, grpc::InsecureChannelCredentials(), ch_args);\n        m_Stub = ::trtis::GRPCService::NewStub(m_Channel);\n        m_Executor = std::make_shared<::nvrpc::client::Executor>(client_threads);\n    }\n\n    std::vector<std::string> Models()\n    {\n        const auto& status = TrtisStatus();\n        auto model_status = status.server_status().model_status();\n        DLOG(INFO) << status.DebugString();\n        const ::trtis::ModelConfig* model_config;\n        std::vector<std::string> models;\n        m_Models.clear();\n        for(auto it = model_status.begin(); it != model_status.end(); it++)\n        {\n            DLOG(INFO) << it->first;\n            models.push_back(it->first);\n            m_Models[it->first] = std::make_shared<TrtisModel>(it->second.config());\n            /*\n            if(FLAGS_model == it->first)\n            {\n                LOG(INFO) << \"found model_config for \" << FLAGS_model;\n                model_config = &(it->second.config());\n            }\n            */\n        }\n        return models;\n    }\n\n    std::shared_ptr<PyInferRemoteRunner> InferRunner(const std::string& model_name)\n    {\n        auto infer_prepare_fn = [this](::grpc::ClientContext * context,\n                                       const ::trtis::InferRequest& request,\n                                       ::grpc::CompletionQueue* cq) -> auto\n        {\n            return std::move(m_Stub->PrepareAsyncInfer(context, request, cq));\n        };\n\n        auto runner = std::make_unique<\n            ::nvrpc::client::ClientUnary<::trtis::InferRequest, ::trtis::InferResponse>>(\n            infer_prepare_fn, m_Executor);\n\n        return std::make_shared<PyInferRemoteRunner>(GetModel(model_name), std::move(runner));\n    }\n\n    std::shared_ptr<TrtisModel> GetModel(const std::string& name) const\n    {\n        auto search = m_Models.find(name);\n        LOG_IF(FATAL, search == m_Models.end()) << \"Model: \" << name << \" not found\";\n        return search->second;\n    }\n\n  protected:\n    ::trtis::StatusResponse TrtisStatus()\n    {\n        ::grpc::ClientContext context;\n        ::trtis::StatusRequest request;\n        ::trtis::StatusResponse response;\n        auto status = m_Stub->Status(&context, request, &response);\n        CHECK(status.ok());\n        return response;\n    }\n\n  private:\n    std::string m_Hostname;\n    std::map<std::string, std::shared_ptr<TrtisModel>> m_Models;\n    std::shared_ptr<::grpc::Channel> m_Channel;\n    std::unique_ptr<::trtis::GRPCService::Stub> m_Stub;\n    std::shared_ptr<::nvrpc::client::Executor> m_Executor;\n};\n\nstruct TrtisModel : BaseModel\n{\n    TrtisModel(const ::trtis::ModelConfig& model)\n    {\n        SetName(model.name());\n        m_MaxBatchSize = model.max_batch_size();\n        for(int i = 0; i < model.input_size(); i++)\n        {\n            const auto& b = model.input(i);\n            TensorBindingInfo binding;\n            binding.name = b.name();\n            binding.isInput = true;\n            binding.dtype = nvinfer1::DataType::kFLOAT;\n            binding.dtypeSize =\n                SizeofDataType(binding.dtype); // TODO: map trtis DataType enum; model.data_type()\n            size_t count = 1;\n            for(int j = 0; j < b.dims_size(); j++)\n            {\n                auto val = b.dims(j);\n                binding.dims.push_back(val);\n                count *= val;\n            }\n\n            binding.elementsPerBatchItem = count;\n            binding.bytesPerBatchItem = count * binding.dtypeSize;\n            AddBinding(std::move(binding));\n        }\n        for(int i = 0; i < model.output_size(); i++)\n        {\n            const auto& b = model.output(i);\n            TensorBindingInfo binding;\n            binding.name = b.name();\n            binding.isInput = false;\n            binding.dtype = nvinfer1::DataType::kFLOAT;\n            binding.dtypeSize =\n                SizeofDataType(binding.dtype); // TODO: map trtis DataType enum; model.data_type()\n            size_t count = 1;\n            for(int j = 0; j < b.dims_size(); j++)\n            {\n                auto val = b.dims(j);\n                binding.dims.push_back(val);\n                count *= val;\n            }\n\n            binding.elementsPerBatchItem = count;\n            binding.bytesPerBatchItem = count * binding.dtypeSize;\n            AddBinding(std::move(binding));\n        }\n    }\n    ~TrtisModel() override {}\n\n    int GetMaxBatchSize() const final override { return m_MaxBatchSize; }\n\n  private:\n    int m_MaxBatchSize;\n};\n\nstruct PyInferRemoteRunner\n{\n    PyInferRemoteRunner(\n        std::shared_ptr<TrtisModel> model,\n        std::unique_ptr<::nvrpc::client::ClientUnary<::trtis::InferRequest, ::trtis::InferResponse>>\n            runner)\n        : m_Model(model), m_Runner(std::move(runner))\n    {\n    }\n\n    using InferResults = py::dict;\n    using InferFuture = std::shared_future<InferResults>;\n\n    const BaseModel& GetModel() const { return *m_Model; }\n\n    InferFuture Infer(py::kwargs kwargs)\n    {\n        const auto& model = GetModel();\n        int batch_size = -1; // will be infered from the input tensors\n\n        // Build InferRequest\n        ::trtis::InferRequest request;\n        request.set_model_name(model.Name());\n        // request.set_version(\"\");\n        auto meta_data = request.mutable_meta_data();\n\n        DLOG(INFO) << \"Processing Python kwargs - holding the GIL\";\n        for(auto item : kwargs)\n        {\n            auto key = py::cast<std::string>(item.first);\n            DLOG(INFO) << \"Processing Python Keyword: \" << key;\n            const auto& binding = model.GetBinding(key);\n            // TODO: throw a python exception\n            LOG_IF(FATAL, !binding.isInput) << item.first << \" is not an InputBinding\";\n            if(binding.isInput)\n            {\n                CHECK(py::isinstance<py::array>(item.second));\n                auto data = py::cast<py::array_t<float>>(item.second);\n                CHECK_LE(data.shape(0), model.GetMaxBatchSize());\n                if(batch_size == -1)\n                {\n                    DLOG(INFO) << \"Inferred batch_size=\" << batch_size << \" from dimensions \";\n                    batch_size = data.shape(0);\n                }\n                else\n                {\n                    CHECK_EQ(data.shape(0), batch_size);\n                }\n                CHECK_EQ(data.nbytes(), binding.bytesPerBatchItem * batch_size);\n                request.add_raw_input(data.data(), data.nbytes());\n                auto meta = meta_data->add_input();\n                meta->set_name(binding.name);\n                meta->set_byte_size(binding.elementsPerBatchItem);\n            }\n        }\n\n        for(auto id : model.GetOutputBindingIds())\n        {\n            const auto& binding = model.GetBinding(id);\n            auto meta = meta_data->add_output();\n            meta->set_name(binding.name);\n            meta->set_byte_size(binding.elementsPerBatchItem);\n        }\n        meta_data->set_batch_size(batch_size);\n\n        // Submit to TRTIS\n        py::gil_scoped_release release;\n        return m_Runner->Enqueue(std::move(request),\n                                 [this](::trtis::InferRequest& request,\n                                        ::trtis::InferResponse& response,\n                                        ::grpc::Status& status) -> py::dict {\n                                     // Convert InferResponse to py::dict\n                                     LOG(INFO) << response.DebugString();\n                                     return ConvertResponseToNumpy(response);\n                                 });\n    }\n\n    py::dict InputBindings() const\n    {\n        auto dict = py::dict();\n        for(const auto& id : GetModel().GetInputBindingIds())\n        {\n            AddBindingInfo(dict, id);\n        }\n        return dict;\n    }\n\n    py::dict OutputBindings() const\n    {\n        auto dict = py::dict();\n        for(const auto& id : GetModel().GetOutputBindingIds())\n        {\n            AddBindingInfo(dict, id);\n        }\n        return dict;\n    }\n\n  protected:\n    py::dict ConvertResponseToNumpy(const ::trtis::InferResponse& response)\n    {\n        py::gil_scoped_acquire acquire;\n        py::dict results;\n        const auto& meta_data = response.meta_data();\n        for(int i = 0; i < meta_data.output_size(); i++)\n        {\n            const auto& out = meta_data.output(i);\n            const auto& binding = GetModel().GetBinding(out.name());\n            LOG(INFO) << \"Processing binding: \" << out.name();\n            auto value = py::array(DataTypeToNumpy(binding.dtype), binding.dims);\n            py::buffer_info buffer = value.request();\n            CHECK_EQ(value.nbytes(), binding.bytesPerBatchItem * meta_data.batch_size());\n            const auto& raw = response.raw_output(i);\n            std::memcpy(buffer.ptr, raw.c_str(), value.nbytes());\n            py::str key = binding.name;\n            results[key] = value;\n        }\n        return results;\n    }\n\n    void AddBindingInfo(py::dict& dict, int id) const\n    {\n        const auto& binding = GetModel().GetBinding(id);\n        py::str key = binding.name;\n        py::dict value;\n        value[\"shape\"] = binding.dims;\n        value[\"dtype\"] = DataTypeToNumpy(binding.dtype);\n        dict[key] = value;\n    }\n\n  private:\n    std::shared_ptr<TrtisModel> m_Model;\n    std::unique_ptr<::nvrpc::client::ClientUnary<::trtis::InferRequest, ::trtis::InferResponse>>\n        m_Runner;\n};\n\nstruct PyInferRunner : public InferRunner\n{\n    using InferRunner::InferRunner;\n    using InferResults = py::dict;\n    using InferFuture = std::shared_future<InferResults>;\n\n    auto Infer(py::kwargs kwargs)\n    {\n        const auto& model = GetModel();\n        auto bindings = InitializeBindings();\n        int batch_size = -1;\n        DLOG(INFO) << \"Processing Python kwargs - holding the GIL\";\n        {\n            // py::gil_scoped_acquire acquire;\n            for(auto item : kwargs)\n            {\n                auto key = py::cast<std::string>(item.first);\n                DLOG(INFO) << \"Processing Python Keyword: \" << key;\n                const auto& binding = model.GetBinding(key);\n                // TODO: throw a python exception\n                LOG_IF(FATAL, !binding.isInput) << item.first << \" is not an InputBinding\";\n                if(binding.isInput)\n                {\n                    const void* ptr;\n                    size_t size;\n                    size_t batch;\n                    CHECK(py::isinstance<py::array>(item.second));\n                    switch(binding.dtype)\n                    {\n                        case nvinfer1::DataType::kFLOAT:\n                        {\n                            auto data = py::cast<py::array_t<float>>(item.second);\n                            ptr = data.data();\n                            size = data.nbytes();\n                            batch = data.shape(0);\n                            break;\n                        }\n                        case nvinfer1::DataType::kINT8:\n                        {\n                            auto data = py::cast<py::array_t<std::int8_t>>(item.second);\n                            ptr = data.data();\n                            size = data.nbytes();\n                            batch = data.shape(0);\n                            break;\n                        }\n                        case nvinfer1::DataType::kINT32:\n                        {\n                            auto data = py::cast<py::array_t<std::int32_t>>(item.second);\n                            ptr = data.data();\n                            size = data.nbytes();\n                            batch = data.shape(0);\n                            break;\n                        }\n                        default:\n                            LOG(FATAL) << \"Unknown dtype\";\n                    }\n                    CHECK_LE(batch, model.GetMaxBatchSize());\n                    if(batch_size == -1)\n                    {\n                        batch_size = batch;\n                        DLOG(INFO) << \"Inferred batch_size=\" << batch_size << \" from dimensions\";\n                    }\n                    else\n                    {\n                        CHECK_EQ(batch, batch_size);\n                    }\n                    CHECK_EQ(size, binding.bytesPerBatchItem * batch_size);\n                    auto id = model.BindingId(key);\n                    auto host = bindings->HostAddress(id);\n                    // TODO: enhance the Copy method for py::buffer_info objects\n                    DLOG(INFO) << \"Copying data from \" << ptr << \" to \" << host << \" \" << size << \"bytes\";\n                    std::memcpy(host, ptr, size);\n                }\n            }\n        }\n        // py::gil_scoped_release release;\n        bindings->SetBatchSize(batch_size);\n        return InferRunner::Infer(\n            bindings, [](std::shared_ptr<Bindings>& bindings) -> InferResults {\n                DLOG(INFO) << \"post processing thread - trying to acquire gil\";\n                py::gil_scoped_acquire acquire;\n                DLOG(INFO) << \"post processing thread - gil acquired\";\n                auto results = InferResults();\n                DLOG(INFO) << \"Copying Output Bindings to Numpy arrays\";\n                for(const auto& id : bindings->OutputBindings())\n                {\n                    const auto& binding = bindings->GetModel()->GetBinding(id);\n                    DLOG(INFO) << \"Processing binding: \" << binding.name << \"with index \" << id;\n                    std::vector<int> dims;\n                    dims.push_back(bindings->BatchSize());\n                    for(const auto& d : binding.dims)\n                    {\n                        dims.push_back(d);\n                    }\n                    auto value = py::array(DataTypeToNumpy(binding.dtype), dims);\n                    // auto value = py::array_t<float>(binding.dims);\n                    // auto value = py::array_t<float>(binding.elementsPerBatchItem *\n                    // bindings->BatchSize());\n                    py::buffer_info buffer = value.request();\n                    CHECK_EQ(value.nbytes(), bindings->BindingSize(id));\n                    std::memcpy(buffer.ptr, bindings->HostAddress(id), value.nbytes());\n                    py::str key = binding.name;\n                    results[key] = value;\n                }\n                DLOG(INFO) << \"Finished Postprocessing Numpy arrays - setting future/promise value\";\n                return results;\n            });\n    }\n\n    py::dict InputBindings() const\n    {\n        auto dict = py::dict();\n        for(const auto& id : GetModel().GetInputBindingIds())\n        {\n            AddBindingInfo(dict, id);\n        }\n        return dict;\n    }\n\n    py::dict OutputBindings() const\n    {\n        auto dict = py::dict();\n        for(const auto& id : GetModel().GetOutputBindingIds())\n        {\n            AddBindingInfo(dict, id);\n        }\n        return dict;\n    }\n\n  protected:\n    void AddBindingInfo(py::dict& dict, int id) const\n    {\n        const auto& binding = GetModel().GetBinding(id);\n        py::str key = binding.name;\n        py::dict value;\n        value[\"shape\"] = binding.dims;\n        value[\"dtype\"] = DataTypeToNumpy(binding.dtype);\n        dict[key] = value;\n    }\n};\n\nclass StatusContext final\n    : public Context<::trtis::StatusRequest, ::trtis::StatusResponse, InferenceManager>\n{\n    void ExecuteRPC(::trtis::StatusRequest& request,\n                    ::trtis::StatusResponse& response) final override\n    {\n        GetResources()->AcquireThreadPool(\"post\").enqueue([this, &request, &response] {\n            // create a status response\n            auto server_status = response.mutable_server_status();\n            server_status->set_ready_state(::trtis::ServerReadyState::SERVER_READY);\n            auto model_status = server_status->mutable_model_status();\n\n            // populate each model\n            GetResources()->ForEachModel([model_status](const Model& model) {\n                auto config = (*model_status)[model.Name()].mutable_config();\n                config->set_name(model.Name());\n                config->set_max_batch_size(model.GetMaxBatchSize());\n                for(auto i : model.GetInputBindingIds())\n                {\n                    const auto& binding = model.GetBinding(i);\n                    auto input = config->add_input();\n                    input->set_name(binding.name);\n                    input->set_data_type(::trtis::DataType::TYPE_FP32);\n                    for(auto d : binding.dims)\n                    {\n                        input->add_dims(d);\n                    }\n                }\n                for(auto i : model.GetOutputBindingIds())\n                {\n                    const auto& binding = model.GetBinding(i);\n                    auto output = config->add_output();\n                    output->set_name(binding.name);\n                    output->set_data_type(::trtis::DataType::TYPE_FP32);\n                    for(auto d : binding.dims)\n                    {\n                        output->add_dims(d);\n                    }\n                }\n            });\n\n            auto request_status = response.mutable_request_status();\n            request_status->set_code(::trtis::RequestStatusCode::SUCCESS);\n            LOG(INFO) << response.DebugString();\n            this->FinishResponse();\n        });\n    }\n};\n\nclass InferContext final\n    : public Context<::trtis::InferRequest, ::trtis::InferResponse, InferenceManager>\n{\n    void ExecuteRPC(RequestType& input, ResponseType& output) final override\n    {\n        // Executing on a Executor threads - we don't want to block message handling, so we offload\n        GetResources()->AcquireThreadPool(\"pre\").enqueue([this, &input, &output]() {\n            // Executed on a thread from CudaThreadPool\n            auto model = GetResources()->GetModel(input.model_name());\n            auto buffers = GetResources()->GetBuffers(); // <=== Limited Resource; May Block !!!\n            auto bindings = buffers->CreateBindings(model);\n\n            // prepare input bindings - copy data from input\n            const auto& meta_data = input.meta_data();\n            bindings->SetBatchSize(meta_data.batch_size());\n            for(int input_idx = 0; input_idx < input.raw_input_size(); input_idx++)\n            {\n                const auto& in = meta_data.input(input_idx);\n                auto binding_idx = model->BindingId(in.name());\n                const std::string& raw = input.raw_input(input_idx);\n                CHECK_EQ(raw.size(), bindings->BindingSize(binding_idx));\n                DLOG(INFO) << \"Copying binding \" << in.name() << \" from raw_input \" << input_idx\n                           << \" to binding \" << binding_idx;\n                std::memcpy(bindings->HostAddress(binding_idx), raw.c_str(), raw.size());\n            }\n            InferRunner runner(model, GetResources());\n            runner.Infer(bindings, [this, &input, &output](std::shared_ptr<Bindings>& bindings) {\n                // post processing function - write response\n                // for each output binding - write populate the response from data in bindings\n                const auto& input_meta_data = input.meta_data();\n                auto output_meta_data = output.mutable_meta_data();\n                output_meta_data->set_model_name(bindings->GetModel()->Name());\n                output_meta_data->set_batch_size(bindings->BatchSize());\n                for(int idx = 0; idx < input_meta_data.output_size(); idx++)\n                {\n                    const auto& out = input_meta_data.output(idx);\n                    auto binding_idx = bindings->GetModel()->BindingId(out.name());\n                    auto meta = output_meta_data->add_output();\n                    meta->set_name(out.name());\n                    output.add_raw_output(bindings->HostAddress(binding_idx),\n                                          bindings->BindingSize(binding_idx));\n                }\n                this->FinishResponse();\n            });\n        });\n    }\n};\n\nvoid BasicInferService(std::shared_ptr<InferenceManager> resources, int port,\n                       const std::string& max_recv_msg_size)\n{\n    // registerAllTensorRTPlugins();\n\n    // Create a gRPC server bound to IP:PORT\n    std::ostringstream ip_port;\n    ip_port << \"0.0.0.0:\" << port;\n    Server server(ip_port.str());\n\n    // Modify MaxReceiveMessageSize\n    auto bytes = trtlab::StringToBytes(max_recv_msg_size);\n    server.Builder().SetMaxReceiveMessageSize(bytes);\n    LOG(INFO) << \"gRPC MaxReceiveMessageSize = \" << trtlab::BytesToString(bytes);\n\n    // A server can host multiple services\n    auto inferenceService = server.RegisterAsyncService<::trtis::GRPCService>();\n\n    auto rpcCompute = inferenceService->RegisterRPC<InferContext>(\n        &::trtis::GRPCService::AsyncService::RequestInfer);\n\n    auto rpcStatus = inferenceService->RegisterRPC<StatusContext>(\n        &::trtis::GRPCService::AsyncService::RequestStatus);\n\n    // Create Executors - Executors provide the messaging processing resources for the RPCs\n    LOG(INFO) << \"Initializing Executor\";\n    auto executor = server.RegisterExecutor(new Executor(1));\n\n    // You can register RPC execution contexts from any registered RPC on any executor.\n    executor->RegisterContexts(rpcCompute, resources, 100);\n    executor->RegisterContexts(rpcStatus, resources, 10);\n\n    LOG(INFO) << \"Running Server\";\n    server.Run(std::chrono::milliseconds(1000), [] {});\n}\n\nusing PyInferFuture = std::shared_future<typename PyInferRunner::InferResults>;\nPYBIND11_MAKE_OPAQUE(PyInferFuture);\n\nPYBIND11_MODULE(trtlab, m)\n{\n    py::class_<PyInferenceManager, std::shared_ptr<PyInferenceManager>>(m, \"InferenceManager\")\n        .def(py::init<int, int, int, int, int>(), py::arg(\"max_exec_concurrency\") = 1,\n             py::arg(\"max_copy_concurrency\") = 0, py::arg(\"pre_threads\") = 1,\n             py::arg(\"cuda_threads\") = 1, py::arg(\"post_threads\") = 3)\n        .def(\"register_tensorrt_engine\", &PyInferenceManager::RegisterModelByPath)\n        .def(\"update_resources\", &PyInferenceManager::AllocateResources)\n        .def(\"infer_runner\", &PyInferenceManager::InferRunner)\n        .def(\"get_model\", &PyInferenceManager::GetModel)\n        .def(\"get_models\", &PyInferenceManager::Models)\n        .def(\"serve\", &PyInferenceManager::Serve, py::arg(\"port\") = 50052);\n    // py::call_guard<py::gil_scoped_release>());\n\n    py::class_<PyRemoteInferenceManager, std::shared_ptr<PyRemoteInferenceManager>>(\n        m, \"RemoteInferenceManager\")\n        .def(py::init(\n            [](py::kwargs kwargs) { return std::make_shared<PyRemoteInferenceManager>(kwargs); }))\n        .def(\"get_models\", &PyRemoteInferenceManager::Models)\n        .def(\"infer_runner\", &PyRemoteInferenceManager::InferRunner);\n\n    py::class_<PyInferRunner, std::shared_ptr<PyInferRunner>>(m, \"InferRunner\")\n        .def(\"infer\", &PyInferRunner::Infer)\n        .def(\"input_bindings\", &PyInferRunner::InputBindings)\n        .def(\"output_bindings\", &PyInferRunner::OutputBindings)\n        .def(\"max_batch_size\", &PyInferRunner::MaxBatchSize);\n    //      .def(\"__repr__\", [](const PyInferRunner& obj) {\n    //          return obj.Description();\n    //      });\n\n    py::class_<PyInferRemoteRunner, std::shared_ptr<PyInferRemoteRunner>>(m, \"InferRemoteRunner\")\n        .def(\"infer\", &PyInferRemoteRunner::Infer)\n        .def(\"input_bindings\", &PyInferRemoteRunner::InputBindings)\n        .def(\"output_bindings\", &PyInferRemoteRunner::OutputBindings);\n\n    py::class_<PyInferFuture, std::shared_ptr<PyInferFuture>>(m, \"InferFuture\")\n        .def(\"wait\", &std::shared_future<typename PyInferRunner::InferResults>::wait, py::call_guard<py::gil_scoped_release>())\n        .def(\"get\", &std::shared_future<typename PyInferRunner::InferResults>::get, py::call_guard<py::gil_scoped_release>());\n\n    /*\n        py::class_<InferBench, std::shared_ptr<InferBench>>(m, \"InferBench\")\n            .def(py::init([](std::shared_ptr<PyInferenceManager> man) {\n                return std::make_shared<InferBench>(man);\n            }))\n            .def(\"run\", py::overload_cast<std::shared_ptr<Model>, uint32_t,\n       double>(&InferBench::Run));\n\n        py::class_<Model, std::shared_ptr<Model>>(m, \"Model\");\n\n        py::class_<typename InferBench::Results>(m, \"InferBenchResults\");\n    */\n    // py::bind_map<std::map<std::string, double>>(m, \"InferBenchResults\");\n}\n"
  },
  {
    "path": "trtlab/pybind/trtlab/utils.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"utils.h\"\n\n#include <glog/logging.h>\n\nnamespace py = pybind11;\n\nnamespace trtlab {\nnamespace TensorRT {\n\npy::dtype DataTypeToNumpy(::nvinfer1::DataType dtype)\n{\n    switch(dtype)\n    {\n        case nvinfer1::DataType::kFLOAT:\n            return py::dtype(\"float32\");\n        case nvinfer1::DataType::kHALF:\n            return py::dtype(\"float16\");\n        case nvinfer1::DataType::kINT32:\n            return py::dtype(\"int32\");\n        case nvinfer1::DataType::kINT8:\n            return py::dtype(\"int8\");\n        default:\n            LOG(FATAL) << \"Unknown TensorRT DataType\";\n    }\n}\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/pybind/trtlab/utils.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <pybind11/numpy.h>\n#include <pybind11/pybind11.h>\n\n#include <NvInfer.h>\n\nnamespace trtlab {\nnamespace TensorRT {\n\n/**\n * @brief Number of bytes for a given TensorRT DataType\n */\npybind11::dtype DataTypeToNumpy(::nvinfer1::DataType dtype);\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/BUILD.bazel",
    "content": "\ncc_library(\n    name = \"tensorrt\",\n    srcs = glob([\n        \"src/**/*.cc\",\n        \"src/**/*.h\",\n    ]),\n    hdrs = glob([\n        \"include/**/*.h\",\n    ]),\n    deps = [\n        \"//trtlab/core\",\n        \"//trtlab/cuda\",\n        \"@local_config_tensorrt//:tensorrt_headers\",\n        \"@local_config_tensorrt//:tensorrt_infer\",\n    ],\n    linkopts = [\n        \"-L/usr/local/cuda/lib64/stubs\",\n    ],\n    strip_include_prefix = \"include\",\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "trtlab/tensorrt/CMakeLists.txt",
    "content": "# find tensorrt\nfind_package(TensorRT REQUIRED 4.0.1)\nmessage(STATUS \"TensorRT IncludeDir ${TensorRT_INCLUDE_DIRS}\")\nmessage(STATUS \"TensorRT Version ${TensorRT_VERSION_STRING}\")\n\nadd_library(tensorrt\n  src/allocator.cc\n# src/bindings.cc\n# src/buffers.cc\n  src/execution_context.cc\n# src/inference_manager.cc\n# src/infer_bench.cc\n  src/model.cc\n  src/runtime.cc\n  src/utils.cc\n  src/workspace.cc\n)\n\nadd_library(${PROJECT_NAME}::tensorrt ALIAS tensorrt)\n\ntarget_link_libraries(tensorrt\n    ${PROJECT_NAME}::core\n    ${PROJECT_NAME}::cuda\n    ${TensorRT_LIBRARY}\n)\n\ntarget_include_directories(tensorrt\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n    ${TensorRT_INCLUDE_DIRS}\n)\n\nset_target_properties(tensorrt PROPERTIES OUTPUT_NAME ${PROJECT_NAME}_tensorrt)\n\ninstall(\n  TARGETS tensorrt\n  EXPORT ${PROJECT_NAME}-targets\n  RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}\n  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\ninstall(\n  DIRECTORY include/\n  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n)\n\nif(ENABLE_TESTING)\n  add_subdirectory(tests)\nendif()\n\n#if(benchmark_FOUND)\n#  add_subdirectory(benchmarks)\n#endif()\n\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/allocator.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <memory>\n#include <mutex>\n#include <vector>\n\n#include <NvInfer.h>\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        class NvAllocator : public ::nvinfer1::IGpuAllocator\n        {\n        public:\n            struct Pointer\n            {\n                void*  addr;\n                size_t size;\n            };\n\n            NvAllocator() : m_UseWeightAllocator(false) {}\n            virtual ~NvAllocator() override {}\n\n            NvAllocator(const NvAllocator&) = delete;\n            NvAllocator& operator=(const NvAllocator&) = delete;\n\n            NvAllocator(NvAllocator&&) noexcept = delete;\n            NvAllocator& operator=(NvAllocator&&) noexcept = delete;\n\n            // TensorRT IGpuAllocator virtual overrides\n            void* allocate(uint64_t size, uint64_t alignment, uint32_t flags) final override;\n            void  free(void* ptr) final override;\n\n            template <class F, class... Args>\n            auto use_weights_allocator(F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type\n            {\n                std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n                m_Pointers.clear();\n                m_UseWeightAllocator = true;\n                auto retval          = f(std::forward<Args>(args)...);\n                m_UseWeightAllocator = false;\n                m_Pointers.clear();\n                return retval;\n            }\n\n            const std::vector<Pointer>& get_pointers();\n\n        private:\n            bool                 m_UseWeightAllocator;\n            std::recursive_mutex m_Mutex;\n            std::vector<Pointer> m_Pointers;\n            virtual void         weights_allocate(void**, size_t) = 0;\n        };\n\n        class StandardAllocator : public NvAllocator\n        {\n            using NvAllocator::NvAllocator;\n            void weights_allocate(void** ptr, size_t) final override;\n        };\n\n        class ManagedAllocator : public NvAllocator\n        {\n            using NvAllocator::NvAllocator;\n            void weights_allocate(void** ptr, size_t) override;\n        };\n\n    } // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/bindings.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n#include <map>\n\n#include \"trtlab/tensorrt/buffers.h\"\n#include \"trtlab/tensorrt/common.h\"\n#include \"trtlab/tensorrt/model.h\"\n\n//#include \"trtlab/core/memory/descriptor.h\"\n//#include \"trtlab/core/memory/host_memory.h\"\n//#include \"trtlab/cuda/memory/device_memory.h\"\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nnamespace trtlab {\nnamespace TensorRT {\n\nclass Model;\nclass Buffers;\n\n/**\n * @brief Manages memory addresses and transfers for input/output tensors.\n *\n * Bindings manages the addresses for the input/output tensors.  Bindings are created\n * from a Buffers object and maintain a reference.  All device bindings must be configured\n * before calling ExecutionContext::Infer.  Similarly, the respective host binding must\n * be set before calling an of the implicit CopyTo/CopyFromDevice methods.\n *\n * A Bindings object holds the state of the input/output tensors over the course of an\n * inference calculation.\n */\n\n/*\nclass Bindings\n{\n  public:\n    using HostDescriptor = DescriptorHandle<HostMemory>;\n    using DeviceDescriptor = DescriptorHandle<DeviceMemory>;\n\n    virtual ~Bindings();\n\n    void* HostAddress(uint32_t binding_id);\n    void* DeviceAddress(uint32_t binding_id);\n    void** DeviceAddresses();\n\n    [[deprecated]] void SetHostAddress(int binding_id, void* addr);\n    [[deprecated]] void SetDeviceAddress(int binding_id, void* addr);\n\n    void SetHostAddress(int binding_id, HostDescriptor);\n    void SetDeviceAddress(int binding_id, DeviceDescriptor);\n\n    HostDescriptor& HostMemoryDescriptor(int binding_id);\n    // const HostMemory& HostMemory(int binding_id) const;\n\n    void* ActivationsAddress() { return m_ActivationsAddress; }\n    void SetActivationsAddress(void* addr) { m_ActivationsAddress = addr; }\n\n    void CopyToDevice(uint32_t);\n    void CopyToDevice(const std::vector<uint32_t>&);\n    void CopyToDevice(uint32_t, void*, size_t);\n\n    void CopyFromDevice(uint32_t);\n    void CopyFromDevice(const std::vector<uint32_t>&);\n    void CopyFromDevice(uint32_t, void*, size_t);\n\n    auto InputBindings() const { return m_Model->GetInputBindingIds(); }\n    auto OutputBindings() const { return m_Model->GetOutputBindingIds(); }\n\n    auto GetModel() -> const std::shared_ptr<Model>& { return m_Model; }\n    auto BatchSize() const { return m_BatchSize; }\n    void SetBatchSize(uint32_t);\n\n    inline cudaStream_t Stream() const { return m_Buffers->Stream(); }\n    void Synchronize() const { m_Buffers->Synchronize(); }\n\n    size_t BindingSize(uint32_t binding_id) const;\n\n  private:\n    Bindings(const std::shared_ptr<Model>, const std::shared_ptr<Buffers>);\n\n    const std::shared_ptr<Model> m_Model;\n    const std::shared_ptr<Buffers> m_Buffers;\n    uint32_t m_BatchSize;\n\n    std::vector<void*> m_HostAddresses;\n    std::vector<void*> m_DeviceAddresses;\n\n    std::map<int, HostDescriptor> m_HostDescriptors;\n    std::map<int, DeviceDescriptor> m_DeviceDescriptors;\n\n    void* m_ActivationsAddress;\n\n    friend class Buffers;\n};\n*/\n\n\n/*\nclass Workspace\n{\n  public:\n    void RegisterModel(std::shared_ptr<Model>);\n\n    template<typename T>\n    void RegisterObject(const std::string& model_name, T obj);\n\n    template<typename T>\n    void RegisterObject(const std::string& model_name, std::shared_ptr<T> shared_obj);\n\n    template<typename T>\n    void RegisterObject(const std::string& model_name, std::unique_ptr<T> unique_obj);\n\n    void RegisterBindings(const std::string& model_name, ISmartAllocator& allocator);\n\n    template<typename T>\n    void RegisterBindings(const std::string& model_name, std::shared_ptr<MemoryStack<T>>& stack);\n\n    void RegisterBinding(const std::string& model_name, const std::string& binding_name, CoreMemory& memory);\n    void RegisterHostBinding(const std::string& model_name, const std::string& binding_name, void*);\n    void RegisterDeviceBinding(const std::string& model_name, const std::string& binding_name, void*);\n\n  protected:\n    class ModelWorkspace\n    {\n      private:\n        std::vector<void*> Bindings() const;\n\n        std::map<std::string, void*> m_HostPointers;\n        std::map<std::string, void*> m_DevicePointers;\n\n        std::vector<std::function<void()> m_CapturedObjects;\n    }\n\n    HostMemory& HostDescriptor(const std::string&);\n    const HostMemory& HostDescriptor(const std::string&) const;\n    void HostDescriptor(const std::string&, DescriptorHandle<HostMemory>);\n\n    DeviceMemory& DeviceDescriptor(const std::string&);\n    const HostMemory& DeviceDescriptor(const std::string&) const;\n    void DeviceDescriptor(const std::string&, DescriptorHandle<DeviceMemory>);\n\n    std::shared_ptr<Bindings> ExportBindings(const std::string& model);\n\n  private:\n    std::map<std::string, DescriptorHandle<HostMemory>> m_HostDescriptors;\n    std::map<std::string, DescriptorHandle<DeviceMemory>> m_DeviceDescriptors;\n    std::shared_ptr<InferenceManager> m_Resources;\n};\n*/\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/buffers.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <memory>\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n//#include \"trtlab/tensorrt/common.h\"\n//#include \"trtlab/core/memory/cyclic_allocator.h\"\n//#include \"trtlab/core/memory/memory_stack.h\"\n//#include \"trtlab/cuda/memory/cuda_device.h\"\n//#include \"trtlab/cuda/memory/cuda_pinned_host.h\"\n\nnamespace trtlab {\nnamespace TensorRT {\n\n/**\n * @brief Manages inpu/output buffers and CudaStream\n *\n * Primary TensorRT resource class used to manage both a host and a device memory stacks\n * and owns the cudaStream_t that should be used for transfers or compute on these\n * resources.\n */\n\n/*\nclass Buffers : public std::enable_shared_from_this<Buffers>\n{\n  public:\n    Buffers();\n    virtual ~Buffers();\n\n    auto CreateBindings(const std::shared_ptr<Model>&) -> std::shared_ptr<Bindings>;\n\n    inline cudaStream_t Stream() { return m_Stream; }\n    void Synchronize();\n\n  protected:\n    virtual void Reset() = 0;\n    void ConfigureBindings(const std::shared_ptr<Model>& model, std::shared_ptr<Bindings>);\n\n    virtual std::unique_ptr<HostMemory> AllocateHost(size_t size) = 0;\n    virtual std::unique_ptr<DeviceMemory> AllocateDevice(size_t size) = 0;\n\n  private:\n    cudaStream_t m_Stream;\n    friend class InferenceManager;\n};\n\ntemplate<typename HostMemoryType, typename DeviceMemoryType>\nclass FixedBuffers : public Buffers\n{\n  public:\n    FixedBuffers(size_t host_size, size_t device_size)\n        : m_HostStack(std::make_unique<MemoryStack<HostMemoryType>>(host_size)),\n          m_DeviceStack(std::make_unique<MemoryStack<DeviceMemoryType>>(device_size)), Buffers()\n    {\n    }\n\n    ~FixedBuffers() override {}\n\n  protected:\n    template<typename MemoryType>\n    class BufferStackDescriptor final : public Descriptor<MemoryType>\n    {\n      public:\n        BufferStackDescriptor(void* ptr, size_t size)\n            : Descriptor<MemoryType>(ptr, size, []{},\n                std::string(\"BufferStack<\" + std::string(MemoryType::TypeName()) + \">\").c_str())\n        {\n        }\n        ~BufferStackDescriptor() final override {}\n    };\n\n    std::unique_ptr<HostMemory> AllocateHost(size_t size) final override\n    {\n        return std::move(std::make_unique<BufferStackDescriptor<HostMemoryType>>(\n            m_HostStack->Allocate(size), size));\n    }\n\n    std::unique_ptr<DeviceMemory> AllocateDevice(size_t size) final override\n    {\n        return std::move(std::make_unique<BufferStackDescriptor<DeviceMemoryType>>(\n            m_DeviceStack->Allocate(size), size));\n    }\n\n    void Reset() final override\n    {\n        m_HostStack->Reset();\n        m_DeviceStack->Reset();\n    }\n\n  private:\n    std::unique_ptr<MemoryStack<HostMemoryType>> m_HostStack;\n    std::unique_ptr<MemoryStack<DeviceMemoryType>> m_DeviceStack;\n};\n\ntemplate<typename HostMemoryType, typename DeviceMemoryType>\nclass CyclicBuffers : public Buffers\n{\n  public:\n    using HostAllocatorType = std::unique_ptr<CyclicAllocator<HostMemoryType>>;\n    using DeviceAllocatorType = std::unique_ptr<CyclicAllocator<DeviceMemoryType>>;\n\n    using HostDescriptor = typename CyclicAllocator<HostMemoryType>::Descriptor;\n    using DeviceDescriptor = typename CyclicAllocator<DeviceMemoryType>::Descriptor;\n\n    CyclicBuffers(HostAllocatorType host, DeviceAllocatorType device)\n        : m_HostAllocator{std::move(host)}, m_DeviceAllocator{std::move(device)}\n    {\n    }\n    ~CyclicBuffers() override {}\n\n    std::unique_ptr<HostMemory> AllocateHost(size_t size)\n    {\n        return m_HostAllocator->Allocate(size);\n    }\n\n    std::unique_ptr<DeviceMemory> AllocateDevice(size_t size)\n    {\n        return m_DeviceAllocator->Allocate(size);\n    }\n\n    void Reset() final override {}\n\n  private:\n    HostAllocatorType m_HostAllocator;\n    DeviceAllocatorType m_DeviceAllocator;\n};\n*/\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/common.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <functional>\n#include <memory>\n\n#include <NvInfer.h>\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        struct NvInferDeleter\n        {\n            NvInferDeleter()\n            {\n                NvInferDeleter([] {});\n            }\n            NvInferDeleter(std::function<void()> capture) : m_Capture{capture} {}\n\n            template <typename T>\n            void operator()(T* obj) const\n            {\n                if (obj)\n                {\n                    obj->destroy();\n                    if (m_Capture)\n                    {\n                        m_Capture();\n                    }\n                }\n            }\n\n        private:\n            std::function<void()> m_Capture;\n        };\n\n        template <typename T>\n        std::shared_ptr<T> nv_shared(T* obj)\n        {\n            if (!obj)\n            {\n                throw std::runtime_error(\"Failed to create object\");\n            }\n            return std::shared_ptr<T>(obj, NvInferDeleter());\n        };\n\n        template <typename T>\n        std::shared_ptr<T> nv_shared(T* obj, std::function<void()> capture)\n        {\n            if (!obj)\n            {\n                throw std::runtime_error(\"Failed to create object\");\n            }\n            return std::shared_ptr<T>(obj, NvInferDeleter(capture));\n        };\n\n        template <typename T>\n        using unique_t = std::unique_ptr<T, NvInferDeleter>;\n\n        template <typename T>\n        std::unique_ptr<T, NvInferDeleter> nv_unique(T* obj)\n        {\n            if (!obj)\n            {\n                throw std::runtime_error(\"Failed to create object\");\n            }\n            return std::unique_ptr<T, NvInferDeleter>(obj);\n        }\n\n    } // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/execution_context.h",
    "content": "#pragma once\n\n#include <trtlab/memory/descriptor.h>\n#include <trtlab/core/utils.h>\n\n#include \"NvInfer.h\"\n#include \"trtlab/tensorrt/model.h\"\n#include \"trtlab/tensorrt/common.h\"\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        class ExecutionContext\n        {\n        public:\n            using model_t   = std::shared_ptr<Model>;\n            using context_t = nvinfer1::IExecutionContext;\n\n            ExecutionContext(model_t);\n            virtual ~ExecutionContext();\n\n            ExecutionContext(ExecutionContext&&) noexcept = default;\n            ExecutionContext& operator=(ExecutionContext&&) noexcept = default;\n\n            DELETE_COPYABILITY(ExecutionContext);\n\n            context_t& context()\n            {\n                return *m_Context;\n            }\n\n            const Model& model() const\n            {\n                return *m_Model;\n            }\n\n            const nvinfer1::ICudaEngine& engine() const\n            {\n                return m_Context->getEngine();\n            }\n\n            std::string binding_info(std::uint32_t binding_id);\n            std::string profile_info(std::uint32_t profile_id);\n\n            std::size_t binding_size_in_bytes(std::uint32_t binding_id);\n\n        private:\n            unique_t<context_t> m_Context;\n            model_t             m_Model;\n        };\n\n    } // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/infer_bench.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"trtlab/tensorrt/inference_manager.h\"\n#include \"trtlab/tensorrt/model.h\"\n\nnamespace trtlab {\nnamespace TensorRT {\n\nenum InferBenchKey\n{\n    kMaxExecConcurrency = 0,\n    kMaxCopyConcurrency,\n    kBatchSize,\n    kWalltime,\n    kBatchesComputed,\n    kBatchesPerSecond,\n    kInferencesPerSecond,\n    kSecondsPerBatch,\n    kExecutionTimePerBatch\n};\n\nclass InferBench\n{\n  public:\n    InferBench(std::shared_ptr<InferenceManager>);\n    virtual ~InferBench();\n\n    using ModelsList = std::vector<std::shared_ptr<Model>>;\n    using Results = std::map<InferBenchKey, double>;\n\n    std::unique_ptr<Results> Run(const std::shared_ptr<Model> model, uint32_t batch_size,\n                                 double seconds = 5.0);\n    std::unique_ptr<Results> Run(const ModelsList& models, uint32_t batch_size,\n                                 double seconds = 5.0);\n\n  protected:\n    InferenceManager& InferResources() { return *m_Resources; }\n\n  private:\n    std::shared_ptr<InferenceManager> m_Resources;\n};\n\n} // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/infer_runner.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include \"trtlab/tensorrt/bindings.h\"\n#include \"trtlab/core/async_compute.h\"\n#include \"trtlab/tensorrt/inference_manager.h\"\n#include \"trtlab/tensorrt/model.h\"\n\nnamespace trtlab {\nnamespace TensorRT {\n\nstruct InferRunner : public AsyncComputeWrapper<void(std::shared_ptr<Bindings>&)>\n{\n    InferRunner(std::shared_ptr<Model> model, std::shared_ptr<InferenceManager> resources)\n        : m_Model{model}, m_Resources{resources}\n    {\n    }\n\n    InferRunner(InferRunner&&) = delete;\n    InferRunner& operator=(InferRunner&&) = delete;\n\n    InferRunner(const InferRunner&) = delete;\n    InferRunner& operator=(const InferRunner&) = delete;\n\n    virtual ~InferRunner() {}\n\n    using BindingsHandle = std::shared_ptr<Bindings>;\n    using PreFn = std::function<void(Bindings&)>;\n\n    template<typename Post>\n    auto Infer(PreFn pre, Post post)\n    {\n        auto compute = Wrap(post);\n        auto future = compute->Future();\n        Enqueue(pre, compute);\n        return future.share();\n    }\n\n    template<typename Post>\n    auto Infer(std::shared_ptr<Bindings> bindings, Post post)\n    {\n        auto compute = Wrap(post);\n        auto future = compute->Future();\n        Enqueue(bindings, compute);\n        return future.share();\n    }\n\n  protected:\n    template<typename T>\n    void Enqueue(PreFn Pre, std::shared_ptr<AsyncCompute<T>> Post)\n    {\n        Workers(\"pre\").enqueue([this, Pre, Post]() mutable {\n            auto bindings = InitializeBindings();\n            Pre(*bindings);\n            Enqueue(bindings, Post);\n        });\n    }\n\n    template<typename T>\n    void Enqueue(std::shared_ptr<Bindings> bindings, std::shared_ptr<AsyncCompute<T>> Post)\n    {\n        Workers(\"cuda\").enqueue([this, bindings, Post]() mutable {\n            DLOG(INFO) << \"H2D\";\n            bindings->CopyToDevice(bindings->InputBindings());\n            DLOG(INFO) << \"Compute\";\n            auto trt_ctx = Compute(bindings);\n            bindings->CopyFromDevice(bindings->OutputBindings());\n            Workers(\"post\").enqueue([this, bindings, trt_ctx, Post]() mutable {\n                trt_ctx->Synchronize();\n                trt_ctx.reset();\n                DLOG(INFO) << \"Sync TRT\";\n                bindings->Synchronize();\n                DLOG(INFO) << \"Sync D2H\";\n                (*Post)(bindings);\n                bindings.reset();\n                DLOG(INFO) << \"Execute Finished\";\n            });\n        });\n    }\n\n    BindingsHandle InitializeBindings()\n    {\n        auto buffers = m_Resources->GetBuffers();\n        return buffers->CreateBindings(m_Model);\n    }\n\n    auto Compute(BindingsHandle& bindings) -> std::shared_ptr<ExecutionContext>\n    {\n        auto trt_ctx = m_Resources->GetExecutionContext(bindings->GetModel());\n        trt_ctx->Infer(bindings);\n        return trt_ctx;\n    }\n\n    inline ThreadPool& Workers(std::string name) { return m_Resources->AcquireThreadPool(name); }\n    /*\n        void CopyInputsToInputBindings(const HostMap& inputs, BindingsHandle& bindings)\n        {\n            for (const auto& id : bindings->InputBindings())\n            {\n                const auto& b = bindings->GetBindings(id);\n                auto search = inputs.find(b.name);\n                CHECK(search != inputs.end());\n                Copy(bindings->HostMemoryDescriptor(id), *inputs[b.name],\n       bindings->BindingSize(id));\n            }\n        }\n    */\n    /*j\n        const Model& Model() const\n        {\n            return *m_Model;\n        }\n\n        const InferenceManager& Resources() const\n        {\n            return *m_Resources;\n        }\n    */\n\n  public:\n    const int MaxBatchSize() const { return m_Model->GetMaxBatchSize(); }\n\n    const Model& GetModel() const { return *m_Model; }\n\n    const std::shared_ptr<Model> GetModelSmartPtr() const { return m_Model; }\n\n    InferenceManager& Resources() { return *m_Resources; }\n\n  private:\n    std::shared_ptr<Model> m_Model;\n    std::shared_ptr<InferenceManager> m_Resources;\n};\n\n} // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/inference_manager.h",
    "content": "#pragma once\n#include <memory>\n\n#include <trtlab/tensorrt/model.h>\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        class InferenceManager : public std::enable_shared_from_this<InferenceManager>\n        {\n            struct key {};\n\n        public:\n            static std::shared_ptr<InferenceManager> Create();\n\n            InferenceManager(key);\n            virtual ~InferenceManager();\n\n            void RegisterModel(std::shared_ptr<Model>);\n        };\n\n    } // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/model.h",
    "content": "#pragma once\n#include <memory>\n#include <vector>\n\n#include \"NvInfer.h\"\n\n#include \"trtlab/tensorrt/allocator.h\"\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        struct BaseModel\n        {\n        };\n\n        class Model : public BaseModel\n        {\n        public:\n            using engine_t  = std::shared_ptr<nvinfer1::ICudaEngine>;\n            using weights_t = std::vector<typename NvAllocator::Pointer>;\n\n            Model(engine_t, const weights_t&);\n            virtual ~Model();\n\n            nvinfer1::ICudaEngine& engine()\n            {\n                return *m_Engine;\n            }\n\n            std::string profiles_info() const;\n            std::string profile_info(std::uint32_t profile_id, nvinfer1::OptProfileSelector) const;\n\n            std::string bindings_info() const;\n            std::string binding_info(std::uint32_t) const;\n            static std::string dims_info(const nvinfer1::Dims&);\n\n            std::size_t binding_element_count(std::uint32_t binding_id) const;\n            std::size_t binding_size_in_bytes(std::uint32_t binding_id) const;\n\n        protected:\n\n\n        private:\n            engine_t  m_Engine;\n            weights_t m_Weights;\n        };\n\n    } // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/runtime.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#pragma once\n\n#include <fstream>\n#include <memory>\n#include <mutex>\n#include <type_traits>\n#include <vector>\n\n#include \"trtlab/tensorrt/allocator.h\"\n#include \"trtlab/tensorrt/common.h\"\n#include \"trtlab/tensorrt/model.h\"\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        class Runtime : public std::enable_shared_from_this<Runtime>\n        {\n            Runtime(const Runtime&) = delete;\n            Runtime& operator=(const Runtime&) = delete;\n\n            Runtime(Runtime&&) noexcept = delete;\n            Runtime& operator=(Runtime&&) = delete;\n\n        public:\n            virtual ~Runtime();\n\n            std::shared_ptr<Model>         deserialize_engine(const std::string&);\n            std::shared_ptr<Model>         deserialize_engine(const std::string&, ::nvinfer1::IPluginFactory*);\n            std::shared_ptr<Model>         deserialize_engine(const void*, size_t);\n            virtual std::shared_ptr<Model> deserialize_engine(const void*, size_t, ::nvinfer1::IPluginFactory*) = 0;\n\n        protected:\n            Runtime();\n\n            ::nvinfer1::IRuntime& get_runtime() const;\n            std::vector<char>     read_engine_file(const std::string&) const;\n\n        private:\n            class Logger : public ::nvinfer1::ILogger\n            {\n            public:\n                virtual ~Logger() override;\n                void log(::nvinfer1::ILogger::Severity severity, const char* msg) final override;\n            };\n\n            // Order is important.  In C++ variables in the member initializer list are instantiated in\n            // the order they are declared, not in the order they appear in the initializer list.\n            // Inverting these causes m_Runtime to be initialized with a NULL m_Logger and was the\n            // source of much head banging.\n            std::unique_ptr<::nvinfer1::ILogger>                  m_Logger;\n            std::unique_ptr<::nvinfer1::IRuntime, NvInferDeleter> m_Runtime;\n        };\n\n        class RuntimeWithAllocator : public Runtime\n        {\n        public:\n            using Runtime::Runtime;\n            virtual ~RuntimeWithAllocator() override;\n\n            using Runtime::deserialize_engine;\n            std::shared_ptr<Model> deserialize_engine(const void*, size_t, ::nvinfer1::IPluginFactory*) final override;\n        protected:\n            RuntimeWithAllocator(std::unique_ptr<NvAllocator> allocator);\n\n\n            NvAllocator& get_allocator()\n            {\n                return *m_Allocator;\n            }\n\n        private:\n            std::unique_ptr<NvAllocator> m_Allocator;\n        };\n\n        template <typename AllocatorType>\n        struct CustomRuntime : public RuntimeWithAllocator\n        {\n            CustomRuntime() : RuntimeWithAllocator(std::make_unique<AllocatorType>()) {}\n            virtual ~CustomRuntime() override {}\n        };\n\n        using StandardRuntime = CustomRuntime<StandardAllocator>;\n        using ManagedRuntime  = CustomRuntime<ManagedAllocator>;\n\n    } // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/utils.h",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <memory>\n\n#include <NvInfer.h>\n\nnamespace trtlab {\nnamespace TensorRT {\n\n/**\n * @brief Number of bytes for a given TensorRT DataType\n */\nstd::size_t SizeofDataType(const nvinfer1::DataType& dtype);\n\nstd::size_t dims_element_count(const nvinfer1::Dims& dims);\nstd::size_t data_type_size(const nvinfer1::DataType& dtype);\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/include/trtlab/tensorrt/workspace.h",
    "content": "#pragma once\n\n#include <vector>\n\n#include <cuda_runtime.h>\n\n#include <trtlab/core/utils.h>\n\n#include <trtlab/memory/descriptor.h>\n\n#include <trtlab/tensorrt/model.h>\n#include <trtlab/tensorrt/execution_context.h>\n\nnamespace trtlab\n{\n    namespace TensorRT\n    {\n        class WorkspaceBase\n        {\n            WorkspaceBase();\n            virtual ~WorkspaceBase();\n\n            cudaStream_t stream() { return m_Stream; }\n\n        private:\n            cudaStream_t m_Stream;\n        };\n\n        class StaticSingleModelGraphWorkspace\n        {\n        public:\n            using descriptor_t = trtlab::memory::descriptor;\n\n            StaticSingleModelGraphWorkspace(std::shared_ptr<Model>);\n            virtual ~StaticSingleModelGraphWorkspace();\n\n            DELETE_COPYABILITY(StaticSingleModelGraphWorkspace);\n            DELETE_MOVEABILITY(StaticSingleModelGraphWorkspace);\n\n            void enqueue();\n\n            descriptor_t& binding(std::uint32_t binding_id);\n\n            cudaStream_t stream()\n            {\n                return m_Stream;\n            }\n\n            std::size_t batch_size();\n\n            std::string name() const\n            {\n                return m_Name;\n            }\n\n        protected:\n            ExecutionContext& exec_ctx() { return m_Context; }\n\n        private:\n            ExecutionContext          m_Context;\n            std::vector<descriptor_t> m_Bindings;\n            std::vector<void*>        m_BindingPointers;\n            descriptor_t              m_DeviceMemory;\n            cudaStream_t              m_Stream;\n            cudaGraph_t               m_Graph;\n            cudaGraphExec_t           m_GraphExecutor;\n            std::string               m_Name;\n        };\n\n        class BenchmarkWorkspace : public StaticSingleModelGraphWorkspace\n        {\n        public:\n            BenchmarkWorkspace(std::shared_ptr<Model>);\n            ~BenchmarkWorkspace() override = default;\n\n            descriptor_t& host_binding(std::uint32_t binding_id);\n\n            void async_h2d();\n            void async_d2h();\n\n        private:\n            std::vector<descriptor_t> m_HostBindings;\n\n        };\n\n        class TimedBenchmarkWorkspace : private BenchmarkWorkspace\n        {\n        public:\n            TimedBenchmarkWorkspace(std::shared_ptr<Model>);\n            ~TimedBenchmarkWorkspace() override = default;\n\n            void enqueue_pipeline();\n\n            float get_compute_time_ms();\n            float get_h2d_time_ms();\n            float get_d2h_time_ms();\n\n            using BenchmarkWorkspace::binding;\n            using BenchmarkWorkspace::stream;\n\n        private:\n            cudaEvent_t m_Start;\n            cudaEvent_t m_CompleteAsyncH2D;\n            cudaEvent_t m_CompleteCompute;\n            cudaEvent_t m_CompleteAsyncD2H;\n        };\n\n    } // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/src/allocator.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/allocator.h\"\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <glog/logging.h>\n\n#include <trtlab/cuda/common.h>\n\nusing namespace trtlab;\nusing namespace TensorRT;\n\nvoid* NvAllocator::allocate(size_t size, uint64_t alignment, uint32_t flags)\n{\n    void*                                 ptr;\n    std::lock_guard<std::recursive_mutex> lock(m_Mutex);\n    if (m_UseWeightAllocator)\n    {\n        weights_allocate(&ptr, size);\n        m_Pointers.push_back(Pointer{ptr, size});\n    }\n    else\n    {\n        CHECK_CUDA(cudaMalloc(&ptr, size));\n        VLOG(2) << \"TensorRT cudaMalloc size = \" << size;\n    }\n    return ptr;\n}\n\nvoid NvAllocator::free(void* ptr)\n{\n    VLOG(3) << \"TensorRT cudaFree \" << ptr;\n    CHECK_CUDA(cudaFree(ptr));\n}\n\nconst std::vector<NvAllocator::Pointer>& NvAllocator::get_pointers()\n{\n    return m_Pointers;\n}\n\nvoid StandardAllocator::weights_allocate(void** ptr, size_t size)\n{\n    CHECK_CUDA(cudaMalloc(ptr, size));\n    VLOG(2) << \"TensorRT cudaMalloc size = \" << size << \"; \" << *ptr;\n}\n\nvoid ManagedAllocator::weights_allocate(void** ptr, size_t size)\n{\n    CHECK_CUDA(cudaMallocManaged(ptr, size));\n    VLOG(2) << \"TensorRT cudaMallocManaged size = \" << size << \"; \" << *ptr;\n    CHECK_CUDA(cudaMemAdvise(*ptr, size, cudaMemAdviseSetReadMostly, 0));\n}\n"
  },
  {
    "path": "trtlab/tensorrt/src/bindings.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/bindings.h\"\n\n#include <glog/logging.h>\n\n#include \"trtlab/core/memory/descriptor.h\"\n\nusing trtlab::Descriptor;\nusing trtlab::DescriptorHandle;\nusing trtlab::DeviceMemory;\nusing trtlab::HostMemory;\n\n/*\nnamespace {\nclass RawHostMemoryDescriptor final : public Descriptor<HostMemory>\n{\n  public:\n    RawHostMemoryDescriptor(void* ptr, size_t size)\n        : Descriptor<HostMemory>(ptr, size, \"BindingsRawPtr\")\n    {\n    }\n    ~RawHostMemoryDescriptor() final override {}\n};\n} // namespace\n*/\n\nnamespace trtlab {\nnamespace TensorRT {\n\nBindings::Bindings(const std::shared_ptr<Model> model, const std::shared_ptr<Buffers> buffers)\n    : m_Model(model), m_Buffers(buffers), m_BatchSize(0)\n{\n    auto count = model->GetBindingsCount();\n    m_HostAddresses.resize(count);\n    m_DeviceAddresses.resize(count);\n    for(auto i = 0; i < count; i++)\n    {\n        m_HostAddresses[i] = m_DeviceAddresses[i] = nullptr;\n    }\n}\n\nBindings::~Bindings() {}\n\ntypename Bindings::HostDescriptor& Bindings::HostMemoryDescriptor(int binding_id)\n{\n    CHECK_LT(binding_id, m_HostAddresses.size());\n    return m_HostDescriptors[binding_id];\n}\n\n/*\nvoid Bindings::SetHostAddress(int binding_id, void* addr)\n{\n    CHECK_LT(binding_id, m_HostAddresses.size());\n    auto mdesc = std::make_unique<RawHostMemoryDescriptor>(addr, BindingSize(binding_id));\n    m_HostAddresses[binding_id] = addr;\n    m_HostDescriptors[binding_id] = std::move(mdesc);\n}\n\n\nvoid Bindings::SetDeviceAddress(int binding_id, void* addr)\n{\n    CHECK_LT(binding_id, m_DeviceAddresses.size());\n    m_DeviceAddresses[binding_id] = addr;\n    m_DeviceDescriptors.erase(binding_id);\n}\n*/\n\nvoid Bindings::SetHostAddress(int binding_id, DescriptorHandle<HostMemory> mdesc)\n{\n    CHECK_LT(binding_id, m_HostAddresses.size());\n    m_HostAddresses[binding_id] = mdesc->Data();\n    m_HostDescriptors[binding_id] = std::move(mdesc);\n}\n\nvoid Bindings::SetDeviceAddress(int binding_id, DescriptorHandle<DeviceMemory> mdesc)\n{\n    CHECK_LT(binding_id, m_DeviceAddresses.size());\n    m_DeviceAddresses[binding_id] = mdesc->Data();\n    m_DeviceDescriptors[binding_id] = std::move(mdesc);\n}\n\nvoid* Bindings::HostAddress(uint32_t binding_id)\n{\n    CHECK_LT(binding_id, m_HostAddresses.size());\n    return m_HostAddresses[binding_id];\n}\n\nvoid* Bindings::DeviceAddress(uint32_t binding_id)\n{\n    CHECK_LT(binding_id, m_DeviceAddresses.size());\n    return m_DeviceAddresses[binding_id];\n}\n\nvoid** Bindings::DeviceAddresses() { return (void**)m_DeviceAddresses.data(); }\n\nvoid Bindings::CopyToDevice(uint32_t device_binding_id)\n{\n    auto host_src = HostAddress(device_binding_id);\n    auto bytes = BindingSize(device_binding_id);\n    CopyToDevice(device_binding_id, host_src, bytes);\n}\n\nvoid Bindings::CopyToDevice(const std::vector<uint32_t>& ids)\n{\n    for(auto id : ids)\n    {\n        CopyToDevice(id);\n    }\n}\n\nvoid Bindings::CopyToDevice(uint32_t device_binding_id, void* src, size_t bytes)\n{\n    auto dst = DeviceAddress(device_binding_id);\n    DLOG(INFO) << \"CopyToDevice binding_id: \" << device_binding_id << \"; size: \" << bytes;\n    CHECK_EQ(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyHostToDevice, Stream()), CUDA_SUCCESS);\n}\n\nvoid Bindings::CopyFromDevice(uint32_t device_binding_id)\n{\n    auto host_dst = HostAddress(device_binding_id);\n    auto bytes = BindingSize(device_binding_id);\n    CopyFromDevice(device_binding_id, host_dst, bytes);\n}\n\nvoid Bindings::CopyFromDevice(const std::vector<uint32_t>& ids)\n{\n    for(auto id : ids)\n    {\n        CopyFromDevice(id);\n    }\n}\n\nvoid Bindings::CopyFromDevice(uint32_t device_binding_id, void* dst, size_t bytes)\n{\n    auto src = DeviceAddress(device_binding_id);\n    DLOG(INFO) << \"CopyFromDevice binding_id: \" << device_binding_id << \"; size: \" << bytes;\n    CHECK_EQ(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyDeviceToHost, Stream()), CUDA_SUCCESS);\n}\n\nvoid Bindings::SetBatchSize(uint32_t batch_size)\n{\n    CHECK_LE(batch_size, m_Model->GetMaxBatchSize());\n    m_BatchSize = batch_size;\n}\n\nsize_t Bindings::BindingSize(uint32_t binding_id) const\n{\n    return m_Model->GetBinding(binding_id).bytesPerBatchItem *\n           (m_BatchSize ? m_BatchSize : m_Model->GetMaxBatchSize());\n}\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/src/buffers.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/buffers.h\"\n#include \"trtlab/tensorrt/bindings.h\"\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#include <glog/logging.h>\n\nusing trtlab::CudaDeviceMemory;\nusing trtlab::CudaPinnedHostMemory;\nusing trtlab::MemoryStack;\n\nnamespace trtlab {\nnamespace TensorRT {\n\nBuffers::Buffers()\n{\n    // CHECK(cudaStreamCreateWithFlags(&m_Stream, cudaStreamNonBlocking) == cudaSuccess); <-- breaks\n    CHECK_EQ(cudaStreamCreate(&m_Stream), cudaSuccess);\n}\n\nBuffers::~Buffers()\n{\n    DLOG(INFO) << \"Buffers Deconstructor\";\n    CHECK_EQ(cudaStreamSynchronize(m_Stream), CUDA_SUCCESS);\n    CHECK_EQ(cudaStreamDestroy(m_Stream), CUDA_SUCCESS);\n}\n\nauto Buffers::CreateBindings(const std::shared_ptr<Model>& model) -> std::shared_ptr<Bindings>\n{\n    auto bindings = std::shared_ptr<Bindings>(new Bindings(model, shared_from_this()));\n    ConfigureBindings(model, bindings);\n    return bindings;\n}\n\nvoid Buffers::ConfigureBindings(const std::shared_ptr<Model>& model,\n                                std::shared_ptr<Bindings> bindings)\n{\n    for(uint32_t i = 0; i < model->GetBindingsCount(); i++)\n    {\n        auto binding_size = model->GetBinding(i).bytesPerBatchItem * model->GetMaxBatchSize();\n        DLOG(INFO) << \"Configuring Binding \" << i << \": pushing \" << binding_size\n                   << \" to host/device stacks\";\n        bindings->SetHostAddress(i, AllocateHost(binding_size));\n        bindings->SetDeviceAddress(i, AllocateDevice(binding_size));\n    }\n}\n\nvoid Buffers::Synchronize()\n{\n    CHECK_EQ(cudaStreamSynchronize(m_Stream), CUDA_SUCCESS) << \"Stream Sync failed\";\n}\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/src/execution_context.cc",
    "content": "#include \"trtlab/tensorrt/execution_context.h\"\n#include \"trtlab/tensorrt/utils.h\"\n\n#include <glog/logging.h>\n\nusing namespace trtlab;\nusing namespace TensorRT;\n\nExecutionContext::ExecutionContext(model_t model)\n: m_Model(model), m_Context(nv_unique(model->engine().createExecutionContextWithoutDeviceMemory()))\n{\n}\n\nExecutionContext::~ExecutionContext()\n{\n    if (m_Context)\n    {\n        VLOG(2) << \"Destroying IExecutionContext \" << m_Context.get();\n    }\n}\n\nstd::size_t ExecutionContext::binding_size_in_bytes(std::uint32_t binding_id)\n{\n    auto dims = m_Context->getBindingDimensions(binding_id);\n    auto dtype = m_Context->getEngine().getBindingDataType(binding_id);\n    return dims_element_count(dims) * data_type_size(dtype);\n}\n"
  },
  {
    "path": "trtlab/tensorrt/src/infer_bench.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/infer_bench.h\"\n#include \"trtlab/tensorrt/bindings.h\"\n#include \"trtlab/tensorrt/infer_runner.h\"\n\n#include <glog/logging.h>\n\nnamespace trtlab {\nnamespace TensorRT {\n\nInferBench::InferBench(std::shared_ptr<InferenceManager> resources) : m_Resources(resources) {}\nInferBench::~InferBench() {}\n\nstd::unique_ptr<InferBench::Results> InferBench::Run(std::shared_ptr<Model> model,\n                                                     uint32_t batch_size, double seconds)\n{\n    std::vector<std::shared_ptr<Model>> models = {model};\n    return std::move(Run(models, batch_size, seconds));\n}\n\nstd::unique_ptr<InferBench::Results> InferBench::Run(const ModelsList& models, uint32_t batch_size,\n                                                     double seconds)\n{\n    size_t batch_count = 0;\n    std::vector<std::shared_future<void>> futures;\n    futures.reserve(1024 * 1024);\n\n    // Check ModelsList to ensure the requested batch_size is appropriate\n    for(const auto& model : models)\n    {\n        CHECK_LE(batch_size, model->GetMaxBatchSize());\n    }\n\n    // Setup std::chrono deadline - no more elapsed lambda\n    auto start = std::chrono::high_resolution_clock::now();\n    auto last = start + std::chrono::milliseconds(static_cast<long>(seconds * 1000));\n\n    // Benchmark loop over Models modulo size of ModelsList\n    while(std::chrono::high_resolution_clock::now() < last && ++batch_count)\n    {\n        size_t model_idx = batch_count % models.size();\n        const auto& model = models[model_idx];\n\n        auto buffers = InferResources().GetBuffers(); // <=== Limited Resource; May Block !!!\n        auto bindings = buffers->CreateBindings(model);\n        bindings->SetBatchSize(batch_size);\n\n        InferRunner runner(model, m_Resources);\n        futures.push_back(runner.Infer(\n            bindings, [](std::shared_ptr<Bindings>& bindings) mutable { bindings.reset(); }));\n    }\n\n    // Join worker threads\n    for(const auto& f : futures)\n    {\n        f.wait();\n    }\n\n    auto total_time =\n        std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start).count();\n    auto inferences = batch_count * batch_size;\n\n    auto results_ptr = std::make_unique<InferBench::Results>();\n    Results& results = *results_ptr;\n    results[kBatchSize] = batch_size;\n    results[kMaxExecConcurrency] = m_Resources->MaxExecConcurrency();\n    results[kMaxCopyConcurrency] = m_Resources->MaxCopyConcurrency();\n    results[kBatchesComputed] = batch_count;\n    results[kWalltime] = total_time;\n    results[kBatchesPerSecond] = batch_count / total_time;\n    results[kInferencesPerSecond] = inferences / total_time;\n    results[kExecutionTimePerBatch] =\n        total_time / (batch_count / m_Resources->MaxExecConcurrency());\n\n    DLOG(INFO) << \"Benchmark Run Complete\";\n\n    DLOG(INFO) << \"Inference Results: \" << results[kBatchesComputed] << \" batches computed in \"\n               << results[kWalltime] << \" seconds on \" << results[kMaxExecConcurrency]\n               << \" compute streams using batch_size: \" << results[kBatchSize]\n               << \"; inf/sec: \" << results[kInferencesPerSecond]\n               << \"; batches/sec: \" << results[kBatchesPerSecond]\n               << \"; execution time per batch: \" << results[kExecutionTimePerBatch];\n\n    return std::move(results_ptr);\n}\n\n} // namespace TensorRT\n} // namespace trtlab"
  },
  {
    "path": "trtlab/tensorrt/src/inference_manager.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/inference_manager.h\"\n\n#include <glog/logging.h>\n\n#include \"trtlab/cuda/device_info.h\"\n#include \"trtlab/cuda/memory/cuda_device.h\"\n#include \"trtlab/cuda/memory/cuda_pinned_host.h\"\n\nusing trtlab::CudaDeviceMemory;\nusing trtlab::CudaPinnedHostMemory;\n\nnamespace trtlab {\nnamespace TensorRT {\n\n/**\n * @brief General TensorRT Resource class\n *\n * Derived from trtlab::Resources, this InferenceManager object provides the basic memory and\n * compute resources needed for using with a TensorRT Context.  Limited quanity resources such as\n * Buffers and ExecutionContexts are managed by thead-safe Pools.  In general, the compute is always\n * limited by the number of resources. For example, limiting the number of ExecutionContexts to 1\n * will ensure only 1 Inference calcuation is using the GPU.  This will ensure best possible\n * latency. However, if you wish to improve throughput at the cost of increased latency, you can\n * increase the number of in-flight ExecutionContexts.  This will cause competition between the\n * multiple forward passes; however, it will also allow the GPU to better utilize the compute\n * resources of the GPU.\n *\n * Note: the number of Buffers should alway be nExec+1 or larger to ensure you are not resource\n * bound on the Buffers used for the Input and Output Tensors of the DNN.\n *\n * @see Pool for more details on how limited quantity Resources are managed.\n */\nInferenceManager::InferenceManager(int max_executions, int max_buffers)\n    : m_MaxExecutions(max_executions), m_MaxBuffers(max_buffers ? max_buffers : max_executions * 2),\n      m_HostStackSize(0), m_DeviceStackSize(0),\n      m_ActivationsSize(0), m_Buffers{nullptr}, m_ActiveRuntime{nullptr}\n{\n    // RegisterRuntime(\"default\", std::make_unique<CustomRuntime<StandardAllocator>>());\n    // SetActiveRuntime(\"default\");\n    LOG(INFO) << \"-- Initialzing TensorRT Resource Manager --\";\n    LOG(INFO) << \"Maximum Execution Concurrency: \" << m_MaxExecutions;\n    LOG(INFO) << \"Maximum Copy Concurrency: \" << m_MaxBuffers;\n}\n\nInferenceManager::~InferenceManager() { JoinAllThreads(); }\n\nint InferenceManager::MaxExecConcurrency() const { return m_MaxExecutions; }\n\nint InferenceManager::MaxCopyConcurrency() const { return m_MaxBuffers; }\n\n/**\n * @brief Register a Model with the InferenceManager object\n */\nvoid InferenceManager::RegisterModel(const std::string& name, std::shared_ptr<Model> model)\n{\n    RegisterModel(name, model, m_MaxExecutions);\n}\n\n/**\n * @brief Register a Model with the InferenceManager object\n *\n * This variant allows you to specify an alternate maximum concurrency for this model.  The value\n * must be 1 <= concurrency <= MaxConcurrency.  Larger values will be capped to the maximum\n * concurrency allowed by the InferenceManager object.\n */\nvoid InferenceManager::RegisterModel(const std::string& name, std::shared_ptr<Model> model,\n                                     uint32_t max_concurrency)\n{\n    auto item = m_Models.find(name);\n    if(item != m_Models.end())\n    {\n        LOG(ERROR) << \"Model naming collsion; Model with name=\" << name\n                   << \" is already registered.\";\n        return;\n    }\n\n    if(max_concurrency > m_MaxExecutions)\n    {\n        LOG(WARNING) << \"Requested concurrency (\" << max_concurrency\n                     << \") exceeds max concurrency. \"\n                     << \"Concurrency will be capped to \" << m_MaxExecutions;\n        max_concurrency = m_MaxExecutions;\n    }\n\n    // Size according to largest padding - device alignment\n    size_t bindings =\n        model->GetBindingMemorySize() + model->GetBindingsCount() * DeviceInfo::Alignment();\n    size_t activations = Align(model->GetActivationsMemorySize(), 128 * 1024); // add a cacheline\n\n    size_t host = Align(bindings, 32 * 1024);\n    size_t device = Align(bindings, 128 * 1024);\n\n    // TODO: Check to see if m_Buffers has been allocated.  If so, we should thown an exception\n    // if the registered model requirements are larger than our allocated buffers.\n    if(m_Buffers)\n    {\n        if(host > m_HostStackSize || device > m_DeviceStackSize)\n        {\n            throw std::runtime_error(\n                \"Required binding resources are greater than allocated capacity\");\n        }\n    }\n    if(m_ExecutionContexts)\n    {\n        if(activations > m_ActivationsSize)\n        {\n            throw std::runtime_error(\n                \"Required activation workspace is greater than allocated capacity\");\n        }\n    }\n\n    m_HostStackSize = std::max(m_HostStackSize, host);\n    m_DeviceStackSize = std::max(m_DeviceStackSize, device);\n    m_ActivationsSize = std::max(m_ActivationsSize, activations);\n\n    LOG(INFO) << \"-- Registering Model: \" << name << \" --\";\n    LOG(INFO) << \"Input/Output Tensors require \" << BytesToString(model->GetBindingMemorySize());\n    LOG(INFO) << \"Execution Activations require \"\n              << BytesToString(model->GetActivationsMemorySize());\n    auto weights = model->GetWeightsMemorySize();\n    if(weights) LOG(INFO) << \"Weights require \" << BytesToString(weights);\n\n    model->SetName(name);\n    m_Models[name] = model;\n    m_ModelExecutionContexts[model.get()] = Pool<::nvinfer1::IExecutionContext>::Create();\n    for(int i = 0; i < max_concurrency; i++)\n    {\n        m_ModelExecutionContexts[model.get()]->Push(model->CreateExecutionContext());\n    }\n}\n\nRuntime& InferenceManager::ActiveRuntime() { return *m_ActiveRuntime; }\n\nvoid InferenceManager::RegisterRuntime(const std::string& name, std::shared_ptr<Runtime> runtime)\n{\n    auto search = m_Runtimes.find(name);\n    CHECK(search == m_Runtimes.end());\n    m_Runtimes[name] = std::move(runtime);\n}\n\nvoid InferenceManager::SetActiveRuntime(const std::string& name)\n{\n    auto search = m_Runtimes.find(name);\n    CHECK(search != m_Runtimes.end());\n    m_ActiveRuntime = search->second.get();\n}\n\n/**\n * @brief Allocates Host and Device Resources for Inference\n *\n * Buffers are sized according to the registered models.  Models registered after\n * AllocateInferenceManager has been call that require larger buffers should throw an exception\n * (TODO).\n */\nvoid InferenceManager::AllocateResources()\n{\n    LOG(INFO) << \"-- Allocating TensorRT Resources --\";\n    LOG(INFO) << \"Creating \" << m_MaxExecutions << \" TensorRT execution tokens.\";\n    LOG(INFO) << \"Creating a Pool of \" << m_MaxBuffers << \" Host/Device Memory Stacks\";\n    LOG(INFO) << \"Each Host Stack contains \" << BytesToString(m_HostStackSize);\n    LOG(INFO) << \"Each Device Stack contains \" << BytesToString(m_DeviceStackSize);\n    LOG(INFO) << \"Total GPU Memory: \"\n              << BytesToString(m_MaxBuffers * m_DeviceStackSize +\n                               m_MaxExecutions * m_ActivationsSize);\n\n    m_Buffers = Pool<Buffers>::Create();\n    for(int i = 0; i < m_MaxBuffers; i++)\n    {\n        DLOG(INFO) << \"Allocating Host/Device Buffers #\" << i;\n        m_Buffers->Push(std::make_shared<FixedBuffers<CudaPinnedHostMemory, CudaDeviceMemory>>(\n            m_HostStackSize, m_DeviceStackSize));\n    }\n\n    m_ExecutionContexts = Pool<ExecutionContext>::Create();\n    for(int i = 0; i < m_MaxExecutions; i++)\n    {\n        m_ExecutionContexts->EmplacePush(new ExecutionContext(m_ActivationsSize));\n    }\n}\n\n/**\n * @brief Get a registered Model by name\n *\n * @param model_name\n * @return std::shared_ptr<Model>\n */\nauto InferenceManager::GetModel(std::string model_name) -> std::shared_ptr<Model>\n{\n    auto item = m_Models.find(model_name);\n    CHECK(item != m_Models.end()) << \"Unable to find entry for model: \" << model_name;\n    return item->second;\n}\n\n/**\n * @brief Get a Buffers from the Resource Pool (May Block!)\n *\n * This method aquires a limited quantity Buffers object from the Pool of Buffers.  This call may\n * block foward execution of the thread if no resources are available.\n *\n * Note: The resource will be returned to the resource Pool when the reference count of the\n * shared_ptr goes to zero.  No action on the user is required, unless they want to release the\n * object earlier by using the reset() function on all instances of the shared_ptr.\n *\n * @return std::shared_ptr<Buffers>\n */\nauto InferenceManager::GetBuffers() -> std::shared_ptr<Buffers>\n{\n    CHECK(m_Buffers) << \"Call AllocateResources() before trying to acquire a Buffers object.\";\n    return m_Buffers->Pop([](Buffers* ptr) {\n        ptr->Reset();\n        DLOG(INFO) << \"Releasing Buffers\";\n    });\n}\n\n/**\n * @brief Get an Exeuction Context object from the Resource Pool (May Block!)\n *\n * This method aquires a limited quantity ExecutionContext object from the Pool of\n * ExecutionContexts. This call may block foward execution of the thread if no resources are\n * available.\n *\n * Note: The resource will be returned to the resource Pool when the reference count of the\n * shared_ptr goes to zero.  No action on the user is required, unless they want to release the\n * object earlier by using the reset() function on all instances of the shared_ptr.\n *\n * @return std::shared_ptr<ExecutionContext>\n */\nauto InferenceManager::GetExecutionContext(const Model* model) -> std::shared_ptr<ExecutionContext>\n{\n    CHECK(m_ExecutionContexts)\n        << \"Call AllocateResources() before trying to acquire an ExeuctionContext.\";\n    auto item = m_ModelExecutionContexts.find(model);\n    CHECK(item != m_ModelExecutionContexts.end())\n        << \"No ExectionContext for model \" << model->Name();\n    // This is the global concurrency limiter - it owns the activation scratch memory\n    auto ctx = m_ExecutionContexts->Pop([](ExecutionContext* ptr) {\n        ptr->Reset();\n        DLOG(INFO) << \"Returning Execution Concurrency Limiter to Pool\";\n    });\n    // This is the model concurrency limiter - it owns the TensorRT IExecutionContext\n    // for which the pointer to the global limiter's memory buffer will be set\n    ctx->SetContext(item->second->Pop([](::nvinfer1::IExecutionContext* ptr) {\n        DLOG(INFO) << \"Returning Model IExecutionContext to Pool\";\n    }));\n    DLOG(INFO) << \"Acquired Concurrency Limiting Execution Context\";\n    return ctx;\n}\n\n/**\n * @brief Get an Exeuction Context object from the Resource Pool (May Block!)\n *\n * Convenience method for accepting a shared_ptr<Model> as input.\n *\n * @param model\n * @return std::shared_ptr<ExecutionContext>\n */\nauto InferenceManager::GetExecutionContext(const std::shared_ptr<Model>& model)\n    -> std::shared_ptr<ExecutionContext>\n{\n    return GetExecutionContext(model.get());\n}\n\nauto InferenceManager::AcquireThreadPool(const std::string& name) -> ThreadPool&\n{\n    // std::shared_lock<std::shared_mutex> lock(m_ThreadPoolMutex);\n    auto search = m_ThreadPools.find(name);\n    CHECK(search != m_ThreadPools.end());\n    return *(search->second);\n}\n\nvoid InferenceManager::RegisterThreadPool(const std::string& name,\n                                          std::unique_ptr<ThreadPool> threads)\n{\n    // std::unique_lock<std::shared_mutex> lock(m_ThreadPoolMutex);\n    DLOG(INFO) << \"Registering ThreadPool: \" << name;\n    // Old threadpools will continute to live until all threads are joined.\n    // this may need a mutex\n    m_ThreadPools[name].swap(threads);\n}\n\nbool InferenceManager::HasThreadPool(const std::string& name) const\n{\n    auto search = m_ThreadPools.find(name);\n    return (bool)(search != m_ThreadPools.end());\n}\n\nvoid InferenceManager::JoinAllThreads()\n{\n    // std::unique_lock<std::shared_mutex> lock(m_ThreadPoolMutex);\n    DLOG(INFO) << \"Joining All Threads\";\n    m_ThreadPools.clear();\n    DLOG(INFO) << \"All Threads Checked-In and Joined\";\n}\n\nvoid InferenceManager::ForEachModel(std::function<void(const Model&)> callback)\n{\n    for(const auto& item : m_Models)\n    {\n        callback(*(item.second));\n    }\n}\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/src/model.cc",
    "content": "#include \"trtlab/tensorrt/model.h\"\n#include \"trtlab/tensorrt/utils.h\"\n\n#include <glog/logging.h>\n\nusing namespace trtlab;\nusing namespace TensorRT;\n\nnamespace\n{\n    std::string ProfileSelectorString(nvinfer1::OptProfileSelector selector)\n    {\n        if (selector == nvinfer1::OptProfileSelector::kMIN)\n        {\n            return \"MIN\";\n        }\n        else if (selector == nvinfer1::OptProfileSelector::kOPT)\n        {\n            return \"OPT\";\n        }\n        else if (selector == nvinfer1::OptProfileSelector::kMAX)\n        {\n            return \"MAX\";\n        }\n        else\n        {\n            LOG(FATAL) << \"unknown profile selector\";\n        }\n    }\n} // namespace\n\nModel::Model(engine_t engine, const weights_t& weights) : m_Engine(engine), m_Weights(weights) {}\n\nModel::~Model()\n{\n    VLOG(2) << \"Destroying ICudaEngine \" << m_Engine.get();\n}\n\nstd::string Model::profiles_info() const\n{\n    std::stringstream ss;\n    ss << \"Optimization Profiles\" << std::endl;\n\n    for (int profile_id = 0; profile_id < m_Engine->getNbOptimizationProfiles(); profile_id++)\n    {\n        for (auto selector : {nvinfer1::OptProfileSelector::kMIN, nvinfer1::OptProfileSelector::kOPT, nvinfer1::OptProfileSelector::kMAX})\n        {\n            ss << \"Profile \" << profile_id << \" \"  << profile_info(profile_id, selector);\n        }\n    }\n    return ss.str();\n}\n\nstd::string Model::profile_info(std::uint32_t profile_id, nvinfer1::OptProfileSelector selector) const\n{\n    CHECK_LT(profile_id, m_Engine->getNbOptimizationProfiles());\n    std::stringstream ss;\n\n    for (int binding_id = 0; binding_id < m_Engine->getNbBindings(); binding_id++)\n    {\n        if (m_Engine->bindingIsInput(binding_id))\n        {\n            auto dims = m_Engine->getProfileDimensions(binding_id, profile_id, selector);\n            ss << ProfileSelectorString(selector) << \" - input_binding \" << binding_id << \": name=\" << m_Engine->getBindingName(binding_id)\n               << \"; \";\n            ss << TensorRT::Model::dims_info(dims);\n            ss << std::endl;\n        }\n    }\n    return ss.str();\n}\n\nstd::string Model::bindings_info() const\n{\n    std::stringstream ss;\n    for (int i = 0; i < m_Engine->getNbBindings(); i++)\n    {\n        ss << binding_info(i) << std::endl;\n    }\n    return ss.str();\n}\n\nstd::string Model::binding_info(std::uint32_t binding_id) const\n{\n    std::stringstream ss;\n    ss << \"binding \" << binding_id << \": name=\" << m_Engine->getBindingName(binding_id) << \"; \";\n    ss << dims_info(m_Engine->getBindingDimensions(binding_id));\n    ss << \"; isInput=\" << (m_Engine->bindingIsInput(binding_id) ? \"TRUE\" : \"FALSE\");\n    return ss.str();\n}\n\nstd::string Model::dims_info(const nvinfer1::Dims& dims)\n{\n    std::stringstream ss;\n    ss << \"ndims=\" << dims.nbDims << \"; [\";\n    for (int i = 0; i < dims.nbDims; i++)\n        ss << \" \" << dims.d[i];\n    ss << \" ]\";\n    return ss.str();\n}\n\nstd::size_t Model::binding_element_count(std::uint32_t binding_id) const\n{\n    auto dims = m_Engine->getBindingDimensions(binding_id);\n    std::size_t count = 1;\n    for(int i=0; i<dims.nbDims; i++)\n    {\n        count *= dims.d[i];\n    }\n    return count;\n}\n\nstd::size_t Model::binding_size_in_bytes(std::uint32_t binding_id) const\n{\n    auto dtype = m_Engine->getBindingDataType(binding_id);\n    return data_type_size(dtype) * binding_element_count(binding_id);\n}"
  },
  {
    "path": "trtlab/tensorrt/src/runtime.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/runtime.h\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <glog/logging.h>\n\nusing namespace trtlab;\nusing namespace TensorRT;\n\nnamespace\n{\n    bool file_exists(const std::string& name)\n    {\n        struct stat buffer;\n        return (stat(name.c_str(), &buffer) == 0);\n    }\n} // namespace\n\nRuntime::Runtime() : m_Logger(std::make_unique<Logger>()), m_Runtime(nv_unique(::nvinfer1::createInferRuntime(*(m_Logger.get()))))\n{\n    m_Logger->log(::nvinfer1::ILogger::Severity::kINFO, \"IRuntime Logger Initialized\");\n}\n\nRuntime::~Runtime()\n{\n    VLOG(2) << \"Destorying Runtime \" << this;\n}\n\n::nvinfer1::IRuntime& Runtime::get_runtime() const\n{\n    return *m_Runtime;\n}\n\nstd::shared_ptr<Model> Runtime::deserialize_engine(const std::string& plan_file)\n{\n    VLOG(2) << \"Deserializing TensorRT ICudaEngine from file: \" << plan_file;\n    const auto& buffer = read_engine_file(plan_file);\n    return deserialize_engine(buffer.data(), buffer.size(), nullptr);\n}\n\nstd::shared_ptr<Model> Runtime::deserialize_engine(const std::string& plan_file, ::nvinfer1::IPluginFactory* plugin_factory)\n{\n    VLOG(2) << \"Deserializing TensorRT ICudaEngine from file: \" << plan_file;\n    const auto& buffer = read_engine_file(plan_file);\n    return deserialize_engine(buffer.data(), buffer.size(), plugin_factory);\n}\n\nstd::shared_ptr<Model> Runtime::deserialize_engine(const void* data, size_t size)\n{\n    return deserialize_engine(data, size, nullptr);\n}\n\nstd::vector<char> Runtime::read_engine_file(const std::string& plan_file) const\n{\n    if(!file_exists(plan_file))\n    {\n        throw std::runtime_error(\"tensorrt engine file does not exist: \" + plan_file);\n    }\n    VLOG(2) << \"Reading Engine: \" << plan_file;\n    std::ifstream   file(plan_file, std::ios::binary | std::ios::ate);\n    std::streamsize size = file.tellg();\n    CHECK_GT(size, 0);\n    std::vector<char> buffer(size);\n    file.seekg(0, std::ios::beg);\n    CHECK(file.read(buffer.data(), size)) << \"Unable to read engine file: \" << plan_file;\n    return buffer;\n}\n\nRuntime::Logger::~Logger()\n{\n    VLOG(2) << \"Destroying Logger \" << this;\n}\n\nvoid Runtime::Logger::log(::nvinfer1::ILogger::Severity severity, const char* msg)\n{\n    switch (severity)\n    {\n    case Severity::kINTERNAL_ERROR:\n        LOG(FATAL) << \"[TensorRT.INTERNAL_ERROR]: \" << msg;\n        break;\n    case Severity::kERROR:\n        LOG(FATAL) << \"[TensorRT.ERROR]: \" << msg;\n        break;\n    case Severity::kWARNING:\n        LOG(WARNING) << \"[TensorRT.WARNING]: \" << msg;\n        break;\n    case Severity::kINFO:\n        VLOG(2) << \"[TensorRT.INFO]: \" << msg;\n        break;\n    default:\n        VLOG(2) << \"[TensorRT.DEBUG]: \" << msg;\n        break;\n    }\n}\n\nRuntimeWithAllocator::RuntimeWithAllocator(std::unique_ptr<NvAllocator> allocator) : Runtime(), m_Allocator(std::move(allocator))\n{\n    get_runtime().setGpuAllocator(m_Allocator.get());\n}\n\nRuntimeWithAllocator::~RuntimeWithAllocator()\n{\n    get_runtime().setGpuAllocator(nullptr);\n}\n\nstd::shared_ptr<Model> RuntimeWithAllocator::deserialize_engine(const void* data, size_t size, ::nvinfer1::IPluginFactory* plugin_factory)\n{\n    VLOG(2) << \"Deserializing Custom TensorRT ICudaEngine\";\n    return get_allocator().use_weights_allocator([this, data, size, plugin_factory]() mutable -> std::shared_ptr<Model> {\n        auto runtime = this->shared_from_this();\n        auto engine  = nv_shared(get_runtime().deserializeCudaEngine(data, size, plugin_factory), [runtime]() mutable { runtime.reset(); });\n        CHECK(engine) << \"Unable to create ICudaEngine\";\n        return std::make_shared<Model>(engine, get_allocator().get_pointers());\n    });\n}\n"
  },
  {
    "path": "trtlab/tensorrt/src/utils.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/core/utils.h\"\n\n#include <NvInfer.h>\n\n#include <glog/logging.h>\n\nnamespace trtlab {\nnamespace TensorRT {\n\nstd::size_t SizeofDataType(const nvinfer1::DataType& dtype)\n{\n    switch(dtype)\n    {\n        case nvinfer1::DataType::kFLOAT:\n        case nvinfer1::DataType::kINT32:\n            return 4;\n        case nvinfer1::DataType::kHALF:\n            return 2;\n        case nvinfer1::DataType::kINT8:\n            return 1;\n        default:\n            LOG(FATAL) << \"Unknown TensorRT DataType\";\n    }\n}\n\nstd::size_t data_type_size(const nvinfer1::DataType& dtype)\n{\n    return SizeofDataType(dtype);\n}\n\nstd::size_t dims_element_count(const nvinfer1::Dims& dims)\n{\n    std::size_t count = 1;\n    for(int i=0; i<dims.nbDims; i++)\n    {\n        count *= dims.d[i];\n    }\n    return count;\n}\n\n} // namespace TensorRT\n} // namespace trtlab\n"
  },
  {
    "path": "trtlab/tensorrt/src/workspace.cc",
    "content": "#include <trtlab/tensorrt/workspace.h>\n#include <trtlab/tensorrt/utils.h>\n\n#include <trtlab/cuda/common.h>\n#include <trtlab/cuda/memory/cuda_allocators.h>\n\nusing namespace trtlab;\nusing namespace TensorRT;\n\nWorkspaceBase::WorkspaceBase()\n{\n    CHECK_CUDA(cudaStreamCreate(&m_Stream));\n}\n\nWorkspaceBase::~WorkspaceBase()\n{\n    CHECK_CUDA(cudaStreamSynchronize(m_Stream));\n    CHECK_CUDA(cudaStreamDestroy(m_Stream));\n}\n\nStaticSingleModelGraphWorkspace::StaticSingleModelGraphWorkspace(std::shared_ptr<Model> model) : m_Context(model)\n{\n    auto& engine      = m_Context.engine();\n    auto  cuda_malloc = memory::make_cuda_allocator();\n\n    std::stringstream ss;\n    ss << this;\n    m_Name = ss.str();\n\n    //m_Context.context().setOptimizationProfile(0);\n\n    for (int i = 0; i < engine.getNbBindings(); i++)\n    {\n        auto bytes = m_Context.binding_size_in_bytes(i);\n        VLOG(2) << \"binding \" << i << \": bytes = \" << bytes;\n        m_Bindings.emplace_back(cuda_malloc.allocate_descriptor(bytes));\n        m_BindingPointers.push_back(m_Bindings[i].data());\n    }\n\n    m_DeviceMemory = cuda_malloc.allocate_descriptor(engine.getDeviceMemorySize());\n    m_Context.context().setDeviceMemory(m_DeviceMemory.data());\n    VLOG(2) << \"execution context device memory: \" << m_DeviceMemory.size();\n\n    CHECK_CUDA(cudaStreamCreate(&m_Stream));\n\n    // warm up and let mContext do cublas initialization\n    m_Context.context().enqueueV2(m_BindingPointers.data(), m_Stream, nullptr);\n\n    // create graph\n    //CHECK_CUDA(cudaStreamBeginCapture(m_Stream, cudaStreamCaptureModeThreadLocal));\n    CHECK_CUDA(cudaStreamBeginCapture(m_Stream, cudaStreamCaptureModeRelaxed));\n    m_Context.context().enqueueV2(m_BindingPointers.data(), m_Stream, nullptr);\n    CHECK_CUDA(cudaStreamEndCapture(m_Stream, &m_Graph));\n\n    // create graph executor\n    CHECK_CUDA(cudaGraphInstantiate(&m_GraphExecutor, m_Graph, NULL, NULL, 0));\n}\n\nStaticSingleModelGraphWorkspace::~StaticSingleModelGraphWorkspace()\n{\n    DVLOG(3) << \"StaticSingleModelGraphWorkspace Deconstructor\";\n    CHECK_CUDA(cudaStreamSynchronize(m_Stream));\n\n    DVLOG(4) << \"Destroying GraphExecutors\";\n    CHECK_CUDA(cudaGraphExecDestroy(m_GraphExecutor));\n\n    DVLOG(4) << \"Destroying Graphs\";\n    CHECK_CUDA(cudaGraphDestroy(m_Graph));\n\n    CHECK_CUDA(cudaStreamDestroy(m_Stream));\n}\n\nvoid StaticSingleModelGraphWorkspace::enqueue()\n{\n    CHECK_CUDA(cudaGraphLaunch(m_GraphExecutor, m_Stream));\n}\n\nmemory::descriptor& StaticSingleModelGraphWorkspace::binding(std::uint32_t binding_id)\n{\n    DCHECK_LT(binding_id, m_Bindings.size());\n    return m_Bindings[binding_id];\n}\n\nstd::size_t StaticSingleModelGraphWorkspace::batch_size()\n{\n    auto dims = m_Context.context().getBindingDimensions(0);\n    return dims.d[0];\n}\n\nBenchmarkWorkspace::BenchmarkWorkspace(std::shared_ptr<Model> model) : StaticSingleModelGraphWorkspace(model)\n{\n    auto pinned_alloc = memory::make_allocator(memory::cuda_malloc_host_allocator());\n\n    for (int i = 0; i < exec_ctx().engine().getNbBindings(); i++)\n    {\n        auto bytes = binding(i).size();\n        VLOG(2) << \"binding \" << i << \": bytes = \" << bytes;\n        m_HostBindings.emplace_back(pinned_alloc.allocate_descriptor(bytes));\n    }\n}\n\nvoid BenchmarkWorkspace::async_h2d()\n{\n    for (int i = 0; i < m_HostBindings.size(); i++)\n    {\n        if (exec_ctx().engine().bindingIsInput(i))\n        {\n            CHECK_CUDA(\n                cudaMemcpyAsync(binding(i).data(), m_HostBindings[i].data(), m_HostBindings[i].size(), cudaMemcpyHostToDevice, stream()));\n        }\n    }\n}\n\nvoid BenchmarkWorkspace::async_d2h()\n{\n    for (int i = 0; i < m_HostBindings.size(); i++)\n    {\n        if (!exec_ctx().engine().bindingIsInput(i))\n        {\n            CHECK_CUDA(\n                cudaMemcpyAsync(m_HostBindings[i].data(), binding(i).data(), m_HostBindings[i].size(), cudaMemcpyDeviceToHost, stream()));\n        }\n    }\n}\n\nTimedBenchmarkWorkspace::TimedBenchmarkWorkspace(std::shared_ptr<Model> model) : BenchmarkWorkspace(model)\n{\n    CHECK_CUDA(cudaEventCreate(&m_Start));\n    CHECK_CUDA(cudaEventCreate(&m_CompleteAsyncH2D));\n    CHECK_CUDA(cudaEventCreate(&m_CompleteCompute));\n    CHECK_CUDA(cudaEventCreate(&m_CompleteAsyncD2H));\n}\n\nvoid TimedBenchmarkWorkspace::enqueue_pipeline()\n{\n    CHECK_CUDA(cudaEventRecord(m_Start, stream()));\n    async_h2d();\n    CHECK_CUDA(cudaEventRecord(m_CompleteAsyncH2D, stream()));\n    enqueue();\n    CHECK_CUDA(cudaEventRecord(m_CompleteCompute, stream()));\n    async_d2h();\n    CHECK_CUDA(cudaEventRecord(m_CompleteAsyncD2H, stream()));\n}\n\nfloat TimedBenchmarkWorkspace::get_compute_time_ms()\n{\n    float ms = 0.0;\n    CHECK_CUDA(cudaEventElapsedTime(&ms, m_CompleteAsyncH2D, m_CompleteCompute));\n    return ms;\n}\n\nfloat TimedBenchmarkWorkspace::get_h2d_time_ms()\n{\n    float ms = 0.0;\n    CHECK_CUDA(cudaEventElapsedTime(&ms, m_Start, m_CompleteAsyncH2D));\n    return ms;\n}\n\nfloat TimedBenchmarkWorkspace::get_d2h_time_ms()\n{\n    float ms = 0.0;\n    CHECK_CUDA(cudaEventElapsedTime(&ms, m_CompleteCompute, m_CompleteAsyncD2H));\n    return ms;\n}\n"
  },
  {
    "path": "trtlab/tensorrt/tests/CMakeLists.txt",
    "content": "# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions\n# are met:\n#  * Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#  * Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#  * Neither the name of NVIDIA CORPORATION nor the names of its\n#    contributors may be used to endorse or promote products derived\n#    from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#include_directories(${GTEST_INCLUDE_DIRS})\n\nadd_executable(test_tensorrt\n  test_buffers.cc\n)\n\ntarget_link_libraries(test_tensorrt\n    ${PROJECT_NAME}::tensorrt\n    ${GTEST_BOTH_LIBRARIES}\n)\n\nadd_test(\n  NAME tensorrt\n  COMMAND $<TARGET_FILE:test_tensorrt\n)\n"
  },
  {
    "path": "trtlab/tensorrt/tests/test_buffers.cc",
    "content": "/* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *  * Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of NVIDIA CORPORATION nor the names of its\n *    contributors may be used to endorse or promote products derived\n *    from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"trtlab/tensorrt/buffers.h\"\n#include \"trtlab/tensorrt/inference_manager.h\"\n\n#include \"trtlab/core/memory/malloc.h\"\n#include \"trtlab/cuda/memory/cuda_device.h\"\n#include \"trtlab/cuda/memory/cuda_managed.h\"\n#include \"trtlab/cuda/memory/cuda_pinned_host.h\"\n#include \"gtest/gtest.h\"\n\n#include <list>\n\nusing namespace trtlab;\nusing namespace trtlab;\nusing namespace trtlab::TensorRT;\n\nnamespace {\n\nstatic size_t one_mb = 1024 * 1024;\n\n/*\ntemplate<typename T>\nclass TestBuffers : public ::testing::Test\n{\n};\n\nusing MemoryTypes =\n    ::testing::Types<Malloc, CudaDeviceMemory, CudaManagedMemory, CudaPinnedHostMemory>;\n\nTYPED_TEST_CASE(TestBuffers, MemoryTypes);\n\nTYPED_TEST(TestBuffers, make_shared)\n{\n    auto buffers = std::make_shared<FixedBuffers>(one_mb, one_mb);\n}\n*/\n\nclass TestCyclicBuffers : public ::testing::Test\n{\n};\n\nTEST_F(TestCyclicBuffers, CyclicBuffers)\n{\n    auto host = std::make_unique<CyclicAllocator<CudaPinnedHostMemory>>(5, 1024 * 1024);\n    auto device = std::make_unique<CyclicAllocator<CudaDeviceMemory>>(5, 1024 * 1024);\n\n    auto buffers = std::make_shared<CyclicBuffers<CudaPinnedHostMemory, CudaDeviceMemory>>(\n        std::move(host), std::move(device));\n\n    auto b0 = buffers->AllocateHost(1024);\n    auto b1 = buffers->AllocateDevice(1024);\n}\n\n} // namespace\n"
  }
]