├── test ├── build-apollo-test.sh ├── build-test-cuda.sh ├── build-apollo-overhead.sh ├── build-test-hip.sh ├── sosd.stop.sh ├── run.all.tests.sourceme ├── sosd.init.sh ├── CMakeLists.txt ├── apollo-test-simple.cpp ├── apollo-test.cpp ├── apollo-test-mpi.cpp ├── apollo-overhead.cpp ├── test-cuda.cpp └── test-hip.cpp ├── .gitignore ├── apollo.pc.in ├── src ├── python │ ├── .gitignore │ ├── analysis │ │ ├── run-exhaustive.py │ │ ├── rfc2dot.py │ │ ├── dtree2dot.py │ │ ├── rfc2dot_opencv.py │ │ ├── plot-trace.py │ │ └── analyze-traces.py │ └── modeling │ │ └── create-dataset.py ├── models │ ├── Static.cpp │ ├── DatasetMap.cpp │ ├── Random.cpp │ ├── Optimal.cpp │ ├── impl │ │ ├── RandomForestImpl.h │ │ ├── DecisionTreeImpl.h │ │ └── RandomForestImpl.cpp │ ├── RoundRobin.cpp │ ├── DecisionTree.cpp │ ├── RandomForest.cpp │ └── RegressionTree.cpp ├── helpers │ ├── ErrorHandling.h │ ├── OutputFormatter.cpp │ ├── Parser.h │ ├── TimeTrace.h │ ├── OutputFormatter.h │ └── Parser.cpp ├── timers │ ├── TimerSync.h │ ├── TimerHipAsync.h │ ├── TimerCudaAsync.h │ ├── TimerSync.cpp │ ├── TimerHipAsync.cpp │ └── TimerCudaAsync.cpp ├── Config.cpp ├── connectors │ └── kokkos │ │ └── include │ │ └── impl │ │ ├── Kokkos_Profiling_DeviceInfo.hpp │ │ ├── Kokkos_Profiling_Interface.hpp │ │ └── Kokkos_Profiling_C_Interface.h ├── CMakeLists.txt ├── Dataset.cpp └── ModelFactory.cpp ├── cmake ├── ApolloProjectMacros.cmake ├── GetGitRevisionDescription.cmake.in ├── PreventInSourceBuilds.cmake ├── FindSOS.cmake ├── FindAPOLLO.cmake ├── FindCaliper.cmake └── GetGitRevisionDescription.cmake ├── docs ├── index.rst ├── Makefile └── conf.py ├── include └── apollo │ ├── Timer.h │ ├── TimingModel.h │ ├── models │ ├── Optimal.h │ ├── RoundRobin.h │ ├── Random.h │ ├── RegressionTree.h │ ├── Static.h │ ├── DatasetMap.h │ ├── DecisionTree.h │ ├── RandomForest.h │ └── PolicyNet.h │ ├── PolicyModel.h │ ├── ModelFactory.h │ ├── Dataset.h │ ├── Config.h │ ├── Apollo.h │ └── Region.h ├── .clang-format ├── LICENSE ├── NOTICE ├── README.md ├── apollo-config.cmake.in ├── apollo-config.h.in ├── CMakeLists.txt └── HOWTO.md /test/build-apollo-test.sh: -------------------------------------------------------------------------------- 1 | # Assumes Apollo built and installed under ../build/install 2 | 3 | set -x 4 | 5 | c++ -O3 -std=c++14 -I ../build/install/include -L ../build/install/lib \ 6 | -Wl,-rpath,../build/install/lib apollo-test.cpp -o ./apollo-test.x -lapollo 7 | -------------------------------------------------------------------------------- /test/build-test-cuda.sh: -------------------------------------------------------------------------------- 1 | # Assumes apollo has been built in ../build, installed in ../build/install 2 | 3 | nvcc -x cu -g -Xlinker "-rpath,../build/install/lib" \ 4 | -I ../build/install/include test-cuda.cpp -L ../build/install/lib -o test-cuda.x -lapollo -lcudart 5 | -------------------------------------------------------------------------------- /test/build-apollo-overhead.sh: -------------------------------------------------------------------------------- 1 | # Assumes Apollo built and installed under ../build/install 2 | 3 | set -x 4 | 5 | c++ -O3 -std=c++14 -I ../build/install/include -L ../build/install/lib \ 6 | -Wl,-rpath,../build/install/lib apollo-overhead.cpp -o ./apollo-overhead.x \ 7 | -lapollo 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build 3 | install 4 | data 5 | go 6 | go.hard 7 | run 8 | app.log 9 | *.pyc 10 | sosd.*.db 11 | sosd.*.key 12 | *.swp 13 | .gdb_history 14 | .vscode/ 15 | examples/caliper-examples 16 | CMakeCache.txt 17 | CMakeFiles/ 18 | GTAGS 19 | GPATH 20 | GRTAGS 21 | tags 22 | -------------------------------------------------------------------------------- /test/build-test-hip.sh: -------------------------------------------------------------------------------- 1 | # Assumes apollo has been built in ../build, installed in ../build/install. 2 | # Assumes hipcc in the path shown. 3 | 4 | /opt/rocm-4.5.2/bin/hipcc -I ../build/install/include -L ../build/install/lib \ 5 | -Wl,-rpath,../build/install/lib test-hip.cpp -o test-hip.x -lapollo -ldl 6 | -------------------------------------------------------------------------------- /apollo.pc.in: -------------------------------------------------------------------------------- 1 | Name: ${PROJECT_NAME} 2 | Description: Apollo is an in situ machine learning tool for performance portability. 3 | Version: ${APOLLO_VERSION} 4 | prefix=${CMAKE_INSTALL_PREFIX} 5 | includedir=${PKG_CONFIG_INCLUDEDIR} 6 | libdir=${PKG_CONFIG_LIBDIR} 7 | Libs: ${PKG_CONFIG_LIBS} 8 | Cflags: ${PKG_CONFIG_CFLAGS} 9 | -------------------------------------------------------------------------------- /src/python/.gitignore: -------------------------------------------------------------------------------- 1 | sos_tmp 2 | trace_times.csv 3 | trace_times.png 4 | trace_model.json 5 | trace_models 6 | trace_keyerror.log 7 | output 8 | ssos_python.so 9 | model.dot 10 | model.json 11 | model.png 12 | regress.dot 13 | regress.json 14 | regress.png 15 | *.pyc 16 | sosd.*.id 17 | sosd.*.db 18 | sosd.*.key 19 | -------------------------------------------------------------------------------- /test/sosd.stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "x$SOS_BUILD_DIR" == "x" ] ; then 3 | echo "" 4 | echo "ERROR: Please set \$\{SOS_BUILD_DIR\} before running this script." 5 | echo "" 6 | kill -INT $$ 7 | fi 8 | set +m 9 | SOS_CMD_PORT=22888 ${SOS_BUILD_DIR}/bin/sosd_stop 10 | rm -f ./sosd.00000.id 11 | set -m 12 | -------------------------------------------------------------------------------- /test/run.all.tests.sourceme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "x${SOS_BUILD_DIR}" == "x" ] ; then 3 | echo "" 4 | echo "ERROR: Please set \$\{SOS_BUILD_DIR\} before running this script." 5 | echo "" 6 | kill -INT $$ 7 | fi 8 | 9 | EXISTING_SOS_CMD_PORT=${SOS_CMD_PORT} 10 | export SOS_CMD_PORT=22888 11 | 12 | 13 | 14 | export SOS_CMD_PORT=${EXISTING_SOS_CMD_PORT} 15 | unset EXISTING_SOS_CMD_PORT 16 | -------------------------------------------------------------------------------- /cmake/ApolloProjectMacros.cmake: -------------------------------------------------------------------------------- 1 | # Macro for supporting C99 for all versions of CMake 2 | 3 | macro(use_c99) 4 | if (CMAKE_VERSION VERSION_LESS "3.1") 5 | if (CMAKE_C_COMPILER_ID STREQUAL "GNU") 6 | set (CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}") 7 | else () 8 | set (CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}") 9 | endif () 10 | else () 11 | set (CMAKE_C_STANDARD 99) 12 | endif () 13 | endmacro(use_c99) 14 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. rlsl documentation master file, created by 2 | sphinx-quickstart on Fri Feb 20 01:11:46 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to rlsl's documentation! 7 | ================================ 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | Indices and tables 15 | ================== 16 | 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | 21 | -------------------------------------------------------------------------------- /src/models/Static.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/Static.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace apollo 12 | { 13 | 14 | int Static::getIndex(std::vector &features) { return policy_choice; } 15 | 16 | } // end namespace apollo. -------------------------------------------------------------------------------- /src/helpers/ErrorHandling.h: -------------------------------------------------------------------------------- 1 | #ifndef APOLLO_ERROR_HANDLING_H 2 | #define APOLLO_ERROR_HANDLING_H 3 | 4 | #include 5 | 6 | namespace apollo 7 | { 8 | 9 | static void fatal_error_internal(const std::string &msg, 10 | const char *file, 11 | const unsigned line) 12 | { 13 | std::cerr << file << ":" << line << " " << msg << "\n"; 14 | abort(); 15 | } 16 | 17 | } // namespace apollo 18 | 19 | #define fatal_error(msg) apollo::fatal_error_internal(msg, __FILE__, __LINE__) 20 | 21 | #endif -------------------------------------------------------------------------------- /src/helpers/OutputFormatter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "OutputFormatter.h" 7 | 8 | OutputFormatter::OutputFormatter(std::ostream &os) : os(os), level(0) {} 9 | 10 | OutputFormatter &OutputFormatter::operator++() 11 | { 12 | level++; 13 | return *this; 14 | } 15 | 16 | OutputFormatter &OutputFormatter::operator--() 17 | { 18 | level--; 19 | return *this; 20 | } -------------------------------------------------------------------------------- /test/sosd.init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "x$SOS_BUILD_DIR" == "x" ] ; then 3 | echo "" 4 | echo "ERROR: Please set \$\{SOS_BUILD_DIR\} before running this script." 5 | echo "" 6 | kill -INT $$ 7 | fi 8 | set +m 9 | rm -f ./sosd.00000.pid 10 | source ${SOS_BUILD_DIR}/../hosts/linux/setenv.sh quiet 11 | export SOS_BATCH_ENVIRONMENT="TRUE" 12 | export SOS_DB_DISABLED="FALSE" 13 | export SOS_UPDATE_LATEST_FRAME="TRUE" 14 | export SOS_IN_MEMORY_DATABASE="TRUE" 15 | export SOS_EXPORT_DB_AT_EXIT="FALSE" 16 | echo "" 17 | SOS_CMD_PORT=22888 ${SOS_BUILD_DIR}/bin/sosd -l 0 -a 1 -r aggregator -k 0 -w ${SOS_WORK} & 18 | set -m 19 | -------------------------------------------------------------------------------- /src/timers/TimerSync.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_TIMER_SYNC_H 7 | #define APOLLO_TIMER_SYNC_H 8 | 9 | #include "apollo/Timer.h" 10 | 11 | class TimerSync : public Apollo::Timer 12 | { 13 | public: 14 | TimerSync(){}; 15 | ~TimerSync(){}; 16 | void start(); 17 | void stop(); 18 | bool isDone(double &metric); 19 | 20 | private: 21 | double exec_time_begin, exec_time_end; 22 | }; 23 | 24 | #endif -------------------------------------------------------------------------------- /src/helpers/Parser.h: -------------------------------------------------------------------------------- 1 | #ifndef APOLLO_HELPERS_PARSER_H 2 | #define APOLLO_HELPERS_PARSER_H 3 | 4 | #include 5 | #include 6 | 7 | class Parser 8 | { 9 | public: 10 | Parser(std::istream &is) : is(is){}; 11 | 12 | template 13 | void parse(T &out); 14 | 15 | void parseExpected(const char *expected); 16 | 17 | const char *getNextToken(); 18 | const char *getToken() const; 19 | bool getTokenEquals(const char *s); 20 | bool getNextTokenEquals(const char *s); 21 | 22 | private: 23 | std::istream &is; 24 | static constexpr size_t BUFSIZE = 64; 25 | char buffer[BUFSIZE]; 26 | char *token; 27 | void error(const std::string &msg); 28 | }; 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/timers/TimerHipAsync.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_TIMER_HIP_ASYNC_H 7 | #define APOLLO_TIMER_HIP_ASYNC_H 8 | 9 | #include 10 | 11 | #include "apollo/Timer.h" 12 | 13 | class TimerHipAsync : public Apollo::Timer 14 | { 15 | public: 16 | TimerHipAsync(); 17 | ~TimerHipAsync(); 18 | void start(); 19 | void stop(); 20 | bool isDone(double &metric); 21 | 22 | private: 23 | hipEvent_t event_start; 24 | hipEvent_t event_stop; 25 | }; 26 | 27 | #endif -------------------------------------------------------------------------------- /src/timers/TimerCudaAsync.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_TIMER_CUDA_ASYNC_H 7 | #define APOLLO_TIMER_CUDA_ASYNC_H 8 | 9 | #include 10 | 11 | #include "apollo/Timer.h" 12 | 13 | class TimerCudaAsync : public Apollo::Timer 14 | { 15 | public: 16 | TimerCudaAsync(); 17 | ~TimerCudaAsync(); 18 | void start(); 19 | void stop(); 20 | bool isDone(double &metric); 21 | 22 | private: 23 | cudaEvent_t event_start; 24 | cudaEvent_t event_stop; 25 | }; 26 | 27 | #endif -------------------------------------------------------------------------------- /src/timers/TimerSync.cpp: -------------------------------------------------------------------------------- 1 | #include "timers/TimerSync.h" 2 | 3 | #include 4 | #include 5 | 6 | template <> 7 | std::unique_ptr Apollo::Timer::create() 8 | { 9 | return std::make_unique(); 10 | } 11 | 12 | void TimerSync::start() 13 | { 14 | struct timespec ts; 15 | clock_gettime(CLOCK_MONOTONIC, &ts); 16 | exec_time_begin = ts.tv_sec + ts.tv_nsec / 1e9; 17 | } 18 | 19 | void TimerSync::stop() 20 | { 21 | struct timespec ts; 22 | clock_gettime(CLOCK_MONOTONIC, &ts); 23 | exec_time_end = ts.tv_sec + ts.tv_nsec / 1e9; 24 | } 25 | 26 | bool TimerSync::isDone(double &metric) 27 | { 28 | metric = exec_time_end - exec_time_begin; 29 | return true; 30 | } 31 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | # Apollo project developers. Produced at the Lawrence Livermore National 3 | # Laboratory. See the top-level LICENSE file for details. 4 | # SPDX-License-Identifier: MIT 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(apollo-test-simple apollo-test-simple.cpp) 9 | add_executable(apollo-test apollo-test.cpp) 10 | add_executable(apollo-overhead apollo-overhead.cpp) 11 | 12 | target_link_libraries(apollo-test-simple apollo) 13 | target_link_libraries(apollo-test apollo) 14 | target_link_libraries(apollo-overhead apollo) 15 | 16 | if (ENABLE_MPI) 17 | add_executable(apollo-test-mpi apollo-test-mpi.cpp) 18 | target_link_libraries(apollo-test-mpi apollo) 19 | endif() 20 | -------------------------------------------------------------------------------- /include/apollo/Timer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_TIMER_H 7 | #define APOLLO_TIMER_H 8 | 9 | #include 10 | 11 | #include "apollo/Apollo.h" 12 | 13 | class Apollo::Timer 14 | { 15 | public: 16 | Timer() {} 17 | virtual ~Timer() {} 18 | 19 | virtual void start() = 0; 20 | virtual void stop() = 0; 21 | virtual bool isDone(double &metric) = 0; 22 | 23 | template 24 | static std::unique_ptr create(); 25 | 26 | struct Sync; 27 | struct CudaAsync; 28 | struct HipAsync; 29 | }; // end: Timer (abstract class) 30 | 31 | 32 | #endif -------------------------------------------------------------------------------- /include/apollo/TimingModel.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_TIMING_MODEL_H 7 | #define APOLLO_TIMING_MODEL_H 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/Dataset.h" 13 | 14 | // Abstract 15 | class TimingModel 16 | { 17 | public: 18 | TimingModel(std::string name) : name(name){}; 19 | virtual ~TimingModel() {} 20 | virtual double getTimePrediction(std::vector &features) = 0; 21 | virtual void store(const std::string &filename) = 0; 22 | 23 | std::string name = ""; 24 | }; // end: TimingModel (abstract class) 25 | 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle : google 2 | IndentWidth : 2 3 | BreakBeforeBraces : Linux 4 | KeepEmptyLinesAtTheStartOfBlocks : true 5 | MaxEmptyLinesToKeep : 2 6 | AccessModifierOffset : -2 7 | UseTab: Never 8 | AllowShortIfStatementsOnASingleLine : true 9 | ConstructorInitializerAllOnOneLineOrOnePerLine : true 10 | AllowShortFunctionsOnASingleLine : true 11 | AllowShortLoopsOnASingleLine : false 12 | BinPackParameters : false 13 | AllowAllParametersOfDeclarationOnNextLine : false 14 | AlignTrailingComments : true 15 | ColumnLimit : 80 16 | PenaltyBreakBeforeFirstCallParameter : 100 17 | PenaltyReturnTypeOnItsOwnLine : 65000 18 | PenaltyBreakString : 10 19 | 20 | # These improve formatting results but require clang 3.6/7 or higher 21 | BreakBeforeBinaryOperators : None 22 | AlignAfterOpenBracket: true 23 | BinPackArguments : false 24 | AlignOperands : true 25 | AlwaysBreakTemplateDeclarations : true 26 | Cpp11BracedListStyle : true 27 | 28 | -------------------------------------------------------------------------------- /src/models/DatasetMap.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/DatasetMap.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace apollo 12 | { 13 | 14 | int DatasetMap::getIndex(std::vector &features) 15 | { 16 | if (best_policies.count(features) == 0) { 17 | std::cerr << "DatasetMap does not have an entry for those features\n"; 18 | abort(); 19 | } 20 | 21 | int policy = best_policies[features].first; 22 | 23 | return policy; 24 | } 25 | 26 | void DatasetMap::train(Apollo::Dataset &dataset) 27 | { 28 | std::vector> features; 29 | std::vector policies; 30 | dataset.findMinMetricPolicyByFeatures(features, policies, best_policies); 31 | } 32 | 33 | } // end namespace apollo. -------------------------------------------------------------------------------- /include/apollo/models/Optimal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_OPTIMAL_H 7 | #define APOLLO_MODELS_OPTIMAL_H 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/PolicyModel.h" 13 | 14 | namespace apollo 15 | { 16 | 17 | class Optimal : public PolicyModel 18 | { 19 | public: 20 | Optimal(std::string file); 21 | Optimal(); 22 | ~Optimal(){}; 23 | 24 | // 25 | int getIndex(std::vector &features); 26 | void load(const std::string &filename); 27 | void store(const std::string &filename){}; 28 | bool isTrainable() { return false; } 29 | void train(Apollo::Dataset &dataset) {} 30 | 31 | private: 32 | std::deque optimal_policy; 33 | 34 | }; // end: Optimal (class) 35 | 36 | } // end namespace apollo. 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/apollo/models/RoundRobin.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_ROUNDROBIN_H 7 | #define APOLLO_MODELS_ROUNDROBIN_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "apollo/PolicyModel.h" 14 | 15 | namespace apollo 16 | { 17 | class RoundRobin : public PolicyModel 18 | { 19 | public: 20 | RoundRobin(int num_policies); 21 | ~RoundRobin(); 22 | 23 | int getIndex(std::vector &features); 24 | void load(const std::string &filename){}; 25 | void store(const std::string &filename){}; 26 | bool isTrainable() { return false; } 27 | void train(Apollo::Dataset &dataset) {} 28 | 29 | private: 30 | std::map, int> policies; 31 | int last_policy; 32 | 33 | }; // end: RoundRobin (class) 34 | 35 | } // end namespace apollo. 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/models/Random.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/Random.h" 7 | 8 | #include 9 | 10 | #include "apollo/Config.h" 11 | 12 | namespace apollo 13 | { 14 | 15 | int Random::getIndex(std::vector &features) 16 | { 17 | int choice = 0; 18 | 19 | if (policy_count > 1) { 20 | choice = random_dist(random_gen); 21 | //std::cout << "Choose [ " << 0 << ", " << (policy_count - 1) \ 22 | << " ]: " << choice << std::endl; 23 | } else { 24 | choice = 0; 25 | } 26 | 27 | return choice; 28 | } 29 | 30 | Random::Random(int num_policies) : PolicyModel(num_policies, "Random") 31 | { 32 | random_gen = std::mt19937(random_dev()); 33 | random_dist = std::uniform_int_distribution<>(0, policy_count - 1); 34 | } 35 | 36 | Random::~Random() { return; } 37 | 38 | } // end namespace apollo. 39 | -------------------------------------------------------------------------------- /test/apollo-test-simple.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include 7 | 8 | #include "apollo/Apollo.h" 9 | #include "apollo/Region.h" 10 | 11 | #define NUM_FEATURES 1 12 | #define NUM_POLICIES 2 13 | 14 | int main() 15 | { 16 | std::cout << "=== Apollo: Simple Compilation Testing\n"; 17 | 18 | Apollo *apollo = Apollo::instance(); 19 | 20 | // Create region. 21 | Apollo::Region *r = 22 | new Apollo::Region(NUM_FEATURES, "test-region", NUM_POLICIES); 23 | 24 | 25 | for (int i = 0; i < 10; ++i) { 26 | r->begin(); 27 | r->setFeature(float(1.0)); 28 | 29 | int policy = r->getPolicyIndex(); 30 | 31 | std::cout << "Executing with policy " << policy << "\n"; 32 | 33 | r->end(); 34 | } 35 | 36 | std::cout << "PASSED\n"; 37 | 38 | std::cout << "=== Testing complete\n"; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /include/apollo/models/Random.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_RANDOM_H 7 | #define APOLLO_MODELS_RANDOM_H 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/PolicyModel.h" 13 | 14 | namespace apollo 15 | { 16 | class Random : public PolicyModel 17 | { 18 | public: 19 | Random(int num_policies); 20 | ~Random(); 21 | 22 | // 23 | int getIndex(std::vector &features); 24 | void load(const std::string &filename){}; 25 | void store(const std::string &filename){}; 26 | bool isTrainable() { return false; } 27 | void train(Apollo::Dataset &dataset) {} 28 | 29 | private: 30 | std::random_device random_dev; 31 | std::mt19937 random_gen; 32 | std::uniform_int_distribution<> random_dist; 33 | }; // end: Apollo::Model::Random (class) 34 | 35 | } // end namespace apollo 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/apollo/models/RegressionTree.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_REGRESSIONTREE_H 7 | #define APOLLO_MODELS_REGRESSIONTREE_H 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace cv; 13 | using namespace cv::ml; 14 | 15 | #include "apollo/TimingModel.h" 16 | 17 | class RegressionTree : public TimingModel 18 | { 19 | 20 | public: 21 | RegressionTree(Apollo::Dataset &dataset); 22 | 23 | 24 | ~RegressionTree(); 25 | 26 | double getTimePrediction(std::vector &features); 27 | void store(const std::string &filename); 28 | 29 | private: 30 | // Ptr dtree; 31 | Ptr dtree; 32 | // Ptr dtree; 33 | // Ptr dtree; 34 | // Ptr dtree; 35 | // Ptr dtree; 36 | }; // end: RegressionTree (class) 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/apollo/models/Static.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_STATIC_H 7 | #define APOLLO_MODELS_STATIC_H 8 | 9 | #include 10 | 11 | #include "apollo/PolicyModel.h" 12 | 13 | namespace apollo 14 | { 15 | class Static : public PolicyModel 16 | { 17 | public: 18 | Static(int num_policies, int policy_choice) 19 | : PolicyModel(num_policies, "Static," + std::to_string(policy_choice)), 20 | policy_choice(policy_choice){}; 21 | ~Static(){}; 22 | 23 | // 24 | int getIndex(std::vector &features); 25 | void load(const std::string &filename){}; 26 | void store(const std::string &filename){}; 27 | bool isTrainable() { return false; } 28 | void train(Apollo::Dataset &dataset) {} 29 | 30 | private: 31 | int policy_choice; 32 | 33 | }; // end: Static (class) 34 | 35 | } // end namespace apollo. 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/apollo/models/DatasetMap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_DATASETMAP_H 7 | #define APOLLO_MODELS_DATASETMAP_H 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/PolicyModel.h" 13 | 14 | namespace apollo 15 | { 16 | class DatasetMap : public PolicyModel 17 | { 18 | public: 19 | DatasetMap(int num_policies) : PolicyModel(num_policies, "DatasetMap"){}; 20 | ~DatasetMap(){}; 21 | 22 | // 23 | int getIndex(std::vector &features); 24 | void load(const std::string &filename){}; 25 | void store(const std::string &filename){}; 26 | bool isTrainable() { return false; } 27 | void train(Apollo::Dataset &dataset); 28 | 29 | private: 30 | // Maps features -> policy. 31 | std::map, std::pair> best_policies; 32 | 33 | }; // end: DatasetMap (class) 34 | 35 | } // end namespace apollo. 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/apollo/PolicyModel.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_POLICY_MODEL_H 7 | #define APOLLO_POLICY_MODEL_H 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/Dataset.h" 13 | 14 | 15 | namespace apollo 16 | { 17 | // Abstract 18 | class PolicyModel 19 | { 20 | public: 21 | PolicyModel(int num_policies, std::string name) 22 | : policy_count(num_policies), name(name){}; 23 | virtual ~PolicyModel() {} 24 | // 25 | virtual int getIndex(std::vector &features) = 0; 26 | 27 | virtual void store(const std::string &filename) = 0; 28 | virtual void load(const std::string &filename) = 0; 29 | 30 | virtual bool isTrainable() = 0; 31 | virtual void train(Apollo::Dataset &dataset) = 0; 32 | 33 | 34 | int policy_count; 35 | std::string name = ""; 36 | }; // end: PolicyModel (abstract class) 37 | 38 | } // end namespace apollo. 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/helpers/TimeTrace.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_HELPERS_TIMETRACE_H 7 | #define APOLLO_HELPERS_TIMETRACE_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "apollo/Timer.h" 15 | 16 | // Simple time tracing class, outputs time elapsed in a block scope. 17 | class TimeTrace 18 | { 19 | std::string ref; 20 | std::unique_ptr timer; 21 | 22 | public: 23 | TimeTrace(std::string ref) 24 | : ref(ref), timer(Apollo::Timer::create()) 25 | { 26 | timer->start(); 27 | } 28 | ~TimeTrace() 29 | { 30 | timer->stop(); 31 | double duration; 32 | timer->isDone(duration); 33 | std::stringstream outs; 34 | outs << std::fixed << std::setprecision(0) << duration * 1e6; 35 | std::cout << "=== T ref " << ref << " = " << outs.str() << " us" 36 | << std::endl; 37 | } 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /include/apollo/ModelFactory.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODEL_FACTORY_H 7 | #define APOLLO_MODEL_FACTORY_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "apollo/PolicyModel.h" 14 | #include "apollo/TimingModel.h" 15 | 16 | namespace apollo 17 | { 18 | // Factory 19 | class ModelFactory 20 | { 21 | public: 22 | static std::unique_ptr createPolicyModel( 23 | const std::string &model_name, 24 | int num_policies, 25 | const std::string &path); 26 | static std::unique_ptr createPolicyModel( 27 | const std::string &model_name, 28 | int num_features, 29 | int num_policies, 30 | std::unordered_map &model_params); 31 | 32 | static std::unique_ptr createRegressionTree( 33 | Apollo::Dataset &dataset); 34 | }; // end: ModelFactory 35 | 36 | } // end namespace apollo. 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/python/analysis/run-exhaustive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import subprocess 5 | import os 6 | 7 | # TODO: compare between local vs. collective training 8 | 9 | def main(): 10 | parser = argparse.ArgumentParser(description='Run an exhaustive experiments for a program.') 11 | parser.add_argument('-n', '--npolicies', type=int, help='the number of policies to test.', required=True) 12 | parser.add_argument('-x', '--exe', help='the executable to run with arguments.', required=True) 13 | args = parser.parse_args() 14 | 15 | print('args.npolicies ', args.npolicies) 16 | 17 | subenv = os.environ.copy() 18 | subenv['APOLLO_TRACE_CSV'] = '1' 19 | subenv['APOLLO_RETRAIN_ENABLE'] = '0' 20 | for i in range(0, args.npolicies): 21 | subenv['APOLLO_POLICY_MODEL'] = 'Static,policy=%d'%(i) 22 | subprocess.run(args.exe, shell=True, check=True, env=subenv) 23 | 24 | #subenv['APOLLO_COLLECTIVE_TRAINING'] = '0' 25 | #subenv['APOLLO_LOCAL_TRAINING'] = '1' 26 | subenv['APOLLO_POLICY_MODEL'] = 'RoundRobin' 27 | subprocess.run(args.exe, shell=True, check=True, env=subenv) 28 | 29 | if __name__ == "__main__": 30 | main() 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015-2024 Lawrence Livermore National Security, LLC and other 2 | Apollo Project Developers. See the top-level README.md file for details. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the "Software"), 6 | to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of 2 | Energy by Lawrence Livermore National Laboratory under Contract 3 | DE-AC52-07NA27344. 4 | 5 | This work was prepared as an account of work sponsored by an agency of 6 | the United States Government. Neither the United States Government nor 7 | Lawrence Livermore National Security, LLC, nor any of their employees 8 | makes any warranty, expressed or implied, or assumes any legal liability 9 | or responsibility for the accuracy, completeness, or usefulness of any 10 | information, apparatus, product, or process disclosed, or represents that 11 | its use would not infringe privately owned rights. 12 | 13 | Reference herein to any specific commercial product, process, or service 14 | by trade name, trademark, manufacturer, or otherwise does not necessarily 15 | constitute or imply its endorsement, recommendation, or favoring by the 16 | United States Government or Lawrence Livermore National Security, LLC. 17 | 18 | The views and opinions of authors expressed herein do not necessarily 19 | state or reflect those of the United States Government or Lawrence 20 | Livermore National Security, LLC, and shall not be used for advertising 21 | or product endorsement purposes. 22 | -------------------------------------------------------------------------------- /src/Config.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/Config.h" 7 | 8 | #include 9 | 10 | int Config::APOLLO_COLLECTIVE_TRAINING; 11 | int Config::APOLLO_LOCAL_TRAINING; 12 | int Config::APOLLO_SINGLE_MODEL; 13 | int Config::APOLLO_REGION_MODEL; 14 | int Config::APOLLO_TRACE_POLICY; 15 | int Config::APOLLO_RETRAIN_ENABLE; 16 | float Config::APOLLO_RETRAIN_TIME_THRESHOLD; 17 | float Config::APOLLO_RETRAIN_REGION_THRESHOLD; 18 | int Config::APOLLO_STORE_MODELS; 19 | int Config::APOLLO_TRACE_RETRAIN; 20 | int Config::APOLLO_TRACE_ALLGATHER; 21 | int Config::APOLLO_TRACE_BEST_POLICIES; 22 | int Config::APOLLO_GLOBAL_TRAIN_PERIOD; 23 | int Config::APOLLO_PER_REGION_TRAIN_PERIOD; 24 | int Config::APOLLO_TRACE_CSV; 25 | int Config::APOLLO_PERSISTENT_DATASETS; 26 | int Config::APOLLO_STORE_EXEC_INFO; 27 | std::string Config::APOLLO_POLICY_MODEL; 28 | std::string Config::APOLLO_OUTPUT_DIR; 29 | std::string Config::APOLLO_DATASETS_DIR; 30 | std::string Config::APOLLO_TRACES_DIR; 31 | std::string Config::APOLLO_MODELS_DIR; 32 | -------------------------------------------------------------------------------- /src/python/analysis/rfc2dot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import yaml 5 | from dtree2dot import parse_tree 6 | 7 | 8 | def parse_rfc(y): 9 | rfc = y['rfc'] 10 | dot = 'rfc [ shape=oval, label=\"rfc\n' 11 | for k in rfc: 12 | if 'tree' in k: 13 | continue 14 | if k == 'data': 15 | continue 16 | dot += '%s: %s' % (k, rfc[k]) 17 | dot += ',\n' 18 | dot += '\"];\n' 19 | 20 | for tree_idx in range(rfc['num_trees']): 21 | dot += parse_tree(rfc['trees'][tree_idx], 'tree_%s' % (tree_idx)) 22 | dot += 'rfc -> tree_%s\n' % (tree_idx) 23 | 24 | return dot 25 | 26 | 27 | def main(): 28 | parser = argparse.ArgumentParser( 29 | description='Generate dot graph file from Apollo random forests yaml.') 30 | parser.add_argument( 31 | '-i', '--input', help='input yaml file.', required=True) 32 | parser.add_argument( 33 | '-o', '--output', help='output dot file.', required=True) 34 | args = parser.parse_args() 35 | 36 | with open(args.input, 'r') as f: 37 | y = yaml.safe_load(f) 38 | 39 | dot = 'digraph G {\n' 40 | dot += parse_rfc(y) 41 | dot += '\n}' 42 | 43 | with open(args.output, 'w') as f: 44 | f.write(dot) 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /include/apollo/Dataset.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_DATASET_H 7 | #define APOLLO_DATASET_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "apollo/Apollo.h" 16 | 17 | class Apollo::Dataset 18 | { 19 | public: 20 | size_t size(); 21 | void clear(); 22 | 23 | void insert(std::vector &features, int policy, double metric); 24 | void insert(Apollo::Dataset &ds); 25 | 26 | const std::vector, int, double>> 27 | toVectorOfTuples() const; 28 | 29 | void findMinMetricPolicyByFeatures( 30 | std::vector> &features, 31 | std::vector &policies, 32 | std::map, std::pair> &min_metric_policies) 33 | const; 34 | 35 | void load(std::istream &is); 36 | void store(std::ostream &os); 37 | 38 | private: 39 | // Key: features, policy -> value: metric (execution time) exponential moving 40 | // average. 41 | std::map, int>, double> data; 42 | }; // end: Apollo::Dataset 43 | 44 | #endif -------------------------------------------------------------------------------- /src/helpers/OutputFormatter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_OUTPUTFORMATTER_H 7 | #define APOLLO_MODELS_OUTPUTFORMATTER_H 8 | 9 | #include 10 | 11 | // Output formatting that indents by level (2 spaces) using overloaded operator 12 | // << , or outputs inline, using overloaded operator &. Level is inc/dec by 13 | // overloaded operators ++/--. 14 | class OutputFormatter 15 | { 16 | public: 17 | OutputFormatter(std::ostream &os); 18 | 19 | template 20 | OutputFormatter &operator<<(T output); 21 | 22 | template 23 | OutputFormatter &operator&(T output); 24 | 25 | OutputFormatter &operator++(); 26 | OutputFormatter &operator--(); 27 | 28 | 29 | private: 30 | std::ostream &os; 31 | unsigned level; 32 | }; 33 | 34 | template 35 | OutputFormatter &OutputFormatter::operator<<(T output) 36 | { 37 | for (unsigned int i = 0; i < level; ++i) 38 | os << " "; 39 | os << output; 40 | return *this; 41 | } 42 | 43 | template 44 | OutputFormatter &OutputFormatter::operator&(T output) 45 | { 46 | os << output; 47 | return *this; 48 | } 49 | 50 | #endif -------------------------------------------------------------------------------- /include/apollo/Config.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_CONFIG_H 7 | #define APOLLO_CONFIG_H 8 | 9 | #include 10 | 11 | class Config 12 | { 13 | public: 14 | static int APOLLO_COLLECTIVE_TRAINING; 15 | static int APOLLO_LOCAL_TRAINING; 16 | static int APOLLO_SINGLE_MODEL; 17 | static int APOLLO_REGION_MODEL; 18 | static int APOLLO_TRACE_POLICY; 19 | static int APOLLO_RETRAIN_ENABLE; 20 | static float APOLLO_RETRAIN_TIME_THRESHOLD; 21 | static float APOLLO_RETRAIN_REGION_THRESHOLD; 22 | static int APOLLO_STORE_MODELS; 23 | static int APOLLO_TRACE_RETRAIN; 24 | static int APOLLO_TRACE_ALLGATHER; 25 | static int APOLLO_TRACE_BEST_POLICIES; 26 | static int APOLLO_GLOBAL_TRAIN_PERIOD; 27 | static int APOLLO_PER_REGION_TRAIN_PERIOD; 28 | static int APOLLO_TRACE_CSV; 29 | static int APOLLO_PERSISTENT_DATASETS; 30 | static int APOLLO_STORE_EXEC_INFO; 31 | static std::string APOLLO_POLICY_MODEL; 32 | static std::string APOLLO_OUTPUT_DIR; 33 | static std::string APOLLO_DATASETS_DIR; 34 | static std::string APOLLO_TRACES_DIR; 35 | static std::string APOLLO_MODELS_DIR; 36 | 37 | private: 38 | Config(); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/models/Optimal.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/Optimal.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace apollo 14 | { 15 | 16 | Optimal::Optimal(std::string file) : PolicyModel(0, "Optimal") 17 | { 18 | std::ifstream infile(file); 19 | std::string policy_str; 20 | 21 | while (std::getline(infile, policy_str, ',')) 22 | optimal_policy.push_back(std::stoi(policy_str)); 23 | 24 | infile.close(); 25 | } 26 | 27 | Optimal::Optimal() : PolicyModel(0, "Optimal") {} 28 | 29 | int Optimal::getIndex(std::vector &features) 30 | { 31 | if (optimal_policy.empty()) { 32 | std::cerr << "Optimal policy queue is empty!" << std::endl; 33 | abort(); 34 | } 35 | 36 | int policy = optimal_policy.front(); 37 | optimal_policy.pop_front(); 38 | return policy; 39 | } 40 | 41 | void Optimal::load(const std::string &filename) 42 | { 43 | std::ifstream infile(filename); 44 | std::string policy_str; 45 | 46 | while (std::getline(infile, policy_str, ',')) 47 | optimal_policy.push_back(std::stoi(policy_str)); 48 | 49 | infile.close(); 50 | } 51 | 52 | } // end namespace apollo. -------------------------------------------------------------------------------- /include/apollo/models/DecisionTree.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_DECISIONTREE_H 7 | #define APOLLO_MODELS_DECISIONTREE_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "apollo/PolicyModel.h" 14 | 15 | #ifdef ENABLE_OPENCV 16 | #include 17 | using namespace cv; 18 | using namespace cv::ml; 19 | #endif 20 | class DecisionTreeImpl; 21 | 22 | namespace apollo 23 | { 24 | class DecisionTree : public PolicyModel 25 | { 26 | 27 | public: 28 | DecisionTree(int num_policies, 29 | unsigned max_depth, 30 | std::unique_ptr &explorer); 31 | DecisionTree(int num_policies, std::string path); 32 | 33 | ~DecisionTree(); 34 | 35 | int getIndex(void); 36 | int getIndex(std::vector &features); 37 | void store(const std::string &filename); 38 | bool isTrainable(); 39 | void load(const std::string &filename); 40 | void train(Apollo::Dataset &dataset); 41 | 42 | private: 43 | #ifdef ENABLE_OPENCV 44 | Ptr dtree; 45 | #else 46 | std::unique_ptr dtree; 47 | #endif 48 | bool trainable; 49 | std::unique_ptr explorer; 50 | }; 51 | 52 | } // end namespace apollo. 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/models/impl/RandomForestImpl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_RANDOMFORESTIMPL_H 7 | #define APOLLO_MODELS_RANDOMFORESTIMPL_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "DecisionTreeImpl.h" 14 | 15 | class RandomForestImpl 16 | { 17 | public: 18 | RandomForestImpl(int num_classes, std::string filename); 19 | RandomForestImpl(int num_classes, unsigned num_trees, unsigned max_depth); 20 | RandomForestImpl(int num_classes, 21 | std::vector> &features, 22 | std::vector &responses, 23 | unsigned num_trees, 24 | unsigned max_depth); 25 | 26 | void train(std::vector> &features, 27 | std::vector &responses); 28 | void load(const std::string &filename); 29 | void save(const std::string &filename); 30 | int predict(const std::vector &features); 31 | void print_forest(); 32 | 33 | private: 34 | void parse_rfc(std::ifstream &ifs); 35 | void output_rfc(OutputFormatter &outfmt); 36 | std::vector> rfc; 37 | int num_classes; 38 | unsigned num_trees; 39 | unsigned max_depth; 40 | }; 41 | 42 | #endif -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright Iowa State University 2009-2010. 12 | # Distributed under the Boost Software License, Version 1.0. 13 | # (See accompanying file LICENSE_1_0.txt or copy at 14 | # http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | set(HEAD_HASH) 17 | 18 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 19 | 20 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 21 | if(HEAD_CONTENTS MATCHES "ref") 22 | # named branch 23 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 24 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 25 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 26 | else() 27 | configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 28 | file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 29 | if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 30 | set(HEAD_HASH "${CMAKE_MATCH_1}") 31 | endif() 32 | endif() 33 | else() 34 | # detached HEAD 35 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 36 | endif() 37 | 38 | if(NOT HEAD_HASH) 39 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 40 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 41 | endif() 42 | -------------------------------------------------------------------------------- /include/apollo/models/RandomForest.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_RANDOMFOREST_H 7 | #define APOLLO_MODELS_RANDOMFOREST_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "apollo/PolicyModel.h" 14 | 15 | #ifdef ENABLE_OPENCV 16 | #include 17 | using namespace cv; 18 | using namespace cv::ml; 19 | #endif 20 | 21 | class RandomForestImpl; 22 | 23 | namespace apollo 24 | { 25 | 26 | class RandomForest : public PolicyModel 27 | { 28 | public: 29 | RandomForest(int num_policies, 30 | unsigned num_trees, 31 | unsigned max_depth, 32 | std::unique_ptr &explorer); 33 | RandomForest(int num_policies, std::string path); 34 | 35 | ~RandomForest(); 36 | 37 | int getIndex(void); 38 | int getIndex(std::vector &features); 39 | void store(const std::string &filename); 40 | void load(const std::string &filename); 41 | bool isTrainable(); 42 | void train(Apollo::Dataset &dataset); 43 | 44 | private: 45 | #ifdef ENABLE_OPENCV 46 | Ptr rfc; 47 | #else 48 | std::unique_ptr rfc; 49 | #endif 50 | bool trainable; 51 | std::unique_ptr explorer; 52 | }; 53 | 54 | } // end namespace apollo. 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /cmake/PreventInSourceBuilds.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # This function will prevent in-source builds 3 | function(AssureOutOfSourceBuilds) 4 | # make sure the user doesn't play dirty with symlinks 5 | get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) 6 | get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) 7 | 8 | # disallow in-source builds 9 | if("${srcdir}" STREQUAL "${bindir}") 10 | message("######################################################") 11 | message("# APOLLO should not be configured & built in the source directory") 12 | message("# You must run cmake in a build directory.") 13 | message("# For example:") 14 | message("# mkdir build ; cd build") 15 | message("#") 16 | message("# Then you can proceed to configure and build") 17 | message("# by using the following commands") 18 | message("#") 19 | message("# cd build") 20 | message("# cmake .. # or ccmake, or cmake-gui ") 21 | message("# make") 22 | message("#") 23 | message("# NOTE: Given that you already tried to make an in-source build") 24 | message("# CMake may have already created several files & directories") 25 | message("# in your source tree. run 'git status' to find them and") 26 | message("# remove them by doing:") 27 | message("#") 28 | message("# git clean -n -d") 29 | message("# git clean -f -d") 30 | message("# git checkout --") 31 | message("#") 32 | message("######################################################") 33 | message(FATAL_ERROR "Quitting configuration") 34 | endif() 35 | endfunction() 36 | 37 | AssureOutOfSourceBuilds() 38 | -------------------------------------------------------------------------------- /src/models/RoundRobin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/RoundRobin.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "apollo/Config.h" 12 | 13 | namespace apollo 14 | { 15 | 16 | int RoundRobin::getIndex(std::vector &features) 17 | { 18 | int choice = (last_policy + 1) % policy_count; 19 | last_policy = choice; 20 | return choice; 21 | 22 | #if 0 23 | int choice; 24 | if( policies.find( features ) == policies.end() ) { 25 | policies[ features ] = 0; 26 | } 27 | else { 28 | // made a full circle, stop 29 | if( policies[ features ] == 0 ) 30 | return 0; 31 | } 32 | choice = policies[ features ]; 33 | policies[ features ] = ( policies[ features ] + 1) % policy_count; 34 | //std::cout \ 35 | << "features "; \ 36 | for(auto &f : features ) { \ 37 | std::cout << (int) f << ", "; \ 38 | } \ 39 | std::cout << " policy_choice " << choice \ 40 | << " next " << policies[ features ] \ 41 | << std::endl; 42 | 43 | return choice; 44 | #endif 45 | } 46 | 47 | RoundRobin::RoundRobin(int num_policies) 48 | : PolicyModel(num_policies, "RoundRobin") 49 | { 50 | // TODO: Distributed RoundRobin uses mpi rank for offset. 51 | last_policy = -1; 52 | 53 | return; 54 | } 55 | 56 | RoundRobin::~RoundRobin() { return; } 57 | 58 | } // end namespace apollo. 59 | -------------------------------------------------------------------------------- /include/apollo/models/PolicyNet.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_POLICYNET_H 7 | #define APOLLO_MODELS_POLICYNET_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "apollo/PolicyModel.h" 15 | 16 | namespace apollo 17 | { 18 | 19 | class Net; 20 | 21 | class PolicyNet : public PolicyModel 22 | { 23 | public: 24 | PolicyNet(int num_policies, 25 | int num_features, 26 | double lr, 27 | double beta, 28 | double beta1, 29 | double beta2, 30 | double threshold); 31 | 32 | ~PolicyNet(); 33 | 34 | int getIndex(std::vector &features); 35 | 36 | void trainNet(std::vector> &states, 37 | std::vector &actions, 38 | std::vector &rewards); 39 | bool isTrainable(); 40 | void train(Apollo::Dataset &dataset); 41 | 42 | void store(const std::string &filename); 43 | void load(const std::string &filename); 44 | 45 | std::unordered_map> actionProbabilityMap; 46 | 47 | private: 48 | int numPolicies; 49 | std::unique_ptr net; 50 | std::mt19937_64 gen; 51 | double rewardMovingAvg = 0; 52 | double beta; 53 | double threshold; 54 | int trainCount = 0; 55 | bool trainable; 56 | }; // end: PolicyNet (class) 57 | 58 | } // end namespace apollo. 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/python/analysis/dtree2dot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import yaml 5 | 6 | 7 | def parse_node(node, name): 8 | dot = name + ' [ shape=box, label=\"' + name + '\n' 9 | for k in node: 10 | if k == 'left' or k == 'right': 11 | continue 12 | dot += '%s: %s' % (k, node[k]) 13 | dot += ',\n' 14 | 15 | dot += '\"];\n' 16 | 17 | if 'left' in node: 18 | dot += parse_node(node['left'], name + '_left') 19 | dot += name + ' -> ' + name + '_left\n' 20 | 21 | if 'right' in node: 22 | dot += parse_node(node['right'], name + '_right') 23 | dot += name + ' -> ' + name + '_right\n' 24 | 25 | return dot 26 | 27 | 28 | def parse_tree(y, name): 29 | tree = y['tree'] 30 | dot = name + ' [ shape=oval, label=\"' + name + '\n' 31 | for k in tree: 32 | if k == 'root': 33 | continue 34 | if k == 'data': 35 | continue 36 | dot += '%s: %s' % (k, tree[k]) 37 | dot += ',\n' 38 | dot += '\"];\n' 39 | 40 | dot += parse_node(tree['root'], name + '_root') 41 | dot += name + ' -> ' + name + '_root\n' 42 | 43 | return dot 44 | 45 | 46 | def main(): 47 | parser = argparse.ArgumentParser( 48 | description='Generate dot graph file from Apollo decision trees yaml.') 49 | parser.add_argument( 50 | '-i', '--input', help='input yaml file.', required=True) 51 | parser.add_argument( 52 | '-o', '--output', help='output dot file.', required=True) 53 | args = parser.parse_args() 54 | 55 | with open(args.input, 'r') as f: 56 | y = yaml.safe_load(f) 57 | 58 | dot = 'digraph G {\n' 59 | dot += parse_tree(y, 'tree') 60 | dot += '\n}' 61 | 62 | with open(args.output, 'w') as f: 63 | f.write(dot) 64 | 65 | 66 | if __name__ == "__main__": 67 | main() 68 | -------------------------------------------------------------------------------- /cmake/FindSOS.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # Setup SOSflow 4 | # 5 | ############################################################################### 6 | # 7 | # Expects SOS_DIR to point to a SOSflow installation. 8 | # 9 | # This file defines the following CMake variables: 10 | # SOS_FOUND - If SOSflow was found 11 | # SOS_INCLUDE_DIRS - The SOSflow include directories 12 | # SOS_LIBRARY - Path to the libsos file 13 | # 14 | # If found, the SOSflow CMake targets will also be imported. 15 | # The main SOSflow library targets are: 16 | # sos 17 | # 18 | ############################################################################### 19 | 20 | ############################################################################### 21 | # Check for SOS_DIR 22 | ############################################################################### 23 | if(NOT SOS_DIR) 24 | MESSAGE(FATAL_ERROR "Could not find SOSflow. SOSflow requires explicit SOS_DIR.") 25 | endif() 26 | 27 | if(NOT EXISTS ${SOS_DIR}/lib/cmake/sosflow.cmake) 28 | MESSAGE(FATAL_ERROR "Could not find SOSflow CMake include file (${SOS_DIR}/lib/cmake/sosflow.cmake)") 29 | endif() 30 | 31 | ############################################################################### 32 | # Import SOSflow's CMake targets 33 | ############################################################################### 34 | include(${SOS_DIR}/lib/cmake/sosflow.cmake) 35 | 36 | ############################################################################### 37 | # Set remaining CMake variables 38 | ############################################################################### 39 | # we found SOS 40 | set(SOS_FOUND TRUE) 41 | # provide location of the headers and libraries 42 | set(SOS_INCLUDE_DIRS ${SOS_DIR}/include) 43 | find_library(SOS_LIBRARY NAMES sos HINTS ${SOS_DIR}/lib) 44 | set(SOS_LIB_DIRS ${SOS_DIR}/lib) 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/timers/TimerHipAsync.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "timers/TimerHipAsync.h" 7 | 8 | #include 9 | 10 | #define hipErrchk(ans) \ 11 | { \ 12 | hipAssert((ans), __FILE__, __LINE__); \ 13 | } 14 | 15 | static inline void hipAssert(hipError_t code, const char *file, int line) 16 | { 17 | if (code != hipSuccess) { 18 | std::cerr << "HIP error " << hipGetErrorString(code) << " at " << file 19 | << ":" << line << std::endl; 20 | abort(); 21 | } 22 | } 23 | 24 | template <> 25 | std::unique_ptr Apollo::Timer::create() 26 | { 27 | return std::make_unique(); 28 | } 29 | 30 | TimerHipAsync::TimerHipAsync() 31 | { 32 | hipErrchk(hipEventCreateWithFlags(&event_start, hipEventDefault)); 33 | hipErrchk(hipEventCreateWithFlags(&event_stop, hipEventDefault)); 34 | } 35 | 36 | TimerHipAsync::~TimerHipAsync() 37 | { 38 | hipErrchk(hipEventDestroy(event_start)); 39 | hipErrchk(hipEventDestroy(event_stop)); 40 | } 41 | 42 | void TimerHipAsync::start() 43 | { 44 | // TODO: handle multiple streams. 45 | hipErrchk(hipEventRecord(event_start, 0)); 46 | } 47 | 48 | void TimerHipAsync::stop() { hipErrchk(hipEventRecord(event_stop, 0)); } 49 | 50 | bool TimerHipAsync::isDone(double &metric) 51 | { 52 | float hipTime; 53 | 54 | static hipError_t code; 55 | if ((code = hipEventElapsedTime(&hipTime, event_start, event_stop)) != 56 | hipSuccess) { 57 | if (code == hipErrorNotReady) return false; 58 | 59 | hipAssert(code, __FILE__, __LINE__); 60 | } 61 | 62 | // Convert from ms to s 63 | metric = hipTime / 1000.0; 64 | 65 | return true; 66 | } 67 | -------------------------------------------------------------------------------- /cmake/FindAPOLLO.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # Setup APOLLO 4 | # 5 | ############################################################################### 6 | # 7 | # Expects APOLLO_DIR to point to an Apollo installation. 8 | # 9 | # This file defines the following CMake variables: 10 | # APOLLO_FOUND - If Apollo was found 11 | # APOLLO_INCLUDE_DIRS - The Apollo include directories 12 | # APOLLO_LIBRARY - Path to the libapollo file 13 | # 14 | # If found, the Apollo CMake targets will also be imported. 15 | # The main Apollo library targets are: 16 | # apollo 17 | # 18 | ############################################################################### 19 | 20 | ############################################################################### 21 | # Check for APOLLO_DIR 22 | ############################################################################### 23 | if(NOT APOLLO_DIR) 24 | MESSAGE(FATAL_ERROR "Could not find Apollo. Apollo requires explicit APOLLO_DIR.") 25 | endif() 26 | 27 | if(NOT EXISTS ${APOLLO_DIR}/lib/cmake/apollo.cmake) 28 | MESSAGE(FATAL_ERROR "Could not find Apollo CMake include file (${APOLLO_DIR}/lib/cmake/apollo.cmake)") 29 | endif() 30 | 31 | ############################################################################### 32 | # Import APOLLO's CMake targets 33 | ############################################################################### 34 | include(${APOLLO_DIR}/lib/cmake/apollo.cmake) 35 | 36 | ############################################################################### 37 | # Set remaining CMake variables 38 | ############################################################################### 39 | # We found Apollo 40 | set(APOLLO_FOUND TRUE) 41 | # Provide location of the headers and libraries 42 | set(APOLLO_INCLUDE_DIRS ${APOLLO_DIR}/include) 43 | find_library(APOLLO_LIBRARY NAMES apollo HINTS ${APOLLO_DIR}/lib) 44 | set(APOLLO_LIB_DIRS ${APOLLO_DIR}/lib) 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/timers/TimerCudaAsync.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "timers/TimerCudaAsync.h" 7 | 8 | #include 9 | 10 | #define cudaErrchk(ans) \ 11 | { \ 12 | cudaAssert((ans), __FILE__, __LINE__); \ 13 | } 14 | 15 | static inline void cudaAssert(cudaError_t code, const char *file, int line) 16 | { 17 | if (code != cudaSuccess) { 18 | std::cerr << "CUDA error " << cudaGetErrorString(code) << " at " << file 19 | << ":" << line << std::endl; 20 | abort(); 21 | } 22 | } 23 | 24 | template <> 25 | std::unique_ptr Apollo::Timer::create() 26 | { 27 | return std::make_unique(); 28 | } 29 | 30 | TimerCudaAsync::TimerCudaAsync() 31 | { 32 | cudaErrchk(cudaEventCreateWithFlags(&event_start, cudaEventDefault)); 33 | cudaErrchk(cudaEventCreateWithFlags(&event_stop, cudaEventDefault)); 34 | } 35 | 36 | TimerCudaAsync::~TimerCudaAsync() 37 | { 38 | cudaErrchk(cudaEventDestroy(event_start)); 39 | cudaErrchk(cudaEventDestroy(event_stop)); 40 | } 41 | 42 | void TimerCudaAsync::start() 43 | { 44 | // TODO: handle multiple streams. 45 | cudaErrchk(cudaEventRecord(event_start, 0)); 46 | } 47 | 48 | void TimerCudaAsync::stop() { cudaErrchk(cudaEventRecord(event_stop, 0)); } 49 | 50 | bool TimerCudaAsync::isDone(double &metric) 51 | { 52 | float cudaTime; 53 | 54 | static cudaError_t code; 55 | if ((code = cudaEventElapsedTime(&cudaTime, event_start, event_stop)) != 56 | cudaSuccess) { 57 | if (code == cudaErrorNotReady) return false; 58 | 59 | cudaAssert(code, __FILE__, __LINE__); 60 | } 61 | 62 | // Convert from ms to s 63 | metric = cudaTime / 1000.0; 64 | return true; 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apollo 2 | 3 | Apollo is a distributed tuning framework for parallel applications. You 4 | instrument your code with the Apollo API, tell Apollo what the tuning 5 | options are, and Apollo recommends tuning options so that your code 6 | runs faster. 7 | 8 | ## Contributing 9 | 10 | To contribute to Apollo please send a 11 | [pull request](https://help.github.com/articles/using-pull-requests/) on the 12 | `develop` branch of this repo. Apollo follows Gitflow for managing development. 13 | 14 | ## Authors 15 | 16 | Apollo is currently developed by Giorgis Georgakoudis (georgakoudis1@llnl.gov) and other 17 | [contributors](https://github.com/LLNL/apollo/graphs/contributors). 18 | 19 | Apollo was originally created by David Beckingsale, david@llnl.gov 20 | 21 | If you are referencing Apollo in a publication, please cite this repo and 22 | the following papers: 23 | 24 | * David Beckingsale and Olga Pearce and Ignacio Laguna and Todd Gamblin. 25 | [**Apollo: Reusable Models for Fast, Dynamic Tuning of Input-Dependent Code**](https://www.osti.gov/biblio/1367962). In *IEEE International Parallel & Distributed Processing Symposium (IPDPS'17)*, Orlando, FL, May 29-June 2 2017. LLNL-CONF-723337. 26 | * Chad Wood and Giorgis Georgakoudis and David Beckingsale and David Poliakoff and Alfredo Giménez and Kevin A. Huck and Allen D. Mallony and Todd Gamblin. 27 | [**Artemis: Automatic Runtime Tuning of Parallel Execution Parameters Using Machine Learning**](https://www.osti.gov/servlets/purl/1778645). 28 | In *In International Conference on High Performance Computing, pp. 453-472. Springer, Cham, 2021*. LLNL-CONF-809192. 29 | 30 | ## License 31 | 32 | Apollo is distributed under the terms of both the MIT license. All new 33 | contributions must be made under the MIT license. 34 | 35 | See [LICENSE](https://github.com/LLNL/apollo/blob/master/LICENSE) and 36 | [NOTICE](https://github.com/LLNL/apollo/blob/master/NOTICE) for details. 37 | 38 | SPDX-License-Identifier: MIT 39 | 40 | LLNL-CODE-733798 41 | -------------------------------------------------------------------------------- /src/connectors/kokkos/include/impl/Kokkos_Profiling_DeviceInfo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | //@HEADER 3 | // ************************************************************************ 4 | // 5 | // Kokkos v. 3.0 6 | // Copyright (2020) National Technology & Engineering 7 | // Solutions of Sandia, LLC (NTESS). 8 | // 9 | // Under the terms of Contract DE-NA0003525 with NTESS, 10 | // the U.S. Government retains certain rights in this software. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining 13 | // a copy of this software and associated documentation files (the "Software"), 14 | // to deal in the Software without restriction, including without limitation 15 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | // and/or sell copies of the Software, and to permit persons to whom the 17 | // Software is furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | // DEALINGS IN THE SOFTWARE. 29 | // Questions? Contact Christian R. Trott (crtrott@sandia.gov) 30 | // @HEADER 31 | */ 32 | 33 | #ifndef KOKKOSP_DEVICE_INFO_HPP 34 | #define KOKKOSP_DEVICE_INFO_HPP 35 | 36 | #include 37 | #include 38 | namespace Kokkos { 39 | namespace Profiling { 40 | using KokkosPDeviceInfo = Kokkos_Profiling_KokkosPDeviceInfo; 41 | } // namespace Profiling 42 | } // namespace Kokkos 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /cmake/FindCaliper.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # Setup Caliper 4 | # 5 | ############################################################################### 6 | # 7 | # Expects CALIPER_DIR to point to a Caliper installation. 8 | # 9 | # This file defines the following CMake variables: 10 | # CALIPER_FOUND - If Caliper was found 11 | # CALIPER_INCLUDE_DIRS - The Caliper include directories 12 | # CALIPER_LIBRARY - Path to the libcaliper file 13 | # CALIPER_LIB_DIRS - Where the library file lives 14 | # 15 | # If found, the Caliper CMake targets will also be imported. 16 | # The main Caliper library targets are: 17 | # caliper 18 | # 19 | ############################################################################### 20 | 21 | ############################################################################### 22 | # Check for CALIPER_DIR 23 | ############################################################################### 24 | if(NOT CALIPER_DIR) 25 | MESSAGE(FATAL_ERROR "Could not find Caliper. Caliper requires explicit CALIPER_DIR.") 26 | endif() 27 | 28 | if(NOT EXISTS ${CALIPER_DIR}/share/cmake/caliper/caliper.cmake) 29 | MESSAGE(FATAL_ERROR "Could not find Caliper CMake include file (${CALIPER_DIR}/share/cmake/caliper/caliper.cmake)") 30 | endif() 31 | 32 | ############################################################################### 33 | # Import Caliper's CMake targets 34 | ############################################################################### 35 | include(${CALIPER_DIR}/share/cmake/caliper/caliper.cmake) 36 | 37 | ############################################################################### 38 | # Set remaining CMake variables 39 | ############################################################################### 40 | # we found Caliper 41 | set(CALIPER_FOUND TRUE) 42 | # provide location of the headers and libraries 43 | set(CALIPER_INCLUDE_DIRS ${CALIPER_DIR}/include) 44 | find_library(CALIPER_LIBRARY NAMES caliper HINTS ${CALIPER_DIR}/lib) 45 | set(CALIPER_LIB_DIRS ${CALIPER_DIR}/lib) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /apollo-config.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | # Apollo project developers. Produced at the Lawrence Livermore National 3 | # Laboratory. See the top-level LICENSE file for details. 4 | # SPDX-License-Identifier: MIT 5 | 6 | #============================================================================= 7 | # 8 | # Apollo is an online machine learning utility designed to support 9 | # performance portability of HPC codes. 10 | # 11 | #=== Usage =================================================================== 12 | # 13 | # This file allows Apollo to be automatically detected by other libraries 14 | # using CMake. To build with Apollo, you can do one of two things: 15 | # 16 | # 1. Set the apollo_DIR environment variable to the root of the Apollo 17 | # installation. If you loaded apollo through a dotkit, this may already 18 | # be set, and apollo will be autodetected by CMake. 19 | # 20 | # 2. Configure your project with this option: 21 | # -Dapollo_DIR=/share/ 22 | # 23 | # If you have done either of these things, then CMake should automatically 24 | # find and include this file when you call find_package(apollo) from your 25 | # CMakeLists.txt file. 26 | # 27 | #=== Components ============================================================== 28 | # 29 | # To link against these, just do, for example: 30 | # 31 | # find_package(apollo REQUIRED) 32 | # add_executable(foo foo.c) 33 | # target_link_libraries(foo apollo) 34 | # 35 | # 36 | if (NOT apollo_CONFIG_LOADED) 37 | set(apollo_CONFIG_LOADED TRUE) 38 | 39 | # Install layout 40 | set(apollo_INSTALL_PREFIX @CMAKE_INSTALL_PREFIX@) 41 | set(apollo_INCLUDE_DIR ${apollo_INSTALL_PREFIX}/include) 42 | set(apollo_LIB_DIR ${apollo_INSTALL_PREFIX}/lib) 43 | set(apollo_CMAKE_DIR ${apollo_INSTALL_PREFIX}/share/cmake/apollo) 44 | 45 | # Includes needed to use apollo 46 | set(apollo_INCLUDE_PATH ${apollo_INCLUDE_DIR}) 47 | set(apollo_LIB_PATH ${apollo_LIB_DIR}) 48 | 49 | # Library targets imported from file 50 | include(${apollo_CMAKE_DIR}/apollo.cmake) 51 | endif() 52 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | # Apollo project developers. Produced at the Lawrence Livermore National 3 | # Laboratory. See the top-level LICENSE file for details. 4 | # SPDX-License-Identifier: MIT 5 | 6 | include_directories(${PROJECT_BINARY_DIR}) 7 | include_directories( 8 | ./connectors/kokkos/include 9 | ) 10 | set(APOLLO_HEADERS 11 | ../include/apollo/Apollo.h 12 | ../include/apollo/Config.h 13 | ../include/apollo/Dataset.h 14 | ../include/apollo/Region.h 15 | ../include/apollo/PolicyModel.h 16 | ../include/apollo/TimingModel.h 17 | ../include/apollo/ModelFactory.h 18 | ../include/apollo/Timer.h 19 | ) 20 | 21 | set(APOLLO_SOURCES 22 | Apollo.cpp 23 | Config.cpp 24 | Dataset.cpp 25 | ModelFactory.cpp 26 | Region.cpp 27 | helpers/OutputFormatter.cpp 28 | helpers/Parser.cpp 29 | models/Random.cpp 30 | models/Static.cpp 31 | models/DatasetMap.cpp 32 | models/RoundRobin.cpp 33 | models/DecisionTree.cpp 34 | models/RandomForest.cpp 35 | models/PolicyNet.cpp 36 | models/impl/DecisionTreeImpl.cpp 37 | models/impl/RandomForestImpl.cpp 38 | models/Optimal.cpp 39 | connectors/kokkos/kokkos-connector.cpp 40 | timers/TimerSync.cpp 41 | ) 42 | 43 | if(ENABLE_OPENCV) 44 | list(APPEND APOLLO_SOURCES 45 | models/RegressionTree.cpp 46 | ) 47 | endif() 48 | 49 | if(ENABLE_CUDA) 50 | list(APPEND APOLLO_SOURCES 51 | timers/TimerCudaAsync.cpp 52 | ) 53 | endif() 54 | 55 | if(ENABLE_HIP) 56 | list(APPEND APOLLO_SOURCES 57 | timers/TimerHipAsync.cpp 58 | ) 59 | endif() 60 | 61 | if(BUILD_SHARED_LIBS) 62 | add_library(apollo SHARED ${APOLLO_SOURCES}) 63 | else() 64 | add_library(apollo STATIC ${APOLLO_SOURCES}) 65 | endif() 66 | 67 | if(ENABLE_MPI) 68 | target_link_libraries(apollo PUBLIC MPI::MPI_CXX) 69 | endif() 70 | 71 | if(ENABLE_OPENCV) 72 | target_link_libraries(apollo PRIVATE dl ${OpenCV_LIBS}) 73 | endif() 74 | 75 | if(ENABLE_JIT_DTREE) 76 | target_link_libraries(apollo PRIVATE ${CMAKE_DL_LIBS}) 77 | endif() 78 | 79 | install(FILES ${APOLLO_HEADERS} DESTINATION include/apollo) 80 | 81 | install(TARGETS apollo 82 | EXPORT apollo 83 | ARCHIVE DESTINATION lib 84 | LIBRARY DESTINATION lib) 85 | -------------------------------------------------------------------------------- /include/apollo/Apollo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_H 7 | #define APOLLO_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "apollo/Config.h" 15 | 16 | class Apollo 17 | { 18 | public: 19 | ~Apollo(); 20 | // disallow copy constructor 21 | Apollo(const Apollo &) = delete; 22 | Apollo &operator=(const Apollo &) = delete; 23 | 24 | static Apollo *instance(void) noexcept 25 | { 26 | static Apollo the_instance; 27 | return &the_instance; 28 | } 29 | 30 | class Region; 31 | struct RegionContext; 32 | class Dataset; 33 | class Timer; 34 | 35 | // 36 | int mpiSize; // 1 if no MPI 37 | int mpiRank; // 0 if no MPI 38 | 39 | // NOTE(chad): We default to walk_distance of 2 so we can 40 | // step out of this method, then step out of 41 | // some portable policy template, and get to the 42 | // module name and offset where that template 43 | // has been instantiated in the application code. 44 | std::string getCallpathOffset(int walk_distance = 2); 45 | void *callpath_ptr; 46 | 47 | // DEPRECATED, use train. 48 | void flushAllRegionMeasurements(int step); 49 | void train(int step, bool doCollectPendingContext = true); 50 | 51 | private: 52 | Apollo(); 53 | // 54 | void gatherCollectiveTrainingData(int step); 55 | // Key: region name, value: region raw pointer 56 | std::map regions; 57 | // Count total number of region invocations 58 | unsigned long long region_executions; 59 | std::ofstream gtrace_file; 60 | }; // end: Apollo 61 | 62 | extern "C" { 63 | void *__apollo_region_create(int num_features, 64 | const char *id, 65 | int num_policies, 66 | int min_training_data, 67 | const char *model_info); 68 | void __apollo_region_begin(Apollo::Region *r); 69 | void __apollo_region_end(Apollo::Region *r); 70 | void __apollo_region_set_feature(Apollo::Region *r, float feature); 71 | int __apollo_region_get_policy(Apollo::Region *r); 72 | void __apollo_region_train(Apollo::Region *r, int step); 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /apollo-config.h.in: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) 2019, Lawrence Livermore National Security, LLC. 3 | // Produced at the Lawrence Livermore National Laboratory 4 | // 5 | // This file is part of Apollo. 6 | // OCEC-17-092 7 | // All rights reserved. 8 | // 9 | // Apollo is currently developed by Chad Wood, wood67@llnl.gov, with the help 10 | // of many collaborators. 11 | // 12 | // Apollo was originally created by David Beckingsale, david@llnl.gov 13 | // 14 | // For details, see https://github.com/LLNL/apollo. 15 | // 16 | // Permission is hereby granted, free of charge, to any person obtaining 17 | // a copy of this software and associated documentation files (the "Software"), 18 | // to deal in the Software without restriction, including without limitation 19 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 | // and/or sell copies of the Software, and to permit persons to whom the 21 | // Software is furnished to do so, subject to the following conditions: 22 | // 23 | // The above copyright notice and this permission notice shall be included in 24 | // all copies or substantial portions of the Software. 25 | // 26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | // DEALINGS IN THE SOFTWARE. 33 | 34 | 35 | #ifndef APOLLO_CONFIG_H 36 | #define APOLLO_CONFIG_H 37 | 38 | 39 | // Version information -- numerical and a version string 40 | #define APOLLO_MAJOR_VERSION @APOLLO_MAJOR_VERSION@ 41 | #define APOLLO_MINOR_VERSION @APOLLO_MINOR_VERSION@ 42 | #define APOLLO_PATCH_VERSION @APOLLO_PATCH_VERSION@ 43 | #define APOLLO_VERSION "@APOLLO_VERSION@" 44 | #define APOLLO_GIT_SHA1 "@APOLLO_GIT_SHA1@" 45 | 46 | #define APOLLO_BUILD_TYPE "@APOLLO_BUILD_TYPE@" 47 | 48 | #define APOLLO_HOST_NODE_NAME "@APOLLO_HOST_NODE_NAME@" 49 | #define APOLLO_HOST_KNOWN_AS "@APOLLO_HOST_KNOWN_AS@" 50 | #define APOLLO_HOST_DETAILED @APOLLO_HOST_DETAILED@ 51 | 52 | #define APOLLO_CXX_COMPILER "@APOLLO_CXX_COMPILER@" 53 | #define APOLLO_CXX_FLAGS "@APOLLO_CXX_FLAGS@" 54 | #define APOLLO_LINK_FLAGS "@APOLLO_LINK_FLAGS@" 55 | 56 | 57 | 58 | 59 | #endif // APOLLO_CONFIG_H 60 | -------------------------------------------------------------------------------- /src/helpers/Parser.cpp: -------------------------------------------------------------------------------- 1 | #include "helpers/Parser.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "helpers/ErrorHandling.h" 9 | 10 | const char *Parser::getToken() const { return token; } 11 | 12 | bool Parser::getTokenEquals(const char *s) 13 | { 14 | return (std::strcmp(token, s) == 0); 15 | } 16 | 17 | const char *Parser::getNextToken() 18 | { 19 | std::istreambuf_iterator it(is); 20 | std::istreambuf_iterator end; 21 | 22 | int idx = 0; 23 | if (it != end) { 24 | while (std::isspace(*it)) 25 | ++it; 26 | 27 | while (*it == '#') { 28 | is.ignore(std::numeric_limits::max(), '\n'); 29 | while (std::isspace(*it)) 30 | ++it; 31 | } 32 | 33 | while (!std::isspace(*it)) { 34 | buffer[idx] = *it; 35 | ++idx; 36 | ++it; 37 | if (idx >= BUFSIZE) fatal_error("Token exceeds buffer size"); 38 | } 39 | } 40 | buffer[idx] = '\0'; 41 | 42 | token = buffer; 43 | 44 | return token; 45 | } 46 | 47 | bool Parser::getNextTokenEquals(const char *s) 48 | { 49 | getNextToken(); 50 | return getTokenEquals(s); 51 | } 52 | 53 | void Parser::error(const std::string &msg) 54 | { 55 | is.clear(); 56 | int err_pos = is.tellg(); 57 | is.seekg(0); 58 | int col = 1; 59 | int lineno = 1; 60 | // Find the line, line number, and column of the error. 61 | std::string line; 62 | while (std::getline(is, line)) { 63 | if (is.tellg() >= err_pos) break; 64 | lineno++; 65 | col = is.tellg(); 66 | } 67 | 68 | col = err_pos - col; 69 | std::cerr << line << "\n"; 70 | 71 | for (int j = 0; j < col - 1; ++j) 72 | std::cerr << " "; 73 | std::cerr << "^\n"; 74 | std::cerr << "Line: " << lineno << " Col: " << col << ", Parse error: " << msg 75 | << "\n"; 76 | abort(); 77 | } 78 | 79 | void Parser::parseExpected(const char *expected) 80 | { 81 | if (std::strcmp(token, expected)) { 82 | std::stringstream error_msg; 83 | error_msg << "Expected \"" << expected << "\" but parsed \"" << token 84 | << "\""; 85 | error(error_msg.str()); 86 | } 87 | } 88 | 89 | template <> 90 | void Parser::parse(int &val) 91 | { 92 | std::size_t pos; 93 | val = std::stoi(token, &pos); 94 | token = &buffer[pos]; 95 | } 96 | 97 | template <> 98 | void Parser::parse(double &val) 99 | { 100 | std::size_t pos; 101 | val = std::stod(token, &pos); 102 | token = &buffer[pos]; 103 | } 104 | 105 | template <> 106 | void Parser::parse(float &val) 107 | { 108 | std::size_t pos; 109 | val = std::stof(token, &pos); 110 | token = &buffer[pos]; 111 | } 112 | 113 | 114 | template <> 115 | void Parser::parse(unsigned int &val) 116 | { 117 | std::size_t pos; 118 | val = std::stoul(token, &pos); 119 | token = &buffer[pos]; 120 | } 121 | 122 | 123 | template <> 124 | void Parser::parse(unsigned long &val) 125 | { 126 | std::size_t pos; 127 | val = std::stoull(token, &pos); 128 | token = &buffer[pos]; 129 | } 130 | -------------------------------------------------------------------------------- /test/apollo-test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/Apollo.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "apollo/Region.h" 12 | 13 | #define NUM_FEATURES 1 14 | #define NUM_POLICIES 4 15 | #define REPS 4 16 | #define DELAY 0.01 17 | #define FREQ 1 18 | 19 | 20 | static void delay_loop(const double delay) 21 | { 22 | auto start = std::chrono::steady_clock::now(); 23 | auto end = std::chrono::steady_clock::now(); 24 | std::chrono::duration elapsed = end - start; 25 | // Artificial delay when feature mismatches policy. 26 | while (elapsed.count() < delay) { 27 | end = std::chrono::steady_clock::now(); 28 | elapsed = end - start; 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | std::cout << "=== Testing Apollo correctness\n"; 35 | 36 | Apollo *apollo = Apollo::instance(); 37 | 38 | // Create region, DecisionTree with max_depth 3 will always pick the optimal 39 | // policy. 40 | Apollo::Region *r = new Apollo::Region(NUM_FEATURES, 41 | "test-region", 42 | NUM_POLICIES, 43 | /* min_training_data */ 0, 44 | "DecisionTree,max_depth=3"); 45 | 46 | int match; 47 | // Outer loop to simulate iterative execution of inner region, install tuned 48 | // model after first iteration that fully explores features and variants. 49 | for (int j = 1; j <= 2; j++) { 50 | match = 0; 51 | // Features match policies, iterate over all possible pairs when RoundRobin. 52 | // Do so REPS times to gather multiple measurements per pair. 53 | for (int n = 0; n < REPS; n++) { 54 | for (int i = 0; i < NUM_POLICIES; i++) { 55 | for (int k = 0; k < NUM_POLICIES; k++) { 56 | int feature = (k + i) % NUM_POLICIES; 57 | r->begin(); 58 | r->setFeature(float(feature)); 59 | 60 | int policy = r->getPolicyIndex(); 61 | 62 | // printf("Feature %d Policy %d\n", feature, policy); 63 | 64 | if (policy != feature) { 65 | delay_loop(DELAY); 66 | } else { 67 | // No delay when feature matches the policy. 68 | // printf("Match!\n"); 69 | match++; 70 | } 71 | 72 | r->end(); 73 | } 74 | } 75 | } 76 | 77 | // Second outer loop iteration should have perfect matching. 78 | printf("test-region iteration %d matched %d / %d\n", 79 | j, 80 | match, 81 | REPS * NUM_POLICIES * NUM_POLICIES); 82 | if (j == 1) { 83 | printf("Install model\n"); 84 | apollo->train(0); 85 | } 86 | } 87 | 88 | if (match == REPS * NUM_POLICIES * NUM_POLICIES) 89 | std::cout << "PASSED\n"; 90 | else 91 | std::cout << "FAILED\n"; 92 | 93 | std::cout << "=== Testing complete\n"; 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /test/apollo-test-mpi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-2021, Lawrence Livermore National Security, LLC 2 | // and other Apollo project developers. 3 | // Produced at the Lawrence Livermore National Laboratory. 4 | // See the top-level LICENSE file for details. 5 | // SPDX-License-Identifier: MIT 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "apollo/Apollo.h" 13 | #include "apollo/Region.h" 14 | 15 | #define NUM_FEATURES 1 16 | #define NUM_POLICIES 4 17 | #define REPS 4 18 | #define DELAY 0.1 19 | 20 | 21 | static void delay_loop(const double delay) 22 | { 23 | auto start = std::chrono::steady_clock::now(); 24 | auto end = std::chrono::steady_clock::now(); 25 | std::chrono::duration elapsed = end - start; 26 | // Artificial delay when feature mismatches policy. 27 | while (elapsed.count() < delay) { 28 | end = std::chrono::steady_clock::now(); 29 | elapsed = end - start; 30 | } 31 | } 32 | 33 | int main() 34 | { 35 | fprintf(stdout, "testing Apollo.\n"); 36 | 37 | MPI_Init(NULL, NULL); 38 | 39 | int rank; 40 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 41 | printf("rank %d REPORTING\n", rank); 42 | 43 | Apollo *apollo = Apollo::instance(); 44 | 45 | Apollo::Region *r = new Apollo::Region(NUM_FEATURES, 46 | "test-region", 47 | NUM_POLICIES, 48 | /* min_training_data */ 0, 49 | "DecisionTree,max_depth=3"); 50 | 51 | int match; 52 | // Outer loop to simulate iterative execution of inner region, install tuned 53 | // model after first iteration. 54 | for (int j = 0; j < 2; j++) { 55 | match = 0; 56 | // Features match policies, iterate over all possible pairs when RoundRobin. 57 | // Do so REPS times to gather multiple measurements per pair. 58 | for (int n = 0; n < REPS; n++) { 59 | for (int i = 0; i < NUM_POLICIES; i++) { 60 | for (int k = 0; k < NUM_POLICIES; k++) { 61 | int feature = (k + i) % NUM_POLICIES; 62 | r->begin(); 63 | r->setFeature(float(feature)); 64 | 65 | int policy = r->getPolicyIndex(); 66 | 67 | printf("Feature %d Policy %d\n", feature, policy); 68 | 69 | if (policy != feature) { 70 | delay_loop(DELAY); 71 | } else { 72 | // No delay when feature matches the policy. 73 | printf("Match!\n"); 74 | match++; 75 | } 76 | 77 | r->end(); 78 | } 79 | } 80 | } 81 | 82 | // Second outer loop iteration should have perfect matching. 83 | printf("matched region j %d %d / %d\n", 84 | j, 85 | match, 86 | REPS * NUM_POLICIES * NUM_POLICIES); 87 | if (j == 0) { 88 | printf("Install model\n"); 89 | apollo->train(0); 90 | } 91 | } 92 | 93 | fprintf(stdout, "testing complete.\n"); 94 | if (match == REPS * NUM_POLICIES * NUM_POLICIES) 95 | printf("PASSED\n"); 96 | else 97 | printf("FAILED\n"); 98 | 99 | MPI_Finalize(); 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /include/apollo/Region.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_REGION_H 7 | #define APOLLO_REGION_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "apollo/Apollo.h" 17 | #include "apollo/Dataset.h" 18 | #include "apollo/PolicyModel.h" 19 | #include "apollo/Timer.h" 20 | #include "apollo/TimingModel.h" 21 | 22 | #ifdef ENABLE_MPI 23 | #include 24 | #endif // ENABLE_MPI 25 | 26 | struct Apollo::RegionContext { 27 | std::vector features; 28 | int policy; 29 | unsigned long long idx; 30 | std::unique_ptr timer; 31 | }; // end: Apollo::RegionContext 32 | 33 | class Apollo::Region 34 | { 35 | 36 | public: 37 | enum TimingKind { TIMING_SYNC, TIMING_CUDA_ASYNC, TIMING_HIP_ASYNC }; 38 | Region(const int num_features, 39 | const char *regionName, 40 | int numAvailablePolicies, 41 | int min_training_data = 0, 42 | const std::string &model_info = "", 43 | const std::string &modelYamlFile = ""); 44 | ~Region(); 45 | 46 | char name[64]; 47 | 48 | // DEPRECATED interface assuming synchronous execution, will be removed 49 | void end(); 50 | void end(double metric); 51 | int getPolicyIndex(void); 52 | void setFeature(float value); 53 | // END of DEPRECATED 54 | 55 | Apollo::RegionContext *begin(); 56 | Apollo::RegionContext *begin(TimingKind tk); 57 | Apollo::RegionContext *begin(const std::vector &features); 58 | void end(Apollo::RegionContext *context); 59 | void end(Apollo::RegionContext *context, double metric); 60 | int getPolicyIndex(Apollo::RegionContext *context); 61 | void setFeature(Apollo::RegionContext *, float value); 62 | 63 | int idx; 64 | int num_features; 65 | int num_policies; 66 | 67 | // Stores measurements of features, policy, metric. 68 | Apollo::Dataset dataset; 69 | 70 | std::unique_ptr time_model; 71 | std::unique_ptr model; 72 | 73 | void collectPendingContexts(); 74 | void train(int step, 75 | bool doCollectPendingContexts = true, 76 | bool force = false); 77 | 78 | void parsePolicyModel(const std::string &model_info); 79 | // Model information, name and params. 80 | std::string model_info; 81 | std::string model_name; 82 | std::unordered_map model_params; 83 | 84 | private: 85 | Apollo *apollo; 86 | // DEPRECATED wil be removed 87 | Apollo::RegionContext *current_context; 88 | Apollo::RegionContext sync_context; 89 | std::ofstream trace_file; 90 | 91 | std::vector pending_contexts; 92 | Apollo::RegionContext *createRegionContext(TimingKind tk); 93 | void destroyRegionContext(Apollo::RegionContext *context); 94 | void collectContext(Apollo::RegionContext *, double); 95 | Apollo::RegionContext *getSyncContext(); 96 | 97 | void autoTrain(); 98 | 99 | int min_training_data; 100 | }; // end: Apollo::Region 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/python/analysis/rfc2dot_opencv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import cv2 5 | 6 | def parse_node(node): 7 | if node.isMap(): 8 | keys = node.keys() 9 | #print('map keys ', keys) 10 | dot = '{\n' 11 | for k in keys: 12 | dot += '%s: '%(k) 13 | dot += parse_node(node.getNode(k)) 14 | dot += ',\n' 15 | dot += ' }\n' 16 | elif node.isSeq(): 17 | #print('seq size ', node.size()) 18 | dot = '[ ' 19 | for k in range(0, node.size()): 20 | if k>0: 21 | dot += ', ' 22 | dot += parse_node(node.at(k)) 23 | dot += ' ]\n' 24 | else: 25 | if node.isInt(): 26 | #print('int val ', int(node.real())) 27 | dot = '%d'%(int(node.real())) 28 | elif node.isReal(): 29 | #print('real val ', node.real()) 30 | dot = '%f'%(node.real()) 31 | elif node.isString(): 32 | #print('string val ', node.string()) 33 | dot = '\"%s\"'%(node.real()) 34 | else: 35 | assert(False) 36 | 37 | return dot 38 | 39 | 40 | def parse_tree(tid, tree): 41 | dot = '' 42 | treenodes = tree.getNode('nodes') 43 | assert(treenodes.isSeq()) 44 | # Create nodes. 45 | for i in range(0, treenodes.size()): 46 | node = treenodes.at(i) 47 | depth = int( node.getNode('depth').real() ) 48 | dot += 'tree_%d_d_%d_n_%d [ label=\"' % (tid, depth, i) 49 | dot += parse_node(node) 50 | dot += '\" ];\n' 51 | # Create edges. 52 | stack = [(0,0)] 53 | for i in range(1, treenodes.size()): 54 | node = treenodes.at(i) 55 | depth = int( node.getNode('depth').real() ) 56 | (j, d) = stack.pop() 57 | while d >= depth: 58 | (j, d) = stack.pop() 59 | 60 | dot += 'tree_%d_d_%d_n_%d -> '%(tid, d, j) 61 | dot += 'tree_%d_d_%d_n_%d;\n'%(tid, depth, i); 62 | stack.append((j,d)) 63 | # append node if there are more nodes to traverse. 64 | if i < treenodes.size() - 1: 65 | stack.append((i,depth)) 66 | 67 | (j,d) = stack.pop() 68 | assert((j,d) == (0,0)) 69 | 70 | return dot 71 | 72 | def parse(node): 73 | dot = 'root [ shape=box, label=\"' 74 | assert(node.isMap()) 75 | keys = node.keys() 76 | keys.remove('trees') 77 | dot += '{\n' 78 | for k in keys: 79 | dot += '%s: '%(k) 80 | dot += parse_node(node.getNode(k)) 81 | dot += ',\n' 82 | dot += ' }\n' 83 | 84 | dot += '\"];\n' 85 | 86 | for r in range(0, node.getNode('trees').size()): 87 | dot += parse_tree(r, node.getNode('trees').at(r)) 88 | dot += 'root -> tree_%d_d_0_n_0;\n'%(r) 89 | return dot 90 | 91 | 92 | def main(): 93 | parser = argparse.ArgumentParser(description='Generate dot graph file from rtrees yaml.') 94 | parser.add_argument('-i', '--input', help='the input yaml file.', required=True) 95 | parser.add_argument('-o', '--output', help='the output dot file.', required=True) 96 | args = parser.parse_args() 97 | 98 | fs = cv2.FileStorage(args.input, cv2.FILE_STORAGE_READ) 99 | 100 | fn = fs.getFirstTopLevelNode() 101 | 102 | dot = 'digraph G {' 103 | dot += parse(fn); 104 | dot += '\n}' 105 | 106 | with open(args.output, 'w') as f: 107 | f.write(dot) 108 | 109 | fs.release() 110 | 111 | if __name__ == "__main__": 112 | main() 113 | -------------------------------------------------------------------------------- /test/apollo-overhead.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "apollo/Apollo.h" 12 | #include "apollo/Region.h" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | if (argc < 5) { 17 | std::cerr << "Usage: ./apollo-overhead \n"; 20 | return 1; 21 | } 22 | 23 | #ifdef ENABLE_MPI 24 | MPI_Init(nullptr, nullptr); 25 | #endif 26 | 27 | unsigned NUM_FEATURES = atoi(argv[1]); 28 | unsigned NUM_POLICIES = atoi(argv[2]); 29 | unsigned NUM_TRAINING_DATA = atoi(argv[3]); 30 | unsigned REPS = atoi(argv[4]); 31 | 32 | if (NUM_TRAINING_DATA > REPS) { 33 | std::cerr << "NUM_TRAINING_DATA " << NUM_TRAINING_DATA 34 | << " must be less than or equal to than REPS " << REPS << "\n"; 35 | return 1; 36 | } 37 | 38 | std::cout << "=== Testing Apollo overhead\n"; 39 | 40 | Apollo *apollo = Apollo::instance(); 41 | 42 | Apollo::Region *r = new Apollo::Region(NUM_FEATURES, 43 | "test-overhead", 44 | NUM_POLICIES, 45 | /* min_training_data */ 0, 46 | "DecisionTree,max_depth=2"); 47 | 48 | auto start = std::chrono::steady_clock::now(); 49 | 50 | unsigned i; 51 | int policy; 52 | for (i = 0; i < REPS; ++i) { 53 | r->begin(); 54 | for (unsigned j = 0; j < NUM_FEATURES; ++j) 55 | r->setFeature(i % NUM_TRAINING_DATA); 56 | // r->setFeature(1); 57 | // r->setFeature(2); 58 | // r->setFeature(3); 59 | // r->setFeature(2); 60 | policy = r->getPolicyIndex(); 61 | r->end(); 62 | } 63 | 64 | auto end = std::chrono::steady_clock::now(); 65 | double duration = std::chrono::duration(end - start).count(); 66 | 67 | start = std::chrono::steady_clock::now(); 68 | for (i = 0; i < REPS; ++i) 69 | r->train(0, true, true); 70 | end = std::chrono::steady_clock::now(); 71 | double model_building_duration = 72 | std::chrono::duration(end - start).count(); 73 | 74 | r->begin(); 75 | start = std::chrono::steady_clock::now(); 76 | for (i = 0; i < REPS; ++i) 77 | r->getPolicyIndex(); 78 | end = std::chrono::steady_clock::now(); 79 | r->end(); 80 | double model_evaluation_duration = 81 | std::chrono::duration(end - start).count(); 82 | 83 | struct rusage rs; 84 | getrusage(RUSAGE_SELF, &rs); 85 | 86 | std::cout << "Execution time overhead total " << duration * 1e3 << " ms," 87 | << " per iteration " << (duration / REPS) * 1e6 << " us\n" 88 | << "Memory usage (maxrss) " << rs.ru_maxrss / (1024.0 * 1024.0) 89 | << " MB\n" 90 | << "Model building overhead total " << model_building_duration * 1e3 91 | << " ms, " 92 | << "per iteration " << (model_building_duration / REPS) * 1e6 93 | << " us\n" 94 | << "Model evaluation overhead total " 95 | << model_evaluation_duration * 1e3 << " ms, " 96 | << "per iteration " << (model_evaluation_duration / REPS) * 1e6 97 | << " us\n"; 98 | 99 | std::cout << "=== Testing complete\n"; 100 | 101 | #ifdef ENABLE_MPI 102 | MPI_Finalize(); 103 | #endif 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /src/python/analysis/plot-trace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | import seaborn as sns 8 | import re 9 | 10 | # TODO: assumes a single feature indicated by f0. Generalize for more features. 11 | 12 | def plot_bars(ax, df): 13 | sns.countplot(data=df, x='policy', hue='f0', ax=ax) 14 | # build labels 15 | bar_labels = [] 16 | policies = df['policy'].unique() 17 | policies.sort() 18 | features = df['f0'].unique() 19 | features.sort() 20 | #print('policies', policies) 21 | #print('features', features) 22 | 23 | for policy in policies: 24 | for feature in features: 25 | xtimes = df.loc[df['f0'] == feature].loc[df['policy'] == policy][['f0', 'policy', 'xtime']] 26 | if xtimes.empty: 27 | bar_labels.append(0) 28 | continue 29 | values = list(xtimes['xtime']) 30 | #values.remove(max(values)) 31 | #values.remove(min(values)) 32 | mean = np.mean(values) 33 | #print('xtimes', xtimes, 'mean', mean) 34 | bar_labels.append('%.2f'%(mean*1e6)) 35 | for i, container in enumerate(ax.containers): 36 | #print('container', i) 37 | #print('bar_labels', bar_labels[i::3]) 38 | text_list = ax.bar_label(container, labels=bar_labels[i::len(features)]) 39 | for t in text_list: 40 | t.set_rotation(90) 41 | 42 | def main(): 43 | parser = argparse.ArgumentParser(description='Analyze exhaustive experiments for a program.') 44 | parser.add_argument('--file', help='the trace file to plot.', required=True) 45 | parser.add_argument('--ntraining', type=int, help='the number of training executions.', required=True) 46 | parser.add_argument('--drop-first', help='drop first measurement outlier.', action='store_true') 47 | parser.add_argument('--title', help='add to title.', nargs='?', default='') 48 | args = parser.parse_args() 49 | 50 | m = re.match('trace-(.*?)-.*', args.file) 51 | model_name = m.group(1) 52 | #print('model_name', model_name) 53 | with open(args.file, 'r') as f: 54 | df = pd.read_csv(f, sep=' ', header=0) 55 | 56 | fig, ax = plt.subplots(1, 2, sharey=True, figsize=(12,6) ) 57 | 58 | start = 0 59 | if args.drop_first: 60 | start = 1 61 | plot_bars(ax[0], df[start:args.ntraining]) 62 | plot_bars(ax[1], df[args.ntraining:]) 63 | ntuned = len(df[args.ntraining:]) 64 | 65 | ax[0].legend(title='Feature') 66 | ax[0].spines['top'].set_visible(False) 67 | ax[0].spines['right'].set_visible(False) 68 | ax[1].spines['top'].set_visible(False) 69 | ax[1].spines['right'].set_visible(False) 70 | ax[1].get_legend().remove() 71 | ax[0].set_title('Training data for the first ' + str(args.ntraining-start) + \ 72 | ' iterations (drop-first ' + str(args.drop_first) + ')', pad=50) 73 | ax[1].set_title('Tuning data for the next ' + str(ntuned) + ' iterations', pad=50) 74 | 75 | suptitle = model_name + '\n' + bytes(args.title, 'utf-8').decode('unicode_escape') + '\nBar labels are mean execution times in ms\n' 76 | plt.suptitle(suptitle) 77 | 'Tuning block size for Apollo RAJA daxpy on HIP forall\nFeature is vector size. Policy 0: 64 threads, 1: 256 threads, 2: 1024 threads' 78 | #sns.catplot(data=df[501:], x='policy', y='f0', kind='bar', ax=ax[1]) 79 | #sns.violinplot(data=df[:501], ax=ax[0], y='policy', x='f0') 80 | #sns.catplot(data=df[501:], ax=ax[1], y='policy', x='f0') 81 | #sns.violinplot(data=df, x=df.index, y='policy') 82 | plt.tight_layout() 83 | #plt.show() 84 | plt.savefig(model_name + '-plot.pdf') 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /src/models/DecisionTree.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/DecisionTree.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "models/impl/DecisionTreeImpl.h" 21 | 22 | #ifdef ENABLE_OPENCV 23 | #include 24 | #endif 25 | 26 | namespace apollo 27 | { 28 | 29 | static inline bool fileExists(std::string path) 30 | { 31 | struct stat stbuf; 32 | return (stat(path.c_str(), &stbuf) == 0); 33 | } 34 | 35 | DecisionTree::DecisionTree(int num_policies, std::string path) 36 | : PolicyModel(num_policies, "DecisionTree"), trainable(false) 37 | { 38 | if (not fileExists(path)) { 39 | std::cerr << "== APOLLO: Cannot access the DecisionTree model requested:\n" 40 | << "== APOLLO: " << path << "\n" 41 | << "== APOLLO: Exiting.\n"; 42 | abort(); 43 | } 44 | // The file at least exists... attempt to load a model from it! 45 | std::cout << "== APOLLO: Loading the requested DecisionTree:\n" 46 | << "== APOLLO: " << path << "\n"; 47 | #ifdef ENABLE_OPENCV 48 | dtree = DTrees::load(path.c_str()); 49 | #else 50 | dtree = std::make_unique(num_policies, path); 51 | #endif 52 | 53 | return; 54 | } 55 | 56 | DecisionTree::DecisionTree(int num_policies, 57 | unsigned max_depth, 58 | std::unique_ptr &explorer) 59 | : PolicyModel(num_policies, "DecisionTree"), 60 | trainable(true), 61 | explorer(std::move(explorer)) 62 | { 63 | #ifdef ENABLE_OPENCV 64 | dtree = DTrees::create(); 65 | 66 | dtree->setMaxDepth(max_depth); 67 | 68 | dtree->setMinSampleCount(1); 69 | dtree->setRegressionAccuracy(0); 70 | dtree->setUseSurrogates(false); 71 | dtree->setMaxCategories(policy_count); 72 | dtree->setCVFolds(0); 73 | dtree->setUse1SERule(false); 74 | dtree->setTruncatePrunedTree(false); 75 | dtree->setPriors(Mat()); 76 | 77 | #else 78 | dtree = std::make_unique(num_policies, max_depth); 79 | #endif 80 | 81 | return; 82 | } 83 | 84 | DecisionTree::~DecisionTree() { return; } 85 | 86 | bool DecisionTree::isTrainable() { return trainable; } 87 | 88 | void DecisionTree::train(Apollo::Dataset &dataset) 89 | { 90 | std::vector> features; 91 | std::vector responses; 92 | std::map, std::pair> min_metric_policies; 93 | dataset.findMinMetricPolicyByFeatures(features, 94 | responses, 95 | min_metric_policies); 96 | 97 | #ifdef ENABLE_OPENCV 98 | Mat fmat; 99 | for (auto &i : features) { 100 | Mat tmp(1, i.size(), CV_32F, &i[0]); 101 | fmat.push_back(tmp); 102 | } 103 | 104 | Mat rmat; 105 | Mat(fmat.rows, 1, CV_32S, &responses[0]).copyTo(rmat); 106 | 107 | dtree->train(fmat, ROW_SAMPLE, rmat); 108 | #else 109 | dtree->train(features, responses); 110 | #endif 111 | 112 | trainable = false; 113 | } 114 | 115 | int DecisionTree::getIndex(std::vector &features) 116 | { 117 | if (!trainable) return dtree->predict(features); 118 | 119 | return explorer->getIndex(features); 120 | } 121 | 122 | void DecisionTree::load(const std::string &filename) 123 | { 124 | trainable = false; 125 | dtree->load(filename); 126 | } 127 | void DecisionTree::store(const std::string &filename) { dtree->save(filename); } 128 | 129 | } // end namespace apollo. 130 | -------------------------------------------------------------------------------- /src/models/RandomForest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/RandomForest.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "models/impl/RandomForestImpl.h" 20 | 21 | #ifdef ENABLE_OPENCV 22 | #include 23 | #endif 24 | 25 | using namespace std; 26 | 27 | namespace apollo 28 | { 29 | 30 | static inline bool fileExists(std::string path) 31 | { 32 | struct stat stbuf; 33 | return (stat(path.c_str(), &stbuf) == 0); 34 | } 35 | 36 | RandomForest::RandomForest(int num_policies, std::string path) 37 | : PolicyModel(num_policies, "RandomForest"), trainable(false) 38 | { 39 | if (not fileExists(path)) { 40 | std::cerr << "== APOLLO: Cannot access the RandomForest model requested:\n" 41 | << "== APOLLO: " << path << "\n" 42 | << "== APOLLO: Exiting.\n"; 43 | abort(); 44 | } 45 | // The file at least exists... attempt to load a model from it! 46 | std::cout << "== APOLLO: Loading the requested RandomForest:\n" 47 | << "== APOLLO: " << path << "\n"; 48 | #ifdef ENABLE_OPENCV 49 | rfc = RTrees::load(path.c_str()); 50 | #else 51 | rfc = std::make_unique(num_policies, path); 52 | #endif 53 | return; 54 | } 55 | 56 | RandomForest::RandomForest(int num_policies, 57 | unsigned num_trees, 58 | unsigned max_depth, 59 | std::unique_ptr &explorer) 60 | : PolicyModel(num_policies, "RandomForest"), 61 | trainable(true), 62 | explorer(std::move(explorer)) 63 | { 64 | #ifdef ENABLE_OPENCV 65 | rfc = RTrees::create(); 66 | rfc->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 67 | num_trees, 68 | 0.01)); 69 | 70 | rfc->setMaxDepth(max_depth); 71 | 72 | rfc->setMinSampleCount(1); 73 | rfc->setRegressionAccuracy(0); 74 | rfc->setUseSurrogates(false); 75 | rfc->setMaxCategories(policy_count); 76 | rfc->setCVFolds(0); 77 | rfc->setUse1SERule(false); 78 | rfc->setTruncatePrunedTree(false); 79 | rfc->setPriors(Mat()); 80 | 81 | #else 82 | rfc = std::make_unique(num_policies, num_trees, max_depth); 83 | #endif 84 | 85 | return; 86 | } 87 | 88 | bool RandomForest::isTrainable() { return trainable; } 89 | 90 | void RandomForest::train(Apollo::Dataset &dataset) 91 | { 92 | 93 | std::vector> features; 94 | std::vector responses; 95 | std::map, std::pair> min_metric_policies; 96 | dataset.findMinMetricPolicyByFeatures(features, 97 | responses, 98 | min_metric_policies); 99 | #ifdef ENABLE_OPENCV 100 | Mat fmat; 101 | for (auto &i : features) { 102 | Mat tmp(1, i.size(), CV_32F, &i[0]); 103 | fmat.push_back(tmp); 104 | } 105 | 106 | Mat rmat; 107 | Mat(fmat.rows, 1, CV_32S, &responses[0]).copyTo(rmat); 108 | 109 | rfc->train(fmat, ROW_SAMPLE, rmat); 110 | #else 111 | rfc->train(features, responses); 112 | #endif 113 | 114 | trainable = false; 115 | } 116 | 117 | RandomForest::~RandomForest() { return; } 118 | 119 | int RandomForest::getIndex(std::vector &features) 120 | { 121 | if (!trainable) return rfc->predict(features); 122 | 123 | return explorer->getIndex(features); 124 | } 125 | 126 | void RandomForest::load(const std::string &filename) 127 | { 128 | trainable = false; 129 | rfc->load(filename); 130 | } 131 | void RandomForest::store(const std::string &filename) { rfc->save(filename); } 132 | 133 | } // end namespace apollo. -------------------------------------------------------------------------------- /src/models/impl/DecisionTreeImpl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #ifndef APOLLO_MODELS_DECISIONTREEIMPL_H 7 | #define APOLLO_MODELS_DECISIONTREEIMPL_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "helpers/OutputFormatter.h" 21 | #include "helpers/Parser.h" 22 | 23 | class DecisionTreeImpl 24 | { 25 | public: 26 | DecisionTreeImpl(int num_classes, std::istream &is); 27 | DecisionTreeImpl(int num_classes, std::string filename); 28 | DecisionTreeImpl(int num_classes, unsigned max_depth); 29 | DecisionTreeImpl(int num_classes, 30 | std::vector> &features, 31 | std::vector &responses, 32 | unsigned max_depth); 33 | ~DecisionTreeImpl(); 34 | 35 | void train(std::vector> &features, 36 | std::vector &responses); 37 | void load(const std::string &filename); 38 | void save(const std::string &filename); 39 | int predict(const std::vector &features); 40 | void output_tree(OutputFormatter &outfmt, 41 | std::string key, 42 | bool include_data = true); 43 | void print_tree(); 44 | 45 | private: 46 | struct Node { 47 | float gini; 48 | size_t num_samples; 49 | int predicted_class; 50 | int feature_idx; 51 | float threshold; 52 | Node *left; 53 | Node *right; 54 | std::vector count_per_class; 55 | DecisionTreeImpl &DT; 56 | 57 | Node(DecisionTreeImpl &DT, 58 | float gini, 59 | size_t num_samples, 60 | int predicted_class, 61 | int feature_idx, 62 | float threshold, 63 | Node *left, 64 | Node *right, 65 | std::vector &count_per_class); 66 | 67 | 68 | Node(DecisionTreeImpl &DT, 69 | std::vector &count_per_class, 70 | float gini, 71 | size_t num_samples); 72 | }; 73 | 74 | // Returns pair(counts per class, gini value) 75 | template 76 | void compute_gini(const Iterator &Begin, 77 | const Iterator &End, 78 | float &gini_score); 79 | 80 | template 81 | std::vector get_count_per_class(const Iterator &Begin, 82 | const Iterator &End); 83 | 84 | int evaluate_tree(const Node &tree, const std::vector &features); 85 | void compile_and_link_jit_evaluate_function(); 86 | void generate_source(Node &node, OutputFormatter &source_code); 87 | int (*jit_evaluate_function)(const std::vector &features); 88 | 89 | // Returns tuple(min gini, iterator to split, feature index of split) 90 | template 91 | std::tuple split(const Iterator &Begin, 92 | const Iterator &End); 93 | 94 | 95 | template 96 | Node *build_tree(const Iterator &Begin, 97 | const Iterator &End, 98 | const size_t max_depth, 99 | size_t depth); 100 | 101 | void output_node(OutputFormatter &outfmt, Node &tree, std::string key); 102 | std::vector parse_count_per_class(Parser &parser); 103 | 104 | void parse_tree(std::istream &is); 105 | Node *parse_node(Parser &parser); 106 | void parse_data(Parser &parser); 107 | 108 | std::vector, int>> data; 109 | std::set classes; 110 | Node *root; 111 | unsigned num_features; 112 | unsigned max_depth; 113 | unsigned num_classes; 114 | unsigned unique_id; 115 | static int unique_counter; 116 | std::vector tree_nodes; 117 | }; 118 | 119 | #endif -------------------------------------------------------------------------------- /src/models/RegressionTree.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/models/RegressionTree.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | 18 | RegressionTree::RegressionTree(Apollo::Dataset &dataset) 19 | : TimingModel("RegressionTree") 20 | { 21 | std::vector> features; 22 | std::vector responses; 23 | std::map, std::pair> min_metric_policies; 24 | dataset.findMinMetricPolicyByFeatures(features, 25 | responses, 26 | min_metric_policies); 27 | // std::chrono::steady_clock::time_point t1, t2; 28 | // t1 = std::chrono::steady_clock::now(); 29 | 30 | // 31 | // dtree = KNearest::create(); 32 | // 33 | 34 | ////dtree = DTrees::create(); 35 | dtree = RTrees::create(); 36 | dtree->setMinSampleCount(1); 37 | dtree->setTermCriteria( 38 | TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 50, 0.001)); 39 | // dtree->setTermCriteria( TermCriteria( TermCriteria::MAX_ITER, 50, 0.01 ) 40 | // ); dtree->setMaxDepth(8); 41 | dtree->setRegressionAccuracy(1e-6); 42 | dtree->setUseSurrogates(false); 43 | dtree->setCVFolds(0); 44 | dtree->setUse1SERule(false); 45 | dtree->setTruncatePrunedTree(false); 46 | dtree->setPriors(Mat()); 47 | 48 | Mat fmat; 49 | for (auto &i : features) { 50 | Mat tmp(1, i.size(), CV_32FC1, &i[0]); 51 | fmat.push_back(tmp); 52 | } 53 | 54 | Mat rmat; 55 | // rmat = Mat::zeros( fmat.rows, num_policies, CV_32F ); 56 | // for( int i = 0; i < responses.size(); i++ ) { 57 | // int j = responses[i]; 58 | // rmat.at(i, j) = 1.f; 59 | // } 60 | Mat(fmat.rows, 1, CV_32F, &responses[0]).copyTo(rmat); 61 | 62 | // std::cout << "fmat: " << fmat << std::endl; 63 | // std::cout << "features.size: " << features.size() << std::endl; 64 | // std::cout << "rmat: " << rmat << std::endl; 65 | 66 | // ANN_MLP 67 | // dtree->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM); 68 | // Mat layers(3, 1, CV_16U); 69 | // layers.row(0) = Scalar(fmat.cols); 70 | // layers.row(1) = Scalar(4); 71 | // layers.row(2) = Scalar(rmat.cols); 72 | // dtree->setLayerSizes( layers ); 73 | // dtree->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP); 74 | 75 | dtree->train(fmat, ROW_SAMPLE, rmat); 76 | // Ptr data = TrainData::create(fmat, ROW_SAMPLE, rmat); 77 | // dtree->train(data); 78 | // for(int i = 0; i<1000; i++) 79 | // dtree->train(data, ANN_MLP::TrainFlags::UPDATE_WEIGHTS); 80 | 81 | // if(!dtree->isTrained()) { 82 | // std::cout << "MODEL IS NOT TRAINED!" << std::endl; 83 | // abort(); 84 | // } 85 | 86 | // t2 = std::chrono::steady_clock::now(); 87 | // double duration = std::chrono::duration(t2 - t1).count(); 88 | // std::cout << "Train regression tree " << " : " << duration << " seconds" << 89 | // std::endl; 90 | 91 | return; 92 | } 93 | 94 | RegressionTree::~RegressionTree() { return; } 95 | 96 | double RegressionTree::getTimePrediction(std::vector &features) 97 | { 98 | 99 | // std::chrono::steady_clock::time_point t1, t2; 100 | // t1 = std::chrono::steady_clock::now(); 101 | // Keep choice around for easier debugging, if needed: 102 | double choice = 0; 103 | 104 | // Mat fmat; 105 | // fmat.push_back( Mat(1, features.size(), CV_32F, &features[0]) ); 106 | // Mat result; 107 | // choice = dtree->predict( features, result ); 108 | // std::cout << "Results: " << result << std::endl; 109 | // 110 | choice = dtree->predict(features); 111 | 112 | // t2 = std::chrono::steady_clock::now(); 113 | // double duration = std::chrono::duration(t2 - t1).count(); 114 | // std::cout << "predict duration: " << duration << " choice: " << choice << 115 | // endl; //ggout std::cout << "Features: [ "; for(auto &i: features) 116 | // std::cout << i; 117 | // std::cout << " ] -> " << choice << std::endl; 118 | 119 | // Find the recommendation of the decision tree: 120 | 121 | return choice; 122 | } 123 | 124 | void RegressionTree::store(const std::string &filename) 125 | { 126 | dtree->save(filename); 127 | } 128 | -------------------------------------------------------------------------------- /test/test-cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "apollo/Apollo.h" 9 | #include "apollo/Region.h" 10 | 11 | __global__ void kernel_add(double* a, double* b, double c, int size) 12 | { 13 | int id = blockIdx.x * blockDim.x + threadIdx.x; 14 | if (id < size) a[id] += b[id] * c; 15 | } 16 | 17 | void checkResult(double* v1, double* v2, int len); 18 | void printResult(double* v, int len); 19 | 20 | int main() 21 | { 22 | 23 | std::cout << "\n\ndaxpy example...\n"; 24 | 25 | // 26 | // Define vector length 27 | // 28 | const int N = 100000; 29 | // const int N = 1000; 30 | 31 | // 32 | // Allocate and initialize vector data. 33 | // 34 | double* a0 = new double[N]; 35 | double* aref = new double[N]; 36 | 37 | double* ta = new double[N]; 38 | double* tb = new double[N]; 39 | 40 | double c = 3.14159; 41 | 42 | for (int i = 0; i < N; i++) { 43 | a0[i] = 1.0; 44 | tb[i] = 2.0; 45 | } 46 | 47 | double *d_a, *d_b; 48 | cudaMalloc((void**)&d_a, sizeof(double) * N); 49 | cudaMalloc((void**)&d_b, sizeof(double) * N); 50 | 51 | // 52 | // Declare and set pointers to array data. 53 | // We reset them for each daxpy version so that 54 | // they all look the same. 55 | // 56 | 57 | double* a = ta; 58 | double* b = tb; 59 | 60 | 61 | //----------------------------------------------------------------------------// 62 | 63 | std::cout << "\n Running C-version of daxpy...\n"; 64 | 65 | std::memcpy(a, a0, N * sizeof(double)); 66 | 67 | for (int i = 0; i < N; ++i) { 68 | a[i] += b[i] * c; 69 | } 70 | 71 | std::memcpy(aref, a, N * sizeof(double)); 72 | 73 | //----------------------------------------------------------------------------// 74 | 75 | //----------------------------------------------------------------------------// 76 | Apollo* apollo = Apollo::instance(); 77 | Apollo::Region* r = new Apollo::Region(/*num_features*/ 1, 78 | "cuda-region", 79 | /*num_policies*/ 2); 80 | 81 | 82 | for (int j = 0; j < 20; j++) { 83 | 84 | std::memcpy(a, a0, N * sizeof(double)); 85 | 86 | cudaMemcpy(d_a, a, sizeof(double) * N, cudaMemcpyHostToDevice); 87 | cudaMemcpy(d_b, b, sizeof(double) * N, cudaMemcpyHostToDevice); 88 | 89 | Apollo::RegionContext *ctx = r->begin({N}); 90 | int policy = r->getPolicyIndex(); 91 | std::cout << "EXECUTION " << j << "\n"; 92 | // Create and install a CudaAsync Timer for this context to override the 93 | // default Sync Timer. The new timer must be started by the user. Apollo 94 | // will stop the timer at region->end() as before. 95 | ctx->timer = Apollo::Timer::create(); 96 | // Start the timer. 97 | ctx->timer->start(); 98 | 99 | int block_size; 100 | switch(policy) { 101 | case 0: 102 | block_size = 1; break; 103 | case 1: 104 | block_size = 1024; break; 105 | default: 106 | abort(); 107 | } 108 | 109 | int grid_size = std::ceil((float)N / block_size); 110 | kernel_add<<>>(d_a, d_b, c, N); 111 | 112 | cudaMemcpy(a, d_a, sizeof(double) * N, cudaMemcpyDeviceToHost); 113 | 114 | r->end(); 115 | 116 | checkResult(a, aref, N); 117 | 118 | if(j==10) 119 | apollo->train(0); 120 | } 121 | 122 | 123 | //----------------------------------------------------------------------------// 124 | 125 | //----------------------------------------------------------------------------// 126 | 127 | //----------------------------------------------------------------------------// 128 | 129 | // 130 | // Clean up. 131 | // 132 | delete[] a0; 133 | delete[] aref; 134 | delete[] ta; 135 | delete[] tb; 136 | 137 | std::cout << "\n DONE!...\n"; 138 | 139 | return 0; 140 | } 141 | 142 | // 143 | // Function to compare result to reference and report P/F. 144 | // 145 | void checkResult(double* v1, double* v2, int len) 146 | { 147 | bool match = true; 148 | for (int i = 0; i < len; i++) { 149 | if (v1[i] != v2[i]) { 150 | match = false; 151 | } 152 | } 153 | if (match) { 154 | std::cout << "\n\t result -- PASS\n"; 155 | } else { 156 | std::cout << "\n\t result -- FAIL\n"; 157 | } 158 | } 159 | 160 | // 161 | // Function to print result. 162 | // 163 | void printResult(double* v, int len) 164 | { 165 | std::cout << std::endl; 166 | for (int i = 0; i < len; i++) { 167 | std::cout << "result[" << i << "] = " << v[i] << std::endl; 168 | } 169 | std::cout << std::endl; 170 | } 171 | -------------------------------------------------------------------------------- /test/test-hip.cpp: -------------------------------------------------------------------------------- 1 | // Produced using hipify-perl on test-cuda.cpp. 2 | 3 | #include "hip/hip_runtime.h" 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "apollo/Apollo.h" 12 | #include "apollo/Region.h" 13 | 14 | __global__ void kernel_add(double* a, double* b, double c, int size) 15 | { 16 | int id = blockIdx.x * blockDim.x + threadIdx.x; 17 | if (id < size) a[id] += b[id] * c; 18 | } 19 | 20 | void checkResult(double* v1, double* v2, int len); 21 | void printResult(double* v, int len); 22 | 23 | int main() 24 | { 25 | 26 | std::cout << "\n\ndaxpy example...\n"; 27 | 28 | // 29 | // Define vector length 30 | // 31 | const int N = 1000000; 32 | // const int N = 1000; 33 | 34 | // 35 | // Allocate and initialize vector data. 36 | // 37 | double* a0 = new double[N]; 38 | double* aref = new double[N]; 39 | 40 | double* ta = new double[N]; 41 | double* tb = new double[N]; 42 | 43 | double c = 3.14159; 44 | 45 | for (int i = 0; i < N; i++) { 46 | a0[i] = 1.0; 47 | tb[i] = 2.0; 48 | } 49 | 50 | double *d_a, *d_b; 51 | hipMalloc((void**)&d_a, sizeof(double) * N); 52 | hipMalloc((void**)&d_b, sizeof(double) * N); 53 | 54 | // 55 | // Declare and set pointers to array data. 56 | // We reset them for each daxpy version so that 57 | // they all look the same. 58 | // 59 | 60 | double* a = ta; 61 | double* b = tb; 62 | 63 | 64 | //----------------------------------------------------------------------------// 65 | 66 | std::cout << "\n Running C-version of daxpy...\n"; 67 | 68 | std::memcpy(a, a0, N * sizeof(double)); 69 | 70 | for (int i = 0; i < N; ++i) { 71 | a[i] += b[i] * c; 72 | } 73 | 74 | std::memcpy(aref, a, N * sizeof(double)); 75 | 76 | //----------------------------------------------------------------------------// 77 | 78 | //----------------------------------------------------------------------------// 79 | Apollo* apollo = Apollo::instance(); 80 | Apollo::Region* r = new Apollo::Region(/*num_features*/ 1, 81 | "hip-region", 82 | /*num_policies*/ 3); 83 | 84 | 85 | for (int j = 0; j < 20; j++) { 86 | 87 | std::memcpy(a, a0, N * sizeof(double)); 88 | 89 | hipMemcpy(d_a, a, sizeof(double) * N, hipMemcpyHostToDevice); 90 | hipMemcpy(d_b, b, sizeof(double) * N, hipMemcpyHostToDevice); 91 | 92 | Apollo::RegionContext *ctx = r->begin({N}); 93 | int policy = r->getPolicyIndex(); 94 | std::cout << "EXECUTION " << j << "\n"; 95 | // Create and install a HipAsync Timer for this context to override the 96 | // default Sync Timer. The new timer must be started by the user. Apollo 97 | // will stop the timer at region->end() as before. 98 | ctx->timer = Apollo::Timer::create(); 99 | // Start the timer. 100 | ctx->timer->start(); 101 | 102 | int block_size; 103 | switch(policy) { 104 | case 0: 105 | block_size = 64; break; 106 | case 1: 107 | block_size = 256; break; 108 | case 2: 109 | block_size = 1024; break; 110 | default: 111 | abort(); 112 | } 113 | 114 | int grid_size = std::ceil((float)N / block_size); 115 | hipLaunchKernelGGL(kernel_add, grid_size, block_size, 0, 0, d_a, d_b, c, N); 116 | r->end(); 117 | 118 | hipMemcpy(a, d_a, sizeof(double) * N, hipMemcpyDeviceToHost); 119 | 120 | 121 | checkResult(a, aref, N); 122 | 123 | if(j==10) 124 | apollo->train(0); 125 | } 126 | 127 | 128 | //----------------------------------------------------------------------------// 129 | 130 | //----------------------------------------------------------------------------// 131 | 132 | //----------------------------------------------------------------------------// 133 | 134 | // 135 | // Clean up. 136 | // 137 | delete[] a0; 138 | delete[] aref; 139 | delete[] ta; 140 | delete[] tb; 141 | 142 | std::cout << "\n DONE!...\n"; 143 | 144 | return 0; 145 | } 146 | 147 | // 148 | // Function to compare result to reference and report P/F. 149 | // 150 | void checkResult(double* v1, double* v2, int len) 151 | { 152 | bool match = true; 153 | for (int i = 0; i < len; i++) { 154 | if (v1[i] != v2[i]) { 155 | match = false; 156 | } 157 | } 158 | if (match) { 159 | std::cout << "\n\t result -- PASS\n"; 160 | } else { 161 | std::cout << "\n\t result -- FAIL\n"; 162 | } 163 | } 164 | 165 | // 166 | // Function to print result. 167 | // 168 | void printResult(double* v, int len) 169 | { 170 | std::cout << std::endl; 171 | for (int i = 0; i < len; i++) { 172 | std::cout << "result[" << i << "] = " << v[i] << std::endl; 173 | } 174 | std::cout << std::endl; 175 | } 176 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | singlehtml: 50 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 51 | @echo 52 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 53 | 54 | pickle: 55 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 56 | @echo 57 | @echo "Build finished; now you can process the pickle files." 58 | 59 | json: 60 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 61 | @echo 62 | @echo "Build finished; now you can process the JSON files." 63 | 64 | htmlhelp: 65 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 66 | @echo 67 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 68 | ".hhp project file in $(BUILDDIR)/htmlhelp." 69 | 70 | qthelp: 71 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 72 | @echo 73 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 74 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 75 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rlsl.qhcp" 76 | @echo "To view the help file:" 77 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rlsl.qhc" 78 | 79 | devhelp: 80 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 81 | @echo 82 | @echo "Build finished." 83 | @echo "To view the help file:" 84 | @echo "# mkdir -p $$HOME/.local/share/devhelp/rlsl" 85 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rlsl" 86 | @echo "# devhelp" 87 | 88 | epub: 89 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 90 | @echo 91 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 92 | 93 | latex: 94 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 95 | @echo 96 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 97 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 98 | "(use \`make latexpdf' here to do that automatically)." 99 | 100 | latexpdf: 101 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 102 | @echo "Running LaTeX files through pdflatex..." 103 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 104 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 105 | 106 | text: 107 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 108 | @echo 109 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 110 | 111 | man: 112 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 113 | @echo 114 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 115 | 116 | changes: 117 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 118 | @echo 119 | @echo "The overview file is in $(BUILDDIR)/changes." 120 | 121 | linkcheck: 122 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 123 | @echo 124 | @echo "Link check complete; look for any errors in the above output " \ 125 | "or in $(BUILDDIR)/linkcheck/output.txt." 126 | 127 | doctest: 128 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 129 | @echo "Testing of doctests in the sources finished, look at the " \ 130 | "results in $(BUILDDIR)/doctest/output.txt." 131 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | # Apollo project developers. Produced at the Lawrence Livermore National 3 | # Laboratory. See the top-level LICENSE file for details. 4 | # SPDX-License-Identifier: MIT 5 | 6 | # 7 | # Apollo 8 | # 9 | 10 | project(APOLLO LANGUAGES CXX C) 11 | cmake_minimum_required(VERSION 3.9) 12 | 13 | set(CMAKE_CXX_STANDARD 14) 14 | 15 | # #### 16 | # 17 | # Options 18 | # 19 | option(ENABLE_MPI "Require and enable MPI for collective training" OFF) 20 | option(ENABLE_OpenCV "Require and enable OpenCV for ML models" OFF) 21 | option(ENABLE_JIT_DTREE "Enable JIT generated DecisionTree eval functions (supported only by Apollo implementation)" OFF) 22 | option(ENABLE_CUDA "Enable CUDA for asynchronous timing of CUDA regions" OFF) 23 | option(ENABLE_HIP "Enable HIP for asynchronous timing of HIP regions" OFF) 24 | option(ENABLE_TESTS "Enable building Apollo tests" OFF) 25 | option(BUILD_SHARED_LIBS "Build Apollo as a shared library instead of static" OFF) 26 | 27 | # 28 | # #### 29 | 30 | # Version information 31 | set(APOLLO_MAJOR_VERSION 2) 32 | set(APOLLO_MINOR_VERSION 0) 33 | set(APOLLO_PATCH_VERSION 0) 34 | set(APOLLO_VERSION "${APOLLO_MAJOR_VERSION}.${APOLLO_MINOR_VERSION}.${APOLLO_PATCH_VERSION}") 35 | 36 | set(APOLLO_BUILD_TYPE "${CMAKE_BUILD_TYPE}") 37 | 38 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) 39 | include(PreventInSourceBuilds) 40 | 41 | # 42 | # Setup variables to pass to ApolloConfig.h 43 | # 44 | # Pull in macros 45 | include(ApolloProjectMacros) 46 | 47 | # Pull in the GIT repo information 48 | include(GetGitRevisionDescription) 49 | get_git_head_revision(GIT_REFSPEC GIT_SHA1) 50 | 51 | # add_definitions("-DAPOLLO_GIT_SHA1=${GIT_SHA1}") 52 | set(APOLLO_GIT_SHA1 "${GIT_SHA1}") 53 | 54 | # Set some host information 55 | execute_process(COMMAND uname -n OUTPUT_VARIABLE APOLLO_HOST_NODE_NAME) 56 | string(STRIP ${APOLLO_HOST_NODE_NAME} APOLLO_HOST_NODE_NAME) 57 | 58 | if(APPLE) 59 | execute_process(COMMAND uname OUTPUT_VARIABLE APOLLO_HOST_DETAILED_O) 60 | else(APPLE) 61 | execute_process(COMMAND uname -o OUTPUT_VARIABLE APOLLO_HOST_DETAILED_O) 62 | endif(APPLE) 63 | 64 | string(STRIP ${APOLLO_HOST_DETAILED_O} APOLLO_HOST_DETAILED_O) 65 | execute_process(COMMAND uname -r OUTPUT_VARIABLE APOLLO_HOST_DETAILED_R) 66 | string(STRIP ${APOLLO_HOST_DETAILED_R} APOLLO_HOST_DETAILED_R) 67 | execute_process(COMMAND uname -m OUTPUT_VARIABLE APOLLO_HOST_DETAILED_M) 68 | string(STRIP ${APOLLO_HOST_DETAILED_M} APOLLO_HOST_DETAILED_M) 69 | set(APOLLO_HOST_KNOWN_AS ${APOLLO_HOST_NODE_NAME}) 70 | set(APOLLO_HOST_DETAILED "\"${APOLLO_HOST_DETAILED_O} ${APOLLO_HOST_DETAILED_R} ${APOLLO_HOST_DETAILED_M}\"") 71 | message(STATUS "Building on: ${CMAKE_SYSTEM_NAME}") 72 | 73 | # string(TOUPPER ${APOLLO_BUILD_TYPE} CMAKE_BUILD_TYPE) 74 | set(APOLLO_CXX_COMPILER "${CMAKE_CXX_COMPILER} ") 75 | set(APOLLO_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${APOLLO_BUILD_TYPE}} ") 76 | set(APOLLO_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_LINK_FLAGS_${CMAKE_BUILD_TYPE}} ") 77 | 78 | # Create a config header file 79 | configure_file( 80 | ${PROJECT_SOURCE_DIR}/apollo-config.h.in 81 | ${PROJECT_BINARY_DIR}/apollo-config.h) 82 | 83 | # Create pkg-confic .pc file 84 | set(PKG_CONFIG_INCLUDEDIR "\${prefix}/include") 85 | set(PKG_CONFIG_LIBDIR "\${prefix}/lib") 86 | set(PKG_CONFIG_LIBS "-L\${libdir} -lapollo ") 87 | set(PKG_CONFIG_CFLAGS "-I\${includedir} ") 88 | 89 | configure_file( 90 | ${PROJECT_SOURCE_DIR}/apollo.pc.in 91 | ${PROJECT_BINARY_DIR}/apollo.pc) 92 | 93 | # Make apollo findable for cmake 94 | configure_file( 95 | ${PROJECT_SOURCE_DIR}/apollo-config.cmake.in 96 | ${PROJECT_BINARY_DIR}/apollo-config.cmake 97 | @ONLY) 98 | 99 | install(FILES ${PROJECT_BINARY_DIR}/apollo-config.cmake 100 | DESTINATION share/cmake/apollo) 101 | 102 | install(EXPORT apollo 103 | DESTINATION share/cmake/apollo) 104 | 105 | install(FILES ${PROJECT_BINARY_DIR}/apollo-config.h 106 | DESTINATION include/apollo) 107 | 108 | install(FILES ${PROJECT_BINARY_DIR}/apollo.pc 109 | DESTINATION lib/pkgconfig) 110 | 111 | # #### 112 | # 113 | # External libraries 114 | # 115 | if(ENABLE_MPI) 116 | find_package(MPI REQUIRED) 117 | add_definitions(-DENABLE_MPI) 118 | endif() 119 | 120 | if(ENABLE_OPENCV) 121 | find_package(OpenCV REQUIRED) 122 | include_directories(${OpenCV_INCLUDE_DIRS}) 123 | add_definitions(-DENABLE_OPENCV) 124 | endif() 125 | 126 | if(ENABLE_CUDA) 127 | # TODO: Upgrade to CUDAToolkit for better handling, requires cmake 3.17+ 128 | find_package(CUDA REQUIRED) 129 | include_directories(${CUDA_INCLUDE_DIRS}) 130 | endif() 131 | 132 | if(ENABLE_HIP) 133 | find_package(hip REQUIRED) 134 | include_directories(${HSA_HEADER}) 135 | add_definitions(-D__HIP_PLATFORM_AMD__) 136 | endif() 137 | 138 | if(ENABLE_JIT_DTREE) 139 | add_definitions(-DENABLE_JIT_DTREE) 140 | endif() 141 | 142 | # #### 143 | # 144 | # Define build targets for Apollo 145 | # 146 | include_directories(./src ./include ${PROJECT_BINARY_DIR}/include) 147 | 148 | add_subdirectory(src) 149 | 150 | if(ENABLE_TESTS) 151 | add_subdirectory(test) 152 | endif(ENABLE_TESTS) 153 | 154 | # 155 | # EOF 156 | -------------------------------------------------------------------------------- /src/Dataset.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/Dataset.h" 7 | 8 | #include "helpers/Parser.h" 9 | 10 | size_t Apollo::Dataset::size() { return data.size(); } 11 | 12 | void Apollo::Dataset::clear() { data.clear(); } 13 | 14 | const std::vector, int, double>> Apollo::Dataset:: 15 | toVectorOfTuples() const 16 | { 17 | std::vector, int, double>> vector; 18 | for (const auto &d : data) { 19 | const auto &features = d.first.first; 20 | const auto &policy = d.first.second; 21 | const auto &metric = d.second; 22 | vector.push_back(std::make_tuple(features, policy, metric)); 23 | } 24 | 25 | return vector; 26 | } 27 | 28 | void Apollo::Dataset::insert(std::vector &features, 29 | int policy, 30 | double metric) 31 | { 32 | auto key = std::make_pair(std::move(features), policy); 33 | auto it = data.find(key); 34 | if (it == data.end()) 35 | data.emplace(std::move(key), metric); 36 | else 37 | // Exponential moving average (a=0.5) to update the metric. 38 | it->second = .5 * it->second + .5 * metric; 39 | } 40 | 41 | void Apollo::Dataset::insert(Apollo::Dataset &ds) 42 | { 43 | for (auto &d : ds.data) { 44 | auto features = d.first.first; 45 | auto policy = d.first.second; 46 | auto metric = d.second; 47 | insert(features, policy, metric); 48 | } 49 | } 50 | 51 | void Apollo::Dataset::findMinMetricPolicyByFeatures( 52 | std::vector> &features, 53 | std::vector &policies, 54 | std::map, std::pair> &min_metric_policies) 55 | const 56 | { 57 | std::map, std::pair> best_policies; 58 | 59 | // Reduce grouped data to best_policies that minimize the metric. 60 | for (auto &d : data) { 61 | const auto &features = d.first.first; 62 | const auto &policy = d.first.second; 63 | const auto &avg = d.second; 64 | 65 | auto iter = best_policies.find(features); 66 | if (iter == best_policies.end()) { 67 | best_policies.insert( 68 | std::make_pair(features, std::make_pair(policy, avg))); 69 | } else { 70 | double prev_avg = best_policies[features].second; 71 | if (avg < prev_avg) best_policies[features] = std::make_pair(policy, avg); 72 | } 73 | } 74 | 75 | for (auto &b : best_policies) { 76 | #ifdef DEBUG_OUTPUT 77 | std::cout << "best [ "; 78 | for (auto &f : b.first) 79 | std::cout << f << ", "; 80 | std::cout << "] -> " << std::get<0>(b.second) 81 | << ", = " << std::get<1>(b.second) << "\n"; 82 | #endif 83 | 84 | const auto &train_features = b.first; 85 | const auto &policy = b.second.first; 86 | 87 | features.push_back(train_features); 88 | policies.push_back(policy); 89 | } 90 | 91 | min_metric_policies = best_policies; 92 | } 93 | 94 | void Apollo::Dataset::store(std::ostream &os) 95 | { 96 | os << "data: {\n"; 97 | int idx = 0; 98 | for (auto &d : data) { 99 | const auto &features = d.first.first; 100 | const auto &policy = d.first.second; 101 | const auto &metric = d.second; 102 | os << " " << idx << ": { features: [ "; 103 | for (auto &f : features) 104 | os << float(f) << ","; 105 | os << " ], "; 106 | os << "policy: " << policy << ", "; 107 | os << "xtime: " << metric; 108 | os << " },\n"; 109 | ++idx; 110 | } 111 | os << "}\n"; 112 | } 113 | 114 | void Apollo::Dataset::load(std::istream &is) 115 | { 116 | Parser parser(is); 117 | parser.getNextToken(); 118 | parser.parseExpected("data:"); 119 | 120 | parser.getNextToken(); 121 | parser.parseExpected("{"); 122 | 123 | while (!parser.getNextTokenEquals("}")) { 124 | int idx; 125 | int policy; 126 | std::vector features; 127 | double xtime; 128 | 129 | parser.parse(idx); 130 | parser.parseExpected(":"); 131 | 132 | parser.getNextToken(); 133 | parser.parseExpected("{"); 134 | 135 | parser.getNextToken(); 136 | parser.parseExpected("features:"); 137 | 138 | parser.getNextToken(); 139 | parser.parseExpected("["); 140 | 141 | while (!parser.getNextTokenEquals("],")) { 142 | float feature; 143 | parser.parse(feature); 144 | parser.parseExpected(","); 145 | features.push_back(feature); 146 | } 147 | 148 | parser.getNextToken(); 149 | parser.parseExpected("policy:"); 150 | parser.getNextToken(); 151 | parser.parse(policy); 152 | 153 | parser.parseExpected(","); 154 | parser.getNextToken(); 155 | parser.parseExpected("xtime:"); 156 | parser.getNextToken(); 157 | parser.parse(xtime); 158 | 159 | parser.getNextToken(); 160 | parser.parseExpected("},"); 161 | 162 | // std::cout << "=== BEGIN \n"; 163 | // std::cout << "idx " << idx << "\n"; 164 | // std::cout << "features: [ "; 165 | // for (auto &f : features) 166 | // std::cout << f << ", "; 167 | // std::cout << "]\n"; 168 | // std::cout << "policy " << policy << "\n"; 169 | // std::cout << "xtime " << xtime << "\n"; 170 | // std::cout << "=== END \n"; 171 | 172 | insert(features, policy, xtime); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake: -------------------------------------------------------------------------------- 1 | # - Returns a version string from Git 2 | # 3 | # These functions force a re-configure on each git commit so that you can 4 | # trust the values of the variables in your build system. 5 | # 6 | # get_git_head_revision( [ ...]) 7 | # 8 | # Returns the refspec and sha hash of the current head revision 9 | # 10 | # git_describe( [ ...]) 11 | # 12 | # Returns the results of git describe on the source tree, and adjusting 13 | # the output so that it tests false if an error occurs. 14 | # 15 | # git_get_exact_tag( [ ...]) 16 | # 17 | # Returns the results of git describe --exact-match on the source tree, 18 | # and adjusting the output so that it tests false if there was no exact 19 | # matching tag. 20 | # 21 | # git_local_changes() 22 | # 23 | # Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. 24 | # Uses the return code of "git diff-index --quiet HEAD --". 25 | # Does not regard untracked files. 26 | # 27 | # Requires CMake 2.6 or newer (uses the 'function' command) 28 | # 29 | # Original Author: 30 | # 2009-2010 Ryan Pavlik 31 | # http://academic.cleardefinition.com 32 | # Iowa State University HCI Graduate Program/VRAC 33 | # 34 | # Copyright Iowa State University 2009-2010. 35 | # Distributed under the Boost Software License, Version 1.0. 36 | # (See accompanying file LICENSE_1_0.txt or copy at 37 | # http://www.boost.org/LICENSE_1_0.txt) 38 | 39 | if(__get_git_revision_description) 40 | return() 41 | endif() 42 | set(__get_git_revision_description YES) 43 | 44 | # We must run the following at "include" time, not at function call time, 45 | # to find the path to this module rather than the path to a calling list file 46 | get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 47 | 48 | function(get_git_head_revision _refspecvar _hashvar) 49 | set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 50 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 51 | while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories 52 | set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") 53 | get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) 54 | if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) 55 | # We have reached the root directory, we are not in git 56 | set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 57 | set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) 58 | return() 59 | endif() 60 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 61 | endwhile() 62 | # check if this is a submodule 63 | if(NOT IS_DIRECTORY ${GIT_DIR}) 64 | file(READ ${GIT_DIR} submodule) 65 | string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) 66 | get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 67 | get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) 68 | endif() 69 | set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 70 | if(NOT EXISTS "${GIT_DATA}") 71 | file(MAKE_DIRECTORY "${GIT_DATA}") 72 | endif() 73 | 74 | if(NOT EXISTS "${GIT_DIR}/HEAD") 75 | return() 76 | endif() 77 | set(HEAD_FILE "${GIT_DATA}/HEAD") 78 | configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) 79 | 80 | configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 81 | "${GIT_DATA}/grabRef.cmake" 82 | @ONLY) 83 | include("${GIT_DATA}/grabRef.cmake") 84 | 85 | set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) 86 | set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) 87 | endfunction() 88 | 89 | function(git_describe _var) 90 | if(NOT GIT_FOUND) 91 | find_package(Git QUIET) 92 | endif() 93 | get_git_head_revision(refspec hash) 94 | if(NOT GIT_FOUND) 95 | set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) 96 | return() 97 | endif() 98 | if(NOT hash) 99 | set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) 100 | return() 101 | endif() 102 | 103 | # TODO sanitize 104 | #if((${ARGN}" MATCHES "&&") OR 105 | # (ARGN MATCHES "||") OR 106 | # (ARGN MATCHES "\\;")) 107 | # message("Please report the following error to the project!") 108 | # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") 109 | #endif() 110 | 111 | #message(STATUS "Arguments to execute_process: ${ARGN}") 112 | 113 | execute_process(COMMAND 114 | "${GIT_EXECUTABLE}" 115 | describe 116 | ${hash} 117 | ${ARGN} 118 | WORKING_DIRECTORY 119 | "${CMAKE_CURRENT_SOURCE_DIR}" 120 | RESULT_VARIABLE 121 | res 122 | OUTPUT_VARIABLE 123 | out 124 | ERROR_QUIET 125 | OUTPUT_STRIP_TRAILING_WHITESPACE) 126 | if(NOT res EQUAL 0) 127 | set(out "${out}-${res}-NOTFOUND") 128 | endif() 129 | 130 | set(${_var} "${out}" PARENT_SCOPE) 131 | endfunction() 132 | 133 | function(git_get_exact_tag _var) 134 | git_describe(out --exact-match ${ARGN}) 135 | set(${_var} "${out}" PARENT_SCOPE) 136 | endfunction() 137 | 138 | function(git_local_changes _var) 139 | if(NOT GIT_FOUND) 140 | find_package(Git QUIET) 141 | endif() 142 | get_git_head_revision(refspec hash) 143 | if(NOT GIT_FOUND) 144 | set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) 145 | return() 146 | endif() 147 | if(NOT hash) 148 | set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) 149 | return() 150 | endif() 151 | 152 | execute_process(COMMAND 153 | "${GIT_EXECUTABLE}" 154 | diff-index --quiet HEAD -- 155 | WORKING_DIRECTORY 156 | "${CMAKE_CURRENT_SOURCE_DIR}" 157 | RESULT_VARIABLE 158 | res 159 | OUTPUT_VARIABLE 160 | out 161 | ERROR_QUIET 162 | OUTPUT_STRIP_TRAILING_WHITESPACE) 163 | if(res EQUAL 0) 164 | set(${_var} "CLEAN" PARENT_SCOPE) 165 | else() 166 | set(${_var} "DIRTY" PARENT_SCOPE) 167 | endif() 168 | endfunction() 169 | -------------------------------------------------------------------------------- /src/python/modeling/create-dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | import glob 6 | 7 | ''' 8 | Reads data from CSV traces and creates a loadable dataset for training models. 9 | ''' 10 | 11 | 12 | def print_to_str(index, features, policy, xtime): 13 | features = [str(n) for n in features] 14 | output = ' ' + str(index) + ': { features: [ ' 15 | for fi in features: 16 | output += fi + ', ' 17 | output += ']' 18 | output += ', policy: ' + str(policy) 19 | output += ', xtime: ' + str(xtime) 20 | output += ' },\n' 21 | return output 22 | 23 | 24 | def agg_by_none(data_per_region): 25 | output = '# agg by none\n' 26 | 27 | output += 'data: {\n' 28 | feature_cols = list(data_per_region.columns[5:-2]) 29 | 30 | # Output all the data points. 31 | for i, row in data_per_region.iterrows(): 32 | output += print_to_str(i, row[feature_cols], 33 | row['policy'], row['xtime']) 34 | 35 | output += '}\n\n' 36 | return output 37 | 38 | 39 | def agg_by_mean(data_per_region): 40 | output = '# agg by mean\n' 41 | 42 | output += 'data: {\n' 43 | feature_cols = list(data_per_region.columns[5:-2]) 44 | 45 | # Group by features and policy to extract policies per feature with 46 | # their mean xtime. 47 | groups = data_per_region.groupby(by=feature_cols + ['policy']) 48 | index = 0 49 | for name, g in groups: 50 | features = name[:-1] 51 | policy = name[-1] 52 | xtime = g['xtime'].mean() 53 | output += print_to_str(index, features, policy, xtime) 54 | index += 1 55 | 56 | output += '}\n\n' 57 | return output 58 | 59 | 60 | def agg_by_min(data_per_region): 61 | output = '# agg by min\n' 62 | 63 | output += 'data: {\n' 64 | feature_cols = list(data_per_region.columns[5:-2]) 65 | 66 | groups = data_per_region.groupby(by=feature_cols) 67 | index = 0 68 | for _, g in groups: 69 | # Find the index of the minimum xtime. 70 | min_g = g.loc[g['xtime'].idxmin()] 71 | 72 | # Extract data from the minimum xtime data point. 73 | features = min_g[feature_cols] 74 | policy = min_g['policy'] 75 | xtime = min_g['xtime'] 76 | output += print_to_str(index, features, policy, xtime) 77 | index += 1 78 | 79 | output += '}\n\n' 80 | return output 81 | 82 | 83 | def agg_by_mean_min(data_per_region): 84 | output = '# agg by mean_min\n' 85 | 86 | output += 'data: {\n' 87 | feature_cols = list(data_per_region.columns[5:-2]) 88 | 89 | groups = data_per_region.groupby(by=feature_cols) 90 | index = 0 91 | for name, g in groups: 92 | # Group by policy to compute the mean xtime. 93 | g2 = g.groupby(by=['policy']) 94 | mean_g = g2['xtime'].mean() 95 | 96 | # Find the index (equals the policy) with the minimum mean xtime. 97 | idxmin = mean_g.idxmin() 98 | 99 | # Create a list of feature values if there is a single feature. 100 | if len(feature_cols) > 1: 101 | features = name 102 | else: 103 | features = [name] 104 | policy = idxmin 105 | xtime = mean_g.loc[idxmin] 106 | output += print_to_str(index, features, policy, xtime) 107 | index += 1 108 | 109 | output += '}\n\n' 110 | return output 111 | 112 | 113 | def read_tracefiles(tracefiles): 114 | data = pd.DataFrame() 115 | 116 | csv_data = [] 117 | print('Reading tracefiles...') 118 | nfiles = len(tracefiles) 119 | for i, f in enumerate(tracefiles): 120 | print('\r=== Reading %-100s %06d/%06d' % 121 | (f, i+1, nfiles), flush=True, end='') 122 | try: 123 | csv_data.append(pd.read_csv(f, sep=' ', header=0, index_col=False)) 124 | except pd.errors.EmptyDataError: 125 | print('Warning: no data in', f) 126 | print() 127 | 128 | print('Create concat pandas dataframe...') 129 | data = pd.concat(csv_data, ignore_index=True, sort=False) 130 | 131 | return data 132 | 133 | 134 | def read_tracedirs(tracedirs): 135 | data = pd.DataFrame() 136 | 137 | for dir in tracedirs: 138 | globlist = glob.glob('%s/trace*.csv' % (dir)) 139 | data_dir = read_tracefiles(globlist) 140 | data = pd.concat([data, data_dir], ignore_index=True, sort=False) 141 | 142 | return data 143 | 144 | 145 | def main(): 146 | parser = argparse.ArgumentParser( 147 | description='Create loadable training datasets from existing CSV measurements.') 148 | parser.add_argument('--tracedirs', nargs='+', 149 | help='trace directories') 150 | parser.add_argument('--tracefiles', nargs='+', 151 | help='trace filenames') 152 | parser.add_argument('--agg', 153 | help='aggregate measures ', choices=['none', 'mean', 'min', 'mean-min'], required=True) 154 | args = parser.parse_args() 155 | 156 | if not (args.tracedirs or args.tracefiles): 157 | raise RuntimeError('Either tracedirs or tracefiles must be set') 158 | 159 | if args.tracefiles: 160 | data = read_tracefiles(args.tracefiles) 161 | 162 | if args.tracedirs: 163 | data = read_tracedirs(args.tracedirs) 164 | 165 | #print('data\n', data) 166 | regions = data['region'].unique().tolist() 167 | 168 | # Create datasets per region. 169 | print('Creating datasets...') 170 | for r in regions: 171 | print(f'Processing region {r}...') 172 | data_per_region = data.loc[data['region'] == 173 | r].dropna(axis='columns').reset_index() 174 | 175 | if args.agg == 'none': 176 | output = agg_by_none(data_per_region) 177 | elif args.agg == 'mean': 178 | output = agg_by_mean(data_per_region) 179 | elif args.agg == 'min': 180 | output = agg_by_min(data_per_region) 181 | elif args.agg == 'mean-min': 182 | output = agg_by_mean_min(data_per_region) 183 | else: 184 | raise RuntimeError('Invalid aggregation args ' + str(args.agg)) 185 | with open('Dataset-' + r + '.yaml', 'w') as f: 186 | f.write(output) 187 | 188 | 189 | if __name__ == "__main__": 190 | main() 191 | -------------------------------------------------------------------------------- /src/models/impl/RandomForestImpl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "RandomForestImpl.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "DecisionTreeImpl.h" 16 | 17 | RandomForestImpl::RandomForestImpl(int num_classes, std::string filename) 18 | : num_classes(num_classes) 19 | { 20 | load(filename); 21 | } 22 | 23 | RandomForestImpl::RandomForestImpl(int num_classes, 24 | unsigned num_trees, 25 | unsigned max_depth) 26 | : num_classes(num_classes), num_trees(num_trees), max_depth(max_depth) 27 | { 28 | } 29 | 30 | void RandomForestImpl::train(std::vector> &features, 31 | std::vector &responses) 32 | { 33 | // Uniform random generator using Mersenne-Twister for randomness. 34 | std::mt19937 generator; 35 | std::uniform_int_distribution uniform_dist(0, features.size() - 1); 36 | 37 | for (unsigned i = 0; i < num_trees; i++) { 38 | std::vector> sample_features; 39 | std::vector sample_responses; 40 | // Random pick with replacement of features, responses 41 | for (size_t i = 0, end = features.size(); i < end; ++i) { 42 | int sample_idx = uniform_dist(generator); 43 | sample_features.push_back(features[sample_idx]); 44 | sample_responses.push_back(responses[sample_idx]); 45 | } 46 | 47 | rfc.push_back(std::make_unique( 48 | num_classes, sample_features, sample_responses, max_depth)); 49 | } 50 | } 51 | 52 | RandomForestImpl::RandomForestImpl(int num_classes, 53 | std::vector> &features, 54 | std::vector &responses, 55 | unsigned num_trees, 56 | unsigned max_depth) 57 | : num_classes(num_classes), num_trees(num_trees), max_depth(max_depth) 58 | { 59 | // Uniform random generator using Mersenne-Twister for randomness. 60 | std::mt19937 generator; 61 | std::uniform_int_distribution uniform_dist(0, features.size() - 1); 62 | 63 | for (unsigned i = 0; i < num_trees; i++) { 64 | std::vector> sample_features; 65 | std::vector sample_responses; 66 | // Random pick with replacement of features, responses 67 | for (size_t i = 0, end = features.size(); i < end; ++i) { 68 | int sample_idx = uniform_dist(generator); 69 | sample_features.push_back(features[sample_idx]); 70 | sample_responses.push_back(responses[sample_idx]); 71 | } 72 | 73 | rfc.push_back(std::make_unique( 74 | num_classes, sample_features, sample_responses, max_depth)); 75 | } 76 | } 77 | 78 | void RandomForestImpl::output_rfc(OutputFormatter &outfmt) 79 | { 80 | outfmt << "rfc: {\n"; 81 | ++outfmt; 82 | outfmt << "num_trees: " & num_trees & ",\n"; 83 | outfmt << "max_depth: " & max_depth & ",\n"; 84 | outfmt << "classes: [ "; 85 | for (unsigned i = 0; i < num_classes; ++i) { 86 | outfmt &i & ", "; 87 | } 88 | outfmt & "],\n"; 89 | outfmt << "trees:" & " [\n"; 90 | unsigned tree_idx = 0; 91 | for (auto &dtree : rfc) { 92 | ++outfmt; 93 | dtree->output_tree(outfmt, "tree"); 94 | outfmt << ",\n"; 95 | --outfmt; 96 | tree_idx++; 97 | } 98 | outfmt << "]\n"; 99 | --outfmt; 100 | outfmt << "}\n"; 101 | } 102 | 103 | void RandomForestImpl::save(const std::string &filename) 104 | { 105 | std::ofstream ofs(filename, std::ofstream::out); 106 | OutputFormatter outfmt(ofs); 107 | outfmt << "# RandomForestImpl\n"; 108 | output_rfc(outfmt); 109 | ofs.close(); 110 | } 111 | template 112 | static void parseKeyVal(Parser &parser, const char *key, T &val) 113 | { 114 | parser.getNextToken(); 115 | parser.parseExpected(key); 116 | 117 | parser.getNextToken(); 118 | parser.parse(val); 119 | parser.parseExpected(","); 120 | }; 121 | 122 | void RandomForestImpl::parse_rfc(std::ifstream &ifs) 123 | { 124 | Parser parser(ifs); 125 | 126 | parser.getNextToken(); 127 | parser.parseExpected("rfc:"); 128 | 129 | parser.getNextToken(); 130 | parser.parseExpected("{"); 131 | 132 | parseKeyVal(parser, "num_trees:", num_trees); 133 | parseKeyVal(parser, "max_depth:", max_depth); 134 | 135 | parser.getNextToken(); 136 | parser.parseExpected("classes:"); 137 | parser.getNextToken(); 138 | parser.parseExpected("["); 139 | int class_idx = 0; 140 | while (!parser.getNextTokenEquals("],")) { 141 | parser.parse(class_idx); 142 | parser.parseExpected(","); 143 | ++class_idx; 144 | } 145 | if (class_idx != num_classes) 146 | throw std::runtime_error("Expected class_idx " + std::to_string(class_idx) + 147 | " equal to constructor num_classes " + 148 | std::to_string(num_classes)); 149 | 150 | parser.getNextToken(); 151 | parser.parseExpected("trees:"); 152 | parser.getNextToken(); 153 | parser.parseExpected("["); 154 | 155 | for (int i = 0; i < num_trees; ++i) { 156 | rfc.push_back(std::make_unique(num_classes, ifs)); 157 | parser.getNextToken(); 158 | parser.parseExpected(","); 159 | } 160 | parser.getNextToken(); 161 | parser.parseExpected("]"); 162 | 163 | parser.getNextToken(); 164 | parser.parseExpected("}"); 165 | } 166 | 167 | void RandomForestImpl::load(const std::string &filename) 168 | { 169 | std::ifstream ifs(filename); 170 | if (!ifs) throw std::runtime_error("Error loading file: " + filename); 171 | parse_rfc(ifs); 172 | ifs.close(); 173 | } 174 | 175 | int RandomForestImpl::predict(const std::vector &features) 176 | { 177 | // Predict by majority vote over all decision trees. 178 | int count_per_class[num_classes]; 179 | for (size_t i = 0; i < num_classes; ++i) 180 | count_per_class[i] = 0; 181 | 182 | for (auto &dtree : rfc) { 183 | int dtree_prediction = dtree->predict(features); 184 | assert(0 <= dtree_prediction && dtree_prediction < num_classes); 185 | count_per_class[dtree_prediction]++; 186 | } 187 | 188 | int class_idx = 0; 189 | for (size_t i = 1; i < num_classes; ++i) 190 | if (count_per_class[i] > count_per_class[class_idx]) class_idx = i; 191 | 192 | return class_idx; 193 | } 194 | 195 | void RandomForestImpl::print_forest() 196 | { 197 | OutputFormatter outfmt(std::cout); 198 | output_rfc(outfmt); 199 | } 200 | -------------------------------------------------------------------------------- /src/ModelFactory.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2024, Lawrence Livermore National Security, LLC and other 2 | // Apollo project developers. Produced at the Lawrence Livermore National 3 | // Laboratory. See the top-level LICENSE file for details. 4 | // SPDX-License-Identifier: MIT 5 | 6 | #include "apollo/ModelFactory.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "apollo/models/DatasetMap.h" 12 | #include "apollo/models/DecisionTree.h" 13 | #include "apollo/models/Random.h" 14 | #include "apollo/models/RandomForest.h" 15 | #include "apollo/models/RoundRobin.h" 16 | #include "apollo/models/Static.h" 17 | #ifdef ENABLE_OPENCV 18 | #include "apollo/models/RegressionTree.h" 19 | #endif 20 | #include "apollo/models/Optimal.h" 21 | #include "apollo/models/PolicyNet.h" 22 | 23 | namespace apollo 24 | { 25 | 26 | std::unique_ptr ModelFactory::createPolicyModel( 27 | const std::string &model_name, 28 | int num_policies, 29 | const std::string &path) 30 | { 31 | if (model_name == "Static" || model_name == "Random" || 32 | model_name == "RoundRobin" || model_name == "DatasetMap") { 33 | throw std::runtime_error( 34 | "Static, Random, RoundRobin do not support loading model from file."); 35 | } else if (model_name == "Optimal") { 36 | return std::make_unique(path); 37 | } else if (model_name == "DecisionTree") 38 | return std::make_unique(num_policies, path); 39 | else if (model_name == "RandomForest") { 40 | return std::make_unique(num_policies, path); 41 | } else if (model_name == "PolicyNet") { 42 | throw std::runtime_error("Not impl. yet"); 43 | } else { 44 | std::cerr << "Invalid model " << model_name << std::endl; 45 | abort(); 46 | } 47 | } 48 | 49 | std::unique_ptr ModelFactory::createPolicyModel( 50 | const std::string &model_name, 51 | int num_features, 52 | int num_policies, 53 | std::unordered_map &model_params) 54 | { 55 | if (model_name == "Static") { 56 | int policy = 0; 57 | auto it = model_params.find("policy"); 58 | if (it != model_params.end()) policy = std::stoi(it->second); 59 | if (policy < 0) 60 | throw std::runtime_error("Invalid policy " + std::to_string(policy) + 61 | " for Static"); 62 | if (policy >= num_policies) { 63 | std::cerr << "WARNING: policy " << std::to_string(policy) 64 | << " for Static exceeds num_policies " << num_policies 65 | << ", reset to 0\n"; 66 | policy = 0; 67 | } 68 | return std::make_unique(num_policies, policy); 69 | } else if (model_name == "DatasetMap") { 70 | return std::make_unique(num_policies); 71 | } else if (model_name == "Random") { 72 | return std::make_unique(num_policies); 73 | } else if (model_name == "RoundRobin") { 74 | return std::make_unique(num_policies); 75 | } else if (model_name == "DecisionTree") { 76 | // Default max_depth 77 | unsigned max_depth = 2; 78 | auto it = model_params.find("max_depth"); 79 | if (it != model_params.end()) max_depth = std::stoul(it->second); 80 | std::unique_ptr explorer; 81 | it = model_params.find("explore"); 82 | // TODO: enable explore_model_params? unneeded for now. 83 | std::unordered_map explore_model_params; 84 | if (it != model_params.end()) 85 | explorer = createPolicyModel(it->second, 86 | num_features, 87 | num_policies, 88 | explore_model_params); 89 | else 90 | // Default explorer model is RoundRobin. 91 | explorer = createPolicyModel("RoundRobin", 92 | num_features, 93 | num_policies, 94 | explore_model_params); 95 | 96 | return std::make_unique(num_policies, max_depth, explorer); 97 | } else if (model_name == "RandomForest") { 98 | // Default num_trees, max_depth 99 | unsigned num_trees = 10; 100 | unsigned max_depth = 2; 101 | auto it = model_params.find("num_trees"); 102 | if (it != model_params.end()) num_trees = std::stoul(it->second); 103 | it = model_params.find("max_depth"); 104 | if (it != model_params.end()) max_depth = std::stoul(it->second); 105 | std::unique_ptr explorer; 106 | it = model_params.find("explore"); 107 | // TODO: Should we enable explore_model_params? It is unneeded for now since 108 | // exploration models RoundRobin, Random currently have no params. 109 | std::unordered_map explore_model_params; 110 | if (it != model_params.end()) 111 | explorer = createPolicyModel(it->second, 112 | num_features, 113 | num_policies, 114 | explore_model_params); 115 | else 116 | // Default explorer model is RoundRobin. 117 | explorer = createPolicyModel("RoundRobin", 118 | num_features, 119 | num_policies, 120 | explore_model_params); 121 | 122 | return std::make_unique(num_policies, 123 | num_trees, 124 | max_depth, 125 | explorer); 126 | } else if (model_name == "PolicyNet") { 127 | double lr = 1e-2; 128 | double beta = 0.5; 129 | double beta1 = 0.5; 130 | double beta2 = 0.9; 131 | double threshold = 0.0; 132 | auto it = model_params.find("lr"); 133 | if (it != model_params.end()) lr = std::stod(it->second); 134 | it = model_params.find("beta"); 135 | if (it != model_params.end()) beta = std::stod(it->second); 136 | it = model_params.find("beta1"); 137 | if (it != model_params.end()) beta1 = std::stod(it->second); 138 | it = model_params.find("beta2"); 139 | if (it != model_params.end()) beta2 = std::stod(it->second); 140 | it = model_params.find("threshold"); 141 | if (it != model_params.end()) threshold = std::stod(it->second); 142 | 143 | return std::make_unique( 144 | num_policies, num_features, lr, beta, beta1, beta2, threshold); 145 | } else if (model_name == "Optimal") { 146 | return std::make_unique(); 147 | } else { 148 | std::cerr << __FILE__ << ":" << __LINE__ << ":: Invalid model " 149 | << model_name << std::endl; 150 | abort(); 151 | } 152 | } 153 | 154 | std::unique_ptr ModelFactory::createRegressionTree( 155 | Apollo::Dataset &dataset) 156 | { 157 | #ifdef ENABLE_OPENCV 158 | return std::make_unique(dataset); 159 | #else 160 | throw std::runtime_error("Regression trees require OpenCV"); 161 | #endif 162 | } 163 | 164 | } // end namespace apollo. 165 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # rlsl documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Feb 20 01:11:46 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = ['sphinx.ext.autodoc'] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ['_templates'] 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The encoding of source files. 37 | #source_encoding = 'utf-8-sig' 38 | 39 | # The master toctree document. 40 | master_doc = 'index' 41 | 42 | # General information about the project. 43 | project = u'apollo' 44 | copyright = u'2015, David Beckingsale' 45 | 46 | # The version info for the project you're documenting, acts as replacement for 47 | # |version| and |release|, also used in various other places throughout the 48 | # built documents. 49 | # 50 | # The short X.Y version. 51 | version = '0.1' 52 | # The full version, including alpha/beta/rc tags. 53 | release = '0.1a' 54 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation 56 | # for a list of supported languages. 57 | #language = None 58 | 59 | # There are two options for replacing |today|: either, you set today to some 60 | # non-false value, then it is used: 61 | #today = '' 62 | # Else, today_fmt is used as the format for a strftime call. 63 | #today_fmt = '%B %d, %Y' 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | exclude_patterns = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. See the documentation for 93 | # a list of builtin themes. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_domain_indices = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 153 | #html_show_sphinx = True 154 | 155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 156 | #html_show_copyright = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = None 165 | 166 | # Output file base name for HTML help builder. 167 | htmlhelp_basename = 'rlsldoc' 168 | 169 | 170 | # -- Options for LaTeX output -------------------------------------------------- 171 | 172 | # The paper size ('letter' or 'a4'). 173 | #latex_paper_size = 'letter' 174 | 175 | # The font size ('10pt', '11pt' or '12pt'). 176 | #latex_font_size = '10pt' 177 | 178 | # Grouping the document tree into LaTeX files. List of tuples 179 | # (source start file, target name, title, author, documentclass [howto/manual]). 180 | latex_documents = [ 181 | ('index', 'apollo.tex', u'apollo Documentation', 182 | u'David Beckingsale', 'manual'), 183 | ] 184 | 185 | # The name of an image file (relative to this directory) to place at the top of 186 | # the title page. 187 | #latex_logo = None 188 | 189 | # For "manual" documents, if this is true, then toplevel headings are parts, 190 | # not chapters. 191 | #latex_use_parts = False 192 | 193 | # If true, show page references after internal links. 194 | #latex_show_pagerefs = False 195 | 196 | # If true, show URL addresses after external links. 197 | #latex_show_urls = False 198 | 199 | # Additional stuff for the LaTeX preamble. 200 | #latex_preamble = '' 201 | 202 | # Documents to append as an appendix to all manuals. 203 | #latex_appendices = [] 204 | 205 | # If false, no module index is generated. 206 | #latex_domain_indices = True 207 | 208 | 209 | # -- Options for manual page output -------------------------------------------- 210 | 211 | # One entry per manual page. List of tuples 212 | # (source start file, name, description, authors, manual section). 213 | man_pages = [ 214 | ('index', 'apollo', u'apollo Documentation', 215 | [u'David Beckingsale'], 1) 216 | ] 217 | -------------------------------------------------------------------------------- /HOWTO.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | This documentation provides brief instructions on how to build and run with Apollo, 4 | and how to build RAJA with Apollo support. 5 | 6 | 7 | ## Building Apollo 8 | Apollo uses cmake and has only optional dependencies on other libraries. Available cmake parameters are: 9 | 10 | `ENABLE_MPI` enables Apollo distributed training over MPI (default: OFF) 11 | 12 | `ENABLE_OpenCV` enables using OpenCV as the ML library backend (default: OFF, Apollo uses its own builtin ML library) 13 | 14 | `ENABLE_CUDA` enables event-based timing of CUDA kernels (default OFF: used for timing async launched CUDA kernels) 15 | 16 | `ENABLE_HIP` enables event-based timing of HIP kernels in Apollo (default OFF: used for timing async launched HIP kernels) 17 | 18 | `BUILD_SHARED_LIBS` builds Apollo as a shared library instead of static (default OFF) 19 | 20 | `ENABLE_JIT_DTREE` enables JIT compilation of decision tree evaluation (default OFF: **experimental**, 21 | available only with Apollo builtin ML Library, i.e., when `ENABLE_OPENCV=OFF`) 22 | 23 | By default all those flags are OFF and without setting them builds a fully working Apollo runtime library 24 | that can time synchronously executing code regions. When asynchronous CUDA/HIP kernels are used it is required 25 | to set `ENABLE_CUDA` or `ENABLE_HIP` to ON. It is recommended to use the builtin ML library instead of OpenCV 26 | (so keep `ENABLE_OPENCV=OFF`) 27 | 28 | Example build commands for HIP async timing: 29 | 30 | ``` 31 | cd 32 | mkdir -p build 33 | pushd build 34 | cmake .. -DENABLE_HIP=on (enables HIP async timing) -DCMAKE_PREFIX_PATH=./install 35 | make -j install 36 | popd 37 | ``` 38 | 39 | 40 | ## Building RAJA 41 | 42 | The current version of Apollo-enabled RAJA is at: 43 | 44 | https://github.com/ggeorgakoudis/RAJA/tree/feature/apollo 45 | 46 | Buiding RAJA with Apollo support requires to provide the following cmake parameters: 47 | 48 | `-DENABLE_APOLLO=ON -DAPOLLO_DIR=/build/install` 49 | 50 | ## Running with Apollo 51 | 52 | ### Instrumentation 53 | 54 | Users must instrument tunable code regions using the Apollo API (TODO documentation) to enable tuning through Apollo. 55 | 56 | Users of Apollo through RAJA avoid most of the instrumentation as it is is implemented internally to RAJA using Apollo multi-policy interfaces. 57 | For tuning, Apollo requires collecting of training data through exploration on available policies and instructing Apollo to _train_ a tuning model 58 | once training data are sufficient. What is sufficient training data is application-specific. There are two ways to instruct Apollo to 59 | train a model: 60 | 61 | 1. Programmatically by calling the `Apollo::train(int epoch)` method in the application source code (encouraged), which will use collected training data 62 | up to that point and create a tuning model through Apollo. 63 | The parameter `epoch` is used for tracing in Apollo, hence it carries no special meaning for the application. 64 | If tracing is not desired setting it always to 0 is recommended. 65 | 66 | #### Example (RAJA) 67 | ``` 68 | ... 69 | using PolicyList = camp::list< 70 | RAJA::hip_exec<64>, 71 | RAJA::hip_exec<256>, 72 | RAJA::hip_exec<1024>>; 73 | 74 | // Get the handle to the apollo runtime 75 | Apollo *apollo = Apollo::instance() 76 | for(int i=1; i<=ITERS; i++) { 77 | ... 78 | RAJA::forall>( 79 | RAJA::RangeSegment(0, test_size), 80 | [=] RAJA_DEVICE (int i) { 81 | a[i] += b[i] * c; 82 | }); 83 | 84 | // Train every 100 iterations. 85 | if(i%100) 86 | apollo->train(0); 87 | ... 88 | } 89 | ``` 90 | 91 | 2. At runtime using the `APOLLO_GLOBAL_TRAIN_PERIOD=<#>` env var that instructs Apollo to train a tuning model every `<#>` tunable region executions. 92 | #### Example 93 | `$ APOLLO_GLOBAL_TRAIN_PERIOD=100 APOLLO_POLICY_MODEL=DecisionTree,explore=RoundRobin,max_depth=4 ` 94 | 95 | This instructs Apollo train every 100 region executions using a DecisionTree model. The next section describes how 96 | to set policy selection models using the `APOLLO_POLICY_MODEL` env var. 97 | 98 | --- 99 | 100 | Apollo uses an env var to set the policy selection model: 101 | 102 | `APOLLO_POLICY_MODEL` 103 | 104 | It sets the policy selection model given as a string of the policy name followed by comma separated key-value pair parameters that specify the model: 105 | 106 | ### Static 107 | Always select the same fixed policy without exploration or tuning 108 | 109 | #### Parameters 110 | `policy=<#>` set the fixed policy number to select, default 0 111 | 112 | #### Example 113 | `$ APOLLO_POLICY_MODEL=Static,policy=1 ` (runs selecting always policy 1) 114 | 115 | ### RoundRobin 116 | Selects policies cyclically 117 | #### Parameters 118 | None 119 | 120 | #### Example 121 | `$ APOLLO_POLICY_MODEL=RoundRobin ` (runs cycling through policies) 122 | 123 | ### Random 124 | Selects policies uniformly randomly 125 | #### Parameters 126 | None 127 | 128 | #### Example 129 | `$ APOLLO_POLICY_MODEL=Random ` (runs selecting policy at random) 130 | 131 | ### DecisionTree 132 | Select policies by training a decision tree classification tuning model 133 | ### Parameters 134 | `explore=(RoundRobin|Random)` set the model used for exploration collecting training data 135 | 136 | `max_depth=<#>` set the maximum depth of created decision trees (default: 2) 137 | 138 | `load` load a previously trained model (see later on Apollo model storing) 139 | #### Example 140 | `$ APOLLO_POLICY_MODEL=DecisionTree,explore=RoundRobin,max_depth=4 ` 141 | (runs using RoundRobin for exploration and trains a DecisionTree model of depth 4) 142 | 143 | ### RandomForest 144 | Select policies using a random forest classification tuning model 145 | 146 | #### Parameters 147 | `explore=(RoundRobin|Random)` set the model used for exploration collecting training data 148 | 149 | `num_tress=<#>` the number of trees in the forest (default: 10) 150 | 151 | `max_depth=<#>` set the maximum depth of created decision trees (default: 2) 152 | 153 | `load` load a previously trained model (see later on Apollo model storing) 154 | 155 | #### Example 156 | `$ APOLLO_POLICY_MODEL=RandomForest,explore=RoundRobin,num_trees=20,max_depth=4 ` 157 | (runs using RoundRobin for exploration and trains a RandomForest model of 20 decision trees each of maximum depth 4) 158 | 159 | ### PolicyNet 160 | Select policies using a reinforced learning policy network model 161 | #### Parameters 162 | `lr=<#.#>` learning rate for the policy network (default: 0.01) 163 | 164 | `beta=<#.#>` reward moving average damping factor (default: 0.5) 165 | 166 | `beta1=<#.#>` Adam optimizer beta1 first moment damping factor (default: 0.5) 167 | 168 | `beta2=<#.#>` Adam optimizer beta2 second moment damping factor (default: 0.9) 169 | 170 | `load` loads a previously trained model (see later on Apollo model storing) 171 | 172 | By default Apollo executes an applications with a Static model always choosing policy 0 so no 173 | exploration or tuning is performed. The `APOLLO_POLICY_MODEL` env var must be set to enable tuning. 174 | An example of overriding that for a DecisionTree tuning model of depth 4 with RoundRobin exploration is: 175 | 176 | `$ APOLLO_POLICY_MODEL=DecisionTree,explore=RoundRobin,max_depth=4 ` 177 | 178 | --- 179 | 180 | ### Storing and loading models 181 | Apollo can save trained models and load them to bootstrap tuned execution without exploration by setting this env var: 182 | 183 | `APOLLO_STORE_MODELS=1` 184 | 185 | Apollo stores model files under the path `.apollo/models` in the current executing directory and will load those models when a tuning policy 186 | (DecisionTree, RandomForest, PolicyNet) is given the parameter `load` through `APOLLO_POLICY_MODEL` and 187 | the application executable is ran from the directory containing the previously stored model files. 188 | 189 | ### Example 190 | (First run: create models) 191 | ``` 192 | $ APOLLO_STORE_MODELS=1 APOLLO_POLICY_MODEL=DecisionTree,explore=RoundRobin,max_depth=4 ` 193 | ``` 194 | (Second run: load previously stored models) 195 | ``` 196 | $ APOLLO_POLICY_MODEL=DecisionTree,load ` 197 | ``` 198 | 199 | --- 200 | 201 | ### Tracing 202 | 203 | Apollo provides a CSV trace of execution (not intended to be enabled for production runs) capturing region execution and timing information setting this env var: 204 | 205 | `APOLLO_TRACE_CSV=1` 206 | 207 | Trace files are store under the path `.apollo/traces` in the current executing directory. 208 | 209 | 210 | -------------------------------------------------------------------------------- /src/connectors/kokkos/include/impl/Kokkos_Profiling_Interface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | //@HEADER 3 | // ************************************************************************ 4 | // 5 | // Kokkos v. 3.0 6 | // Copyright (2020) National Technology & Engineering 7 | // Solutions of Sandia, LLC (NTESS). 8 | // 9 | // Under the terms of Contract DE-NA0003525 with NTESS, 10 | // the U.S. Government retains certain rights in this software. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining 13 | // a copy of this software and associated documentation files (the "Software"), 14 | // to deal in the Software without restriction, including without limitation 15 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | // and/or sell copies of the Software, and to permit persons to whom the 17 | // Software is furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | // DEALINGS IN THE SOFTWARE. 29 | // Questions? Contact Christian R. Trott (crtrott@sandia.gov) 30 | // @HEADER 31 | */ 32 | 33 | #ifndef KOKKOSP_INTERFACE_HPP 34 | #define KOKKOSP_INTERFACE_HPP 35 | 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | // NOTE: in this Kokkos::Profiling block, do not define anything that shouldn't 42 | // exist should Profiling be disabled 43 | 44 | namespace Kokkos { 45 | namespace Tools { 46 | namespace Experimental { 47 | enum struct DeviceType { 48 | Serial, 49 | OpenMP, 50 | Cuda, 51 | HIP, 52 | OpenMPTarget, 53 | HPX, 54 | Threads, 55 | SYCL, 56 | Unknown 57 | }; 58 | 59 | template 60 | struct DeviceTypeTraits; 61 | 62 | constexpr const size_t device_type_bits = 8; 63 | constexpr const size_t instance_bits = 24; 64 | template 65 | inline uint32_t device_id(ExecutionSpace const& space) noexcept { 66 | auto device_id = static_cast(DeviceTypeTraits::id); 67 | return (device_id << instance_bits) + space.impl_instance_id(); 68 | } 69 | } // namespace Experimental 70 | } // namespace Tools 71 | } // end namespace Kokkos 72 | 73 | #if defined(KOKKOS_ENABLE_LIBDL) 74 | // We check at configure time that libdl is available. 75 | #include 76 | #endif 77 | 78 | #include 79 | #include 80 | 81 | namespace Kokkos { 82 | namespace Tools { 83 | 84 | using SpaceHandle = Kokkos_Profiling_SpaceHandle; 85 | 86 | } // namespace Tools 87 | 88 | namespace Tools { 89 | 90 | namespace Experimental { 91 | using EventSet = Kokkos_Profiling_EventSet; 92 | static_assert(sizeof(EventSet) / sizeof(Kokkos_Tools_functionPointer) == 275, 93 | "sizeof EventSet has changed, this is an error on the part of a " 94 | "Kokkos developer"); 95 | static_assert(sizeof(Kokkos_Tools_ToolSettings) / sizeof(bool) == 256, 96 | "sizeof EventSet has changed, this is an error on the part of a " 97 | "Kokkos developer"); 98 | static_assert(sizeof(Kokkos_Tools_ToolProgrammingInterface) / 99 | sizeof(Kokkos_Tools_functionPointer) == 100 | 32, 101 | "sizeof EventSet has changed, this is an error on the part of a " 102 | "Kokkos developer"); 103 | 104 | using toolInvokedFenceFunction = Kokkos_Tools_toolInvokedFenceFunction; 105 | using provideToolProgrammingInterfaceFunction = 106 | Kokkos_Tools_provideToolProgrammingInterfaceFunction; 107 | using requestToolSettingsFunction = Kokkos_Tools_requestToolSettingsFunction; 108 | using ToolSettings = Kokkos_Tools_ToolSettings; 109 | using ToolProgrammingInterface = Kokkos_Tools_ToolProgrammingInterface; 110 | } // namespace Experimental 111 | using initFunction = Kokkos_Profiling_initFunction; 112 | using finalizeFunction = Kokkos_Profiling_finalizeFunction; 113 | using parseArgsFunction = Kokkos_Profiling_parseArgsFunction; 114 | using printHelpFunction = Kokkos_Profiling_printHelpFunction; 115 | using beginFunction = Kokkos_Profiling_beginFunction; 116 | using endFunction = Kokkos_Profiling_endFunction; 117 | using pushFunction = Kokkos_Profiling_pushFunction; 118 | using popFunction = Kokkos_Profiling_popFunction; 119 | using allocateDataFunction = Kokkos_Profiling_allocateDataFunction; 120 | using deallocateDataFunction = Kokkos_Profiling_deallocateDataFunction; 121 | using createProfileSectionFunction = 122 | Kokkos_Profiling_createProfileSectionFunction; 123 | using startProfileSectionFunction = 124 | Kokkos_Profiling_startProfileSectionFunction; 125 | using stopProfileSectionFunction = Kokkos_Profiling_stopProfileSectionFunction; 126 | using destroyProfileSectionFunction = 127 | Kokkos_Profiling_destroyProfileSectionFunction; 128 | using profileEventFunction = Kokkos_Profiling_profileEventFunction; 129 | using beginDeepCopyFunction = Kokkos_Profiling_beginDeepCopyFunction; 130 | using endDeepCopyFunction = Kokkos_Profiling_endDeepCopyFunction; 131 | using beginFenceFunction = Kokkos_Profiling_beginFenceFunction; 132 | using endFenceFunction = Kokkos_Profiling_endFenceFunction; 133 | using dualViewSyncFunction = Kokkos_Profiling_dualViewSyncFunction; 134 | using dualViewModifyFunction = Kokkos_Profiling_dualViewModifyFunction; 135 | using declareMetadataFunction = Kokkos_Profiling_declareMetadataFunction; 136 | 137 | } // namespace Tools 138 | 139 | } // namespace Kokkos 140 | 141 | // Profiling 142 | 143 | namespace Kokkos { 144 | 145 | namespace Profiling { 146 | 147 | /** The Profiling namespace is being renamed to Tools. 148 | * This is reexposing the contents of what used to be the Profiling 149 | * Interface with their original names, to avoid breaking old code 150 | */ 151 | 152 | namespace Experimental { 153 | 154 | using Kokkos::Tools::Experimental::device_id; 155 | using Kokkos::Tools::Experimental::DeviceType; 156 | using Kokkos::Tools::Experimental::DeviceTypeTraits; 157 | 158 | } // namespace Experimental 159 | 160 | using Kokkos::Tools::allocateDataFunction; 161 | using Kokkos::Tools::beginDeepCopyFunction; 162 | using Kokkos::Tools::beginFunction; 163 | using Kokkos::Tools::createProfileSectionFunction; 164 | using Kokkos::Tools::deallocateDataFunction; 165 | using Kokkos::Tools::destroyProfileSectionFunction; 166 | using Kokkos::Tools::endDeepCopyFunction; 167 | using Kokkos::Tools::endFunction; 168 | using Kokkos::Tools::finalizeFunction; 169 | using Kokkos::Tools::initFunction; 170 | using Kokkos::Tools::parseArgsFunction; 171 | using Kokkos::Tools::popFunction; 172 | using Kokkos::Tools::printHelpFunction; 173 | using Kokkos::Tools::profileEventFunction; 174 | using Kokkos::Tools::pushFunction; 175 | using Kokkos::Tools::SpaceHandle; 176 | using Kokkos::Tools::startProfileSectionFunction; 177 | using Kokkos::Tools::stopProfileSectionFunction; 178 | 179 | } // namespace Profiling 180 | } // namespace Kokkos 181 | 182 | // Tuning 183 | 184 | namespace Kokkos { 185 | namespace Tools { 186 | namespace Experimental { 187 | using ValueSet = Kokkos_Tools_ValueSet; 188 | using ValueRange = Kokkos_Tools_ValueRange; 189 | using StatisticalCategory = Kokkos_Tools_VariableInfo_StatisticalCategory; 190 | using ValueType = Kokkos_Tools_VariableInfo_ValueType; 191 | using CandidateValueType = Kokkos_Tools_VariableInfo_CandidateValueType; 192 | using SetOrRange = Kokkos_Tools_VariableInfo_SetOrRange; 193 | using VariableInfo = Kokkos_Tools_VariableInfo; 194 | using OptimizationGoal = Kokkos_Tools_OptimzationGoal; 195 | using TuningString = Kokkos_Tools_Tuning_String; 196 | using VariableValue = Kokkos_Tools_VariableValue; 197 | 198 | using outputTypeDeclarationFunction = 199 | Kokkos_Tools_outputTypeDeclarationFunction; 200 | using inputTypeDeclarationFunction = Kokkos_Tools_inputTypeDeclarationFunction; 201 | using requestValueFunction = Kokkos_Tools_requestValueFunction; 202 | using contextBeginFunction = Kokkos_Tools_contextBeginFunction; 203 | using contextEndFunction = Kokkos_Tools_contextEndFunction; 204 | using optimizationGoalDeclarationFunction = 205 | Kokkos_Tools_optimizationGoalDeclarationFunction; 206 | } // end namespace Experimental 207 | } // end namespace Tools 208 | 209 | } // end namespace Kokkos 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /src/connectors/kokkos/include/impl/Kokkos_Profiling_C_Interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | //@HEADER 3 | // ************************************************************************ 4 | // 5 | // Kokkos v. 3.0 6 | // Copyright (2020) National Technology & Engineering 7 | // Solutions of Sandia, LLC (NTESS). 8 | // 9 | // Under the terms of Contract DE-NA0003525 with NTESS, 10 | // the U.S. Government retains certain rights in this software. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining 13 | // a copy of this software and associated documentation files (the "Software"), 14 | // to deal in the Software without restriction, including without limitation 15 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | // and/or sell copies of the Software, and to permit persons to whom the 17 | // Software is furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | // DEALINGS IN THE SOFTWARE. 29 | // Questions? Contact Christian R. Trott (crtrott@sandia.gov) 30 | // @HEADER 31 | */ 32 | 33 | #ifndef KOKKOS_PROFILING_C_INTERFACE_HPP 34 | #define KOKKOS_PROFILING_C_INTERFACE_HPP 35 | 36 | #ifdef __cplusplus 37 | #include 38 | #include 39 | #else 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | #define KOKKOSP_INTERFACE_VERSION 20210225 46 | 47 | // Profiling 48 | 49 | struct Kokkos_Profiling_KokkosPDeviceInfo { 50 | size_t deviceID; 51 | }; 52 | 53 | struct Kokkos_Profiling_SpaceHandle { 54 | char name[64]; 55 | }; 56 | 57 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 58 | typedef void (*Kokkos_Profiling_initFunction)( 59 | const int, 60 | const uint64_t, 61 | const uint32_t, 62 | struct Kokkos_Profiling_KokkosPDeviceInfo*); 63 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 64 | typedef void (*Kokkos_Profiling_finalizeFunction)(); 65 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 66 | typedef void (*Kokkos_Profiling_parseArgsFunction)(int, char**); 67 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 68 | typedef void (*Kokkos_Profiling_printHelpFunction)(char*); 69 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 70 | typedef void (*Kokkos_Profiling_beginFunction)(const char*, 71 | const uint32_t, 72 | uint64_t*); 73 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 74 | typedef void (*Kokkos_Profiling_endFunction)(uint64_t); 75 | 76 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 77 | typedef void (*Kokkos_Profiling_pushFunction)(const char*); 78 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 79 | typedef void (*Kokkos_Profiling_popFunction)(); 80 | 81 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 82 | typedef void (*Kokkos_Profiling_allocateDataFunction)( 83 | const struct Kokkos_Profiling_SpaceHandle, 84 | const char*, 85 | const void*, 86 | const uint64_t); 87 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 88 | typedef void (*Kokkos_Profiling_deallocateDataFunction)( 89 | const struct Kokkos_Profiling_SpaceHandle, 90 | const char*, 91 | const void*, 92 | const uint64_t); 93 | 94 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 95 | typedef void (*Kokkos_Profiling_createProfileSectionFunction)(const char*, 96 | uint32_t*); 97 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 98 | typedef void (*Kokkos_Profiling_startProfileSectionFunction)(const uint32_t); 99 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 100 | typedef void (*Kokkos_Profiling_stopProfileSectionFunction)(const uint32_t); 101 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 102 | typedef void (*Kokkos_Profiling_destroyProfileSectionFunction)(const uint32_t); 103 | 104 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 105 | typedef void (*Kokkos_Profiling_profileEventFunction)(const char*); 106 | 107 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 108 | typedef void (*Kokkos_Profiling_beginDeepCopyFunction)( 109 | struct Kokkos_Profiling_SpaceHandle, 110 | const char*, 111 | const void*, 112 | struct Kokkos_Profiling_SpaceHandle, 113 | const char*, 114 | const void*, 115 | uint64_t); 116 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 117 | typedef void (*Kokkos_Profiling_endDeepCopyFunction)(); 118 | typedef void (*Kokkos_Profiling_beginFenceFunction)(const char*, 119 | const uint32_t, 120 | uint64_t*); 121 | typedef void (*Kokkos_Profiling_endFenceFunction)(uint64_t); 122 | 123 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 124 | typedef void (*Kokkos_Profiling_dualViewSyncFunction)(const char*, 125 | const void* const, 126 | bool); 127 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 128 | typedef void (*Kokkos_Profiling_dualViewModifyFunction)(const char*, 129 | const void* const, 130 | bool); 131 | 132 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 133 | typedef void (*Kokkos_Profiling_declareMetadataFunction)(const char*, 134 | const char*); 135 | 136 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 137 | typedef void (*Kokkos_Tools_toolInvokedFenceFunction)(const uint32_t); 138 | 139 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 140 | typedef void (*Kokkos_Tools_functionPointer)(); 141 | struct Kokkos_Tools_ToolProgrammingInterface { 142 | Kokkos_Tools_toolInvokedFenceFunction fence; 143 | // allow addition of more actions 144 | Kokkos_Tools_functionPointer padding[31]; 145 | }; 146 | 147 | struct Kokkos_Tools_ToolSettings { 148 | bool requires_global_fencing; 149 | bool padding[255]; 150 | }; 151 | 152 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 153 | typedef void (*Kokkos_Tools_provideToolProgrammingInterfaceFunction)( 154 | const uint32_t, 155 | struct Kokkos_Tools_ToolProgrammingInterface); 156 | // NOLINTNEXTLINE(modernize-use-using): C compatibility 157 | typedef void (*Kokkos_Tools_requestToolSettingsFunction)( 158 | const uint32_t, 159 | struct Kokkos_Tools_ToolSettings*); 160 | 161 | // Tuning 162 | 163 | #define KOKKOS_TOOLS_TUNING_STRING_LENGTH 64 164 | typedef char Kokkos_Tools_Tuning_String[KOKKOS_TOOLS_TUNING_STRING_LENGTH]; 165 | union Kokkos_Tools_VariableValue_ValueUnion { 166 | int64_t int_value; 167 | double double_value; 168 | Kokkos_Tools_Tuning_String string_value; 169 | }; 170 | 171 | union Kokkos_Tools_VariableValue_ValueUnionSet { 172 | int64_t* int_value; 173 | double* double_value; 174 | Kokkos_Tools_Tuning_String* string_value; 175 | }; 176 | 177 | struct Kokkos_Tools_ValueSet { 178 | size_t size; 179 | union Kokkos_Tools_VariableValue_ValueUnionSet values; 180 | }; 181 | 182 | enum Kokkos_Tools_OptimizationType { 183 | Kokkos_Tools_Minimize, 184 | Kokkos_Tools_Maximize 185 | }; 186 | 187 | struct Kokkos_Tools_OptimzationGoal { 188 | size_t type_id; 189 | enum Kokkos_Tools_OptimizationType goal; 190 | }; 191 | 192 | struct Kokkos_Tools_ValueRange { 193 | union Kokkos_Tools_VariableValue_ValueUnion lower; 194 | union Kokkos_Tools_VariableValue_ValueUnion upper; 195 | union Kokkos_Tools_VariableValue_ValueUnion step; 196 | bool openLower; 197 | bool openUpper; 198 | }; 199 | 200 | enum Kokkos_Tools_VariableInfo_ValueType { 201 | kokkos_value_double, 202 | kokkos_value_int64, 203 | kokkos_value_string, 204 | }; 205 | 206 | enum Kokkos_Tools_VariableInfo_StatisticalCategory { 207 | kokkos_value_categorical, // unordered distinct objects 208 | kokkos_value_ordinal, // ordered distinct objects 209 | kokkos_value_interval, // ordered distinct objects for which distance matters 210 | kokkos_value_ratio // ordered distinct objects for which distance matters, 211 | // division matters, and the concept of zero exists 212 | }; 213 | 214 | enum Kokkos_Tools_VariableInfo_CandidateValueType { 215 | kokkos_value_set, // I am one of [2,3,4,5] 216 | kokkos_value_range, // I am somewhere in [2,12) 217 | kokkos_value_unbounded // I am [text/int/float], but we don't know at 218 | // declaration time what values are appropriate. Only 219 | // valid for Context Variables 220 | }; 221 | 222 | union Kokkos_Tools_VariableInfo_SetOrRange { 223 | struct Kokkos_Tools_ValueSet set; 224 | struct Kokkos_Tools_ValueRange range; 225 | }; 226 | 227 | struct Kokkos_Tools_VariableInfo { 228 | enum Kokkos_Tools_VariableInfo_ValueType type; 229 | enum Kokkos_Tools_VariableInfo_StatisticalCategory category; 230 | enum Kokkos_Tools_VariableInfo_CandidateValueType valueQuantity; 231 | union Kokkos_Tools_VariableInfo_SetOrRange candidates; 232 | void* toolProvidedInfo; 233 | }; 234 | 235 | struct Kokkos_Tools_VariableValue { 236 | size_t type_id; 237 | union Kokkos_Tools_VariableValue_ValueUnion value; 238 | struct Kokkos_Tools_VariableInfo* metadata; 239 | }; 240 | 241 | typedef void (*Kokkos_Tools_outputTypeDeclarationFunction)( 242 | const char*, 243 | const size_t, 244 | struct Kokkos_Tools_VariableInfo* info); 245 | typedef void (*Kokkos_Tools_inputTypeDeclarationFunction)( 246 | const char*, 247 | const size_t, 248 | struct Kokkos_Tools_VariableInfo* info); 249 | 250 | typedef void (*Kokkos_Tools_requestValueFunction)( 251 | const size_t, 252 | const size_t, 253 | const struct Kokkos_Tools_VariableValue*, 254 | const size_t count, 255 | struct Kokkos_Tools_VariableValue*); 256 | typedef void (*Kokkos_Tools_contextBeginFunction)(const size_t); 257 | typedef void (*Kokkos_Tools_contextEndFunction)( 258 | const size_t, 259 | struct Kokkos_Tools_VariableValue); 260 | typedef void (*Kokkos_Tools_optimizationGoalDeclarationFunction)( 261 | const size_t, 262 | const struct Kokkos_Tools_OptimzationGoal goal); 263 | 264 | struct Kokkos_Profiling_EventSet { 265 | Kokkos_Profiling_initFunction init; 266 | Kokkos_Profiling_finalizeFunction finalize; 267 | Kokkos_Profiling_parseArgsFunction parse_args; 268 | Kokkos_Profiling_printHelpFunction print_help; 269 | Kokkos_Profiling_beginFunction begin_parallel_for; 270 | Kokkos_Profiling_endFunction end_parallel_for; 271 | Kokkos_Profiling_beginFunction begin_parallel_reduce; 272 | Kokkos_Profiling_endFunction end_parallel_reduce; 273 | Kokkos_Profiling_beginFunction begin_parallel_scan; 274 | Kokkos_Profiling_endFunction end_parallel_scan; 275 | Kokkos_Profiling_pushFunction push_region; 276 | Kokkos_Profiling_popFunction pop_region; 277 | Kokkos_Profiling_allocateDataFunction allocate_data; 278 | Kokkos_Profiling_deallocateDataFunction deallocate_data; 279 | Kokkos_Profiling_createProfileSectionFunction create_profile_section; 280 | Kokkos_Profiling_startProfileSectionFunction start_profile_section; 281 | Kokkos_Profiling_stopProfileSectionFunction stop_profile_section; 282 | Kokkos_Profiling_destroyProfileSectionFunction destroy_profile_section; 283 | Kokkos_Profiling_profileEventFunction profile_event; 284 | Kokkos_Profiling_beginDeepCopyFunction begin_deep_copy; 285 | Kokkos_Profiling_endDeepCopyFunction end_deep_copy; 286 | Kokkos_Profiling_beginFenceFunction begin_fence; 287 | Kokkos_Profiling_endFenceFunction end_fence; 288 | Kokkos_Profiling_dualViewSyncFunction sync_dual_view; 289 | Kokkos_Profiling_dualViewModifyFunction modify_dual_view; 290 | Kokkos_Profiling_declareMetadataFunction declare_metadata; 291 | Kokkos_Tools_provideToolProgrammingInterfaceFunction 292 | provide_tool_programming_interface; 293 | Kokkos_Tools_requestToolSettingsFunction request_tool_settings; 294 | char profiling_padding[9 * sizeof(Kokkos_Tools_functionPointer)]; 295 | Kokkos_Tools_outputTypeDeclarationFunction declare_output_type; 296 | Kokkos_Tools_inputTypeDeclarationFunction declare_input_type; 297 | Kokkos_Tools_requestValueFunction request_output_values; 298 | Kokkos_Tools_contextBeginFunction begin_tuning_context; 299 | Kokkos_Tools_contextEndFunction end_tuning_context; 300 | Kokkos_Tools_optimizationGoalDeclarationFunction declare_optimization_goal; 301 | char padding[232 * 302 | sizeof( 303 | Kokkos_Tools_functionPointer)]; // allows us to add another 304 | // 256 events to the Tools 305 | // interface without 306 | // changing struct layout 307 | }; 308 | 309 | #endif // KOKKOS_PROFILING_C_INTERFACE_HPP 310 | -------------------------------------------------------------------------------- /src/python/analysis/analyze-traces.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import pandas as pd 5 | import time 6 | import numpy as np 7 | import glob 8 | from IPython import embed 9 | 10 | # TODO: retrofit the best policy selection to Apollo 11 | 12 | 13 | def autolabel(ax, rects): 14 | """Attach a text label above each bar in *rects*, displaying its height.""" 15 | for rect in rects: 16 | height = rect.get_height() 17 | ax.annotate('%.2f' % (height), 18 | xy=(rect.get_x() + rect.get_width() / 2, height), 19 | xytext=(0, 3), # 3 points vertical offset 20 | textcoords="offset points", 21 | ha='center', va='bottom') 22 | 23 | 24 | def read_csv(dir, model, csv_map): 25 | globlist = glob.glob('%s/trace*%s-*.csv' % (dir, model)) 26 | nfiles = len(globlist) 27 | for i, f in enumerate(globlist): 28 | print('\r=== Reading %-100s %06d/%06d' % 29 | (f, i+1, nfiles), flush=True, end='') 30 | try: 31 | csv_map[f] = pd.read_csv(f, sep=' ', header=0) 32 | except pd.errors.EmptyDataError: 33 | print('Warning: no data in', f) 34 | 35 | 36 | def compute_execution_time(rank, data, xtime_per_pol, init_model, trained_model=None): 37 | num_regions = 0 38 | xtimes = data.loc[ 39 | (data['rankid'] == rank) & 40 | (data['training'] == init_model) 41 | ]['xtime'] 42 | xtime_init_model = sum(xtimes) 43 | num_regions += len(xtimes.index) 44 | 45 | if trained_model: 46 | xtimes = data.loc[ 47 | (data['rankid'] == rank) & 48 | (data['training'] == trained_model) 49 | ]['xtime'] 50 | xtime_trained_model = sum(xtimes) 51 | num_regions += len(xtimes.index) 52 | else: 53 | xtime_trained_model = 0 54 | 55 | xtime_per_pol[init_model] = (xtime_init_model, xtime_trained_model) 56 | print('len', num_regions, 57 | 'Rank %d %s=%.6f/%s=%.6f xtime %.6f' % 58 | (rank, init_model, xtime_per_pol[init_model][0], trained_model, xtime_per_pol[init_model][1], 59 | xtime_per_pol[init_model][0]+xtime_per_pol[init_model][1])) 60 | 61 | 62 | def compute_speedup(xtime_per_pol, model, min_xtime_static_pol): 63 | print('%s speedup vs defaults (Static,0 / %s): %.3f' % 64 | ( 65 | model, 66 | model, 67 | sum(xtime_per_pol['Static,0'])/sum(xtime_per_pol[model]), 68 | ) 69 | ) 70 | print('%s speedup vs best static (%s / %s): %.3f' % 71 | ( 72 | model, 73 | min_xtime_static_pol, 74 | model, 75 | sum(xtime_per_pol[min_xtime_static_pol]) / 76 | sum(xtime_per_pol[model]), 77 | ) 78 | ) 79 | 80 | 81 | def compute_accuracy(rank, data, opt_data, npolicies, DIFF_PCT, init_model, trained_model): 82 | # Create dataframes indexed by region, idx to match with isin() in opt (avoids index mismatch). 83 | data_region_idx = data.loc[(data['rankid'] == rank) & \ 84 | # (data['training'].str.contains('RoundRobin|DecisionTree', regex=True))] \ 85 | (data['training'].str.contains(trained_model))][['region', 'idx', 'policy', 'xtime']].set_index( \ 86 | ['region', 'idx']).sort_index() 87 | opt_region_idx = opt_data[['policy', 'xtime']] 88 | # print('=== DATA RR ===') 89 | # print(data_rr_region_idx[['policy']][0:10]) 90 | # input('cont') 91 | # print('=== DATA OPT ===') 92 | # print(opt_region_idx[['policy']][0:10]) 93 | # input('cont') 94 | 95 | cond = data_region_idx[['policy']].isin(opt_region_idx[['policy']]) 96 | 97 | nrows = len(cond.index) 98 | nmatch = cond[cond['policy'] == True].count() 99 | print('= %s|%s' % (init_model, trained_model)) 100 | print('Rank %d %s|%s accuracy %.2f%%' % 101 | (rank, init_model, trained_model, (nmatch*100.0)/nrows)) 102 | # input('cont') 103 | 104 | (hist, bins) = np.histogram( 105 | opt_region_idx['policy'], bins=np.arange(npolicies)) 106 | print('Rank %d Opt' % (rank), *list(zip(bins[:-1], hist))) 107 | (hist, bins) = np.histogram( 108 | data_region_idx['policy'], bins=np.arange(npolicies)) 109 | print('Rank %d %s|%s' % (rank, init_model, trained_model), 110 | *list(zip(bins[:-1], hist))) 111 | 112 | # Compute relaxed accuracy +/- 10% of optimal 113 | # Exclude matching policy indices for relaxed accuracy 114 | data_region_idx = data_region_idx[~data_region_idx.index 115 | .isin(cond[cond['policy'] == True].index)] 116 | opt_region_idx = opt_region_idx[~opt_region_idx.index.isin( 117 | cond[cond['policy'] == True].index)] 118 | 119 | if int(nmatch) < nrows: 120 | diff_opt_rr = abs( 121 | opt_region_idx['xtime'] - data_region_idx['xtime'])*100.0 / opt_region_idx['xtime'] 122 | try: 123 | nrelaxed = diff_opt_rr.le(DIFF_PCT).value_counts()[True] 124 | except KeyError: 125 | nrelaxed = 0 126 | # print('le than %.2f%% %d'%( DIFF_PCT, nrelaxed)) 127 | # input('cont') 128 | nrelaxed += nmatch 129 | else: 130 | nrelaxed = nmatch 131 | print('Rank %d %s|%s relaxed accuracy %.2f%% (+/- %.2f%% optimal)' % (rank, init_model, trained_model, 132 | (nrelaxed*100.0)/nrows, DIFF_PCT)) 133 | 134 | print('===') 135 | return (nmatch, nrelaxed, nrows) 136 | 137 | 138 | def main(): 139 | parser = argparse.ArgumentParser( 140 | description='Analyze exhaustive experiments for a program.') 141 | parser.add_argument('--nstatic', type=int, 142 | help='the number of policies to test.', required=True) 143 | parser.add_argument('--nranks', type=int, 144 | help='the number of processes (ranks).', required=True) 145 | parser.add_argument( 146 | '--dir', help='the directory that contains the trace files.', required=True) 147 | parser.add_argument('--plot', help='plot execution times and optimization potential.', 148 | action='store_true', default=False) 149 | parser.add_argument('--plot2', help='plot another set of execution times and optimization potential.', 150 | action='store_true', default=False) 151 | parser.add_argument('--rr', help='include RoundRobin training traces.', 152 | action='store_true', default=False) 153 | parser.add_argument('--random', help='include Random training traces.', 154 | action='store_true', default=False) 155 | parser.add_argument('--load', help='include Load model.', 156 | action='store_true', default=False) 157 | parser.add_argument('--opt', help='include optimal oracle model.', 158 | action='store_true', default=False) 159 | parser.add_argument('--write-opt', help='write optimal policy csv.', 160 | action='store_true', default=False) 161 | args = parser.parse_args() 162 | 163 | if args.plot: 164 | import matplotlib.pyplot as plt 165 | 166 | print('=== Reading csv files...') 167 | data_map = {} 168 | 169 | if args.nstatic > 0: 170 | csv_map = {} 171 | for p in range(0, args.nstatic): 172 | print(f'\n=== Reading model Static,policy={p}') 173 | read_csv(args.dir, 'Static,policy=%d' % (p), csv_map) 174 | data_map['Static'] = pd.concat( 175 | csv_map.values(), ignore_index=True, sort=True) 176 | 177 | if args.rr: 178 | csv_map = {} 179 | read_csv(args.dir, 'RoundRobin', csv_map) 180 | data_map['RoundRobin'] = pd.concat( 181 | csv_map.values(), ignore_index=True, sort=True) 182 | 183 | if args.random: 184 | csv_map = {} 185 | read_csv(args.dir, 'Random', csv_map) 186 | data_map['Random'] = pd.concat( 187 | csv_map.values(), ignore_index=True, sort=True) 188 | 189 | if args.load: 190 | csv_map = {} 191 | read_csv(args.dir, 'Load', csv_map) 192 | data_map['Load'] = pd.concat( 193 | csv_map.values(), ignore_index=True, sort=True) 194 | 195 | if args.opt: 196 | csv_map = {} 197 | read_csv(args.dir, 'Optimal', csv_map) 198 | data_map['Optimal'] = pd.concat( 199 | csv_map.values(), ignore_index=True, sort=True) 200 | 201 | print() 202 | # Compute execution times per rank and per policy. 203 | for rank in range(args.nranks): 204 | xtime_per_pol = {} 205 | for j in range(args.nstatic): 206 | compute_execution_time( 207 | rank, data_map['Static'], xtime_per_pol, 'Static,%d' % (j)) 208 | if args.rr: 209 | compute_execution_time( 210 | rank, data_map['RoundRobin'], xtime_per_pol, 'RoundRobin', 'DecisionTree') 211 | if args.random: 212 | compute_execution_time( 213 | rank, data_map['Random'], xtime_per_pol, 'Random', 'DecisionTree') 214 | if args.load: 215 | compute_execution_time( 216 | rank, data_map['Load'], xtime_per_pol, 'Load') 217 | if args.opt: 218 | compute_execution_time( 219 | rank, data_map['Optimal'], xtime_per_pol, 'Optimal') 220 | 221 | print('=== Computing optimal policy selection...') 222 | t1 = time.perf_counter() 223 | # Find optimal policy selection (fastest way): select by rank and training equals to Static; 224 | # sort by xtime; 225 | # drop_duplicates grouped by region, idx to keep minimum; 226 | # set index to (region, idx) as the unique identifier 227 | # sort by index for easy visualization and comparison 228 | 229 | # &(data_map['Static']['training'].str.contains('Static'))]\ 230 | opt = data_map['Static'].loc[(data_map['Static']['rankid'] == rank)]\ 231 | .sort_values(by=['xtime'])\ 232 | .drop_duplicates(['region', 'idx'], keep='first')\ 233 | .set_index(['region', 'idx'])\ 234 | .sort_index() 235 | t2 = time.perf_counter() 236 | # with open('opt.txt', 'w') as f: 237 | # print('=========== OPT =============\n', opt.to_string(), '\n=============================', 238 | # file=f) 239 | # NOTE: This assertion does not hold if regions do not have the same number of policies. 240 | # assert len(opt.index) == len( 241 | # data_map['Static'].index)/args.nstatic, 'Data error' 242 | 243 | if args.write_opt: 244 | print('=== Writing out optimal policy selection...') 245 | index_set = set(opt.index.get_level_values(0)) 246 | for region in index_set: 247 | opt_policies = [str(x) for x in opt.loc[region, 'policy']] 248 | with open('opt-%s-rank-%s.txt' % (region, rank), 'w') as f: 249 | f.write(','.join(opt_policies)) 250 | 251 | # print('opt-rank-%d time %.6f s' % (i, t2-t1)) 252 | print('opt-rank-%d xtime %.6f' % (rank, sum(opt['xtime']))) 253 | min_xtime_static_pol = min( 254 | {k: v for k, v in xtime_per_pol.items() if 'Static' in k}, key=xtime_per_pol.get) 255 | 256 | # Create as a tuple to match (init_model, trained_model) tuples of actual policies. 257 | xtime_per_pol['Opt'] = (sum(opt['xtime']), 0) 258 | compute_speedup(xtime_per_pol, 'Opt', min_xtime_static_pol) 259 | 260 | if args.rr: 261 | compute_speedup(xtime_per_pol, 'RoundRobin', min_xtime_static_pol) 262 | if args.random: 263 | compute_speedup(xtime_per_pol, 'Random', min_xtime_static_pol) 264 | 265 | print('=== Compute accuracy...') 266 | 267 | accuracy = {} 268 | DIFF_PCT = 10.0 269 | if args.rr: 270 | accuracy['RoundRobin'] =\ 271 | compute_accuracy( 272 | rank, data_map['RoundRobin'], opt, args.nstatic+1, DIFF_PCT, 'RoundRobin', 'DecisionTree') 273 | if args.random: 274 | accuracy['Random'] =\ 275 | compute_accuracy( 276 | rank, data_map['Random'], opt, args.nstatic+1, DIFF_PCT, 'Random', 'DecisionTree') 277 | if args.load: 278 | accuracy['Load'] =\ 279 | compute_accuracy( 280 | rank, data_map['Load'], opt, args.nstatic+1, DIFF_PCT, 'Load', 'Load') 281 | if args.opt: 282 | accuracy['Optimal'] =\ 283 | compute_accuracy( 284 | rank, data_map['Optimal'], opt, args.nstatic+1, DIFF_PCT, 'Optimal', 'Optimal') 285 | 286 | if args.plot: 287 | fig, ax = plt.subplots(figsize=(10, 6)) 288 | plt.title(args.dir) 289 | plt.ylabel('Execution time (s)') 290 | plt.xlabel('Policy') 291 | rect = ax.bar(np.arange(len(xtime_per_pol)), 292 | [sum(v) for v in xtime_per_pol.values()]) 293 | plt.xticks(np.arange(len(xtime_per_pol)), 294 | xtime_per_pol.keys(), rotation=-90) 295 | textstr = '\n'.join(( 296 | r'Speedup (default) Static,0 / Opt = %.2f' % ( 297 | sum(xtime_per_pol['Static,0'])/sum(xtime_per_pol['Opt'])), 298 | r'Speedup (best) %s / Opt = %.2f' % (min_xtime_static_pol, 299 | sum(xtime_per_pol[min_xtime_static_pol])/sum(xtime_per_pol['Opt'])))) 300 | accuracy_print = [ 301 | r'%s Accuracy strict = %.2f%%|relaxed (+/- %.2f%%) %.2f%%' % 302 | (k, (v[0]*100.0)/v[2], DIFF_PCT, (v[1]*100.0)/v[2]) 303 | for k, v in accuracy.items() 304 | ] 305 | textstr = '\n'.join(accuracy_print) 306 | props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) 307 | ax.text(0.5, 0.95, textstr, transform=ax.transAxes, fontsize=10, 308 | verticalalignment='top', bbox=props) 309 | autolabel(ax, rect) 310 | plt.tight_layout() 311 | plt.savefig(f'analysis-{args.dir}.pdf') 312 | 313 | if args.plot2: 314 | df = data_map['Static'] 315 | for region in df.region.unique(): 316 | print(f'Plot {region}...') 317 | ddf = df[df.region == region].dropna(axis=1) 318 | # TODO: better way for finding features. 319 | features = [v for v in ddf.columns if v.startswith('f')] 320 | piv = pd.pivot_table( 321 | ddf, values='xtime', index=features, columns='training', aggfunc='mean') 322 | ax = piv.plot.bar() 323 | ax.set_ylabel('Time (s)') 324 | ax.set_xlabel('features') 325 | plt.tight_layout() 326 | plt.savefig(f'{region}.pdf') 327 | plt.close() 328 | # groups = ddf.groupby(features) 329 | # fig, axs = plt.subplots(ncol=len(groups)) 330 | # for i, name, group in enumerate(groups): 331 | # print('name', name) 332 | # m = group.groupby('training').xtime.mean() 333 | # ax 334 | # print(m) 335 | # embed() 336 | # input('k') 337 | 338 | 339 | if __name__ == "__main__": 340 | main() 341 | --------------------------------------------------------------------------------