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

Refactoring of packages(dot)md from manual docs #23

Merged
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
19 changes: 9 additions & 10 deletions docs/Manual/09 Parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

# Section 9: Parameters

Accera parameters are placeholders that get replaced with concrete values when we add a function to a package. A parameter can be used in a `Nest`, a `Schedule`, or an `Plan`.
Accera's parameters are placeholders that get replaced with concrete values when adding a function to a package. A parameter can be used in a `Nest`, a `Schedule`, or a `plan`.

## Parameterized nests
Recall that a `Nest` represents the loop-nest logic. We can parameterize the nest shape and the iteration logic. For example, consider the following parameterized version of matrix multiplication:
Recall that a `Nest` represents the loop-nest logic. We can parametrize the nest shape and iteration logic. For example, consider the following parameterized version of matrix multiplication:

```python
# Create parameters
Expand All @@ -32,10 +32,10 @@ package = acc.Package()
package.add(nest, args=(A, B, C), parameters={P0:16, P1:16, P2:16, P3:1.0}, base_name="matmul_16_16_16_1")
package.add(nest, args=(A, B, C), parameters={P0:32, P1:32, P2:32, P3:2.0}, base_name="matmul_32_32_32_2")
```
In this example, the shape of the nest is parameterized by (`P0`, `P1`, `P2`) and its iteration logic includes the parameter `P3`. The nest is used twice, with different settings of these parameters, to create two separate functions in the package.
In the above scenario, the shape of the nest is parameterized by (`P0`, `P1`, `P2`) and its iteration logic includes the parameter `P3`. The nest is used twice with different settings of these parameters to create two separate functions in the package.

## Parameterized schedules and plans
Parameters can also appear in schedules and plans. For example, we could add the following to the code above:
As mentioned before, parameters can be used in schedules and plans. For example, we can add the following code snippet to the above code:
```python
P4, P5 = acc.create_parameters(2)

Expand All @@ -52,15 +52,15 @@ package.add(plan, args=(A, B, C), parameters={P0:16, P1:16, P2:16, P3:1.0, P4:4,
```

## Tuple parameter values
Parameters can be used as placeholders for tuples, and specifically tuples of indices. For example, say that we wanted to parameterize the order of the iteration space dimensions. We could write:
Parameters can be used as placeholders for tuples, specifically for tuples of indices. For example, assume that we want to parameterize the order of the iteration space dimensions. We can then write:
```python
P6 = acc.create_parameters(1)
schedule.reorder(order=P6)
```
Later, we could set the value of `P6` to the index tuple `(j,k,i)`.
Later, we can set the value of `P6` to the index tuple `(j,k,i)`.

## Get parameters from an entire parameter grid
Consider the parameterized nest defined above. Rather than setting each parameter to one specific value, imagine that we had a set of different values for each parameter. For example, say that we wanted `P0` to take a value in the set `{8, 16}`, `P1` in `{16, 32}`, `P2` would always equal 16, and `P3` would take a value in `{1,2}`. This list of all valid parameter combinations is called a *parameter grid*. In this case, the grid includes the following parameter settings:
Consider the parameterized nest defined above. Rather than setting a specific value for each parameter, imagine that we have a set of different values for each parameter. For example, consider that we want `P0` to have a value in set `{8, 16}`, `P1` in `{16, 32}`, `P2` to be always `16`, and `P3` in `{1,2}`. We can define the *parameter grid* with this data, which lists all the valid parameter combinations. In our case, this grid includes the following parameter settings:
```python
{P0:8, P1:16, P2:16, P3:1.0}
{P0:8, P1:16, P2:16, P3:2.0}
Expand All @@ -72,13 +72,12 @@ Consider the parameterized nest defined above. Rather than setting each paramete
{P0:16, P1:32, P2:16, P3:2.0}
```

Accera provides an easy way to add all of the functions that correspond to the parameter grid at once.
Accera provides an easy way to add all the functions that correspond to the parameter grid at once:
```python
parameters = get_parameters_from_grid(parameter_grid={P0:[8,16], P1:[16,32], P2:[16], P3:[1.0,2.0]})
package.add(nest, args=(A, B, C), base_name="matmul", parameters)
```
In this case, `package.add` generates a function eight times, once for each parameter combination in the grid. Instead of `nest`, this function could take a schedule or a plan. All eight functions share the same base name, and Accera automatically adds a unique suffix to each function name to prevent duplicates.
This pattern allows you to optionally perform filtering by inspecting the list of generated parameter values before calling `package.add`.
In this case, `package.add` generates a function eight times, once for each parameter combination in the grid. Instead of `nest`, this function can take a schedule or a plan. All eight functions share the same base name. However, Accera automatically adds a unique suffix to each function name to prevent duplication. This pattern allows optional filtering by inspecting the generated parameter values list before calling `package.add`.


