<jupyter_start><jupyter_text>Accera Quickstart ExampleIn this example, we will:* Implement matrix multiplication with a ReLU activation (matmul + ReLU), commonly used in in machine learning algorithms  * Generate two implementations: a naive algorithm and one with loop transformations* Compare the timings of both implementations  SetupFirst, we'll install Accera using `pip`. Optional: if running this notebook locally* Linux/macOS: install gcc using `apt install gcc`.* Windows: install Microsoft Visual Studio and run `vcvars64.bat` to setup Visual Studio tools in your `PATH` before starting the Jupyter environment.<jupyter_code>!pip install accera<jupyter_output><empty_output><jupyter_text>BuildRun the code below to implement `ReLU(C + A @ B)` on arrays `A`, `B`, and `C`. We'll build a package called `"hello_accera"` that will export both versions as C functions.<jupyter_code>import accera as acc

# define placeholder inputs/output
A = acc.Array(role=acc.Array.Role.INPUT, shape=(512, 512))
B = acc.Array(role=acc.Array.Role.INPUT, shape=(512, 512))
C = acc.Array(role=acc.Array.Role.INPUT_OUTPUT, shape=(512, 512))

# implement the logic for matmul and relu
matmul = acc.Nest(shape=(512, 512, 512))
i1, j1, k1 = matmul.get_indices()
@matmul.iteration_logic
def _():
    C[i1, j1] += A[i1, k1] * B[k1, j1]

relu = acc.Nest(shape=(512, 512))
i2, j2 = relu.get_indices()
@relu.iteration_logic
def _():
    C[i2, j2] = acc.max(C[i2, j2], 0.0)

package = acc.Package()

# fuse the i and j indices of matmul and relu, add to the package
schedule = acc.fuse(matmul.create_schedule(), relu.create_schedule(), partial=2)
package.add(schedule, args=(A, B, C), base_name="matmul_relu_fusion_naive")

# transform the schedule, add to the package
# here we will focus only on the j index. For a more complete example, see:
# https://microsoft.github.io/Accera/Tutorials/Optimized_MatMul/
tile_size_j = 256
target = acc.Target(category=acc.Target.Category.CPU)

f, i, j, k = schedule.get_indices()
jj = schedule.split(j, tile_size_j)
jjj = schedule.split(jj, (target.vector_bytes // 4) * 2) # there are 2 vfma execution units, each holding (target.vector_bytes // 4) 32-bit float elements
jjjj = schedule.split(jjj, target.vector_bytes // 4) # each SIMD register holds (target.vector_bytes // 4) 32-bit float elements

schedule.reorder(j, f, k, i, jj, jjj, jjjj) # reorder the loops
plan = schedule.create_plan(target)
plan.kernelize(unroll_indices=(jjj,), vectorize_indices=jjjj) # unroll and vectorize
package.add(plan, args=(A, B, C), base_name="matmul_relu_fusion_transformed")

# build a dynamically-linked package (a .dll or .so) that exports both functions
print(package.build(name="hello_accera", format=acc.Package.Format.HAT_DYNAMIC))<jupyter_output><empty_output><jupyter_text>BenchmarkIn the previous section, we built a binary (`.so`) and a header file (`.hat`). Next, we will load the package and compare the timings of both implementations.<jupyter_code>import hatlib as hat
import numpy as np

# load the package
_, functions = hat.load("hello_accera.hat")

# call one of the functions with test inputs
A_test = np.random.rand(512, 512).astype(np.float32)
B_test = np.random.rand(512, 512).astype(np.float32)
C_test = np.zeros((512, 512)).astype(np.float32)
C_numpy = np.maximum(C_test + A_test @ B_test, 0.0)

matmul_relu = functions["matmul_relu_fusion_transformed"]
matmul_relu(A_test, B_test, C_test)

# check correctness
np.testing.assert_allclose(C_test, C_numpy, atol=1e-3)

# benchmark all functions
hat.run_benchmark("hello_accera.hat", batch_size=5, min_time_in_sec=5)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11948123620309051, 'fraction_numerical': 0.026490066225165563, 'mean_word_length': 5.663602941176471, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '36334', 'license': 'MIT', 'n_tokens_mistral': 1322, 'n_tokens_neox': 1230, 'n_words': 367, 'path': 'docs/demos/quickstart.ipynb', 'repo_name': 'lisaong/Accera', 'size': '3624'}