From d4e94a5ab422e3d66280e957daf50e7f15b1f125 Mon Sep 17 00:00:00 2001 From: Luca Terracciano Date: Thu, 11 Sep 2025 11:38:47 +0200 Subject: [PATCH 1/5] refactor: update RPC Engine --- include/deployr/deployr.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/deployr/deployr.hpp b/include/deployr/deployr.hpp index 8678c23..6f8feec 100644 --- a/include/deployr/deployr.hpp +++ b/include/deployr/deployr.hpp @@ -114,7 +114,7 @@ class DeployR final } // Sending RPC - _rpcEngine->requestRPC(*instance, initialFcName, runnerId); + _rpcEngine->requestRPC(instance->getId(), initialFcName, runnerId); } // Running initial function, if one has been assigned to the coordinator @@ -209,10 +209,10 @@ class DeployR final else // If not, it's another instance: send RPC and deserialize return value { // Requesting RPC from the remote instance - _rpcEngine->requestRPC(*instance, __DEPLOYR_GET_TOPOLOGY_RPC_NAME); + _rpcEngine->requestRPC(instance->getId(), __DEPLOYR_GET_TOPOLOGY_RPC_NAME); // Getting return value as a memory slot - auto returnValue = _rpcEngine->getReturnValue(*instance); + auto returnValue = _rpcEngine->getReturnValue(); // Receiving raw serialized topology information from the worker std::string serializedTopology = (char *)returnValue->getPointer(); From 46ece4a0d78960c2176bdd8495d38ad819a1e47c Mon Sep 17 00:00:00 2001 From: Luca Terracciano Date: Mon, 15 Sep 2025 12:06:13 +0200 Subject: [PATCH 2/5] feat: temporarily use cloudr not as a submodule --- extern/HiCR | 2 +- extern/cloudrRPC/.clang-format | 126 ++++++ extern/cloudrRPC/.fix-style.sh | 3 + extern/cloudrRPC/.gitignore | 6 + extern/cloudrRPC/.gitlab-ci.yml | 52 +++ extern/cloudrRPC/.gitmodules | 6 + extern/cloudrRPC/LICENSE | 201 +++++++++ extern/cloudrRPC/README.md | 17 + extern/cloudrRPC/examples/clone/clone.cpp | 63 +++ extern/cloudrRPC/examples/clone/meson.build | 6 + extern/cloudrRPC/examples/meson.build | 1 + .../extern/run-clang-format/.clang-format | 12 + .../run-clang-format/.clang-format-ignore | 2 + .../extern/run-clang-format/.travis.yml | 12 + .../cloudrRPC/extern/run-clang-format/LICENSE | 21 + .../extern/run-clang-format/README.rst | 72 ++++ .../run-clang-format/run-clang-format.py | 408 ++++++++++++++++++ .../extern/run-clang-format/screenshot.png | Bin 0 -> 26702 bytes .../extern/run-clang-format/src/foo.cpp | 7 + .../run-clang-format/src/third_party/qux.cpp | 9 + extern/cloudrRPC/gcovr.cfg | 1 + .../backends/cloudr/communicationManager.hpp | 331 ++++++++++++++ .../include/hicr/backends/cloudr/instance.hpp | 109 +++++ .../hicr/backends/cloudr/instanceManager.hpp | 399 +++++++++++++++++ extern/cloudrRPC/meson.build | 65 +++ extern/cloudrRPC/meson_options.txt | 11 + extern/cloudrRPC/tests/meson.build | 26 ++ meson.build | 2 +- 28 files changed, 1968 insertions(+), 2 deletions(-) create mode 100644 extern/cloudrRPC/.clang-format create mode 100755 extern/cloudrRPC/.fix-style.sh create mode 100644 extern/cloudrRPC/.gitignore create mode 100644 extern/cloudrRPC/.gitlab-ci.yml create mode 100644 extern/cloudrRPC/.gitmodules create mode 100644 extern/cloudrRPC/LICENSE create mode 100644 extern/cloudrRPC/README.md create mode 100644 extern/cloudrRPC/examples/clone/clone.cpp create mode 100644 extern/cloudrRPC/examples/clone/meson.build create mode 100644 extern/cloudrRPC/examples/meson.build create mode 100644 extern/cloudrRPC/extern/run-clang-format/.clang-format create mode 100644 extern/cloudrRPC/extern/run-clang-format/.clang-format-ignore create mode 100644 extern/cloudrRPC/extern/run-clang-format/.travis.yml create mode 100644 extern/cloudrRPC/extern/run-clang-format/LICENSE create mode 100644 extern/cloudrRPC/extern/run-clang-format/README.rst create mode 100755 extern/cloudrRPC/extern/run-clang-format/run-clang-format.py create mode 100644 extern/cloudrRPC/extern/run-clang-format/screenshot.png create mode 100644 extern/cloudrRPC/extern/run-clang-format/src/foo.cpp create mode 100644 extern/cloudrRPC/extern/run-clang-format/src/third_party/qux.cpp create mode 100644 extern/cloudrRPC/gcovr.cfg create mode 100644 extern/cloudrRPC/include/hicr/backends/cloudr/communicationManager.hpp create mode 100644 extern/cloudrRPC/include/hicr/backends/cloudr/instance.hpp create mode 100644 extern/cloudrRPC/include/hicr/backends/cloudr/instanceManager.hpp create mode 100644 extern/cloudrRPC/meson.build create mode 100644 extern/cloudrRPC/meson_options.txt create mode 100644 extern/cloudrRPC/tests/meson.build diff --git a/extern/HiCR b/extern/HiCR index 38d39f8..6f49ccb 160000 --- a/extern/HiCR +++ b/extern/HiCR @@ -1 +1 @@ -Subproject commit 38d39f8661ba0c7af5c012280dffda757ac382d4 +Subproject commit 6f49ccb094d1d359ac85ffbd970e2b85bb1eff40 diff --git a/extern/cloudrRPC/.clang-format b/extern/cloudrRPC/.clang-format new file mode 100644 index 0000000..770b743 --- /dev/null +++ b/extern/cloudrRPC/.clang-format @@ -0,0 +1,126 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: 0 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +AllowShortLambdasOnASingleLine: All +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterCaseLabel : true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 180 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Always +EmptyLineBeforeAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: BeforeHash +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: Never +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300000 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 50 +PenaltyReturnTypeOnItsOwnLine: 600 +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++20 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 2 +UseTab: Never +... diff --git a/extern/cloudrRPC/.fix-style.sh b/extern/cloudrRPC/.fix-style.sh new file mode 100755 index 0000000..643e517 --- /dev/null +++ b/extern/cloudrRPC/.fix-style.sh @@ -0,0 +1,3 @@ +.build-tools/style/check-style.sh fix include/ +.build-tools/style/check-style.sh fix examples/ +.build-tools/style/check-style.sh fix tests/ diff --git a/extern/cloudrRPC/.gitignore b/extern/cloudrRPC/.gitignore new file mode 100644 index 0000000..84788f4 --- /dev/null +++ b/extern/cloudrRPC/.gitignore @@ -0,0 +1,6 @@ +build +*.patch +~* +.vscode +atlas_*.sh +**/matrix/ diff --git a/extern/cloudrRPC/.gitlab-ci.yml b/extern/cloudrRPC/.gitlab-ci.yml new file mode 100644 index 0000000..f45f62a --- /dev/null +++ b/extern/cloudrRPC/.gitlab-ci.yml @@ -0,0 +1,52 @@ +build: + image: registry.gitlab.huaweirc.ch/zrc-von-neumann-lab/runtime-system-innovations/cloudr/buildenv:latest + variables: + GIT_SUBMODULE_STRATEGY: recursive + tags: + - docker + - x86 + - infiniband + script: + - export HOME=/home/hicr + - source /home/hicr/.hicr-env.sh + - echo "Building CloudR..." + - mkdir build + - meson setup build -Dbuildtype=debug -Db_coverage=true -DbuildTests=true -DbuildExamples=true -DcompileWarningsAsErrors=true + - meson compile -C build + - echo "Running tests..." + - meson test -C build + - echo "Creating coverage report..." + - ninja -C build coverage + coverage: /^\s*lines:\s*\d+.\d+\%/ + artifacts: + name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA} + expire_in: 2 days + when: always + paths: + - build/meson-logs/* + reports: + coverage_report: + coverage_format: cobertura + path: build/meson-logs/coverage.xml + only: + - master + - merge_requests + - tags + +docs: + image: registry.gitlab.huaweirc.ch/zrc-von-neumann-lab/runtime-system-innovations/hicr/docs:1.0 + tags: + - docker + - tiny + script: + - echo "Checking TaskR source and test formatting..." + - .build-tools/style/check-style.sh check include + - .build-tools/style/check-style.sh check tests + - .build-tools/style/check-style.sh check examples + - echo "Building code documentation..." + - make -j1 -C docs + only: + - master + - merge_requests + - tags + diff --git a/extern/cloudrRPC/.gitmodules b/extern/cloudrRPC/.gitmodules new file mode 100644 index 0000000..509637a --- /dev/null +++ b/extern/cloudrRPC/.gitmodules @@ -0,0 +1,6 @@ +[submodule "extern/HiCR"] + path = extern/HiCR + url = https://github.com/Algebraic-Programming/HiCR.git +[submodule "extern/TaskR"] + path = extern/TaskR + url = https://github.com/Algebraic-Programming/TaskR.git diff --git a/extern/cloudrRPC/LICENSE b/extern/cloudrRPC/LICENSE new file mode 100644 index 0000000..df0bb94 --- /dev/null +++ b/extern/cloudrRPC/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/extern/cloudrRPC/README.md b/extern/cloudrRPC/README.md new file mode 100644 index 0000000..e1afee2 --- /dev/null +++ b/extern/cloudrRPC/README.md @@ -0,0 +1,17 @@ +CloudR is a [HiCR](https://github.com/Algebraic-Programming/HiCR)-based Cloud service emulator. + +## License + +Copyright 2025 Huawei Technologies Co., Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/extern/cloudrRPC/examples/clone/clone.cpp b/extern/cloudrRPC/examples/clone/clone.cpp new file mode 100644 index 0000000..27324e4 --- /dev/null +++ b/extern/cloudrRPC/examples/clone/clone.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void entryPoint(HiCR::backend::cloudr::InstanceManager &cloudr, const HiCR::Topology &localTopology) +{ + printf("[Instance %lu] I am in the entry point.\n", cloudr.getCurrentInstance()->getId()); + + // If I am the root instance, create the others with a similar architecture as mine + if (cloudr.getCurrentInstance()->isRootInstance() == true) + { + // Creating an instance template with our current topology (cloning) + const auto instanceTemplate = cloudr.createInstanceTemplate(localTopology); + + // Creating the other instance based on the template + cloudr.createInstance(*instanceTemplate); + } +} + +int main(int argc, char *argv[]) +{ + // Instantiating base managers + auto instanceManager = HiCR::backend::mpi::InstanceManager::createDefault(&argc, &argv); + auto communicationManager = HiCR::backend::mpi::CommunicationManager(MPI_COMM_WORLD); + auto memoryManager = HiCR::backend::mpi::MemoryManager(); + auto computeManager = HiCR::backend::pthreads::ComputeManager(); + + // Reserving memory for hwloc + hwloc_topology_t hwlocTopology; + hwloc_topology_init(&hwlocTopology); + + // Initializing HWLoc-based host (CPU) topology manager + auto hwlocTopologyManager = HiCR::backend::hwloc::TopologyManager(&hwlocTopology); + + // Finding the first memory space and compute resource to create our RPC engine + const auto &topology = hwlocTopologyManager.queryTopology(); + const auto &firstDevice = topology.getDevices().begin().operator*(); + const auto &RPCMemorySpace = firstDevice->getMemorySpaceList().begin().operator*(); + const auto &RPCComputeResource = firstDevice->getComputeResourceList().begin().operator*(); + + // Instantiating RPC engine + HiCR::frontend::RPCEngine rpcEngine(communicationManager, *instanceManager, memoryManager, computeManager, RPCMemorySpace, RPCComputeResource); + + // Initializing RPC engine + rpcEngine.initialize(); + + // Instantiating CloudR + HiCR::backend::cloudr::InstanceManager cloudrInstanceManager(&rpcEngine, topology, [&]() { entryPoint(cloudrInstanceManager, topology); }); + + // Initializing CloudR + cloudrInstanceManager.initialize(); + + // Finalizing cloudR + cloudrInstanceManager.finalize(); + + // Finalizing base instance manager + instanceManager->finalize(); +} diff --git a/extern/cloudrRPC/examples/clone/meson.build b/extern/cloudrRPC/examples/clone/meson.build new file mode 100644 index 0000000..38fe4b0 --- /dev/null +++ b/extern/cloudrRPC/examples/clone/meson.build @@ -0,0 +1,6 @@ +testSuite = [ 'examples', 'clone' ] + +clone = executable('clone', [ 'clone.cpp'], dependencies: CloudRBuildDep) +if get_option('buildTests') + test('clone', mpirunExecutable, args : [ '-np', '5', '--oversubscribe', clone.full_path() ], timeout: 60, suite: testSuite ) +endif diff --git a/extern/cloudrRPC/examples/meson.build b/extern/cloudrRPC/examples/meson.build new file mode 100644 index 0000000..0e76160 --- /dev/null +++ b/extern/cloudrRPC/examples/meson.build @@ -0,0 +1 @@ +subdir('clone') diff --git a/extern/cloudrRPC/extern/run-clang-format/.clang-format b/extern/cloudrRPC/extern/run-clang-format/.clang-format new file mode 100644 index 0000000..b875084 --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/.clang-format @@ -0,0 +1,12 @@ +# using clang-format version 5.0.0 +Language: Cpp +BasedOnStyle: LLVM + +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +# make adding new members at the end less noisy in diffs +BreakConstructorInitializersBeforeComma: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true diff --git a/extern/cloudrRPC/extern/run-clang-format/.clang-format-ignore b/extern/cloudrRPC/extern/run-clang-format/.clang-format-ignore new file mode 100644 index 0000000..a4767fc --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/.clang-format-ignore @@ -0,0 +1,2 @@ +# ignore third_party code from clang-format checks +src/third_party/* diff --git a/extern/cloudrRPC/extern/run-clang-format/.travis.yml b/extern/cloudrRPC/extern/run-clang-format/.travis.yml new file mode 100644 index 0000000..9f73072 --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/.travis.yml @@ -0,0 +1,12 @@ +language: cpp + +addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + - key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key' + packages: + - clang-format-5.0 + +script: + - ./run-clang-format.py -r src diff --git a/extern/cloudrRPC/extern/run-clang-format/LICENSE b/extern/cloudrRPC/extern/run-clang-format/LICENSE new file mode 100644 index 0000000..e728f24 --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Guillaume Papin + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. diff --git a/extern/cloudrRPC/extern/run-clang-format/README.rst b/extern/cloudrRPC/extern/run-clang-format/README.rst new file mode 100644 index 0000000..aff45d1 --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/README.rst @@ -0,0 +1,72 @@ +===================== + run-clang-format.py +===================== +---------------------------------------------- + Lint files and directories with clang-format +---------------------------------------------- + +.. contents:: + :local: + +Introduction +============ + +A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +.. image:: screenshot.png + + +How to use? +=========== + +Copy `run-clang-format.py `_ in your project, +then run it recursively on directories, or specific files:: + + ./run-clang-format.py -r src include foo.cpp + +It's possible to exclude paths from the recursive search:: + + ./run-clang-format.py -r \ + --exclude src/third_party \ + --exclude '*_test.cpp' \ + src include foo.cpp + +These exclude rules can be put in a ``.clang-format-ignore`` file, +which also supports comments. + +An example configuration is available in this repo:: + + $ cat .clang-format-ignore + # ignore third_party code from clang-format checks + src/third_party/* + + +Continuous integration +====================== + +Check `.travis.yml <.travis.yml>`_. + +For an example of failure in logs, click the badge (build is broken on purpose): + +.. image:: https://travis-ci.org/Sarcasm/run-clang-format.svg?branch=master + :target: https://travis-ci.org/Sarcasm/run-clang-format + + +FAQ +=== + +Can I check only changed files? +------------------------------- + +No, and this is what this repository was initially about. +However, once working around a few shortcommings of ``git clang-format``, +I opted to try an alternative strategy +which expects the whole project to be correctly formatted. + +It would make sense to support this feature as well, +so that the coding style does not need to be enforced but merely suggested. diff --git a/extern/cloudrRPC/extern/run-clang-format/run-clang-format.py b/extern/cloudrRPC/extern/run-clang-format/run-clang-format.py new file mode 100755 index 0000000..dcabaf1 --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/run-clang-format.py @@ -0,0 +1,408 @@ +#!/usr/bin/env python +"""A wrapper script around clang-format, suitable for linting multiple files +and to use for continuous integration. + +This is an alternative API for the clang-format command line. +It runs over multiple files and directories in parallel. +A diff output is produced and a sensible exit code is returned. + +""" + +from __future__ import print_function, unicode_literals + +import argparse +import codecs +import difflib +import fnmatch +import io +import errno +import multiprocessing +import os +import signal +import subprocess +import sys +import traceback + +from functools import partial + +try: + from subprocess import DEVNULL # py3k +except ImportError: + DEVNULL = open(os.devnull, "wb") + + +DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx' +DEFAULT_CLANG_FORMAT_IGNORE = '.clang-format-ignore' + + +class ExitStatus: + SUCCESS = 0 + DIFF = 1 + TROUBLE = 2 + +def excludes_from_file(ignore_file): + excludes = [] + try: + with io.open(ignore_file, 'r', encoding='utf-8') as f: + for line in f: + if line.startswith('#'): + # ignore comments + continue + pattern = line.rstrip() + if not pattern: + # allow empty lines + continue + excludes.append(pattern) + except EnvironmentError as e: + if e.errno != errno.ENOENT: + raise + return excludes; + +def list_files(files, recursive=False, extensions=None, exclude=None): + if extensions is None: + extensions = [] + if exclude is None: + exclude = [] + + out = [] + for file in files: + if recursive and os.path.isdir(file): + for dirpath, dnames, fnames in os.walk(file): + fpaths = [os.path.join(dirpath, fname) for fname in fnames] + for pattern in exclude: + # os.walk() supports trimming down the dnames list + # by modifying it in-place, + # to avoid unnecessary directory listings. + dnames[:] = [ + x for x in dnames + if + not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) + ] + fpaths = [ + x for x in fpaths if not fnmatch.fnmatch(x, pattern) + ] + for f in fpaths: + ext = os.path.splitext(f)[1][1:] + if ext in extensions: + out.append(f) + else: + out.append(file) + return out + + +def make_diff(file, original, reformatted): + return list( + difflib.unified_diff( + original, + reformatted, + fromfile='{}\t(original)'.format(file), + tofile='{}\t(reformatted)'.format(file), + n=3)) + + +class DiffError(Exception): + def __init__(self, message, errs=None): + super(DiffError, self).__init__(message) + self.errs = errs or [] + + +class UnexpectedError(Exception): + def __init__(self, message, exc=None): + super(UnexpectedError, self).__init__(message) + self.formatted_traceback = traceback.format_exc() + self.exc = exc + + +def run_clang_format_diff_wrapper(args, file): + try: + ret = run_clang_format_diff(args, file) + return ret + except DiffError: + raise + except Exception as e: + raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, + e), e) + + +def run_clang_format_diff(args, file): + try: + with io.open(file, 'r', encoding='utf-8') as f: + original = f.readlines() + except IOError as exc: + raise DiffError(str(exc)) + + if args.in_place: + invocation = [args.clang_format_executable, '-i', file] + else: + invocation = [args.clang_format_executable, file] + + if args.style: + invocation.extend(['--style', args.style]) + + if args.dry_run: + print(" ".join(invocation)) + return [], [] + + # Use of utf-8 to decode the process output. + # + # Hopefully, this is the correct thing to do. + # + # It's done due to the following assumptions (which may be incorrect): + # - clang-format will returns the bytes read from the files as-is, + # without conversion, and it is already assumed that the files use utf-8. + # - if the diagnostics were internationalized, they would use utf-8: + # > Adding Translations to Clang + # > + # > Not possible yet! + # > Diagnostic strings should be written in UTF-8, + # > the client can translate to the relevant code page if needed. + # > Each translation completely replaces the format string + # > for the diagnostic. + # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation + # + # It's not pretty, due to Python 2 & 3 compatibility. + encoding_py3 = {} + if sys.version_info[0] >= 3: + encoding_py3['encoding'] = 'utf-8' + + try: + proc = subprocess.Popen( + invocation, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + **encoding_py3) + except OSError as exc: + raise DiffError( + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(invocation), exc + ) + ) + proc_stdout = proc.stdout + proc_stderr = proc.stderr + if sys.version_info[0] < 3: + # make the pipes compatible with Python 3, + # reading lines should output unicode + encoding = 'utf-8' + proc_stdout = codecs.getreader(encoding)(proc_stdout) + proc_stderr = codecs.getreader(encoding)(proc_stderr) + # hopefully the stderr pipe won't get full and block the process + outs = list(proc_stdout.readlines()) + errs = list(proc_stderr.readlines()) + proc.wait() + if proc.returncode: + raise DiffError( + "Command '{}' returned non-zero exit status {}".format( + subprocess.list2cmdline(invocation), proc.returncode + ), + errs, + ) + if args.in_place: + return [], errs + return make_diff(file, original, outs), errs + + +def bold_red(s): + return '\x1b[1m\x1b[31m' + s + '\x1b[0m' + + +def colorize(diff_lines): + def bold(s): + return '\x1b[1m' + s + '\x1b[0m' + + def cyan(s): + return '\x1b[36m' + s + '\x1b[0m' + + def green(s): + return '\x1b[32m' + s + '\x1b[0m' + + def red(s): + return '\x1b[31m' + s + '\x1b[0m' + + for line in diff_lines: + if line[:4] in ['--- ', '+++ ']: + yield bold(line) + elif line.startswith('@@ '): + yield cyan(line) + elif line.startswith('+'): + yield green(line) + elif line.startswith('-'): + yield red(line) + else: + yield line + + +def print_diff(diff_lines, use_color): + if use_color: + diff_lines = colorize(diff_lines) + if sys.version_info[0] < 3: + sys.stdout.writelines((l.encode('utf-8') for l in diff_lines)) + else: + sys.stdout.writelines(diff_lines) + + +def print_trouble(prog, message, use_colors): + error_text = 'error:' + if use_colors: + error_text = bold_red(error_text) + print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--clang-format-executable', + metavar='EXECUTABLE', + help='path to the clang-format executable', + default='clang-format') + parser.add_argument( + '--extensions', + help='comma separated list of file extensions (default: {})'.format( + DEFAULT_EXTENSIONS), + default=DEFAULT_EXTENSIONS) + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='run recursively over directories') + parser.add_argument( + '-d', + '--dry-run', + action='store_true', + help='just print the list of files') + parser.add_argument( + '-i', + '--in-place', + action='store_true', + help='format file instead of printing differences') + parser.add_argument('files', metavar='file', nargs='+') + parser.add_argument( + '-q', + '--quiet', + action='store_true', + help="disable output, useful for the exit code") + parser.add_argument( + '-j', + metavar='N', + type=int, + default=0, + help='run N clang-format jobs in parallel' + ' (default number of cpus + 1)') + parser.add_argument( + '--color', + default='auto', + choices=['auto', 'always', 'never'], + help='show colored diff (default: auto)') + parser.add_argument( + '-e', + '--exclude', + metavar='PATTERN', + action='append', + default=[], + help='exclude paths matching the given glob-like pattern(s)' + ' from recursive search') + parser.add_argument( + '--style', + help='formatting style to apply (LLVM, Google, Chromium, Mozilla, WebKit)') + + args = parser.parse_args() + + # use default signal handling, like diff return SIGINT value on ^C + # https://bugs.python.org/issue14229#msg156446 + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + signal.SIGPIPE + except AttributeError: + # compatibility, SIGPIPE does not exist on Windows + pass + else: + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + colored_stdout = False + colored_stderr = False + if args.color == 'always': + colored_stdout = True + colored_stderr = True + elif args.color == 'auto': + colored_stdout = sys.stdout.isatty() + colored_stderr = sys.stderr.isatty() + + version_invocation = [args.clang_format_executable, str("--version")] + try: + subprocess.check_call(version_invocation, stdout=DEVNULL) + except subprocess.CalledProcessError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + return ExitStatus.TROUBLE + except OSError as e: + print_trouble( + parser.prog, + "Command '{}' failed to start: {}".format( + subprocess.list2cmdline(version_invocation), e + ), + use_colors=colored_stderr, + ) + return ExitStatus.TROUBLE + + retcode = ExitStatus.SUCCESS + + excludes = excludes_from_file(DEFAULT_CLANG_FORMAT_IGNORE) + excludes.extend(args.exclude) + + files = list_files( + args.files, + recursive=args.recursive, + exclude=excludes, + extensions=args.extensions.split(',')) + + if not files: + return + + njobs = args.j + if njobs == 0: + njobs = multiprocessing.cpu_count() + 1 + njobs = min(len(files), njobs) + + if njobs == 1: + # execute directly instead of in a pool, + # less overhead, simpler stacktraces + it = (run_clang_format_diff_wrapper(args, file) for file in files) + pool = None + else: + pool = multiprocessing.Pool(njobs) + it = pool.imap_unordered( + partial(run_clang_format_diff_wrapper, args), files) + pool.close() + while True: + try: + outs, errs = next(it) + except StopIteration: + break + except DiffError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + retcode = ExitStatus.TROUBLE + sys.stderr.writelines(e.errs) + except UnexpectedError as e: + print_trouble(parser.prog, str(e), use_colors=colored_stderr) + sys.stderr.write(e.formatted_traceback) + retcode = ExitStatus.TROUBLE + # stop at the first unexpected error, + # something could be very wrong, + # don't process all files unnecessarily + if pool: + pool.terminate() + break + else: + sys.stderr.writelines(errs) + if outs == []: + continue + if not args.quiet: + print_diff(outs, use_color=colored_stdout) + if retcode == ExitStatus.SUCCESS: + retcode = ExitStatus.DIFF + if pool: + pool.join() + return retcode + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/extern/cloudrRPC/extern/run-clang-format/screenshot.png b/extern/cloudrRPC/extern/run-clang-format/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..f65102db73204dd09585da45056d274573bd8033 GIT binary patch literal 26702 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 + +std::string foo(const std::string &a, const std::string &b) { + std::string sum; + sum = a + b; + return sum; +} diff --git a/extern/cloudrRPC/extern/run-clang-format/src/third_party/qux.cpp b/extern/cloudrRPC/extern/run-clang-format/src/third_party/qux.cpp new file mode 100644 index 0000000..c6c5efa --- /dev/null +++ b/extern/cloudrRPC/extern/run-clang-format/src/third_party/qux.cpp @@ -0,0 +1,9 @@ +// This code is ignored by the .clang-format-ignore file. + +int qux(bool cond) { + if (cond) { + return -1; + } + + return 0; +} diff --git a/extern/cloudrRPC/gcovr.cfg b/extern/cloudrRPC/gcovr.cfg new file mode 100644 index 0000000..2303a96 --- /dev/null +++ b/extern/cloudrRPC/gcovr.cfg @@ -0,0 +1 @@ +filter = include/ diff --git a/extern/cloudrRPC/include/hicr/backends/cloudr/communicationManager.hpp b/extern/cloudrRPC/include/hicr/backends/cloudr/communicationManager.hpp new file mode 100644 index 0000000..b74699f --- /dev/null +++ b/extern/cloudrRPC/include/hicr/backends/cloudr/communicationManager.hpp @@ -0,0 +1,331 @@ +/* + * Copyright 2025 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file communicationManager.hpp + * @brief This file implements the communication manager class for the CloudR backend + * @author S. M. Martin & L. Terracciano + * @date 19/12/2023 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "instanceManager.hpp" + +namespace HiCR::backend::cloudr +{ + +/** + * Implementation of the CloudR backend + */ +class CommunicationManager final : public HiCR::CommunicationManager +{ + public: + + /** + * Constructor for the cloudr backend. + * + * \param[in] communicationManager working communication manager to implement the required functionalities (e.g, MPI instance manager) + * \param[in] instanceManager working instance manager to handle the virtualized resources and trigger RPC for all the instances (free and non) + */ + CommunicationManager(HiCR::CommunicationManager *communicationManager, HiCR::backend::cloudr::InstanceManager *instanceManager) + : HiCR::CommunicationManager(), + _communicationManager(communicationManager), + _instanceManager(instanceManager) + {} + + ~CommunicationManager() override = default; + + /** + * Forward call to getGlobalMemorySlotImpl + * + * \param[in] tag Tag that identifies a subset of all global memory slots + * \param[in] globalKey The sorting key inside the tag subset that distinguished between registered slots + * \return The map of registered global memory slots, filtered by tag and mapped by key + */ + std::shared_ptr getGlobalMemorySlotImpl(GlobalMemorySlot::tag_t tag, GlobalMemorySlot::globalKey_t globalKey) override + { + // Forward call to base communication manager + return _communicationManager->getGlobalMemorySlot(tag, globalKey); + } + + /** + * Forward call to exchangeGlobalMemorySlots + * + * \param[in] tag Tag that identifies a subset of all global memory slots + * \param[in] memorySlots memory slots to exchange + */ + __INLINE__ void exchangeGlobalMemorySlotsImpl(HiCR::GlobalMemorySlot::tag_t tag, const std::vector &memorySlots) override + { + // Request non active instances to participate in the exchange + if (_instanceManager->getCurrentInstance()->isRootInstance()) _instanceManager->requestExchangeGlobalMemorySlots(tag); + + // Initiate the exchange + _communicationManager->exchangeGlobalMemorySlots(tag, memorySlots); + + // Keep track of the initiated exchange + _isExchangePending = true; + } + + /** + * Forward call to queryMemorySlotUpdatesImpl + * + * \param[in] memorySlot memory slots to query + */ + void queryMemorySlotUpdatesImpl(std::shared_ptr memorySlot) override + { + // Forward call to base communication manager + _communicationManager->queryMemorySlotUpdates(memorySlot); + } + + /** + * Forward call to destroyGlobalMemorySlotImpl + * + * \param[in] memorySlot memory slots to destroy + */ + void destroyGlobalMemorySlotImpl(std::shared_ptr memorySlot) override + { + // Forward call to base communication manager + _communicationManager->destroyGlobalMemorySlot(memorySlot); + } + + /** + * Forward call to fenceImpl + * + * \param[in] tag tag on which fence should be performed + */ + __INLINE__ void fenceImpl(HiCR::GlobalMemorySlot::tag_t tag) override + { + // Request non active instances to participate in the fence + if (_instanceManager->getCurrentInstance()->isRootInstance()) _instanceManager->requestFence(tag); + + // Execute the fence + _communicationManager->fence(tag); + + // If any exchange operation was initiated + if (_isExchangePending == true) + { + // Get the global memory slot tag-key map + const auto &globalMap = _communicationManager->getGlobalMemorySlotTagKeyMap(); + + // Update CloudR global memory slot tag-key map + setGlobalMemorySlotTagKeyMap(globalMap); + + // All the changes of the exchange operations are reflected in CloudR + _isExchangePending = false; + } + } + + /** + * Forward call to acquireGlobalLockImpl + * + * \param[in] memorySlot memory slots to lock + * + * \return bool if the operation was successful + */ + bool acquireGlobalLockImpl(std::shared_ptr memorySlot) override + { + // Forward call to base communication manager + return _communicationManager->acquireGlobalLock(memorySlot); + } + + /** + * Forward call to releaseGlobalLockImpl + * + * \param[in] memorySlot memory slots to unlock + */ + void releaseGlobalLockImpl(std::shared_ptr memorySlot) override + { + // Forward call to base communication manager + return _communicationManager->releaseGlobalLock(memorySlot); + } + + /** + * Forward call to serializeGlobalMemorySlot + * + * \param[in] globalSlot global memory slot to serialize + * + * \return pointer to the serialized versoin + */ + uint8_t *serializeGlobalMemorySlot(const std::shared_ptr &globalSlot) const override + { + // Forward call to base communication manager + return _communicationManager->serializeGlobalMemorySlot(globalSlot); + } + + /** + * Forward call to deserializeGlobalMemorySlot + * + * \param[in] buffer the serialize global memory slot + * \param[in] tag global memory slot tag + * + * \return a deserialized global memory slot + */ + std::shared_ptr deserializeGlobalMemorySlot(uint8_t *buffer, GlobalMemorySlot::tag_t tag) override + { + // Forward call to base communication manager + return _communicationManager->deserializeGlobalMemorySlot(buffer, tag); + } + + /** + * Forward call to promoteLocalMemorySlot + * + * \param[in] localMemorySlot memory slot to promote + * \param[in] tag the tag where it should be promoted + * + * \return global memory slot + */ + std::shared_ptr promoteLocalMemorySlot(const std::shared_ptr &localMemorySlot, GlobalMemorySlot::tag_t tag) override + { + // Forward call to base communication manager + return _communicationManager->promoteLocalMemorySlot(localMemorySlot, tag); + } + + /** + * Forward call to destroyPromotedGlobalMemorySlot + * + * \param[in] memorySlot memory slots to destroy + */ + void destroyPromotedGlobalMemorySlot(const std::shared_ptr &memorySlot) override + { + // Forward call to base communication manager + _communicationManager->destroyGlobalMemorySlot(memorySlot); + } + + /** + * Forward call to flushReceived + */ + void flushReceived() override + { + // Forward call to base communication manager + _communicationManager->flushReceived(); + } + + /** + * Forward call to flushSent + */ + void flushSent() override + { + // Forward call to base communication manager + _communicationManager->flushSent(); + } + + /** + * Forward call to deregisterGlobalMemorySlotImpl + * + * \param[in] memorySlot memory slots to deregister + */ + void deregisterGlobalMemorySlotImpl(const std::shared_ptr &memorySlot) override + { + // Forward call to base communication manager + _communicationManager->deregisterGlobalMemorySlot(memorySlot); + } + + /** + * Forward call to memcpyImpl + * + * \param[in] destination + * \param[in] dst_offset + * \param[in] source + * \param[in] src_offset + * \param[in] size + */ + void memcpyImpl(const std::shared_ptr &destination, size_t dst_offset, const std::shared_ptr &source, size_t src_offset, size_t size) override + { + // Forward call to base communication manager + _communicationManager->memcpy(destination, dst_offset, source, src_offset, size); + } + + /** + * Forward call to memcpyImpl + * + * \param[in] destination + * \param[in] dst_offset + * \param[in] source + * \param[in] src_offset + * \param[in] size + */ + void memcpyImpl(const std::shared_ptr &destination, size_t dst_offset, const std::shared_ptr &source, size_t src_offset, size_t size) override + { + // Forward call to base communication manager + _communicationManager->memcpy(destination, dst_offset, source, src_offset, size); + } + + /** + * Forward call to memcpyImpl + * + * \param[in] destination + * \param[in] dst_offset + * \param[in] source + * \param[in] src_offset + * \param[in] size + */ + void memcpyImpl(const std::shared_ptr &destination, size_t dst_offset, const std::shared_ptr &source, size_t src_offset, size_t size) override + { + // Forward call to base communication manager + _communicationManager->memcpy(destination, dst_offset, source, src_offset, size); + } + + /** + * Forward call to fenceImpl + * + * \param[in] slot + * \param[in] expectedSent + * \param[in] expectedRcvd + */ + void fenceImpl(const std::shared_ptr &slot, size_t expectedSent, size_t expectedRcvd) override + { + // Forward call to base communication manager + _communicationManager->fence(slot, expectedSent, expectedRcvd); + } + + /** + * Forward call to fenceImpl + * + * \param[in] slot + * \param[in] expectedSent + * \param[in] expectedRcvd + */ + void fenceImpl(const std::shared_ptr &slot, size_t expectedSent, size_t expectedRcvd) override + { + // Forward call to base communication manager + _communicationManager->fence(slot, expectedSent, expectedRcvd); + } + + private: + + /** + * HiCR Communication manager that does the actual operations + */ + HiCR::CommunicationManager *const _communicationManager; + + /** + * HiCR Instance manager to check whether this is a root instance + */ + HiCR::backend::cloudr::InstanceManager *const _instanceManager; + + /** + * Keep track if there are pending exchanges operations + */ + bool _isExchangePending = false; +}; + +} // namespace HiCR::backend::cloudr diff --git a/extern/cloudrRPC/include/hicr/backends/cloudr/instance.hpp b/extern/cloudrRPC/include/hicr/backends/cloudr/instance.hpp new file mode 100644 index 0000000..4a6d3f6 --- /dev/null +++ b/extern/cloudrRPC/include/hicr/backends/cloudr/instance.hpp @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file instance.hpp + * @brief Provides a definition for the instance class for the CloudR backend + * @author S. M. Martin + * @date 18/06/2025 + */ +#pragma once + +#include +#include + +namespace HiCR::backend::cloudr +{ + +/** + * This class represents an abstract definition for a HICR instance as represented by the Cloudr backend: + */ +class Instance final : public HiCR::Instance +{ + public: + + /** + * Constructor for a Instance class for the CloudR backend + * \param[in] instanceId The instance identifier corresponding to this HiCR instance + * \param[in] baseInstance The base instance corresponding to this HiCR instance + * \param[in] isRoot whether the instance is root + */ + Instance(const instanceId_t instanceId, HiCR::Instance *const baseInstance, const bool isRoot) + : HiCR::Instance(instanceId), + _baseInstance(baseInstance), + _isRoot(isRoot) + {} + + /** + * Default destructor + */ + ~Instance() override = default; + + /** + * \return whether the current instance is root + */ + [[nodiscard]] __INLINE__ bool isRootInstance() const override { return _isRoot; }; + + /** + * Set the instance topology + * + * \param[in] topology + */ + __INLINE__ void setTopology(const HiCR::Topology &topology) { _topology = topology; } + + /** + * Topology getter + * + * \return instance topology + */ + __INLINE__ HiCR::Topology getTopology() const { return _topology; } + + /** + * Checks whether this instance satisfied a certain instance type. + * That is, whether it contains the requested devices in the instance type provided + * + * The devices are checked in order. That is the first instance device that satisfies a requested device + * will be removed from the list when checking the next requested device. + * + * @param[in] requestedTopology The topology to check for + * + * @return true, if this instance satisfies the instance type; false, otherwise. + */ + [[nodiscard]] __INLINE__ bool isCompatible(const HiCR::Topology requestedTopology) { return _topology.isSubset(_topology, requestedTopology); } + + /** + * Getter for base instance, not the emulated one + * + * \return pointer to instance + */ + __INLINE__ HiCR::Instance *getBaseInstance() const { return _baseInstance; } + + private: + + /// Emulated topology for this instance + HiCR::Topology _topology; + + /// Underlying instance implementing this instance + HiCR::Instance *const _baseInstance; + + /// A flag that determines whether this instance is root + const bool _isRoot; + + /// A flag that indicates this instance is currently deployed + bool _isDeployed = false; +}; + +} // namespace HiCR::backend::cloudr diff --git a/extern/cloudrRPC/include/hicr/backends/cloudr/instanceManager.hpp b/extern/cloudrRPC/include/hicr/backends/cloudr/instanceManager.hpp new file mode 100644 index 0000000..4ab077e --- /dev/null +++ b/extern/cloudrRPC/include/hicr/backends/cloudr/instanceManager.hpp @@ -0,0 +1,399 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "instance.hpp" + +namespace HiCR::backend::cloudr +{ + +class CommunicationManager; +class TopologyManager; + +/** + * Instance manager for CloudR +*/ +class InstanceManager final : public HiCR::InstanceManager +{ + friend TopologyManager; + friend CommunicationManager; + + public: + +#define __CLOUDR_GATHER_TOPOLOGIES_RPC_NAME "[CloudR] Gather Topologies" +#define __CLOUDR_LAUNCH_ENTRY_POINT_RPC_NAME "[CloudR] Launch Main" +#define __CLOUDR_RELINQUISH_INSTANCE_RPC_NAME "[CloudR] Relinquish Instance" +#define __CLOUDR_FINALIZE_WORKER_RPC_NAME "[CloudR] Finalize Worker" +#define __CLOUDR_EXCHANGE_GLOBAL_MEMORY_SLOTS_RPC_NAME "[CloudR] Exchange Global Memory Slots" +#define __CLOUDR_FENCE_RPC_NAME "[CloudR] Fence" + + /** + * Type for any entrypoint function + */ + typedef std::function entryPoint_t; + + /** + * Constructor + * + * @param[in] rpcEngine + * @param[in] localTopology + * @param[in] entryPoint + */ + InstanceManager(HiCR::frontend::RPCEngine *rpcEngine, const HiCR::Topology localTopology, entryPoint_t entryPoint) + : HiCR::InstanceManager(), + _rpcEngine(rpcEngine), + _localTopology(localTopology), + _entryPoint(entryPoint) + {} + + ~InstanceManager() = default; + + /** + * Initialize the instance manager. Registers RPCs, stores available instances, detects the root instance, executes the entrypoint + */ + __INLINE__ void initialize() + { + // Registering Topology gathering function + auto gatherTopologiesExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { gatherTopologies(); }); + _rpcEngine->addRPCTarget(__CLOUDR_GATHER_TOPOLOGIES_RPC_NAME, gatherTopologiesExecutionUnit); + + // Registering launch function + auto launchEntryPointExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { _entryPoint(); }); + _rpcEngine->addRPCTarget(__CLOUDR_LAUNCH_ENTRY_POINT_RPC_NAME, launchEntryPointExecutionUnit); + + // Registering relinquish instance function + auto relinquishInstanceExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { relinquishInstance(); }); + _rpcEngine->addRPCTarget(__CLOUDR_RELINQUISH_INSTANCE_RPC_NAME, relinquishInstanceExecutionUnit); + + // Registering finalize function + auto finalizeWorkerExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { finalizeWorker(); }); + _rpcEngine->addRPCTarget(__CLOUDR_FINALIZE_WORKER_RPC_NAME, finalizeWorkerExecutionUnit); + + // Registering exchange global memory slots RPC + auto exchangeGlobalMemorySlotsExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { exchangeGlobalMemorySlotsRPC(); }); + _rpcEngine->addRPCTarget(__CLOUDR_EXCHANGE_GLOBAL_MEMORY_SLOTS_RPC_NAME, exchangeGlobalMemorySlotsExecutionUnit); + + // Registering global fence + auto fenceExecutionUnit = HiCR::backend::pthreads::ComputeManager::createExecutionUnit([this](void *) { fenceRPC(); }); + _rpcEngine->addRPCTarget(__CLOUDR_FENCE_RPC_NAME, fenceExecutionUnit); + + // Creating instance objects from the initially found instances now + HiCR::Instance::instanceId_t instanceIdCounter = 0; + for (auto &instance : _rpcEngine->getInstanceManager()->getInstances()) + { + // Only the current instance is the root one + const bool isRoot = _rpcEngine->getInstanceManager()->getRootInstanceId() == instance->getId(); + + // Creating new cloudr instance object (contains all the emulated information) + auto newInstance = std::make_shared(instanceIdCounter, instance.get(), isRoot); + + // Adding new instance to the internal storage + _cloudrInstances.push_back(newInstance); + + // If this is the current instance, set it now + if (instance->getId() == _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()) + { + // Set as current instance + setCurrentInstance(newInstance); + + // Assigning its topology + newInstance->setTopology(_localTopology); + } + + // If it's root, store its pointer + if (isRoot) + { + // Store root instance pointer for later referencing + _rootInstance = newInstance.get(); + + // Adding instance to the collection of currently active instances + addInstance(newInstance); + } + + // If not root, add to the list of free instances (can be activated later) + if (isRoot == false) _freeInstances.insert(newInstance.get()); + + // Linking base instance id to the respective cloudr instance + _baseIdsToCloudrInstanceMap[instance->getId()] = newInstance.get(); + + // Increasing cloudr instance Id + instanceIdCounter++; + } + // printf("[CloudR] Worker %lu finished.\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + + ///// Now deploying + + // If I'm worker, all I need to do is listen for incoming RPCs + if (_rpcEngine->getInstanceManager()->getCurrentInstance()->isRootInstance() == false) + { + while (_continueListening) + { + // printf("[CloudR] Worker %lu listening...\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + _rpcEngine->listen(); + // printf("[CloudR] Worker %lu back from listening...\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + } + } + else // If I am root, do the following instead + { + // Gather the topologies of all other instances + for (auto &instance : _freeInstances) + { + // Requesting the root + _rpcEngine->requestRPC(instance->getId(), __CLOUDR_GATHER_TOPOLOGIES_RPC_NAME); + + // Getting return value (topology) + auto returnValue = _rpcEngine->getReturnValue(); + + // Receiving raw serialized topology information from the worker + std::string serializedTopology = (char *)returnValue->getPointer(); + + // Parsing serialized raw topology into a json object + auto topologyJson = nlohmann::json::parse(serializedTopology); + + // Freeing return value + _rpcEngine->getMemoryManager()->freeLocalMemorySlot(returnValue); + + // Updating current instance's topology + instance->setTopology(topologyJson); + } + + // Then go straight to the entry point + _entryPoint(); + + // printf("[Root %lu] Exited entry point...\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + } + } + + /** + * This function is the RPC that a running instance receives when it is relinquished. + * + * It does not terminate the worker, but simply confirms the instance is not running. + */ + __INLINE__ void relinquishInstance() + { + // printf("Relinquishing...\n"); + + // Returning confirmation that we are no longer running a function (idle) + int returnOkMessage = 0; + _rpcEngine->submitReturnValue((void *)&returnOkMessage, sizeof(returnOkMessage)); + } + + __INLINE__ void terminateInstanceImpl(const std::shared_ptr instance) override + { + // Requesting relinquish RPC execution on the requested instance + _rpcEngine->requestRPC(instance->getId(), __CLOUDR_RELINQUISH_INSTANCE_RPC_NAME); + + // Getting return value. It's enough to know a value was returned to know it is idling + const auto returnValue = _rpcEngine->getReturnValue(); + + // Adding instance back to free instances + _freeInstances.insert(_baseIdsToCloudrInstanceMap[instance->getId()]); + } + + /** + * Finalization procedure. Send rpc termination to all the non root instances + */ + __INLINE__ void finalize() override + { + // printf("[Instance %lu] Finalizing CloudR...\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + + // The following only be ran by the root rank, send an RPC to all others to finalize them + if (_rpcEngine->getInstanceManager()->getCurrentInstance()->isRootInstance()) + { + for (auto &instance : _cloudrInstances) + if (instance->isRootInstance() == false) _rpcEngine->requestRPC(instance->getId(), __CLOUDR_FINALIZE_WORKER_RPC_NAME); + } + } + + /** + * Abort execution with the specifies error code + * + * @param[in] errorCode + */ + __INLINE__ void abort(int errorCode) override { _rpcEngine->getInstanceManager()->abort(errorCode); } + + /** + * Getter for root instance id + * + * @return root instance id + */ + [[nodiscard]] __INLINE__ HiCR::Instance::instanceId_t getRootInstanceId() const override { return _rootInstance->getId(); } + + /** + * Getter for rpc engine + * + * @return rpc engine + */ + [[nodiscard]] __INLINE__ auto getRPCEngine() const { return _rpcEngine; } + + /** + * Getter for free instances + * + * @return free instances + */ + [[nodiscard]] __INLINE__ const auto &getFreeInstances() const { return _freeInstances; } + + private: + + /** + * Response to gather topology rpc + */ + __INLINE__ void gatherTopologies() + { + // Getting my current instance's topology + auto topology = static_cast(getCurrentInstance().get())->getTopology(); + + // Serializing topology information + const auto serializedTopology = topology.serialize().dump(); + + // Returning serialized topology + _rpcEngine->submitReturnValue((void *)serializedTopology.c_str(), serializedTopology.size() + 1); + } + + __INLINE__ std::shared_ptr createInstanceImpl(const HiCR::InstanceTemplate instanceTemplate) override + { + // If no more free instances available, fail now + // Commented out because we don't want to fail, simply return a nullptr + // if (_freeInstances.empty()) HICR_THROW_LOGIC("Requested the creation of a new instances, but CloudR has ran out of free instances"); + + // Creating instance object to return + std::shared_ptr newInstance = nullptr; + + // Getting requested topology from the instance template + const auto &topology = instanceTemplate.getTopology(); + + // Iterating over free instances to get the first one that satisfies the request + for (const auto &instance : _freeInstances) + if (instance->isCompatible(topology)) + { + // Assigning it as compatible instance + newInstance = std::make_shared(*instance); + + // Erasing it from the list of free instances + _freeInstances.erase(instance); + + // Stop looking into the others + break; + } + + // Commented out because we don't want to fail, simply return a nullptr + // if (newInstance == nullptr) HICR_THROW_LOGIC("Tried to create new instance but did not find any free instances that meet the required topology"); + + // If successful, initialize the new instance + if (newInstance != nullptr) + { + // Request the execution of the main driver function + _rpcEngine->requestRPC(newInstance->getBaseInstance()->getId(), __CLOUDR_LAUNCH_ENTRY_POINT_RPC_NAME); + } + + // Returning result. Nullptr, if no instance was created + return newInstance; + } + + __INLINE__ std::shared_ptr addInstanceImpl(HiCR::Instance::instanceId_t instanceId) override + { + HICR_THROW_LOGIC("The Host backend does not currently support the detection of new instances during runtime"); + } + + /** + * Request exchange memory slots rpc + * + * @param[in] tag the global memory slot tag to exchange + */ + __INLINE__ void requestExchangeGlobalMemorySlots(HiCR::GlobalMemorySlot::tag_t tag) + { + // Asking free instances to run the exchange RPC + for (const auto &instance : _freeInstances) _rpcEngine->requestRPC(instance->getId(), __CLOUDR_EXCHANGE_GLOBAL_MEMORY_SLOTS_RPC_NAME, tag); + } + + /** + * Request fence rpc + * + * @param[in] tag the global memory slot tag to fence + */ + __INLINE__ void requestFence(HiCR::GlobalMemorySlot::tag_t tag) + { + // Asking free instances to run the exchange RPC + for (const auto &instance : _freeInstances) _rpcEngine->requestRPC(instance->getId(), __CLOUDR_FENCE_RPC_NAME, tag); + } + + /** + * Response to request topology rpc + */ + __INLINE__ void requestTopology() + { + // Getting a pointer to the base instance who made the request + auto baseRequesterInstance = _rpcEngine->getRPCRequester(); + + // Getting base instance id + const auto baseInstanceId = baseRequesterInstance->getId(); + + // Getting cloudr instance from the base instance id + const auto cloudrInstance = _baseIdsToCloudrInstanceMap.at(baseInstanceId); + + // Serializing topology information + const auto serializedTopology = cloudrInstance->getTopology().serialize().dump(); + + // Returning serialized topology + _rpcEngine->submitReturnValue((void *)serializedTopology.c_str(), serializedTopology.size() + 1); + } + + /** + * Exit the worker rpc main loop and terminate execution + */ + __INLINE__ void finalizeWorker() + { + // Do not continue listening + // printf("[CloudR] Worker %lu running finalizeWorker() RPC.\n", _rpcEngine->getInstanceManager()->getCurrentInstance()->getId()); + _continueListening = false; + } + + /** + * rpc for exchange memory slots + */ + __INLINE__ void exchangeGlobalMemorySlotsRPC() + { + const auto exchangeTag = _rpcEngine->getRPCArgument(); + _rpcEngine->getCommunicationManager()->exchangeGlobalMemorySlots(exchangeTag, {}); + } + + /** + * rpc for fence + */ + __INLINE__ void fenceRPC() + { + const auto exchangeTag = _rpcEngine->getRPCArgument(); + _rpcEngine->getCommunicationManager()->fence(exchangeTag); + } + + /// RPC engine + HiCR::frontend::RPCEngine *const _rpcEngine; + + /// Storage for this instance's emulated topology + const HiCR::Topology _localTopology; + + /// Storage for the main function to run when a new instance runs + const entryPoint_t _entryPoint; + + // Pointer to the root instance + HiCR::backend::cloudr::Instance *_rootInstance; + + // Flag to signal non-root instances to finish listening + bool _continueListening = true; + + // Map that links the underlying instance ids with the cloudr instances + std::map _baseIdsToCloudrInstanceMap; + + /// Internal collection of cloudr instances + std::vector> _cloudrInstances; + + /// A collection of ready-to-use instances currently on standby + std::set _freeInstances; +}; // class CloudR + +} // namespace HiCR::backend::cloudr \ No newline at end of file diff --git a/extern/cloudrRPC/meson.build b/extern/cloudrRPC/meson.build new file mode 100644 index 0000000..d21ef90 --- /dev/null +++ b/extern/cloudrRPC/meson.build @@ -0,0 +1,65 @@ +project('CloudR', [ 'cpp'], + subproject_dir : 'extern', + default_options : [ + 'cpp_std=c++20', + 'buildtype=release' + ] +) + +CloudRDependencies = [ ] + +####### Getting HiCR dependency (if this is a standalone project) + +CloudRHiCRBackends = [ 'mpi', 'hwloc', 'pthreads' ] +CloudRHiCRFrontends = [ 'RPCEngine', 'channel' ] + +if meson.is_subproject() == false + +# Selecting default HiCR Backends +HiCRProject = subproject('HiCR', required: true, default_options: [ 'backends=' + ','.join(CloudRHiCRBackends), 'frontends=' + ','.join(CloudRHiCRFrontends) ]) +HiCRBuildDep = HiCRProject.get_variable('hicrBuildDep') +mpirunExecutable = HiCRProject.get_variable('mpirunExecutable') +CloudRDependencies += HiCRBuildDep + +endif + +####### Creating CloudR dependency + +# Warning handling option +warningAsErrorFlags=[] +if get_option('compileWarningsAsErrors') == true + warningAsErrorFlags=[ '-Werror' ] +endif + +CloudRBuildCppArgs = [ + '-Wfatal-errors', + warningAsErrorFlags + ] + +CloudRBuildIncludes = include_directories([ + 'include' + ]) + +####### Collect the dependencies + +CloudRBuildDep = declare_dependency( + compile_args: CloudRBuildCppArgs, + include_directories: CloudRBuildIncludes, + dependencies: CloudRDependencies + ) + +####### Build test / example targets only if HiCR is being loaded as a subproject + +if meson.is_subproject() == false + + # Build example targets + if get_option('buildExamples') + subdir('examples') + endif + + # Build test targets + if get_option('buildTests') + subdir('tests') + endif + +endif diff --git a/extern/cloudrRPC/meson_options.txt b/extern/cloudrRPC/meson_options.txt new file mode 100644 index 0000000..e25ec89 --- /dev/null +++ b/extern/cloudrRPC/meson_options.txt @@ -0,0 +1,11 @@ +option('buildTests', type : 'boolean', value : false, + description: 'Indicates whether to build tests' +) + +option('buildExamples', type : 'boolean', value : false, + description: 'Indicates whether to build example apps' +) + +option('compileWarningsAsErrors', type : 'boolean', value : false, + description: 'Indicates whether a compilation warning should result in a fatal error. This is useful for CI testing but may result in inconveniences for normal users, hence it should be false by default' +) diff --git a/extern/cloudrRPC/tests/meson.build b/extern/cloudrRPC/tests/meson.build new file mode 100644 index 0000000..491c8fe --- /dev/null +++ b/extern/cloudrRPC/tests/meson.build @@ -0,0 +1,26 @@ + gtest_dep = dependency('gtest', main: true, required: true) + + TaskRTestCppFlags = [ + ] + + cpp = meson.get_compiler('cpp') + if get_option('b_coverage') + gcov_args = [ + '-fno-inline', + '-Wno-error=cpp', + '-DENABLE_COVERAGE', + ] + if cpp.get_id().to_lower() == 'gcc' + gcov_args += [ + '-fno-default-inline', + '-fno-inline-small-functions', + ] + endif + + TaskRTestCppFlags += gcov_args + endif + + TaskRTestDep = declare_dependency( + compile_args: TaskRTestCppFlags, + dependencies: gtest_dep + ) \ No newline at end of file diff --git a/meson.build b/meson.build index 390ad32..ac4d6f0 100644 --- a/meson.build +++ b/meson.build @@ -40,7 +40,7 @@ endif if 'cloudr' in engines mpirunExecutable = find_program('mpirun', '/usr/bin/mpirun', '/usr/local/bin/mpirun', required : true) - CloudRProject = subproject('cloudr', required: true, default_options: [ ]) + CloudRProject = subproject('cloudrRPC', required: true, default_options: [ ]) CloudRBuildDep = CloudRProject.get_variable('CloudRBuildDep') deployrDependencies += CloudRBuildDep DeployRDistributedCppFlag = '-D_DEPLOYR_DISTRIBUTED_ENGINE_CLOUDR' From 8028bf1e9e0fda128e7f8e02d1386ced7b973fef Mon Sep 17 00:00:00 2001 From: Luca Terracciano Date: Mon, 15 Sep 2025 12:43:32 +0200 Subject: [PATCH 3/5] ci: fix meson configure --- .github/workflows/deployr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deployr.yml b/.github/workflows/deployr.yml index dc19d89..a3d357e 100644 --- a/.github/workflows/deployr.yml +++ b/.github/workflows/deployr.yml @@ -47,7 +47,7 @@ jobs: run: | echo "Building..." mkdir build - meson setup build -Dengine=mpi -DbuildTests=true -DbuildExamples=true -DcompileWarningsAsErrors=true + meson setup build -Dengines=mpi -DbuildTests=true -DbuildExamples=true -DcompileWarningsAsErrors=true meson compile -C build - name: Running tests run: | From 79e4a8db2f770def6d6e5b475cb82cf51dc95c28 Mon Sep 17 00:00:00 2001 From: Luca Terracciano Date: Mon, 15 Sep 2025 12:44:17 +0200 Subject: [PATCH 4/5] feat: remove unusued cloudrRpc files --- extern/cloudrRPC/.clang-format | 126 ------------ extern/cloudrRPC/.fix-style.sh | 3 - extern/cloudrRPC/.gitlab-ci.yml | 52 ----- extern/cloudrRPC/LICENSE | 201 -------------------- extern/cloudrRPC/README.md | 17 -- extern/cloudrRPC/examples/clone/clone.cpp | 63 ------ extern/cloudrRPC/examples/clone/meson.build | 6 - extern/cloudrRPC/examples/meson.build | 1 - extern/cloudrRPC/gcovr.cfg | 1 - extern/cloudrRPC/tests/meson.build | 26 --- 10 files changed, 496 deletions(-) delete mode 100644 extern/cloudrRPC/.clang-format delete mode 100755 extern/cloudrRPC/.fix-style.sh delete mode 100644 extern/cloudrRPC/.gitlab-ci.yml delete mode 100644 extern/cloudrRPC/LICENSE delete mode 100644 extern/cloudrRPC/README.md delete mode 100644 extern/cloudrRPC/examples/clone/clone.cpp delete mode 100644 extern/cloudrRPC/examples/clone/meson.build delete mode 100644 extern/cloudrRPC/examples/meson.build delete mode 100644 extern/cloudrRPC/gcovr.cfg delete mode 100644 extern/cloudrRPC/tests/meson.build diff --git a/extern/cloudrRPC/.clang-format b/extern/cloudrRPC/.clang-format deleted file mode 100644 index 770b743..0000000 --- a/extern/cloudrRPC/.clang-format +++ /dev/null @@ -1,126 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -AccessModifierOffset: 0 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -AlignConsecutiveDeclarations: true -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Always -AllowShortCaseLabelsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -AllowShortLambdasOnASingleLine: All -BreakBeforeBraces: Custom -BraceWrapping: - AfterClass: true - AfterCaseLabel : true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterObjCDeclaration: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - BeforeLambdaBody: false - BeforeWhile: true - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false -BreakBeforeBinaryOperators: None -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: false -ColumnLimit: 180 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Always -EmptyLineBeforeAccessModifier: Always -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - - Regex: '.*' - Priority: 1 -IncludeIsMainRegex: '(Test)?$' -IndentCaseLabels: false -IndentPPDirectives: BeforeHash -IndentWidth: 2 -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: false -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PackConstructorInitializers: Never -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300000 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 50 -PenaltyReturnTypeOnItsOwnLine: 600 -PointerAlignment: Right -ReflowComments: false -SortIncludes: false -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: c++20 -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TabWidth: 2 -UseTab: Never -... diff --git a/extern/cloudrRPC/.fix-style.sh b/extern/cloudrRPC/.fix-style.sh deleted file mode 100755 index 643e517..0000000 --- a/extern/cloudrRPC/.fix-style.sh +++ /dev/null @@ -1,3 +0,0 @@ -.build-tools/style/check-style.sh fix include/ -.build-tools/style/check-style.sh fix examples/ -.build-tools/style/check-style.sh fix tests/ diff --git a/extern/cloudrRPC/.gitlab-ci.yml b/extern/cloudrRPC/.gitlab-ci.yml deleted file mode 100644 index f45f62a..0000000 --- a/extern/cloudrRPC/.gitlab-ci.yml +++ /dev/null @@ -1,52 +0,0 @@ -build: - image: registry.gitlab.huaweirc.ch/zrc-von-neumann-lab/runtime-system-innovations/cloudr/buildenv:latest - variables: - GIT_SUBMODULE_STRATEGY: recursive - tags: - - docker - - x86 - - infiniband - script: - - export HOME=/home/hicr - - source /home/hicr/.hicr-env.sh - - echo "Building CloudR..." - - mkdir build - - meson setup build -Dbuildtype=debug -Db_coverage=true -DbuildTests=true -DbuildExamples=true -DcompileWarningsAsErrors=true - - meson compile -C build - - echo "Running tests..." - - meson test -C build - - echo "Creating coverage report..." - - ninja -C build coverage - coverage: /^\s*lines:\s*\d+.\d+\%/ - artifacts: - name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA} - expire_in: 2 days - when: always - paths: - - build/meson-logs/* - reports: - coverage_report: - coverage_format: cobertura - path: build/meson-logs/coverage.xml - only: - - master - - merge_requests - - tags - -docs: - image: registry.gitlab.huaweirc.ch/zrc-von-neumann-lab/runtime-system-innovations/hicr/docs:1.0 - tags: - - docker - - tiny - script: - - echo "Checking TaskR source and test formatting..." - - .build-tools/style/check-style.sh check include - - .build-tools/style/check-style.sh check tests - - .build-tools/style/check-style.sh check examples - - echo "Building code documentation..." - - make -j1 -C docs - only: - - master - - merge_requests - - tags - diff --git a/extern/cloudrRPC/LICENSE b/extern/cloudrRPC/LICENSE deleted file mode 100644 index df0bb94..0000000 --- a/extern/cloudrRPC/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/extern/cloudrRPC/README.md b/extern/cloudrRPC/README.md deleted file mode 100644 index e1afee2..0000000 --- a/extern/cloudrRPC/README.md +++ /dev/null @@ -1,17 +0,0 @@ -CloudR is a [HiCR](https://github.com/Algebraic-Programming/HiCR)-based Cloud service emulator. - -## License - -Copyright 2025 Huawei Technologies Co., Ltd. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/extern/cloudrRPC/examples/clone/clone.cpp b/extern/cloudrRPC/examples/clone/clone.cpp deleted file mode 100644 index 27324e4..0000000 --- a/extern/cloudrRPC/examples/clone/clone.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -void entryPoint(HiCR::backend::cloudr::InstanceManager &cloudr, const HiCR::Topology &localTopology) -{ - printf("[Instance %lu] I am in the entry point.\n", cloudr.getCurrentInstance()->getId()); - - // If I am the root instance, create the others with a similar architecture as mine - if (cloudr.getCurrentInstance()->isRootInstance() == true) - { - // Creating an instance template with our current topology (cloning) - const auto instanceTemplate = cloudr.createInstanceTemplate(localTopology); - - // Creating the other instance based on the template - cloudr.createInstance(*instanceTemplate); - } -} - -int main(int argc, char *argv[]) -{ - // Instantiating base managers - auto instanceManager = HiCR::backend::mpi::InstanceManager::createDefault(&argc, &argv); - auto communicationManager = HiCR::backend::mpi::CommunicationManager(MPI_COMM_WORLD); - auto memoryManager = HiCR::backend::mpi::MemoryManager(); - auto computeManager = HiCR::backend::pthreads::ComputeManager(); - - // Reserving memory for hwloc - hwloc_topology_t hwlocTopology; - hwloc_topology_init(&hwlocTopology); - - // Initializing HWLoc-based host (CPU) topology manager - auto hwlocTopologyManager = HiCR::backend::hwloc::TopologyManager(&hwlocTopology); - - // Finding the first memory space and compute resource to create our RPC engine - const auto &topology = hwlocTopologyManager.queryTopology(); - const auto &firstDevice = topology.getDevices().begin().operator*(); - const auto &RPCMemorySpace = firstDevice->getMemorySpaceList().begin().operator*(); - const auto &RPCComputeResource = firstDevice->getComputeResourceList().begin().operator*(); - - // Instantiating RPC engine - HiCR::frontend::RPCEngine rpcEngine(communicationManager, *instanceManager, memoryManager, computeManager, RPCMemorySpace, RPCComputeResource); - - // Initializing RPC engine - rpcEngine.initialize(); - - // Instantiating CloudR - HiCR::backend::cloudr::InstanceManager cloudrInstanceManager(&rpcEngine, topology, [&]() { entryPoint(cloudrInstanceManager, topology); }); - - // Initializing CloudR - cloudrInstanceManager.initialize(); - - // Finalizing cloudR - cloudrInstanceManager.finalize(); - - // Finalizing base instance manager - instanceManager->finalize(); -} diff --git a/extern/cloudrRPC/examples/clone/meson.build b/extern/cloudrRPC/examples/clone/meson.build deleted file mode 100644 index 38fe4b0..0000000 --- a/extern/cloudrRPC/examples/clone/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -testSuite = [ 'examples', 'clone' ] - -clone = executable('clone', [ 'clone.cpp'], dependencies: CloudRBuildDep) -if get_option('buildTests') - test('clone', mpirunExecutable, args : [ '-np', '5', '--oversubscribe', clone.full_path() ], timeout: 60, suite: testSuite ) -endif diff --git a/extern/cloudrRPC/examples/meson.build b/extern/cloudrRPC/examples/meson.build deleted file mode 100644 index 0e76160..0000000 --- a/extern/cloudrRPC/examples/meson.build +++ /dev/null @@ -1 +0,0 @@ -subdir('clone') diff --git a/extern/cloudrRPC/gcovr.cfg b/extern/cloudrRPC/gcovr.cfg deleted file mode 100644 index 2303a96..0000000 --- a/extern/cloudrRPC/gcovr.cfg +++ /dev/null @@ -1 +0,0 @@ -filter = include/ diff --git a/extern/cloudrRPC/tests/meson.build b/extern/cloudrRPC/tests/meson.build deleted file mode 100644 index 491c8fe..0000000 --- a/extern/cloudrRPC/tests/meson.build +++ /dev/null @@ -1,26 +0,0 @@ - gtest_dep = dependency('gtest', main: true, required: true) - - TaskRTestCppFlags = [ - ] - - cpp = meson.get_compiler('cpp') - if get_option('b_coverage') - gcov_args = [ - '-fno-inline', - '-Wno-error=cpp', - '-DENABLE_COVERAGE', - ] - if cpp.get_id().to_lower() == 'gcc' - gcov_args += [ - '-fno-default-inline', - '-fno-inline-small-functions', - ] - endif - - TaskRTestCppFlags += gcov_args - endif - - TaskRTestDep = declare_dependency( - compile_args: TaskRTestCppFlags, - dependencies: gtest_dep - ) \ No newline at end of file From 5d2b2656ff7d146badedb99a19b83a1b38d712ea Mon Sep 17 00:00:00 2001 From: Luca Terracciano Date: Mon, 15 Sep 2025 12:51:17 +0200 Subject: [PATCH 5/5] examples: fix resource requirements --- examples/deploy/deployment.json | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/examples/deploy/deployment.json b/examples/deploy/deployment.json index bf3f308..e896d20 100644 --- a/examples/deploy/deployment.json +++ b/examples/deploy/deployment.json @@ -15,12 +15,6 @@ "Type": "NUMA Domain", "Compute Resources": [ - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, { "Type": "Processing Unit" }, { "Type": "Processing Unit" } ], @@ -28,7 +22,7 @@ [ { "Type": "RAM", - "Size": 33554432 + "Size": 10000000 } ] } @@ -45,12 +39,6 @@ "Type": "NUMA Domain", "Compute Resources": [ - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, - { "Type": "Processing Unit" }, { "Type": "Processing Unit" }, { "Type": "Processing Unit" } ], @@ -58,7 +46,7 @@ [ { "Type": "RAM", - "Size": 33554432 + "Size": 10000000 } ] }