Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create an MLIR environment with matrix multiplication #652

Merged
merged 39 commits into from
May 3, 2022
Merged

Conversation

sogartar
Copy link

This also adds config flags to enable the MLIR and LLVM environments. They are mutually exclusive due to their dependence on different LLVM versions and the problem of their coexistence in one CMake configuration.
Enabling them is available through CMake with the flags

COMPILER_GYM_ENABLE_MLIR_ENV
COMPILER_GYM_ENABLE_LLVM_ENV

The LLVM env is enabled by default.
These flags are propagated to python where sub-modules are included conditionally.

Co-authored-by: kyle <kyle.w.herndon@gmail.com>
@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 14, 2022
@codecov-commenter
Copy link

codecov-commenter commented Apr 14, 2022

Codecov Report

Merging #652 (7db7e83) into development (b803856) will decrease coverage by 6.29%.
The diff coverage is 80.41%.

@@               Coverage Diff               @@
##           development     #652      +/-   ##
===============================================
- Coverage        88.42%   82.13%   -6.30%     
===============================================
  Files              119      120       +1     
  Lines             7475     7550      +75     
===============================================
- Hits              6610     6201     -409     
- Misses             865     1349     +484     
Impacted Files Coverage Δ
compiler_gym/bin/service.py 75.80% <0.00%> (ø)
compiler_gym/wrappers/core.py 77.77% <57.57%> (-3.94%) ⬇️
compiler_gym/service/connection.py 71.98% <66.66%> (-7.03%) ⬇️
compiler_gym/envs/__init__.py 85.71% <77.77%> (-14.29%) ⬇️
compiler_gym/spaces/runtime_reward.py 96.77% <96.77%> (ø)
compiler_gym/random_search.py 92.10% <100.00%> (+0.16%) ⬆️
compiler_gym/service/proto/py_converters.py 97.81% <100.00%> (+0.01%) ⬆️
compiler_gym/spaces/__init__.py 100.00% <100.00%> (ø)
compiler_gym/wrappers/__init__.py 100.00% <100.00%> (ø)
compiler_gym/wrappers/llvm.py 100.00% <100.00%> (+2.08%) ⬆️
... and 27 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b803856...7db7e83. Read the comment docs.

@sogartar
Copy link
Author

One thing to note is that the CI from the MLIR env is not setup yet.

@ChrisCummins
Copy link
Contributor

Woohoo! Here comes the big PR! 😄

There's a lot to unpack here. I'll make a start today, but it might take a couple of rounds for me to go through it all.

Great work @sogartar et al!

Cheers,
Chris

@ChrisCummins
Copy link
Contributor

For the CI, could you split the existing CI/build-linux into two jobs, one which builds the LLVM environment, the other which builds the MLIR environment?

Cheers,
Chris

INSTALL.md Outdated Show resolved Hide resolved
Comment on lines 35 to 57
# TODO(boian): Make better config
# observation_spaces = {"runtime": "Runtime"}
# reward_spaces = {"runtime": "Runtime"}
# for reward_space in reward_spaces:
# register(
# id=f"mlir-{reward_space}-v0",
# entry_point="compiler_gym.envs.mlir:MlirEnv",
# kwargs={
# "service": MLIR_SERVICE_BINARY,
# "reward_space": reward_spaces[reward_space],
# },
# )
#
# for observation_space, reward_space in product(observation_spaces, reward_spaces):
# register(
# id=f"mlir-{observation_space}-{reward_space}-v0",
# entry_point="compiler_gym.envs.mlir:MlirEnv",
# kwargs={
# "service": MLIR_SERVICE_BINARY,
# "observation_space": observation_spaces[observation_space],
# "reward_space": reward_spaces[reward_space],
# },
# )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be committed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KyleHerndon is working on this, but it is a big change and it will be in another PR.

def benchmark_uris(self) -> Iterable[str]:
return (self.name_from_size(mnk) for mnk in matmul_sizes)

