Skip to content

Commit

Permalink
update doc
Browse files Browse the repository at this point in the history
  • Loading branch information
archibate committed Jul 14, 2020
1 parent b3e6dd1 commit b581cee
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 17 deletions.
19 changes: 19 additions & 0 deletions a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from time import sleep
import taichi as ti
ti.init()

def do_something_A():
sleep(0.01)

def do_something_B():
sleep(0.1)

ti.profiler.start('A')
do_something_A()
ti.profiler.stop('A')

ti.profiler.start('B')
do_something_B()
ti.profiler.stop('B')

ti.profiler.print()
181 changes: 164 additions & 17 deletions docs/profiler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,157 @@
Profiler
========

Taichi's profiler can help you analyze the run-time cost of your program. There are two profiling systems in Taichi: ``ScopedProfiler`` and ``KernelProfiler``.
Taichi's profiler can help you analyze the run-time cost of your program.

ScopedProfiler
Currently there are three profiling systems in Taichi:

- ``PythonProfiler``
- ``KernelProfiler``
- ``ScopedProfiler`` (for developers)



PythonProfiler
##############

1. ``ScopedProfiler`` measures time spent on the **host tasks** hierarchically.
``PythonProfiler`` basically measures time spent between ``start()`` and ``stop()`` using
the Python-builtin function ``time.time()``.

There are 3 ways to use this profiler:

2. This profiler is automatically on. To show its results, call ``ti.print_profile_info()``. For example:
1. ``ti.profiler.start()`` and ``ti.profiler.stop()``, these are the most fundemental APIs:

.. code-block:: python
from time import sleep
import taichi as ti
ti.init()
ti.init(arch=ti.cpu)
var = ti.var(ti.f32, shape=1)
def do_something_A():
sleep(0.01)
def do_something_B():
sleep(0.1)
@ti.kernel
def compute():
var[0] = 1.0
print("Setting var[0] =", var[0])
ti.profiler.start('A')
do_something_A()
ti.profiler.stop('A')
ti.profiler.start('B')
do_something_B()
ti.profiler.stop('B')
compute()
ti.print_profile_info()
ti.profiler.print()
``ti.print_profile_info()`` prints profiling results in a hierarchical format.
2. ``ti.profiler()``, this one makes our code cleaner:

.. Note::
.. code-block:: python
from time import sleep
import taichi as ti
ti.init()
def do_something_A():
sleep(0.01)
def do_something_B():
sleep(0.1)
ti.profiler('A') # start('A')
do_something_A()
ti.profiler('B') # stop('A') & start('B')
do_something_B()
ti.profiler() # stop('B')
ti.profiler.print()
.. note::

Running 1 and 2 should obtain something like:

.. code-block:: none
min | avg | max | num | total | name
0.100s | 0.100s | 0.100s | 1x | 0.100s | B
10.10ms | 10.10ms | 10.10ms | 1x | 10.10ms | A
3. ``@ti.profiler.timed``, this one is very intuitive when profiling kernels:

.. code-block:: python
from time import sleep
import taichi as ti
ti.init()
@ti.profiler.timed
def do_something_A():
sleep(0.01)
@ti.profiler.timed
def do_something_B():
sleep(0.1)
do_something_A()
do_something_B()
ti.profiler.print()
When combining ``@ti.profiler.timed`` with other decorators like ``@ti.kernel``,
then ``@ti.profiler.timed`` should be put **above** it, e.g.:

.. code-block:: python
@ti.profiler.timed
@ti.kernel
def substep():
...
.. note::

Running 3 should obtain something like:

.. code-block:: none
min | avg | max | num | total | name
0.100s | 0.100s | 0.100s | 1x | 0.100s | do_something_B
10.10ms | 10.10ms | 10.10ms | 1x | 10.10ms | do_something_A
See `misc/mpm99_timed.py <https://github.com/taichi-dev/taichi/blob/master/misc/mpm99_timed.py>`_ for their usage example.


.. warning::

``ti.profiler``, i.e. ``PythonProfiler``, **only works in Python-scope**, e.g.::

@ti.func
def substep():
ti.profiler.start('hello') # won't work as you expected...
...
ti.profiler.stop('hello')

@ti.profiler.timed # won't work as you expected...
@ti.func
def hello():
...

To do profiling **inside Taichi-scope**, please see the ``KernelProfiler`` section below.

``ScopedProfiler`` is a C++ class in the core of Taichi. It is not exposed to Python users.

KernelProfiler
##############

1. ``KernelProfiler`` records the costs of Taichi kernels on devices. To enable this profiler, set ``kernel_profiler=True`` in ``ti.init``.
``KernelProfiler`` records the costs of Taichi kernels on devices.

2. Call ``ti.kernel_profiler_print()`` to show the kernel profiling result. For example:
To enable this profiler, please initialize Taichi using ``ti.init(kernel_profiler=True)``.

Call ``ti.kernel_profiler_print()`` to show the kernel profiling result. For example:

.. code-block:: python
:emphasize-lines: 3, 13
Expand All @@ -67,3 +179,38 @@ The outputs would be:
[ 22.73%] jit_evaluator_0_kernel_0_serial min 0.001 ms avg 0.001 ms max 0.001 ms total 0.000 s [ 1x]
[ 0.00%] jit_evaluator_1_kernel_1_serial min 0.000 ms avg 0.000 ms max 0.000 ms total 0.000 s [ 1x]
[ 77.27%] compute_c4_0_kernel_2_serial min 0.004 ms avg 0.004 ms max 0.004 ms total 0.000 s [ 1x]


ScopedProfiler
##############

``ScopedProfiler`` measures time spent on the **host tasks** hierarchically.

This profiler is automatically on.

To show its results, call ``ti.print_profile_info()``. For example:

.. code-block:: python
import taichi as ti
ti.init(arch=ti.cpu)
var = ti.var(ti.f32, shape=1)
@ti.kernel
def compute():
var[0] = 1.0
print("Setting var[0] =", var[0])
compute()
ti.print_profile_info()
``ti.print_profile_info()`` prints profiling results in a hierarchical format.

.. Note::

``ScopedProfiler`` is a C++ class in the core of Taichi. It is not exposed to Python users.

0 comments on commit b581cee

Please sign in to comment.