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

Update Documentation #729

Merged
merged 26 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ If you're just using Exo, install it using `pip`:
```sh
$ pip install exo-lang
```
In case of `ModuleNotFoundError: No module named 'attrs'` please upgrade your attrs module by `pip install --upgrade attrs`.

## Compile Exo

Expand All @@ -29,11 +30,6 @@ You can use optional arguments to customize the output:
- The `--stem` argument allows you to specify custom names for the C file and header file.


# Examples

Take a look at [examples](examples/avx2_matmul/README.md) for scheduling examples, and [API documentation](docs/API.md) for scheduling interface documentation.


# Build Exo from source

We make active use of newer Python 3.x features. Please use Python 3.9 or 3.10 if you're getting errors about unsupported features.
Expand Down Expand Up @@ -62,7 +58,6 @@ Finally, you can build and install Exo.
(exo) $ pip install dist/*.whl
```


## PySMT

Depending on your setup, getting PySMT to work correctly may be difficult. You
Expand Down Expand Up @@ -117,26 +112,11 @@ pytest --cov=./ --cov-report=html

Then, if you want to see annotated source files, open `./htmlcov/index.html`.

---

# Learn about Exo

# Repository structure

In this repository, folders are structured as follows:

1. `src/exo` is where the core Exo implementation resides.
- **APIs.** Documentation for the APIs can be found in the [API documentation](docs/API.md).
- `API.py` defines a stable API for top-level decorators (`proc`, `instr`, and `config`).
- `API_scheduling.py` defines a API for scheduling primitives.
- `API_cursors.py` defines a API for Cursors.
- **Standard libraries.** These could be user-defined, but we provide them for convenience.
- `libs/` contains some common memory definitions (`memories.py`) and custom malloc implementations.
- `platforms/` contains instruction definitions that are part of the release.
- `stdlib/` contains user-level scheduling functions such as `vectorize`.
- Other files are implementation details of Exo (e.g., `typecheck.py` implements typecheck), are not exposed to users.
2. `apps/` contains some sample applications written in Exo.
3. `dependencies/` contains submodules that Exo's apps and testing depends on.
4. `examples/` contains a step-by-step example of scheduling basic matrix multiplication on AVX2.
5. `tests/` contains the Exo test suite.
6. `docs/` contains additional Exo documentation.
Take a look at the [examples](examples/README.md) directory for scheduling examples and the [documentation](docs/README.md) directory for various documentation about Exo.


# Contact
Expand Down
4 changes: 4 additions & 0 deletions docs/Cursors.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,7 @@ p2 = reorder_scope(p1, p1.forward(c).next(), ...)

In this code, the navigation `.next()` is applied to the forwarded cursor `p1.forward(c)`. Attempting to change `p1.forward(c).next()` to `p1.forward(c.next())` will result in incorrect behavior. This is because navigation and forwarding are *not commutative*.

## Further Reading
More details of the design principles of Cursors can be found in our [ASPLOS '25 paper](.) or in [Kevin Qian's MEng thesis](https://dspace.mit.edu/handle/1721.1/157187).


70 changes: 70 additions & 0 deletions docs/Design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Design Document for Exo

Exo is a domain-specific language designed to enable productive development of high-performance kernel libraries that target specialized hardware accelerators.

The key design principles of Exo are:
- **Performance Transparency**: We do not do "magic optimizations" that are surprising and opaque to users.
- **WYSIWYG**: Exo IR closely models C-style code and will be trivially lowered to C code.
- **User Control**: Give the performance control back to users.

---

# Exocompilation: Externalizing Hardware Targets

One of the main ideas behind Exo is **exocompilation**, which allows users to define hardware targets externally to the compiler in user-level libraries. This has several advantages:

- Hardware vendors can support new accelerators without maintaining compiler forks.
- The cost of adding support for new hardware is significantly reduced.
- Proprietary details of hardware can be protected.

Users can model custom [memories](./memories.md), [instructions](./instructions.md), and configuration state in libraries to target a specific accelerator. These hardware abstractions can then be used to write hand-optimized code or as building blocks for higher-level scheduling transformations.

More info can be found in the [PLDI paper](https://people.csail.mit.edu/yuka/pdf/exo_pldi2022_full.pdf), [instructions.md](./instructions.md), and [memories.md](./memories.md).

## Fine-Grained Primitives for Performance Control

Exo provides a set of fine-grained scheduling primitives that offer users low-level control over performance-critical aspects. These primitives can be combined to create complex transformation schedules. Some examples of these primitives include:

- `replace`: Maps code fragments to custom instructions
- `delete_config`: Removes redundant configuration statements

The key research contributions of Exo were supporting `replace` through unification and the ability to reason about configuration states. Explicit control over these low-level details allows Exo to achieve performance comparable to highly-tuned vendor libraries and hand-optimized assembly code. All the primitives can be found in the [primitives/](./primitives/) directory.

## Rewrite-based Scheduling Language

Exo employs a *rewrite-based* compilation process, which differs from the *lowering-based* approach used by popular frameworks like Halide and TVM.

The rewrite-based approach offers several advantages:

- Reduced complexity and less "magic" involved
- Easier to print and inspect the state of the scheduling process at any point

---

# User-Defined Scheduling Operations

While the flexibility of fine-grained primitives is necessary for achieving peak performance, directly using them can be verbose and laborious. To address this, Exo allows users to define new higher-level scheduling operations by composing the core primitives.

These user-defined scheduling operations can encapsulate common optimization patterns and hardware-specific transformations such as auto-vectorize, tiling, and even simulate scheduling operations from other USLs (like Halide's `compute_at`).
They can be put together in reusable libraries, further enabling modularity and portability.

More infomation can be found in the [ASPLOS paper](.) and [Cursor.md](./Cursor.md).

## The AIR Framework: Action, Inspection, Reference

We identified that Action, Inspection, and Reference are the key scheduling language design mechanisms that enable user-defined scheduling operations.

- **[Actions](./primitives)** are scheduling operations that transform the code. This could be compiler-provided *primitive actions* (e.g., `divide_loop`, `reorder`), or *user-defined* (e.g., tile2D in the ASPLOS paper).
- **[Inspections](./inspection.md)** query properties of the code (e.g., loop bounds, memory access patterns).
- **References** point to specific parts of the code to apply actions to.

Together, AIR allows scheduling operations to be defined as composable rewrites on the code. The language implementation guarantees the correctness of these primitive rewrites with a set of effect analyses.

## Cursors: Enabling Relative References

A novel feature in Exo's design is the concept of cursors, which serve as relative references into the code. Similar to a text editing cursor, an Exo cursor can refer to a specific location in the program AST, such as a statement, loop nest, or even the gap between statements.

Cursors support navigation operations such as `next`, `prev`, `parent`, enabling powerful code transformations using relative positions.
Furthermore, Cursor _forwarding_ let users reuse the cursor from the previous procedure in the current procedure.
Multiple cursors can coexist, allowing different parts of the code to be referenced and modified simultaneously.

97 changes: 97 additions & 0 deletions docs/Imports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Imports in Exo

This document provides an overview of the imports used when writing Exo.

Exo's parser only resolves names in the local and global namespaces, and Exo reserves the attribute syntax (foo.bar) for configurations.
Therefore, if users wish to utilize Exo constructs, they must import them into their local namespace.

## Table of Contents

1. [Standard Python Future Import](#1-standard-python-future-import)
2. [Core Exo Module](#2-core-exo-module)
3. [Memory Libraries](#3-memory-libraries)
4. [Instruction Libraries](#4-instruction-libraries)
5. [Extern Libraries](#5-extern-libraries)
6. [Frontend Syntax Utilities](#6-frontend-syntax-utilities)
7. [Standard Library Scheduling Functions](#7-standard-library-scheduling-functions)
8. [API Cursors](#8-api-cursors)


## 1. Standard Python Future Import

```python
from __future__ import annotations
```

Enables postponed evaluation of type annotations, allowing you to use forward references in type hints without causing issues during runtime. This is necessary to support Exo's `x : f32` syntax.


## 2. Core Exo Module

```python
from exo import *
```
yamaguchi1024 marked this conversation as resolved.
Show resolved Hide resolved

Imports basic classes and functions necessary for defining and manipulating high-performance computational kernels, such as `proc`, `instr`, `config`, `Memory`, `Extern`, `DRAM`, and `SchedulingError`.


## 3. Memory Libraries

Even though users can define memory definitions externally to the compiler in the user code (see [memories.md](./memories.md)), we provide memory definitions for some architectures for convinience.
The supported memory definitions can be found by looking into `src/exo/libs/memories.py`.

```python
from exo.libs.memories import DRAM_STATIC, AVX2, AVX512
```

For example, you can import `DRAM_STATIC`, `AVX2`, or `AVX512` as shown above.


## 4. Instruction Libraries

Similar to memories, we provide some hardware instruction definitions for convinience (see [instructions.md](./instructions.md) to learn how to define your own accelerator instructions).

```python
from exo.platforms.x86 import mm256_loadu_ps, mm256_setzero_ps, mm256_broadcast_ss
```

## 5. Extern Libraries

Similary, convinience extern libraries can be imported as follows. See [externs.md](./externs.md) to learn how to define your own externs.

```python
from exo.libs.externs import sin, relu
```


## 6. Frontend Syntax Utilities

```python
from exo.frontend.syntax import *
```

This module defines special symbols that are used inside Exo code.
Importing this can suppress warnings inside an IDE (like PyCharm).


## 7. Standard Library Scheduling Functions

Exo provides users with the ability to define new scheduling operations using Cursors. For convenience, we have implemented scheduling libraries (standard library) that contain common scheduling operations users may want to use, such as vectorization and tiling. Users can import the standard library as follows:

```python
from exo.stdlib.scheduling import repeat, replace_all
from exo.stdlib.stdlib import vectorize, tile_loops
```

Alternatively, users can define their own scheduling operations by composing scheduling primitives directly in their code.

## 8. API Cursors

Cursors (see [Cursors.md](./Cursors.md)) are Exo's reference mechanism that allows users to navigate and inspect object code. When users define new scheduling operators using Cursors, they may wish to write their own inspection pass (see [inspection.md](./inspection.md)). API Cursors define types that will be useful for user inspection.

```python
from exo.API_cursors import ForCursor, AssignCursor, InvalidCursor
```

These API Cursors provide specific types, such as `ForCursor` for for-loops, `AssignCursor` for assignments, and `InvalidCursor` for invalid cursors. Users can leverage these types when inspecting and manipulating code using Cursors.

11 changes: 0 additions & 11 deletions docs/API.md → docs/Procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,3 @@ Cursors can be obtained by querying patterns on a procedure. All the Cursor rela
- `.transpose(arg_cursor)`: Transposes a 2D buffer argument in the signature and the body. Returns a new procedure and is non-equivalence preserving because the signature has changed.
- `.add_assertion(assertion)`: Adds an assertion to the procedure.
- `.is_eq(other_proc)`: Checks the equivalence of this procedure with another procedure.

## Scheduling Primitives

We have classified scheduling primitives into six categories. Here are the links to each:

- [Buffer Transformations](buffer_ops.md)
- [Loop and Scope Transformations](loop_ops.md)
- [Configuration States](config_ops.md)
- [Subprocedure Operations](subproc_ops.md)
- [Memory, Precision, and Parallelism Transformations](backend_ops.md)
- [Other Operations](other_ops.md)
30 changes: 30 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Documentation

This directory provides detailed documentation about Exo's interface and internal systems.

- To learn about the design principles of Exo, read [Design.md](Design.md).
yamaguchi1024 marked this conversation as resolved.
Show resolved Hide resolved
- To understand how the Exo system is implemented, read [System.md](System.md).
- For information on writing Exo object code, APIs, and imports, refer to [Procedures.md](Procedures.md), [object_code.md](object_code.md), and [Imports.md](Imports.md).
- To learn how to define **hardware targets externally to the compiler**, refer to [externs.md](externs.md), [instructions.md](instructions.md), and [memories.md](memories.md).
- To learn how to define **new scheduling operations externally to the compiler**, refer to [Cursors.md](./Cursors.md) and [inspection.md](./inspection.md).
- To understand the available scheduling primitives and how to use them, look into the [primitives/](./primitives) directory.

The scheduling primitives are classified into six categories:

1. [Buffer Transformations](primitives/buffer_ops.md)
2. [Loop and Scope Transformations](primitives/loop_ops.md)
3. [Configuration States](primitives/config_ops.md)
4. [Subprocedure Operations](primitives/subproc_ops.md)
5. [Memory, Precision, and Parallelism Transformations](primitives/backend_ops.md)
6. [Other Operations](primitives/other_ops.md)

# Further Reading

The following papers provide a high-level and holistic view of Exo as a project:

- [PLDI '22 paper](https://people.csail.mit.edu/yuka/pdf/exo_pldi2022_full.pdf)
- [ASPLOS '25 paper](.)
- [Kevin Qian's MEng thesis](https://dspace.mit.edu/handle/1721.1/157187)
- [Samir Droubi's MEng thesis](https://dspace.mit.edu/handle/1721.1/156752)

For more documentation with running Exo code, refer to the [Examples](../examples/README.md) directory.
Loading
Loading