def benchmark(self, uri: str) -> MatmulBenchmark:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you could use benchmark_from_parsed_uri() instead of benchmark() to save you the string parsing here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is going to be changed in another PR.

@ChrisCummins
Copy link
Contributor

Hey,

Sorry for the delay in the full review, I just moved to a new office and am setting up a new dev environment. I'm hitting this error, not sure if it's related to your changes or my own fault:

$ cmake -DCMAKE_C_COMPILER=clang-7 -DCMAKE_CXX_COMPILER=clang++-7 -DPython3_FIND_VIRTUALENV=FIRST -DCMAKE_BUILD_WITH_INSTALL_RPATH=true -DCOMPILER_GYM_ENABLE_MLIR_ENV=on -DCOMPILER_GYM_ENABLE_LLVM_ENV=off -S $HOME/src/CompilerGym -B /dev/shm/CompilerGymBuilds/mlir


... <snip>

[3/9] Performing build_protobuf step for 'protobuf'

... <snip>

checking whether the C compiler works... no
configure: error: in `/dev/shm/CompilerGymBuilds/mlir/external/protobuf/protobuf/src/protobuf':
configure: error: C compiler cannot create executables
See `config.log' for more details
CMake Error at /private/home/cummins/src/CompilerGym/external/protobuf/build_protobuf.cmake:50 (execute_process):
  execute_process failed command indexes:

    1: "Child return code: 77"

[7/9] No install step for 'protobuf'
FAILED: protobuf/src/protobuf-stamp/protobuf-build_protobuf 
cd /dev/shm/CompilerGymBuilds/mlir/external/protobuf/protobuf/src/protobuf && /private/home/cummins/.local/bin/cmake -E env CC=/bin/clang-7 CXX=/bin/clang++-7 /private/home/cummins/.local/bin/cmake -C /dev/shm/CompilerGymBuilds/mlir/external/protobuf/protobuf_initial_cache.cmake -DGIT_EXECUTABLE=/bin/git -DGIT_REPOSITORY_DIR=/dev/shm/CompilerGymBuilds/mlir/external/protobuf/protobuf/src/protobuf -DCMAKE_INSTALL_PREFIX=/dev/shm/CompilerGymBuilds/mlir/external/protobuf/install -P /private/home/cummins/src/CompilerGym/external/protobuf/build_protobuf.cmake
ninja: build stopped: subcommand failed.
CMake Error at build_tools/cmake/build_external_cmake_project.cmake:37 (execute_process):
  execute_process failed command indexes:

    1: "Child return code: 1"

Have you seen this before?

I started reading through the code and left a bunch of minor comments, but I think I'll hold off until I get a chance to build and test the new environment before I go any further. I don't want to spam you with nitpicks until I understand the big picture 🙂

Note to self: I got as far as compiler_gym/envs/mlir/mlir_env.py when reading through the sources

Cheers,
Chris

@sogartar
Copy link
Author

@ChrisCummins, I added the external dependencies of the MLIR env to the python packaging. It required the clang compiler, Google benchmark and
MLIRExecutionEngine libraries. I am not sure if this is the best approach or to leave them as runtime dependencies for the user to install.