<div style="page-break-after: always;"></div>
20 changes: 10 additions & 10 deletions docs/Manual/10 Packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,45 @@
[//]: # (Version: v1.2.1)

# Section 10: Building Packages
The Accera `Package` class represents a collection of Accera-generated functions. When a package is built, it creates a stand-alone function library that can be used by other pieces of software. Accera currently supports two package formats: HAT and MLIR.
The `Package` class represents a collection of Accera-generated functions. Whenever a package is built, it creates a stand-alone function library that other pieces of software can use. Currently, Accera supports two package formats: HAT and MLIR.

## HAT package format
[HAT](https://github.com/microsoft/hat) is a format for packaging compiled libraries in the C programming language. HAT stands for "Header Annotated with TOML", which implies that a standard C header is decorated with useful metadata in the TOML markup language.
[HAT](https://github.com/microsoft/hat) "Header Annotated with TOML" is a format for packaging compiled libraries in the C programming language. HAT implies that a standard C header is styled with useful metadata in the TOML markup language.

Say that `nest` contains some loop-nest logic. To build a HAT package that contains a function with this logic for the Windows operating system, we do the following:
Consider a nest that holds some loop-nest logic. To build a HAT package containing a function with this logic for the Windows operating system, we write the following lines of code:
```python
package = acc.Package()
package.add(nest, base_name="func1")
package.build(format=acc.Package.Format.HAT_DYNAMIC, name="myPackage", platform=acc.Package.Platform.WINDOWS)
package.build(format=acc.Package.Format.HAT_DYNAMIC, name="myPackage", platform=acc.Packag+-e.Platform.WINDOWS)
```

The result is two files: `MyPackage.hat` and `MyPackage.lib`. The output directory defaults to the current working directory. To change the output directory:
The result will be two files: `myPackage.hat` and `myPackage.dll`. The output directory defaults to current working directory. We can change the output directory with `output_dir` set to a relative or absolute path:

```python
package.build(format=acc.Package.Format.HAT_DYNAMIC, name="myPackage", platform=acc.Package.Platform.WINDOWS, output_dir="hat_packages")
```

## MLIR package format
MLIR format is mainly used for debugging purposes, and as a way to follow the multiple lowering MLIR stages, from Accera DSL all the way to runnable code.
MLIR format is primarily used for debugging the multiple stages of MLIR lowering, from the Accera DSL all the way to runnable code.
```python
package.build(format=acc.Package.Format.MLIR, name="myPackage")
```

## Function names in packages
When a function is added to a package, the user specifies its base name. The full function name is the base name followed by an automatically generated unique identifier. For example, if the base name is "myFunc" then the function name could be "myFunc_8f24bef5". If no base name is given, the function name is just the automatically-generated unique identifier.
We can specify the base name of a function when it is added to a package. The full function name is the base name followed by an automatically generated unique identifier. For example, if the base name is "myFunc" then the function name could be "myFunc_8f24bef5". If no base name is defined, the automatically-generated unique identifier becomes the function name.

The unique identifier ensures that no two functions share the same name, but also makes it harder to call the function from client code. Specifically, each time that the Accera package is updated and rebuilt, the function name could change. Therefore, the HAT file also includes the client code to call the function without the unique identifier. Concretely, if the function signature in C is
The unique identifier ensures that no two functions share the same name. However, invoking the function from the client code becomes cumbersome because the function name changes each time the Accera package is updated and rebuilt. Therefore, the HAT file includes the client code to call the function without the unique identifier. Concretely, if the function signature in C is:
```
void myFunc_8f24bef5(const float* A, float* B);
```
then the HAT file also contains the line:
```
void (*myFunc)(const float* A, float* B) = myFunc_8f24bef5;
```
The above basically makes the abbreviated name `myFunc` a synonym of the full function name `myFunc_8f24bef5`. If multiple functions share the same base name, an arbitrary one of them gets the abbreviation.
The above code makes the abbreviated name `myFunc` an alias of the full function name `myFunc_8f24bef5`. If multiple functions share the same base name, the first function in the HAT file gets the alias.

## Debug mode
A package can be built with the option `mode=acc.Package.Mode.DEBUG`. This creates a special version of each function that checks its own correctness each time the function is called. From the outside, a debugging package looks identical to a standard package. However, each of its functions actually contains two different implementations: the RoboCode implementation (with all of the fancy scheduling and planning) and the trivial default implementation (without any of the scheduling or planning). When called, the function runs both implementations and asserts that their outputs are within some predefined tolerance. If the outputs don't match, the function prints error messages to `stderr`.
A package can be built with` mode=acc.Package.Mode.DEBUG`. Doing so creates a special version of each function that validates its own correctness every time the function is called. From the outside, a debugging package looks identical to a standard package. However, each of its functions actually contains two different implementations: the Accera implementation (with all of the fancy scheduling and planning) and the trivial default implementation (without any scheduling or planning). When called, the function runs both implementations and asserts that their outputs are within the predefined tolerance. If the outputs don't match, the function prints error messages to `stderr`.
```python
package.build(format=acc.Package.Format.HAT_DYNAMIC, name="myPackage", mode=acc.Package.Mode.DEBUG, tolerance=1.0e-6)
```
Expand Down