Skip to content

Commit

Permalink
[Doc] [cc] Doc the workflow for exporting Taichi kernels to C99 source (
Browse files Browse the repository at this point in the history
#1756)

* tmp save

* revert

* wip ok

* [skip ci] update links

* wewe

* revert 2

* fix rendering issue

* [skip ci] enforce code format

* [skip ci] WIP

* [skip ci] Apply suggestions from code review

Co-authored-by: Xudong Feng <xudongfeng1996@gmail.com>

* [skip ci] Apply suggestions from code review

Co-authored-by: Samuel Ainsworth <skainsworth@gmail.com>

* [skip ci] doc cc: add 'C source' to support table

* [skip ci] Apply suggestions from code review

Co-authored-by: Chengchen(Rex) Wang <14366016+rexwangcc@users.noreply.github.com>

* [skip ci] Apply suggestions from code review

Co-authored-by: Yuanming Hu <yuanming-hu@users.noreply.github.com>

Co-authored-by: Taichi Gardener <taichigardener@gmail.com>
Co-authored-by: Xudong Feng <xudongfeng1996@gmail.com>
Co-authored-by: Samuel Ainsworth <skainsworth@gmail.com>
Co-authored-by: Chengchen(Rex) Wang <14366016+rexwangcc@users.noreply.github.com>
Co-authored-by: Yuanming Hu <yuanming-hu@users.noreply.github.com>
  • Loading branch information
6 people authored Sep 3, 2020
1 parent ded4c17 commit de26d08
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 52 deletions.
22 changes: 11 additions & 11 deletions docs/atomic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ Below is a list of all explicit atomic operations:

Supported atomic operations on each backend:

+----------+-----------+-----------+---------+
| type | CPU/CUDA | OpenGL | Metal |
+==========+===========+===========+=========+
| ``i32`` | OK | OK | OK |
+----------+-----------+-----------+---------+
| ``f32`` | OK | OK | OK |
+----------+-----------+-----------+---------+
| ``i64`` | OK | EXT | N/A |
+----------+-----------+-----------+---------+
| ``f64`` | OK | EXT | N/A |
+----------+-----------+-----------+---------+
+------+-----------+-----------+---------+----------+
| type | CPU/CUDA | OpenGL | Metal | C source |
+======+===========+===========+=========+==========+
| i32 | OK | OK | OK | OK |
+------+-----------+-----------+---------+----------+
| f32 | OK | OK | OK | OK |
+------+-----------+-----------+---------+----------+
| i64 | OK | EXT | N/A | OK |
+------+-----------+-----------+---------+----------+
| f64 | OK | EXT | N/A | OK |
+------+-----------+-----------+---------+----------+

(OK: supported; EXT: require extension; N/A: not available)
205 changes: 205 additions & 0 deletions docs/export_kernels.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
Export Taichi kernels to C source
=================================

The C backend of Taichi allows you to **export Taichi kernels to C source**.

The exported Taichi program consists purely of C99-compatible code and does not require Python. This allows you to use the exported code in a C/C++ project, or even to further compile it to Javascript/Web Assembly via Emscripten.

Each C function corresponds to one Taichi kernel.
For example, ``Tk_init_c6_0()`` may correspond to ``init()`` in ``mpm88.py``.

The exported C code is self-contained for portability. Required Taichi runtime functions are included in the code.

For example, this allows programmers to distribute Taichi programs in
a binary format, by compiling and linking exported C code to their project.

.. warning::

Currently, this feature is only officially supported on the C backend on Linux. In the future, we will support OS X and Windows.


The workflow of exporting
-------------------------

Use ``ti.core.start_recording`` in the Taichi program you want to export.

Suppose you want to export `examples/mpm88.py <https://github.com/taichi-dev/taichi/blob/master/examples/mpm88.py>`_, here is the workflow:

Export YAML
+++++++++++

First, modify ``mpm88.py`` as shown below:

.. code-block:: python
import taichi as ti
ti.core.start_recording('mpm88.yml')
ti.init(arch=ti.cc)
... # your program
Then please execute ``mpm88.py``. Close the GUI window once particles are shown up correctly.

This will save all the kernels in ``mpm88.py`` to ``mpm88.yml``:

.. code-block:: yaml
- action: "compile_kernel"
kernel_name: "init_c6_0"
kernel_source: "void Tk_init_c6_0(struct Ti_Context *ti_ctx) {\n for (Ti_i32 tmp0 = 0; tmp0 < 8192...\n"
- action: "launch_kernel"
kernel_name: "init_c6_0"
...
.. note::

Equivalently, you may also specify these two arguments from environment
variables on Unix-like system:

.. code-block:: bash
TI_ARCH=cc TI_ACTION_RECORD=mpm88.yml python mpm88.py
Compose YAML into a single C file
+++++++++++++++++++++++++++++++++

Now, all necessary information is saved in ``mpm88.yml``, in the form of multiple separate records.
You may want to **compose** the separate kernels into **one single file** for more portability.

We provide a useful CLI tool to do this:

.. code-block:: bash
python3 -m taichi cc_compose mpm88.yml mpm88.c mpm88.h
This composes all the kernels and runtimes in ``mpm88.yml`` into a single C
source file ``mpm88.c``:

.. code-block:: c
...
Ti_i8 Ti_gtmp[1048576];
union Ti_BitCast Ti_args[8];
Ti_i32 Ti_earg[8 * 8];
struct Ti_Context Ti_ctx = { // statically-allocated context for convenience!
&Ti_root, Ti_gtmp, Ti_args, Ti_earg,
};
void Tk_init_c6_0(struct Ti_Context *ti_ctx) {
for (Ti_i32 tmp0 = 0; tmp0 < 8192; tmp0 += 1) {
Ti_i32 tmp1 = tmp0;
Ti_f32 tmp2 = Ti_rand_f32();
Ti_f32 tmp3 = Ti_rand_f32();
Ti_f32 tmp4 = 0.4;
Ti_f32 tmp5 = tmp2 * tmp4;
...
... and a C header file ``mpm88.h`` for declarations of data structures, functions
(Taichi kernels) for this file.

.. note::

The generated C source is promised to be C99 compatible.

It should also be functional when compiled using a C++ compiler.


Calling the exported kernels
----------------------------

Then, link the C file (``mpm88.c``) against your C/C++ project.
Include the header file (``mpm88.h``) when Taichi kernels are called.

For example, calling kernel ``init_c6_0`` can be implemented as follows:

.. code-block:: cpp
#include "mpm88.h"
int main(void) {
...
Tk_init_c6_0(&Ti_ctx);
...
}
Alternatively, if you need multiple Taichi contexts within one program:

.. code-block:: cpp
extern "C" { // if you use mpm88.c instead of renaming it to mpm88.cpp
#include "mpm88.h"
}
class MyRenderer {
...
struct Ti_Context per_renderer_taichi_context;
...
};
MyRenderer::MyRenderer() {
// allocate buffers on your own:
per_renderer_taichi_context.root = malloc(...);
...
Tk_init_c6_0(&per_renderer_taichi_context);
}
Specifying scalar arguments
+++++++++++++++++++++++++++

To specify scalar arguments for kernels:

.. code-block:: cpp
Ti_ctx.args[0].val_f64 = 3.14; // first argument, float64
Ti_ctx.args[1].val_i32 = 233; // second argument, int32
Tk_my_kernel_c8_0(&Ti_ctx);
double ret = Ti_ctx.args[0].val_f64; // return value, float64
printf("my_kernel(3.14, 233) = %lf\n", ret);
Passing external arrays
+++++++++++++++++++++++

To pass external arrays as arguments for kernels:

.. code-block:: cpp
float img[640 * 480 * 3];
Ti_ctx.args[0].ptr_f32 = img; // first argument, float32 pointer to array
// specify the shape of that array:
Ti_ctx.earg[0 * 8 + 0] = 640; // img.shape[0]
Ti_ctx.earg[0 * 8 + 1] = 480; // img.shape[1]
Ti_ctx.earg[0 * 8 + 2] = 3; // img.shape[2]
Tk_matrix_to_ext_arr_c12_0(&Ti_ctx);
// note that the array used in Taichi is row-major:
printf("img[3, 2, 1] = %f\n", img[(3 * 480 + 2) * 3 + 1]);
Taichi.js (WIP)
---------------

Once you have C source file generated, you can compile them into Javascript
or WASM via Emscripten.

We provide `Taichi.js <https://github.com/taichi-dev/taichi.js>`_ as an
infrastructure for wrapping Taichi kernels for Javascript.
See `its README.md <https://github.com/taichi-dev/taichi.js/blob/master/README.md>`_ for the complete workflow.

Check out `this page <https://taichi-dev.github.io/taichi.js>`_ for online demos.

Calling Taichi kernels from Julia (WIP)
---------------------------------------

Once you have C source generated, you can then compile the C source into a
shared object. Then it can be called from other langurages that provides a C
interface, including but not limited to Julia, Matlab, Mathematica, Java, etc.

TODO: WIP.
18 changes: 9 additions & 9 deletions docs/hello.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ Taichi programs run on either CPUs or GPUs. Initialize Taichi according to your

Supported backends on different platforms:

+----------+------+------+--------+-------+
| platform | CPU | CUDA | OpenGL | Metal |
+==========+======+======+========+=======+
| Windows | OK | OK | OK | N/A |
+----------+------+------+--------+-------+
| Linux | OK | OK | OK | N/A |
+----------+------+------+--------+-------+
| Mac OS X | OK | N/A | N/A | OK |
+----------+------+------+--------+-------+
+----------+------+------+--------+-------+----------+
| platform | CPU | CUDA | OpenGL | Metal | C source |
+==========+======+======+========+=======+==========+
| Windows | OK | OK | OK | N/A | N/A |
+----------+------+------+--------+-------+----------+
| Linux | OK | OK | OK | N/A | OK |
+----------+------+------+--------+-------+----------+
| Mac OS X | OK | N/A | N/A | OK | N/A |
+----------+------+------+--------+-------+----------+

(OK: supported; N/A: not available)

Expand Down
3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ The Taichi Programming Language
faq
gui
debugging
extension_libraries
export_results
cli_utilities
global_settings
export_kernels
extension_libraries
acknowledgments


Expand Down
18 changes: 18 additions & 0 deletions docs/snode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ Taichi provides *Structural Nodes (SNodes)* to compose the hierarchy and particu

* dynamic: Variable-length array, with a predefined maximum length. It serves the role of ``std::vector`` in C++ or ``list`` in Python, and can be used to maintain objects (e.g. particles) contained in a block.

.. note::

Supported SNode types on each backend:

+-----------+----------+--------+-------+----------+
| SNode | CPU/CUDA | OpenGL | Metal | C source |
+===========+==========+========+=======+==========+
| dense | OK | OK | OK | OK |
+-----------+----------+--------+-------+----------+
| bitmasked | OK | N/A | OK | N/A |
+-----------+----------+--------+-------+----------+
| pointer | OK | N/A | N/A | N/A |
+-----------+----------+--------+-------+----------+
| dynamic | OK | PAR | N/A | N/A |
+-----------+----------+--------+-------+----------+

(OK: supported; PAR: partial support; N/A: not available)


See :ref:`layout` for more details. ``ti.root`` is the root node of the data structure.

Expand Down
47 changes: 24 additions & 23 deletions docs/type.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,32 @@ Currently, supported basic types in Taichi are
- float64 ``ti.f64``

.. note::

Supported types on each backend:

+------+-----------+-----------+---------+
| type | CPU/CUDA | OpenGL | Metal |
+======+===========+===========+=========+
| i8 | OK | N/A | OK |
+------+-----------+-----------+---------+
| i16 | OK | N/A | OK |
+------+-----------+-----------+---------+
| i32 | OK | OK | OK |
+------+-----------+-----------+---------+
| i64 | OK | EXT | N/A |
+------+-----------+-----------+---------+
| u8 | OK | N/A | OK |
+------+-----------+-----------+---------+
| u16 | OK | N/A | OK |
+------+-----------+-----------+---------+
| u32 | OK | N/A | OK |
+------+-----------+-----------+---------+
| u64 | OK | N/A | N/A |
+------+-----------+-----------+---------+
| f32 | OK | OK | OK |
+------+-----------+-----------+---------+
| f64 | OK | OK | N/A |
+------+-----------+-----------+---------+
+------+-----------+-----------+---------+----------+
| type | CPU/CUDA | OpenGL | Metal | C source |
+======+===========+===========+=========+==========+
| i8 | OK | N/A | OK | OK |
+------+-----------+-----------+---------+----------+
| i16 | OK | N/A | OK | OK |
+------+-----------+-----------+---------+----------+
| i32 | OK | OK | OK | OK |
+------+-----------+-----------+---------+----------+
| i64 | OK | EXT | N/A | OK |
+------+-----------+-----------+---------+----------+
| u8 | OK | N/A | OK | OK |
+------+-----------+-----------+---------+----------+
| u16 | OK | N/A | OK | OK |
+------+-----------+-----------+---------+----------+
| u32 | OK | N/A | OK | OK |
+------+-----------+-----------+---------+----------+
| u64 | OK | N/A | N/A | OK |
+------+-----------+-----------+---------+----------+
| f32 | OK | OK | OK | OK |
+------+-----------+-----------+---------+----------+
| f64 | OK | OK | N/A | OK |
+------+-----------+-----------+---------+----------+

(OK: supported, EXT: require extension, N/A: not available)

Expand Down
Loading

0 comments on commit de26d08

Please sign in to comment.