@@ -371,3 +376,70 @@ def multistep(
def convert_reward(self, reward):
"""Translate a reward to the new space."""
raise NotImplementedError


class ConversionWrapperEnv(CompilerEnvWrapper):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this. I like that the wrappers in base gym operate only on action/observation/reward at a time. Could you add the space conversion methods to the relevant wrapper and use them instead? E.g. merge convert_observation_space into ObservationWrapper. You could then have:

env = MlirObservationWrapper(MlirActionWrapper(MlirRewardWrapper(env)))

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

setup.py Outdated Show resolved Hide resolved
@ChrisCummins
Copy link
Contributor

ChrisCummins commented Apr 26, 2022

Okay, I have completed a full pass of the PR. Minor nitpicks left inline, but in general, this looks excellent. Many thanks @sogartar and @KyleHerndon!

While this isn't merge blocking, I'd like to discuss with you folks your goals / timeline is for making the MLIR environment a part of the "core" installable package. In particular, I want to avoid this kind of thing:

if config.enable_llvm_env:
  ...

if config.enable_mlir_env:
  ...

As I understand, it would be totally possible to build a combined LLVM + MLIR environment package, it would just require a couple of passes of the cmake build and merging the generated runfiles, right? Is the idea to split the cmake build into separate projects for each environment so that they can have mutually exclusive dependencies?

If for some reason there are unavoidable extra dependencies that MLIR requires that complicates the build, could we not still have the python class definition available, and defer the config.enable_mlir_env check until instantiation, raising some kind of runtime error like:

>>> compiler_gym.make("mlir-v0")
EnvironmentNotSupported("Please install compiler_gym[mlir] to use this environment")

Again, this doesn't need to be resolved in this PR, assuming that you're okay with the pip wheel continuing to be LLVM-only for the time being.

One final request that is blocking is for you to add a new page in the documentation describing this environment. Take a look at envs/gcc for an example. Since it is still early days, it would be fine to say that its under construction and that the doc can be updated as more features are added, but it's important to have the basic there.

Cheers,
Chris

@sogartar
Copy link
Author

One final request that is blocking is for you to add a new page in the documentation describing this environment. Take a look at envs/gcc for an example.

I added the MlirEnv to the documentation.

While this isn't merge blocking, I'd like to discuss with you folks your goals / timeline is for making the MLIR environment a part of the "core" installable package.

I am also not happy with the logic of the conditional inclusion of the LLVM and MLIR environments in the package. It needs refactoring. Having multiple subpackages that can be separately built and installed with pip seems a good idea.

I think it would be beneficial to have also a development package that has all stuff related to creating new environments. Like the C++ code in compiler_gym/service.

The packages could look like that

compiler_gym # runtime
compiler_gym[dev] # development
compiler_gym[gcc]
compiler_gym[llvm]
compiler_gym[loop_tool]
compiler_gym[mlir]

@ChrisCummins, I will let you know in a few days when we are going to be able to work on that.

@ChrisCummins
Copy link
Contributor

Thanks for the latest iteration of changes, it's coming together great.

I added the MlirEnv to the documentation.

Ah, what I meant was a new rst doc in docs/source/envs which describes in plain english what the optimization problem is and what the features of the environment are. You could start by using the gcc one or the llvm one one as a template.

I think it would be beneficial to have also a development package that has all stuff related to creating new environments. Like the C++ code in compiler_gym/service.

Yep, I'll continue discussion in #669.

Cheers,
Chris

@sogartar
Copy link
Author

Ah, what I meant was a new rst doc in docs/source/envs which describes in plain english what the optimization problem is and what the features of the environment are. You could start by using the gcc one or the llvm one one as a template.

I added some documentation under docs/source/envs/mlir.rst.

@sogartar
Copy link
Author

sogartar commented May 3, 2022

@ChrisCummins, did you got a chance to see the documentation?

Copy link
Contributor

@ChrisCummins ChrisCummins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! This looks ready to merge

@ChrisCummins ChrisCummins merged commit ac34498 into development May 3, 2022
@ChrisCummins ChrisCummins mentioned this pull request May 24, 2022
ChrisCummins added a commit that referenced this pull request May 24, 2022
This release adds a new compiler environment, new APIs, and a suite of backend
improvements to improve the flexibility of CompilerGym environments. Many thanks
to code contributors: @sogartar, @KyleHerndon, @SoumyajitKarmakar@uduse, and
@anthony0727!

Highlights of this release include:

- [mlir] Began work on a new environment for matrix multiplication using MLIR
  ([#652](#652), thanks
  @KyleHerndon and @sogartar!). Note this environment is not yet included in the
  pypi package and must be [compiled from
  source](https://github.com/facebookresearch/CompilerGym/blob/development/INSTALL.md#building-from-source-with-cmake).
- [llvm] Added a new `env.benchmark_from_clang_invocation()` method ([#577](#577)) that can be used for constructing LLVM environment automatically from C/C++ compiler invocations. This makes it much easier to integrate CompilerGym with your existing build scripts.
- Added three new wrapper classes: `Counter`, that provides op counts for
  analysis ([#683](#683));
  `SynchronousSqliteLogger`, that provides logging of environment interactions
  to a relational database
  ([#679](#679)), and
  `ForkOnStep` that provides an `undo()` operation
  ([#682](#682)).
- Added `reward_space` and `observation_space` parameters to `env.reset()`
  ([#659](#659), thanks
  @SoumyajitKarmakar!)

This release includes a number of improvements to the backend APIs that make it
easier to write new CompilerGym environments:

- Refactored the backend to make `CompilerEnv` an abstract interface, and
  `ClientServiceCompilerEnv` the concrete implementation of this interface. This
  enables new environments to be implemented without using gRPC
  ([#633](#633), thanks
  @sogartar!).
- Extended the support for different types of action and observation spaces
  ([#641](#641),
  [#643](#643), thanks
  @sogartar!), including new `Permutation` and `SpaceSequence` spaces
  ([#645](#645), thanks
  @sogartar!)..
- Added a new `disk/` subdirectory to compiler service's working directories,
  which is symlinked to an on-disk location for devices which support in-memory
  working directories. This fixes a bug with leftover temporary directories from
  LLVM ([#672](#672)).

This release also includes numerous bug fixes and improvements, many of which
were reported or fixed by the community. For example, fixing a bug in cache file
locations ([#656](#656),
thanks @uduse!), and a missing flag definition in example code
([#684](#684), thanks
@anthony0727!).

**Full Changelog**:
v0.2.3...v0.2.4

This release brings in deprecating changes to the core `env.step()` routine, and
lays the groundwork for enabling new types of compiler optimizations to be
exposed through CompilerGym. Many thanks to code contributors: @mostafaelhoushi,
@sogartar, @KyleHerndon, @uduse, @parthchadha, and @xtremey!

Highlights of this release include:

- Added a new `TextSizeInBytes` observation space for LLVM
  ([#575](#575)).
* Added a new PPO leaderboard entry
  ([#580](#580). Thanks
  @xtremey!
- Fixed a bug in which temporary directories created by the LLVM environment
  were not cleaned up
  ([#592](#592)).
- **[Backend]** The function `createAndRunCompilerGymService` now returns an
  int, which is the exit return code
  ([#592](#592)).
- Improvements to the examples documentation
  ([#548](#548)) and FAQ
  ([#586](#586))

Deprecations and breaking changes:

- `CompilerEnv.step` no longer accepts a list of actions
  ([#627](#627)). A new
  method, `CompilerEnv.multistep` provides this functionality. This is to
  provide compatibility with environments whose action spaces are lists. To
  update your code, replace any calls to `env.step()` which take a list of
  actions to use `env.multistep()`. Thanks @sogartar!
- The arguments `observations` and `rewards` to `step()` have been renamed
  `observation_spaces` and `reward_spaces`, respectively
  ([#627](#627)).
- `Reward.id` has been renamed `Reward.name`
  ([#565](#565),
  [#612](#612)). Thanks
  @parthchadha!
* The backend protocol buffer schema has been updated to natively support more
  types of observation and action, and to support nested spaces
  ([#531](#531)). Thanks
  @sogartar!
ChrisCummins added a commit that referenced this pull request May 24, 2022
This release adds a new compiler environment, new APIs, and a suite of backend
improvements to improve the flexibility of CompilerGym environments. Many thanks
to code contributors: @sogartar, @KyleHerndon, @SoumyajitKarmakar@uduse, and
@anthony0727!

Highlights of this release include:

- [mlir] Began work on a new environment for matrix multiplication using MLIR
  ([#652](#652), thanks
  @KyleHerndon and @sogartar!). Note this environment is not yet included in the
  pypi package and must be [compiled from
  source](https://github.com/facebookresearch/CompilerGym/blob/development/INSTALL.md#building-from-source-with-cmake).
- [llvm] Added a new `env.benchmark_from_clang_invocation()` method ([#577](#577)) that can be used for constructing LLVM environment automatically from C/C++ compiler invocations. This makes it much easier to integrate CompilerGym with your existing build scripts.
- Added three new wrapper classes: `Counter`, that provides op counts for
  analysis ([#683](#683));
  `SynchronousSqliteLogger`, that provides logging of environment interactions
  to a relational database
  ([#679](#679)), and
  `ForkOnStep` that provides an `undo()` operation
  ([#682](#682)).
- Added `reward_space` and `observation_space` parameters to `env.reset()`
  ([#659](#659), thanks
  @SoumyajitKarmakar!)

This release includes a number of improvements to the backend APIs that make it
easier to write new CompilerGym environments:

- Refactored the backend to make `CompilerEnv` an abstract interface, and
  `ClientServiceCompilerEnv` the concrete implementation of this interface. This
  enables new environments to be implemented without using gRPC
  ([#633](#633), thanks
  @sogartar!).
- Extended the support for different types of action and observation spaces
  ([#641](#641),
  [#643](#643), thanks
  @sogartar!), including new `Permutation` and `SpaceSequence` spaces
  ([#645](#645), thanks
  @sogartar!)..
- Added a new `disk/` subdirectory to compiler service's working directories,
  which is symlinked to an on-disk location for devices which support in-memory
  working directories. This fixes a bug with leftover temporary directories from
  LLVM ([#672](#672)).

This release also includes numerous bug fixes and improvements, many of which
were reported or fixed by the community. For example, fixing a bug in cache file
locations ([#656](#656),
thanks @uduse!), and a missing flag definition in example code
([#684](#684), thanks
@anthony0727!).

**Full Changelog**:
v0.2.3...v0.2.4

This release brings in deprecating changes to the core `env.step()` routine, and
lays the groundwork for enabling new types of compiler optimizations to be
exposed through CompilerGym. Many thanks to code contributors: @mostafaelhoushi,
@sogartar, @KyleHerndon, @uduse, @parthchadha, and @xtremey!

Highlights of this release include:

- Added a new `TextSizeInBytes` observation space for LLVM
  ([#575](#575)).
* Added a new PPO leaderboard entry
  ([#580](#580). Thanks
  @xtremey!
- Fixed a bug in which temporary directories created by the LLVM environment
  were not cleaned up
  ([#592](#592)).
- **[Backend]** The function `createAndRunCompilerGymService` now returns an
  int, which is the exit return code
  ([#592](#592)).
- Improvements to the examples documentation
  ([#548](#548)) and FAQ
  ([#586](#586))

Deprecations and breaking changes:

- `CompilerEnv.step` no longer accepts a list of actions
  ([#627](#627)). A new
  method, `CompilerEnv.multistep` provides this functionality. This is to
  provide compatibility with environments whose action spaces are lists. To
  update your code, replace any calls to `env.step()` which take a list of
  actions to use `env.multistep()`. Thanks @sogartar!
- The arguments `observations` and `rewards` to `step()` have been renamed
  `observation_spaces` and `reward_spaces`, respectively
  ([#627](#627)).
- `Reward.id` has been renamed `Reward.name`
  ([#565](#565),
  [#612](#612)). Thanks
  @parthchadha!
* The backend protocol buffer schema has been updated to natively support more
  types of observation and action, and to support nested spaces
  ([#531](#531)). Thanks
  @sogartar!
ChrisCummins added a commit that referenced this pull request May 24, 2022
This release adds a new compiler environment, new APIs, and a suite of backend
improvements to improve the flexibility of CompilerGym environments. Many thanks
to code contributors: @sogartar, @KyleHerndon, @SoumyajitKarmakar@uduse, and
@anthony0727!

Highlights of this release include:

- [mlir] Began work on a new environment for matrix multiplication using MLIR
  ([#652](#652), thanks
  @KyleHerndon and @sogartar!). Note this environment is not yet included in the
  pypi package and must be [compiled from
  source](https://github.com/facebookresearch/CompilerGym/blob/development/INSTALL.md#building-from-source-with-cmake).
- [llvm] Added a new `env.benchmark_from_clang_invocation()` method ([#577](#577)) that can be used for constructing LLVM environment automatically from C/C++ compiler invocations. This makes it much easier to integrate CompilerGym with your existing build scripts.
- Added three new wrapper classes: `Counter`, that provides op counts for
  analysis ([#683](#683));
  `SynchronousSqliteLogger`, that provides logging of environment interactions
  to a relational database
  ([#679](#679)), and
  `ForkOnStep` that provides an `undo()` operation
  ([#682](#682)).
- Added `reward_space` and `observation_space` parameters to `env.reset()`
  ([#659](#659), thanks
  @SoumyajitKarmakar!)

This release includes a number of improvements to the backend APIs that make it
easier to write new CompilerGym environments:

- Refactored the backend to make `CompilerEnv` an abstract interface, and
  `ClientServiceCompilerEnv` the concrete implementation of this interface. This
  enables new environments to be implemented without using gRPC
  ([#633](#633), thanks
  @sogartar!).
- Extended the support for different types of action and observation spaces
  ([#641](#641),
  [#643](#643), thanks
  @sogartar!), including new `Permutation` and `SpaceSequence` spaces
  ([#645](#645), thanks
  @sogartar!)..
- Added a new `disk/` subdirectory to compiler service's working directories,
  which is symlinked to an on-disk location for devices which support in-memory
  working directories. This fixes a bug with leftover temporary directories from
  LLVM ([#672](#672)).

This release also includes numerous bug fixes and improvements, many of which
were reported or fixed by the community. For example, fixing a bug in cache file
locations ([#656](#656),
thanks @uduse!), and a missing flag definition in example code
([#684](#684), thanks
@anthony0727!).

**Full Changelog**:
v0.2.3...v0.2.4

This release brings in deprecating changes to the core `env.step()` routine, and
lays the groundwork for enabling new types of compiler optimizations to be
exposed through CompilerGym. Many thanks to code contributors: @mostafaelhoushi,
@sogartar, @KyleHerndon, @uduse, @parthchadha, and @xtremey!

Highlights of this release include:

- Added a new `TextSizeInBytes` observation space for LLVM
  ([#575](#575)).
* Added a new PPO leaderboard entry
  ([#580](#580). Thanks
  @xtremey!
- Fixed a bug in which temporary directories created by the LLVM environment
  were not cleaned up
  ([#592](#592)).
- **[Backend]** The function `createAndRunCompilerGymService` now returns an
  int, which is the exit return code
  ([#592](#592)).
- Improvements to the examples documentation
  ([#548](#548)) and FAQ
  ([#586](#586))

Deprecations and breaking changes:

- `CompilerEnv.step` no longer accepts a list of actions
  ([#627](#627)). A new
  method, `CompilerEnv.multistep` provides this functionality. This is to
  provide compatibility with environments whose action spaces are lists. To
  update your code, replace any calls to `env.step()` which take a list of
  actions to use `env.multistep()`. Thanks @sogartar!
- The arguments `observations` and `rewards` to `step()` have been renamed
  `observation_spaces` and `reward_spaces`, respectively
  ([#627](#627)).
- `Reward.id` has been renamed `Reward.name`
  ([#565](#565),
  [#612](#612)). Thanks
  @parthchadha!
* The backend protocol buffer schema has been updated to natively support more
  types of observation and action, and to support nested spaces
  ([#531](#531)). Thanks
  @sogartar!
@ChrisCummins ChrisCummins mentioned this pull request May 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants