.. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_tutorial_01_get_started.py: Getting Started =============== **Author**: Yi-Hsiang Lai (seanlatias@github) In this tutorial, we demonstrate the basic usage of HeteroCL. Import HeteroCL --------------- We usually use ``hcl`` as the acronym of HeteroCL. .. code-block:: default import heterocl as hcl Initialize the Environment -------------------------- We need to initialize the environment for each HeteroCL application. We can do this by calling the API ``hcl.init()``. We can also set the default data type for every computation via this API. The default data type is **32-bit** integers. .. note:: For more information on the data types, please see :ref:`sphx_glr_tutorials_tutorial_05_dtype.py`. .. code-block:: default hcl.init() Algorithm Definition -------------------- After we initialize, we define the algorithm by using a Python function definition, where the arguments are the input tensors. The function can optionally return tensors as outputs. In this example, the two inputs are a scalar `a` and a tensor `A`, and the output is also a tensor `B`. The main difference between a scalar and a tensor is that *a scalar cannot be updated*. Within the algorithm definition, we use HeteroCL APIs to describe the operations. In this example, we use a tensor-based declarative-style operation ``hcl.compute``. We also show the equivalent Python code. .. note:: For more information on the APIs, please see :ref:`sphx_glr_tutorials_tutorial_03_api.py` .. code-block:: default def simple_compute(a, A): B = hcl.compute(A.shape, lambda x, y: A[x, y] + a, "B") """ The above API is equivalent to the following Python code. for x in range(0, 10): for y in range(0, 10): B[x, y] = A[x, y] + a """ return B Inputs/Outputs Definition ------------------------- One of the advantages of such *modularized algorithm definition* is that we can reuse the defined function with different input settings. We use ``hcl.placeholder`` to set the inputs, where we specify the shape, name, and data type. The shape must be specified and should be in the form of a **tuple**. If it is empty (i.e., `()`), the returned object is a *scalar*. Otherwise, the returned object is a *tensor*. The rest two fields are optional. In this example, we define a scalar input `a` and a two-dimensional tensor input `A`. .. note:: For more information on the interfaces, please see :obj:`heterocl.placeholder` .. code-block:: default a = hcl.placeholder((), "a") A = hcl.placeholder((10, 10), "A") Apply Hardware Customization ---------------------------- Usually, our next step is apply various hardware customization techniques to the application. In this tutorial, we skip this step which will be discussed in the later tutorials. However, we still need to build a default schedule by using ``hcl.create_schedule`` whose inputs are a list of inputs and the Python function that defines the algorithm. .. code-block:: default s = hcl.create_schedule([a, A], simple_compute) Inspect the Intermediate Representation (IR) -------------------------------------------- A HeteroCL program will be lowered to an IR before backend code generation. HeteroCL provides an API for users to inspect the lowered IR. This could be helpful for debugging. .. code-block:: default print(hcl.lower(s)) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none // attr [_top] storage_scope = "global" allocate _top[int32 * 1] produce _top { // attr [0] extern_scope = 0 produce B { // attr [0] extern_scope = 0 for (x, 0, 10) { for (y, 0, 10) { B[(y + (x*10))] = int32((int33(A[(y + (x*10))]) + int33(a))) } } } } Create the Executable --------------------- The next step is to build the executable by using ``hcl.build``. You can define the target of the executable, where the default target is `llvm`. Namely, the executable will be run on CPU. The input for this API is the schedule we just created. .. code-block:: default f = hcl.build(s) Prepare the Inputs/Outputs for the Executable --------------------------------------------- To run the generated executable, we can feed it with Numpy arrays by using ``hcl.asarray``. This API transforms a Numpy array to a HeteroCL container that is used as inputs/outputs to the executable. In this tutorial, we randomly generate the values for our input tensor `A`. Note that since we return a new tensor at the end of our algorithm, we also need to prepare an input array for tensor `B`. .. code-block:: default import numpy as np hcl_a = 10 np_A = np.random.randint(100, size = A.shape) hcl_A = hcl.asarray(np_A) hcl_B = hcl.asarray(np.zeros(A.shape)) Run the Executable ------------------ With the prepared inputs/outputs, we can finally feed them to our executable. .. code-block:: default f(hcl_a, hcl_A, hcl_B) View the Results ---------------- To view the results, we can transform the HeteroCL tensors back to Numpy arrays by using ``asnumpy()``. .. code-block:: default np_A = hcl_A.asnumpy() np_B = hcl_B.asnumpy() print(hcl_a) print(np_A) print(np_B) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none 10 [[18 9 4 4 91 23 15 50 6 25] [72 3 67 20 35 45 27 60 52 44] [ 3 99 37 87 24 52 16 92 9 10] [84 67 36 68 49 54 29 28 22 1] [22 52 45 0 25 23 68 3 28 17] [14 69 71 64 94 70 98 55 33 30] [15 97 99 41 47 95 18 45 8 64] [65 74 99 6 31 4 64 21 1 22] [13 19 9 23 93 74 59 34 18 83] [45 78 89 48 98 31 70 12 69 14]] [[ 28 19 14 14 101 33 25 60 16 35] [ 82 13 77 30 45 55 37 70 62 54] [ 13 109 47 97 34 62 26 102 19 20] [ 94 77 46 78 59 64 39 38 32 11] [ 32 62 55 10 35 33 78 13 38 27] [ 24 79 81 74 104 80 108 65 43 40] [ 25 107 109 51 57 105 28 55 18 74] [ 75 84 109 16 41 14 74 31 11 32] [ 23 29 19 33 103 84 69 44 28 93] [ 55 88 99 58 108 41 80 22 79 24]] Let's run a test .. code-block:: default assert np.array_equal(np_B, np_A + 10) .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 0.065 seconds) .. _sphx_glr_download_tutorials_tutorial_01_get_started.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download :download:`Download Python source code: tutorial_01_get_started.py ` .. container:: sphx-glr-download :download:`Download Jupyter notebook: tutorial_01_get_started.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_