Skip to content

Commit

Permalink
[service] Add a CompilationSession abstract base class.
Browse files Browse the repository at this point in the history
The CompilationSession class encapsulates an incremental compilation
session.

This is the first in a series of patches that separates the RPC server
from the compilation session.

Issue facebookresearch#254.
  • Loading branch information
ChrisCummins committed May 11, 2021
1 parent 77d28bc commit efa8dc0
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 1 deletion.
23 changes: 23 additions & 0 deletions compiler_gym/service/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down
26 changes: 26 additions & 0 deletions compiler_gym/service/CompilationSession.cc
Original file line number Diff line number Diff line change
@@ -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 actionHadNoEffect, bool& endOfEpisode,
std::optional<ActionSpace>& newActionSpace) {
return Status::OK;
}

CompilationSession::CompilationSession(const boost::filesystem::path& workingDirectory)
: workingDirectory_(workingDirectory) {}

} // namespace compiler_gym
84 changes: 84 additions & 0 deletions compiler_gym/service/CompilationSession.h
Original file line number Diff line number Diff line change
@@ -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 <grpcpp/grpcpp.h>

#include <vector>

#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<MyCompilationSession>();
// }
//
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<ActionSpace> getActionSpaces() const = 0;

// A list of feature vectors that this compiler provides.
virtual std::vector<ObservationSpace> 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<ActionSpace>& 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<ActionSpace>& 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
2 changes: 2 additions & 0 deletions compiler_gym/service/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -15,6 +16,7 @@

__all__ = [
"CompilerGymServiceConnection",
"CompilationSession",
"ConnectionOpts",
"ServiceError",
"ServiceInitError",
Expand Down
90 changes: 90 additions & 0 deletions compiler_gym/service/compilation_session.py
Original file line number Diff line number Diff line change
@@ -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
<compiler_gym.service.runtime.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")
6 changes: 6 additions & 0 deletions docs/source/compiler_gym/service.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------------------

Expand Down
2 changes: 1 addition & 1 deletion requirements_pre_commit.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
black==19.10b0
isort==4.3.21
pre-commit>=2.9.0
pre-commit>=2.12.1

0 comments on commit efa8dc0

Please sign in to comment.