diff --git a/compiler_gym/service/BUILD b/compiler_gym/service/BUILD index bdddc4fbaa..280d508ebf 100644 --- a/compiler_gym/service/BUILD +++ b/compiler_gym/service/BUILD @@ -3,17 +3,40 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. load("@rules_python//python:defs.bzl", "py_library") +load("@rules_cc//cc:defs.bzl", "cc_library") py_library( name = "service", srcs = ["__init__.py"], visibility = ["//visibility:public"], deps = [ + ":compilation_session", ":connection", "//compiler_gym/service/proto", ], ) +py_library( + name = "compilation_session", + srcs = ["compilation_session.py"], + visibility = ["//visibility:public"], + deps = [ + "//compiler_gym/service/proto", + ], +) + +cc_library( + name = "CompilationSession", + srcs = ["CompilationSession.cc"], + hdrs = ["CompilationSession.h"], + visibility = ["//visibility:public"], + deps = [ + "//compiler_gym/service/proto:compiler_gym_service_cc", + "@boost//:filesystem", + "@com_github_grpc_grpc//:grpc++", + ], +) + py_library( name = "connection", srcs = ["connection.py"], diff --git a/compiler_gym/service/CompilationSession.cc b/compiler_gym/service/CompilationSession.cc new file mode 100644 index 0000000000..3683f1c807 --- /dev/null +++ b/compiler_gym/service/CompilationSession.cc @@ -0,0 +1,26 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. +#include "compiler_gym/service/CompilationSession.h" + +using grpc::Status; +using grpc::StatusCode; + +namespace compiler_gym { + +std::string CompilationSession::getCompilerVersion() const { return ""; } + +Status CompilationSession::init(CompilationSession& other) { + return Status(StatusCode::UNIMPLEMENTED, "CompilationSession::init() not implemented"); +} + +Status CompilationSession::endOfStep(bool& endOfEpisode, + std::optional& newActionSpace) { + return Status::OK; +} + +CompilationSession::CompilationSession(const boost::filesystem::path& workingDirectory) + : workingDirectory_(workingDirectory) {} + +} // namespace compiler_gym diff --git a/compiler_gym/service/CompilationSession.h b/compiler_gym/service/CompilationSession.h new file mode 100644 index 0000000000..218fd7c04d --- /dev/null +++ b/compiler_gym/service/CompilationSession.h @@ -0,0 +1,84 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. +#pragma once + +#include + +#include + +#include "boost/filesystem.hpp" +#include "compiler_gym/service/proto/compiler_gym_service.pb.h" + +namespace compiler_gym { + +// Base class for encapsulating an incremental compilation session. +// +// To add support for a new compiler, subclass from this base and provide +// implementations of the abstract methods, then call +// createAndRunCompilationService() and parametrize it with your class type: +// +// #include "compiler_gym/service/CompilationSession.h" +// #include "compiler_gym/service/runtime/Runtime.h" +// +// using namespace compiler_gym; +// +// class MyCompilationSession final : public CompilationSession { ... } +// +// int main(int argc, char** argv) { +// runtime::createAndRunCompilationService(); +// } +// +class CompilationSession { + public: + // Get the compiler version. + virtual std::string getCompilerVersion() const; + + // A list of action spaces describing the capabilities of the compiler. + virtual std::vector getActionSpaces() const = 0; + + // A list of feature vectors that this compiler provides. + virtual std::vector getObservationSpaces() const = 0; + + // Start a CompilationSession. This will be called after construction and + // before applyAction() or computeObservation(). This will only be called + // once. + [[nodiscard]] virtual grpc::Status init(const ActionSpace& actionSpace, + const Benchmark& benchmark) = 0; + + // Initialize the state from another CompilerSession. This will be called + // after construction and before applyAction() or computeObservation(). This + // will only be called once. + [[nodiscard]] virtual grpc::Status init(CompilationSession& other); + + // Apply an action. + [[nodiscard]] virtual grpc::Status applyAction(const Action& action, bool& endOfEpisode, + std::optional& newActionSpace, + bool& actionHadNoEffect) = 0; + + // Compute an observation. + [[nodiscard]] virtual grpc::Status computeObservation(const ObservationSpace& observationSpace, + Observation& observation) = 0; + + // Optional. This will be called after all applyAction() and + // computeObservation() in a step. Use this method if you would like to + // perform post-transform validation of compiler state. + [[nodiscard]] virtual grpc::Status endOfStep(bool actionHadNoEffect, bool& endOfEpisode, + std::optional& newActionSpace); + + protected: + // Get the working directory, which is a local filesystem directory that this + // CompilationSession can use to store temporary files such as build + // artifacts. + inline const boost::filesystem::path& workingDirectory() { return workingDirectory_; } + + CompilationSession(const boost::filesystem::path& workingDirectory); + + virtual ~CompilationSession() = default; + + private: + const boost::filesystem::path workingDirectory_; +}; + +} // namespace compiler_gym diff --git a/compiler_gym/service/__init__.py b/compiler_gym/service/__init__.py index 9e60c7cedd..baa8c8ea89 100644 --- a/compiler_gym/service/__init__.py +++ b/compiler_gym/service/__init__.py @@ -2,6 +2,7 @@ # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +from compiler_gym.service.compilation_session import CompilationSession from compiler_gym.service.connection import ( CompilerGymServiceConnection, ConnectionOpts, @@ -15,6 +16,7 @@ __all__ = [ "CompilerGymServiceConnection", + "CompilationSession", "ConnectionOpts", "ServiceError", "ServiceInitError", diff --git a/compiler_gym/service/compilation_session.py b/compiler_gym/service/compilation_session.py new file mode 100644 index 0000000000..20c2f76324 --- /dev/null +++ b/compiler_gym/service/compilation_session.py @@ -0,0 +1,90 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +from pathlib import Path +from typing import List, Optional, Tuple + +from compiler_gym.service.proto import ( + Action, + ActionSpace, + Benchmark, + Observation, + ObservationSpace, +) + + +class CompilationSession: + """Base class for encapsulating an incremental compilation session. + + To add support for a new compiler, subclass from this base and provide + implementations of the abstract methods, then call + :func:`create_and_run_compiler_service + ` and pass in + your class type: + + .. code-block:: python + + from compiler_gym.service import CompilationSession + from compiler_gym.service import runtime + + class MyCompilationSession(CompilationSession): + ... + + if __name__ == "__main__": + runtime.create_and_run_compiler_service(MyCompilationSession) + """ + + compiler_version: str = "" + """The compiler version.""" + + action_spaces: List[ActionSpace] = [] + """A list of action spaces describing the capabilities of the compiler.""" + + observation_spaces: List[ObservationSpace] = [] + """A list of feature vectors that this compiler provides.""" + + def __init__( + self, working_dir: Path, action_space: ActionSpace, benchmark: Benchmark + ): + """Start a CompilationSession. + + Subclasses should initialize the parent class first. + + :param working_dir: A directory on the local filesystem that can be used + to store temporary files such as build artifacts. + + :param action_space: The action space to use. + + :param benchmark: The benchmark to use. + """ + del action_space # Subclasses must use this. + del benchmark # Subclasses must use this. + self.working_dir = working_dir + + def apply_action(self, action: Action) -> Tuple[bool, Optional[ActionSpace], bool]: + """Apply an action. + + :param action: The action to apply. + + :return: A tuple: :code:`(end_of_session, new_action_space, + action_had_no_effect)`. + """ + raise NotImplementedError + + def get_observation(self, observation_space: ObservationSpace) -> Observation: + """Compute an observation. + + :param observation_space: The observation space. + + :return: An observation. + """ + raise NotImplementedError + + def fork(self) -> "CompilationSession": + """Optional. Create a copy of current session state. + + :return: A new CopmilationSession with the same state. + """ + # No need to override this if you are not adding support to fork(). + raise NotImplementedError("CompilationSession.fork() not supported") diff --git a/docs/source/compiler_gym/service.rst b/docs/source/compiler_gym/service.rst index 41271dd32b..ac7979f751 100644 --- a/docs/source/compiler_gym/service.rst +++ b/docs/source/compiler_gym/service.rst @@ -13,6 +13,12 @@ client and service is managed by the :class:`CompilerGymServiceConnection .. contents:: Document contents: :local: +.. autoclass:: CompilationSession + :members: + + .. automethod:: __init__ + + The connection object --------------------- diff --git a/requirements_pre_commit.txt b/requirements_pre_commit.txt index 9edeadf335..d3fbab6b5d 100644 --- a/requirements_pre_commit.txt +++ b/requirements_pre_commit.txt @@ -1,3 +1,3 @@ black==19.10b0 isort==4.3.21 -pre-commit>=2.9.0 +pre-commit>=2.12.1