compiler_gym.envs¶
The CompilerEnv
environment
is a drop-in replacement for the basic gym.Env
class, with
extended functionality for compilers. Some compiler services may further
extend the functionality by subclassing from
CompilerEnv
. The following
environment classes are available:
Environment Classes:
CompilerEnv¶
- class compiler_gym.envs.CompilerEnv(service: Union[str, pathlib.Path], rewards: Optional[List[compiler_gym.spaces.reward.Reward]] = None, datasets: Optional[Iterable[compiler_gym.datasets.dataset.Dataset]] = None, benchmark: Optional[Union[str, compiler_gym.datasets.benchmark.Benchmark]] = None, observation_space: Optional[Union[str, compiler_gym.views.observation_space_spec.ObservationSpaceSpec]] = None, reward_space: Optional[Union[str, compiler_gym.spaces.reward.Reward]] = None, action_space: Optional[str] = None, connection_settings: Optional[compiler_gym.service.connection.ConnectionOpts] = None, service_connection: Optional[compiler_gym.service.connection.CompilerGymServiceConnection] = None, logger: Optional[logging.Logger] = None)[source]¶
An OpenAI gym environment for compiler optimizations.
The easiest way to create a CompilerGym environment is to call
gym.make()
on one of the registered environments:>>> env = gym.make("llvm-v0")
See
compiler_gym.COMPILER_GYM_ENVS
for a list of registered environment names.Alternatively, an environment can be constructed directly, such as by connecting to a running compiler service at
localhost:8080
(see this document for more details):>>> env = CompilerEnv( ... service="localhost:8080", ... observation_space="features", ... reward_space="runtime", ... rewards=[env_reward_spaces], ... )
Once constructed, an environment can be used in exactly the same way as a regular
gym.Env
, e.g.>>> observation = env.reset() >>> cumulative_reward = 0 >>> for i in range(100): >>> action = env.action_space.sample() >>> observation, reward, done, info = env.step(action) >>> cumulative_reward += reward >>> if done: >>> break >>> print(f"Reward after {i} steps: {cumulative_reward}") Reward after 100 steps: -0.32123
- Variables
service (compiler_gym.service.CompilerGymServiceConnection) – A connection to the underlying compiler service.
logger (logging.Logger) – A Logger instance used by the environment for communicating info and warnings.
action_spaces (List[str]) – A list of supported action space names.
actions (List[int]) – The list of actions that have been performed since the previous call to
reset()
.reward_range (Tuple[float, float]) – A tuple indicating the range of reward values. Default range is (-inf, +inf).
observation (compiler_gym.views.ObservationView) – A view of the available observation spaces that permits on-demand computation of observations.
reward (compiler_gym.views.RewardView) – A view of the available reward spaces that permits on-demand computation of rewards.
episode_reward (float) – If
CompilerEnv.reward_space
is set, this value is the sum of all rewards for the current episode.
- __init__(service: Union[str, pathlib.Path], rewards: Optional[List[compiler_gym.spaces.reward.Reward]] = None, datasets: Optional[Iterable[compiler_gym.datasets.dataset.Dataset]] = None, benchmark: Optional[Union[str, compiler_gym.datasets.benchmark.Benchmark]] = None, observation_space: Optional[Union[str, compiler_gym.views.observation_space_spec.ObservationSpaceSpec]] = None, reward_space: Optional[Union[str, compiler_gym.spaces.reward.Reward]] = None, action_space: Optional[str] = None, connection_settings: Optional[compiler_gym.service.connection.ConnectionOpts] = None, service_connection: Optional[compiler_gym.service.connection.CompilerGymServiceConnection] = None, logger: Optional[logging.Logger] = None)[source]¶
Construct and initialize a CompilerGym service environment.
In normal use you should use
gym.make(...)
rather than calling the constructor directly.- Parameters
service – The hostname and port of a service that implements the CompilerGym service interface, or the path of a binary file which provides the CompilerGym service interface when executed. See compiler_gym.service for details.
rewards – The reward spaces that this environment supports. Rewards are typically calculated based on observations generated by the service. See
Reward
for details.benchmark – The benchmark to use for this environment. Either a URI string, or a
Benchmark
instance. If not provided, the first benchmark as returned bynext(env.datasets.benchmarks())
will be used as the default.observation_space – Compute and return observations at each
step()
from this space. Accepts a string name or anObservationSpaceSpec
. If not provided,step()
returnsNone
for the observation value. Can be set later usingenv.observation_space
. For available spaces, seeenv.observation.spaces
.reward_space – Compute and return reward at each
step()
from this space. Accepts a string name or aReward
. If not provided,step()
returnsNone
for the reward value. Can be set later usingenv.reward_space
. For available spaces, seeenv.reward.spaces
.action_space – The name of the action space to use. If not specified, the default action space for this compiler is used.
connection_settings – The settings used to establish a connection with the remote service.
service_connection – An existing compiler gym service connection to use.
logger – The logger to use for this environment. If not provided, a
compiler_gym.envs
logger is used and assigned the verbosity returned byget_logging_level()
.
- Raises
FileNotFoundError – If service is a path to a file that is not found.
TimeoutError – If the compiler service fails to initialize within the parameters provided in
connection_settings
.
- property action_space: compiler_gym.spaces.named_discrete.NamedDiscrete¶
The current action space.
- Getter
Get the current action space.
- Setter
Set the action space to use. Must be an entry in
action_spaces
. IfNone
, the default action space is selected.
- apply(state: compiler_gym.compiler_env_state.CompilerEnvState) → None[source]¶
Replay this state on the given an environment.
- Parameters
env – A
CompilerEnv
instance.- Raises
ValueError – If this state cannot be applied.
- property available_datasets: Dict[str, compiler_gym.datasets.dataset.Dataset]¶
A dictionary of datasets.
Deprecated since version 0.1.8: Use
env.datasets.datasets()
instead. More information.
- property benchmark: compiler_gym.datasets.benchmark.Benchmark¶
Get or set the benchmark to use.
- Getter
Get
Benchmark
that is currently in use.- Setter
Set the benchmark to use. Either a
Benchmark
instance, or the URI of a benchmark as inenv.datasets.benchmark_uris()
.
Note
Setting a new benchmark has no effect until
env.reset()
is called.
- property benchmarks: Iterable[str]¶
Enumerate a (possible unbounded) list of available benchmarks.
Deprecated since version 0.1.8: Use
env.datasets.benchmarks()
instead. More information.
- close()[source]¶
Close the environment.
Once closed,
reset()
must be called before the environment is used again.Note
Internally, CompilerGym environments may launch subprocesses and use temporary files to communicate between the environment and the underlying compiler (see compiler_gym.service for details). This means it is important to call
env.close()
after use to free up resources and prevent orphan subprocesses or files. We recommend using thewith
-statement pattern for creating environments:>>> with gym.make("llvm-autophase-ic-v0") as env: ... env.reset() ... # use env how you like
This removes the need to call
env.close()
yourself.
- commandline() → str[source]¶
Interface for
CompilerEnv
subclasses to provide an equivalent commandline invocation to the current environment state.See also
commandline_to_actions()
.Calling this method on a
CompilerEnv
instance raisesNotImplementedError
.- Returns
A string commandline invocation.
- commandline_to_actions(commandline: str) → List[int][source]¶
Interface for
CompilerEnv
subclasses to convert from a commandline invocation to a sequence of actions.See also
commandline()
.Calling this method on a
CompilerEnv
instance raisesNotImplementedError
.- Returns
A list of actions.
- property compiler_version: str¶
The version string of the underlying compiler that this service supports.
- property episode_walltime: float¶
Return the amount of time in seconds since the last call to
reset()
.
- fork() → compiler_gym.envs.compiler_env.CompilerEnv[source]¶
Fork a new environment with exactly the same state.
This creates a duplicate environment instance with the current state. The new environment is entirely independently of the source environment. The user must call
close()
on the original and new environments.If not already in an episode,
reset()
is called.Example usage:
>>> env = gym.make("llvm-v0") >>> env.reset() # ... use env >>> new_env = env.fork() >>> new_env.state == env.state True >>> new_env.step(1) == env.step(1) True
- Returns
A new environment instance.
- get_benchmark_validation_callback() → Optional[Callable[[compiler_gym.envs.compiler_env.CompilerEnv], Iterable[compiler_gym.validation_error.ValidationError]]][source]¶
Return a callback that validates benchmark semantics, if available.
Deprecated since version 0.1.8: Use
env.validate()
instead. More information.
- property in_episode: bool¶
Whether the service is ready for
step()
to be called, i.e.reset()
has been called andclose()
has not.- Returns
True
if in an episode, elseFalse
.
- property observation_space: Optional[gym.spaces.space.Space]¶
The observation space that is used to return an observation value in
step()
.- Getter
Returns the underlying observation space, or
None
if not set.- Setter
Set the default observation space.
- raw_step(actions: Iterable[int], observations: Iterable[compiler_gym.views.observation_space_spec.ObservationSpaceSpec], rewards: Iterable[compiler_gym.spaces.reward.Reward]) → Tuple[Optional[Union[compiler_gym.util.gym_type_hints.ObservationType, List[compiler_gym.util.gym_type_hints.ObservationType]]], Optional[Union[float, List[float]]], bool, Dict[str, Any]][source]¶
Take a step.
- Parameters
actions – A list of actions to be applied.
observations – A list of observations spaces to compute observations from. These are evaluated after the actions are applied.
rewards – A list of reward spaces to compute rewards from. These are evaluated after the actions are applied.
- Returns
A tuple of observations, rewards, done, and info. Observations and rewards are lists.
- Raises
SessionNotFound – If
reset()
has not been called.
Warning
Prefer
step()
toraw_step()
.step()
has equivalent functionality, and is less likely to change in the future.
- register_dataset(dataset: compiler_gym.datasets.dataset.Dataset) → bool[source]¶
Register a new dataset.
Example usage:
>>> my_dataset = Dataset(name="my-dataset-v0", ...) >>> env = gym.make("llvm-v0") >>> env.register_dataset(my_dataset) >>> env.benchmark = "my-dataset-v0/1"
- param dataset
A
Dataset
instance describing the new dataset.- return
True
if the dataset was added, elseFalse
.- raises ValueError
If a dataset with this name is already registered.
Deprecated since version 0.1.8: Use
env.datasets.add()
instead. More information.
- render(mode='human') → Optional[str][source]¶
Render the environment.
CompilerEnv instances support two render modes: “human”, which prints the current environment state to the terminal and return nothing; and “ansi”, which returns a string representation of the current environment state.
- Parameters
mode – The render mode to use.
- Raises
TypeError – If a default observation space is not set, or if the requested render mode does not exist.
- require_dataset(dataset: Union[str, compiler_gym.datasets.dataset.Dataset]) → bool[source]¶
Deprecated function for managing datasets.
Datasets are now installed automatically. See
env.datasets
.- param dataset
The name of the dataset to download, the URL of the dataset, or a
Dataset
instance.- return
True
if the dataset was downloaded, orFalse
if the dataset was already available.
Deprecated since version 0.1.8: Use
env.datasets.require()
instead. More information.
- require_datasets(datasets: List[Union[str, compiler_gym.datasets.dataset.Dataset]]) → bool[source]¶
Deprecated function for managing datasets.
Datasets are now installed automatically. See
env.datasets
.- param datasets
A list of datasets to require. Each dataset is the name of an available dataset, the URL of a dataset to download, or a
Dataset
instance.- return
True
if one or more datasets were downloaded, orFalse
if all datasets were already available.
Deprecated since version 0.1.8: Datasets are now installed automatically, there is no need to call
require()
. More information.
- reset(benchmark: Optional[Union[str, compiler_gym.datasets.benchmark.Benchmark]] = None, action_space: Optional[str] = None, retry_count: int = 0) → Optional[compiler_gym.util.gym_type_hints.ObservationType][source]¶
Reset the environment state.
This method must be called before
step()
.- Parameters
benchmark – The name of the benchmark to use. If provided, it overrides any value that was set during
__init__()
, and becomes subsequent calls toreset()
will use this benchmark. If no benchmark is provided, and no benchmark was provided to__init___()
, the service will randomly select a benchmark to use.action_space – The name of the action space to use. If provided, it overrides any value that set during
__init__()
, and subsequent calls toreset()
will use this action space. If no action space is provided, the default action space is used.
- Returns
The initial observation.
- Raises
BenchmarkInitError – If the benchmark is invalid. In this case, another benchmark must be used.
TypeError – If no benchmark has been set, and the environment does not have a default benchmark to select from.
- property reward_space: Optional[compiler_gym.spaces.reward.Reward]¶
The default reward space that is used to return a reward value from
step()
.- Getter
Returns a
Reward
, orNone
if not set.- Setter
Set the default reward space.
- send_param(key: str, value: str) → str[source]¶
Send a single <key, value> parameter to the compiler service.
See
send_params()
for more information.- Parameters
key – The parameter key.
value – The parameter value.
- Returns
The response from the compiler service.
- Raises
SessionNotFound – If called before
reset()
.
- send_params(*params: Iterable[Tuple[str, str]]) → List[str][source]¶
Send a list of <key, value> parameters to the compiler service.
This provides a mechanism to send messages to the backend compilation session in a way that doesn’t conform to the normal communication pattern. This can be useful for things like configuring runtime debugging settings, or applying “meta actions” to the compiler that are not exposed in the compiler’s action space. Consult the documentation for a specific compiler service to see what parameters, if any, are supported.
Must have called
reset()
first.- Parameters
params – A list of parameters, where each parameter is a
(key, value)
tuple.- Returns
A list of string responses, one per parameter.
- Raises
SessionNotFound – If called before
reset()
.
- property state: compiler_gym.compiler_env_state.CompilerEnvState¶
The tuple representation of the current environment state.
- step(action: Union[int, Iterable[int]], observations: Optional[Iterable[Union[str, compiler_gym.views.observation_space_spec.ObservationSpaceSpec]]] = None, rewards: Optional[Iterable[Union[str, compiler_gym.spaces.reward.Reward]]] = None) → Tuple[Optional[Union[compiler_gym.util.gym_type_hints.ObservationType, List[compiler_gym.util.gym_type_hints.ObservationType]]], Optional[Union[float, List[float]]], bool, Dict[str, Any]][source]¶
Take a step.
- Parameters
action – An action, or a sequence of actions. When multiple actions are provided the observation and reward are returned after running all of the actions.
observations – A list of observation spaces to compute observations from. If provided, this changes the
observation
element of the return tuple to be a list of observations from the requested spaces. The defaultenv.observation_space
is not returned.rewards – A list of reward spaces to compute rewards from. If provided, this changes the
reward
element of the return tuple to be a list of rewards from the requested spaces. The defaultenv.reward_space
is not returned.
- Returns
A tuple of observation, reward, done, and info. Observation and reward are None if default observation/reward is not set.
- Raises
SessionNotFound – If
reset()
has not been called.
- validate(state: Optional[compiler_gym.compiler_env_state.CompilerEnvState] = None) → compiler_gym.validation_result.ValidationResult[source]¶
Validate an environment’s state.
- Parameters
state – A state to environment. If not provided, the current state is validated.
- Returns
- property version: str¶
The version string of the compiler service.
- property versions: compiler_gym.service.proto.compiler_gym_service_pb2.GetVersionReply¶
Get the version numbers from the compiler service.
LlvmEnv¶
- class compiler_gym.envs.LlvmEnv(*args, benchmark: Optional[Union[str, compiler_gym.datasets.benchmark.Benchmark]] = None, datasets_site_path: Optional[pathlib.Path] = None, **kwargs)[source]¶
A specialized CompilerEnv for LLVM.
This extends the default
CompilerEnv
environment, adding extra LLVM functionality. Specifically, the actions use theCommandlineFlag
space, which is a type ofDiscrete
space that provides additional documentation about each action, and theLlvmEnv.commandline()
method can be used to produce an equivalent LLVM opt invocation for the current environment state.- commandline(textformat: bool = False) → str[source]¶
Returns an LLVM
opt
command line invocation for the current environment state.- Parameters
textformat – Whether to generate a command line that processes text-format LLVM-IR or bitcode (the default).
- Returns
A command line string.
- commandline_to_actions(commandline: str) → List[int][source]¶
Returns a list of actions from the given command line.
- Parameters
commandline – A command line invocation, as generated by
env.commandline()
.- Returns
A list of actions.
- Raises
ValueError – In case the command line string is malformed.
- property ir: str¶
Print the LLVM-IR of the program in its current state.
Alias for
env.observation["Ir"]
.- Returns
A string of LLVM-IR.
- property ir_sha1: str¶
Return the 40-characeter hex sha1 checksum of the current IR.
Equivalent to:
hashlib.sha1(env.ir.encode("utf-8")).hexdigest()
.- Returns
A 40-character hexadecimal sha1 string.
- make_benchmark(inputs: Union[str, pathlib.Path, compiler_gym.envs.llvm.llvm_benchmark.ClangInvocation, List[Union[str, pathlib.Path, compiler_gym.envs.llvm.llvm_benchmark.ClangInvocation]]], copt: Optional[List[str]] = None, system_includes: bool = True, timeout: int = 600) → compiler_gym.datasets.benchmark.Benchmark[source]¶
Create a benchmark for use with this environment.
This function takes one or more inputs and uses them to create a benchmark that can be passed to
compiler_gym.envs.LlvmEnv.reset()
.For single-source C/C++ programs, you can pass the path of the source file:
>>> benchmark = make_benchmark('my_app.c') >>> env = gym.make("llvm-v0") >>> env.reset(benchmark=benchmark)
The clang invocation used is roughly equivalent to:
$ clang my_app.c -O0 -c -emit-llvm -o benchmark.bc
Additional compile-time arguments to clang can be provided using the
copt
argument:>>> benchmark = make_benchmark('/path/to/my_app.cpp', copt=['-O2'])
If you need more fine-grained control over the options, you can directly construct a
ClangInvocation
to pass a list of arguments to clang:>>> benchmark = make_benchmark( ClangInvocation(['/path/to/my_app.c'], timeout=10) )
For multi-file programs, pass a list of inputs that will be compiled separately and then linked to a single module:
>>> benchmark = make_benchmark([ 'main.c', 'lib.cpp', 'lib2.bc', ])
If you already have prepared bitcode files, those can be linked and used directly:
>>> benchmark = make_benchmark([ 'bitcode1.bc', 'bitcode2.bc', ])
Note
LLVM bitcode compatibility is not guaranteed, so you must ensure that any precompiled bitcodes are compatible with the LLVM version used by CompilerGym, which can be queried using
LlvmEnv.compiler_version
.- Parameters
inputs – An input, or list of inputs.
copt – A list of command line options to pass to clang when compiling source files.
system_includes – Whether to include the system standard libraries during compilation jobs. This requires a system toolchain. See
get_system_includes()
.timeout – The maximum number of seconds to allow clang to run before terminating.
- Returns
A
Benchmark
instance.- Raises
FileNotFoundError – If any input sources are not found.
TypeError – If the inputs are of unsupported types.
OSError – If a compilation job fails.
TimeoutExpired – If a compilation job exceeds
timeout
seconds.
- render(mode='human') → Optional[str][source]¶
Render the environment.
CompilerEnv instances support two render modes: “human”, which prints the current environment state to the terminal and return nothing; and “ansi”, which returns a string representation of the current environment state.
- Parameters
mode – The render mode to use.
- Raises
TypeError – If a default observation space is not set, or if the requested render mode does not exist.
- reset(*args, **kwargs)[source]¶
Reset the environment state.
This method must be called before
step()
.- Parameters
benchmark – The name of the benchmark to use. If provided, it overrides any value that was set during
__init__()
, and becomes subsequent calls toreset()
will use this benchmark. If no benchmark is provided, and no benchmark was provided to__init___()
, the service will randomly select a benchmark to use.action_space – The name of the action space to use. If provided, it overrides any value that set during
__init__()
, and subsequent calls toreset()
will use this action space. If no action space is provided, the default action space is used.
- Returns
The initial observation.
- Raises
BenchmarkInitError – If the benchmark is invalid. In this case, another benchmark must be used.
TypeError – If no benchmark has been set, and the environment does not have a default benchmark to select from.
- property runtime_observation_count: int¶
The number of runtimes to return for the Runtime observation space.
See the Runtime observation space reference for further details.
Example usage:
>>> env = compiler_gym.make("llvm-v0") >>> env.reset() >>> env.runtime_observation_count = 10 >>> len(env.observation.Runtime()) 10
- Getter
Returns the number of runtimes that will be returned when a
Runtime
observation is requested.- Setter
Set the number of runtimes to compute when a
Runtime
observation is requested.- Type
int
- property runtime_warmup_runs_count: int¶
The number of warmup runs of the binary to perform before measuring the Runtime observation space.
See the Runtime observation space reference for further details.
Example usage:
>>> env = compiler_gym.make("llvm-v0") >>> env.reset() >>> env.runtime_observation_count = 10 >>> len(env.observation.Runtime()) 10
- Getter
Returns the number of runs that be performed before measuring the
Runtime
observation is requested.- Setter
Set the number of warmup runs to perform when a
Runtime
observation is requested.- Type
int
GccEnv¶
- class compiler_gym.envs.GccEnv(*args, gcc_bin: Union[str, pathlib.Path] = 'docker:gcc:11.2.0', benchmark: Union[str, compiler_gym.datasets.benchmark.Benchmark] = 'benchmark://chstone-v0/adpcm', datasets_site_path: Optional[pathlib.Path] = None, connection_settings: Optional[compiler_gym.service.connection.ConnectionOpts] = None, timeout: Optional[int] = None, **kwargs)[source]¶
A specialized CompilerEnv for GCC.
This class exposes the optimization space of GCC’s command line flags as an environment for reinforcement learning. For further details, see the GCC Environment Reference.
- property asm: str¶
Get the assembly code.
- property asm_hash: str¶
Get a hash of the assembly code.
- property asm_size: int¶
Get the assembly code size in bytes.
- property choices: List[int]¶
Get the current choices
- commandline() → str[source]¶
Return a string representing the command line options.
- Returns
A string.
- property gcc_spec: compiler_gym.envs.gcc.gcc.GccSpec¶
A
GccSpec
description of the compiler specification.
- property instruction_counts: Dict[str, int]¶
Get a count of the instruction types in the assembly code.
Note, that it will also count fields beginning with a
.
, like.bss
and.align
. Make sure to remove those if not needed.
- property obj: bytes¶
Get the object code.
- property obj_hash: str¶
Get a hash of the object code.
- property obj_size: int¶
Get the object code size in bytes.
- reset(benchmark: Optional[Union[str, compiler_gym.datasets.benchmark.Benchmark]] = None, action_space: Optional[str] = None, retry_count: int = 0) → Optional[compiler_gym.util.gym_type_hints.ObservationType][source]¶
Reset the environment. This additionally sets the timeout to the correct value.
- property rtl: str¶
Get the final rtl of the program.
- property source: str¶
Get the source code.
- property timeout: Optional[int]¶
Get the current compilation timeout