-
Notifications
You must be signed in to change notification settings - Fork 181
[WIP] #3025
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
base: main
Are you sure you want to change the base?
[WIP] #3025
Changes from all commits
16df05e
6d4af17
dd1cbb5
50821eb
7522a18
619a13b
15c1515
f2221c6
268d110
7092069
a04222f
8b8d2dc
c57eff5
9247b0a
4b3cccd
46e60ff
0de06cd
2d711fe
05dc9f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,28 +7,23 @@ | |||||||||||||||||
| from ml_dtypes import bfloat16 | ||||||||||||||||||
| import numpy as np | ||||||||||||||||||
| import sys | ||||||||||||||||||
| import os | ||||||||||||||||||
|
|
||||||||||||||||||
| import aie.iron as iron | ||||||||||||||||||
| from aie.iron import ExternalFunction | ||||||||||||||||||
| from aie.iron import Compile, ExternalFunction, In, Out | ||||||||||||||||||
| from aie.iron import ObjectFifo, Program, Runtime, Worker, Buffer | ||||||||||||||||||
| from aie.utils.config import cxx_header_path | ||||||||||||||||||
| from aie.iron.placers import SequentialPlacer | ||||||||||||||||||
| from aie.iron.controlflow import range_ | ||||||||||||||||||
| from aie.helpers.util import np_ndarray_type_get_shape | ||||||||||||||||||
| from aie.helpers.dialects.scf import if_, else_ | ||||||||||||||||||
| from aie.utils.config import cxx_header_path | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| # JIT decorator for IRON | ||||||||||||||||||
| # Decorator to compile an IRON kernel into a binary to run on the NPU. | ||||||||||||||||||
| # Parameters: | ||||||||||||||||||
| # - use_cache (bool): Use cached MLIR module if available. Defaults to True. | ||||||||||||||||||
| @iron.jit | ||||||||||||||||||
| def vector_reduce_max(input0, output): | ||||||||||||||||||
| element_type = output.dtype | ||||||||||||||||||
|
|
||||||||||||||||||
| in_tensor_size = input0.shape[0] # Input tensor size | ||||||||||||||||||
| out_tensor_size = output.shape[0] # Output tensor size | ||||||||||||||||||
| def vector_reduce_max(input0: In, output: Out, *, in_tensor_size: Compile[int], element_type: Compile[type]): | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [black] reported by reviewdog 🐶
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| n_cores = 4 | ||||||||||||||||||
| N = 2048 | ||||||||||||||||||
|
|
@@ -43,7 +38,12 @@ def vector_reduce_max(input0, output): | |||||||||||||||||
| in_ty = np.ndarray[(in_tensor_size,), np.dtype[element_type]] | ||||||||||||||||||
| mem_ty = np.ndarray[(N,), np.dtype[element_type]] | ||||||||||||||||||
| op_ty = np.ndarray[(elems_per_core,), np.dtype[element_type]] | ||||||||||||||||||
| out_ty = np.ndarray[(out_tensor_size,), np.dtype[element_type]] | ||||||||||||||||||
| # DMA transfers must be 4-byte aligned; pad to the minimum element count | ||||||||||||||||||
| # that satisfies this: ceil(4 / itemsize). | ||||||||||||||||||
| _dma_align = 4 | ||||||||||||||||||
| _itemsize = np.dtype(element_type).itemsize | ||||||||||||||||||
| out_elems = (_dma_align + _itemsize - 1) // _itemsize | ||||||||||||||||||
| out_ty = np.ndarray[(out_elems,), np.dtype[element_type]] | ||||||||||||||||||
|
|
||||||||||||||||||
| # Input A and Output C | ||||||||||||||||||
| of_in = ObjectFifo(mem_ty, name="of_in") | ||||||||||||||||||
|
|
@@ -68,30 +68,33 @@ def vector_reduce_max(input0, output): | |||||||||||||||||
| names=[f"memA{i}" for i in range(n_cores)], | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| min_val = np.array([bfloat16(float("-inf"))], dtype=element_type) | ||||||||||||||||||
| min_val = np.full(out_elems, bfloat16(float("-inf")), dtype=element_type) | ||||||||||||||||||
| nextC_buffers = [] | ||||||||||||||||||
| tmp_buffers = [] | ||||||||||||||||||
| for i in range(n_cores): | ||||||||||||||||||
| out_fifos.append(ObjectFifo(out_ty, name=f"memC{i}")) | ||||||||||||||||||
| nextC_buffers.append( | ||||||||||||||||||
| Buffer( | ||||||||||||||||||
| type=np.ndarray[(out_tensor_size,), np.dtype[element_type]], | ||||||||||||||||||
| type=out_ty, | ||||||||||||||||||
| initial_value=min_val, | ||||||||||||||||||
| ) | ||||||||||||||||||
| ) | ||||||||||||||||||
| tmp_buffers.append( | ||||||||||||||||||
| Buffer( | ||||||||||||||||||
| type=np.ndarray[(out_tensor_size,), np.dtype[element_type]], | ||||||||||||||||||
| type=out_ty, | ||||||||||||||||||
| initial_value=min_val, | ||||||||||||||||||
| ) | ||||||||||||||||||
| ) | ||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||
| # Task each core will run | ||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||
|
|
||||||||||||||||||
| # Use ExternalFunction with a 2-element output buffer (4 bytes) for DMA alignment. | ||||||||||||||||||
| # kernels.reduce_max() uses a 1-element output which is only 2 bytes for bfloat16, | ||||||||||||||||||
| # violating the 4-byte DMA alignment requirement. | ||||||||||||||||||
| reduce_max_vector = ExternalFunction( | ||||||||||||||||||
| f"reduce_max_vector_bfloat16", | ||||||||||||||||||
| source_file=os.path.join(os.path.dirname(__file__), "reduce_max_vector.cc"), | ||||||||||||||||||
| "reduce_max_vector_bfloat16", | ||||||||||||||||||
| source_file=cxx_header_path() + "/aie_kernels/aie2/reduce_max.cc", | ||||||||||||||||||
| arg_types=[op_ty, out_ty, np.int32], | ||||||||||||||||||
| include_dirs=[cxx_header_path()], | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
@@ -183,21 +186,17 @@ def main(): | |||||||||||||||||
| out_size = 4 | ||||||||||||||||||
| element_type = bfloat16 | ||||||||||||||||||
|
|
||||||||||||||||||
| assert ( | ||||||||||||||||||
| out_size == 4 | ||||||||||||||||||
| ), "Output buffer must be size 4 (4 bytes = 2 bfloat16 elements)." | ||||||||||||||||||
|
|
||||||||||||||||||
| in_tensor_size = in_size // element_type(0).nbytes | ||||||||||||||||||
| out_tensor_size = out_size // element_type(0).nbytes | ||||||||||||||||||
|
|
||||||||||||||||||
| # Construct an input tensor and an output zeroed tensor | ||||||||||||||||||
| # The two tensors are in memory accessible to the NPU | ||||||||||||||||||
| # Allocate output with enough elements for 4-byte DMA alignment. | ||||||||||||||||||
| _dma_align = 4 | ||||||||||||||||||
| out_elems = (_dma_align + element_type(0).nbytes - 1) // element_type(0).nbytes | ||||||||||||||||||
| input0 = iron.arange(in_tensor_size, dtype=element_type, device="npu") | ||||||||||||||||||
| output = iron.arange(out_tensor_size, dtype=element_type, device="npu") | ||||||||||||||||||
| output = iron.zeros(out_elems, dtype=element_type, device="npu") | ||||||||||||||||||
|
|
||||||||||||||||||
| # JIT-compile the kernel then launches the kernel with the given arguments. Future calls | ||||||||||||||||||
| # to the kernel will use the same compiled kernel and loaded code objects | ||||||||||||||||||
| vector_reduce_max(input0, output) | ||||||||||||||||||
| vector_reduce_max(input0, output, in_tensor_size=in_tensor_size, element_type=element_type) | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [black] reported by reviewdog 🐶
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| # Check the correctness of the result and print. | ||||||||||||||||||
| # Initialize to -inf so the reference is correct for all-negative inputs. | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,7 +9,7 @@ | |||||||||||||||||||||||
| import os | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import aie.iron as iron | ||||||||||||||||||||||||
| from aie.iron import ExternalFunction, jit | ||||||||||||||||||||||||
| from aie.iron import Compile, ExternalFunction, In, Out, jit | ||||||||||||||||||||||||
| from aie.iron import Kernel, ObjectFifo, Program, Runtime, Worker | ||||||||||||||||||||||||
| from aie.iron.placers import SequentialPlacer | ||||||||||||||||||||||||
| from aie.iron.controlflow import range_ | ||||||||||||||||||||||||
|
|
@@ -22,16 +22,13 @@ | |||||||||||||||||||||||
| # Parameters: | ||||||||||||||||||||||||
| # - use_cache (bool): Use cached MLIR module if available. Defaults to True. | ||||||||||||||||||||||||
| @iron.jit | ||||||||||||||||||||||||
| def matrix_multiplication_single_core(input0, input1, output): | ||||||||||||||||||||||||
| def matrix_multiplication_single_core(input0: In, input1: In, output: Out, *, M: Compile[int], K: Compile[int], N: Compile[int], element_type: Compile[type]): | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [black] reported by reviewdog 🐶
Suggested change
|
||||||||||||||||||||||||
| # Problem size | ||||||||||||||||||||||||
| # - matrix0 shapes: (M, K) | ||||||||||||||||||||||||
| # - matrix1 shapes: (K, N) | ||||||||||||||||||||||||
| M, K, N = input0.shape[0], input0.shape[1], input1.shape[1] | ||||||||||||||||||||||||
| m, k, n = 64, 64, 64 # Tile size moved to/from the compute cores via mem tiles | ||||||||||||||||||||||||
| r, s, t = 8, 2, 8 # AIE kernel intrinsic size | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| element_type = output.dtype | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||||||||
| # In-Array Data Movement | ||||||||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||||||||
|
|
@@ -176,7 +173,7 @@ def main(): | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # JIT-compile the kernel then launches the kernel with the given arguments. Future calls | ||||||||||||||||||||||||
| # to the kernel will use the same compiled kernel and loaded code objects | ||||||||||||||||||||||||
| matrix_multiplication_single_core(input0, input1, output) | ||||||||||||||||||||||||
| matrix_multiplication_single_core(input0, input1, output, M=M, K=K, N=N, element_type=element_type) | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [black] reported by reviewdog 🐶
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Check the correctness of the result | ||||||||||||||||||||||||
| e = np.equal(ref_vec.flatten(), output.numpy()) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[black] reported by reviewdog 🐶