Skip to content

Taichi Python Runtime Overhead Optimization (Ndarray) #3915

Description

@qiao-bo

Currently, Taichi experiences an noticeable amount of python overhead when executing light kernels using Field or Ndarray. Using cProfile and/or pyinstrument, we can identify a few hot spots that incur this python runtime overhead. Here is an example using pyinstrument:

import taichi as ti
from pyinstrument import Profiler
from pyinstrument.renderers import ConsoleRenderer

ti.init(arch=ti.cuda)

N = 4096
a = ti.ndarray(ti.i32, N)

@ti.kernel
def fill_ones(a: ti.any_arr()):
    for i in a:
        a[i] = 1

def repeat_execution(n):
    for _ in range(n):
        fill_ones(a)

# initial run
repeat_execution(100)

# start profiling
profiler = Profiler()
profiler.start()
repeat_execution(10000)
session = profiler.stop()
profile_renderer = ConsoleRenderer(unicode=True, color=True, show_all=True)
print(profile_renderer.render(session))

On my PC with rtx 3080+i9 11900K, the output is

[Taichi] version 0.8.9, llvm 10.0.0, commit 345f0f04, linux, python 3.9.7
[Taichi] Starting on arch=cuda
[I 12/23/21 14:57:27.289 296821] [llvm_program.cpp:LlvmProgramImpl@84] CUDA max blocks per SM = 16

  _     ._   __/__   _ _  _  _ _/_   Recorded: 14:57:27  Samples:  205
 /_//_/// /_\ / //_// / //_'/ //     Duration: 0.205     CPU time: 0.206
/   _/                      v4.1.1

Program: test.py

0.205 <module>  test1.py:1
└─ 0.205 repeat_execution  test1.py:16
   └─ 0.203 wrapped  taichi/lang/kernel_impl.py:712
      ├─ 0.198 __call__  taichi/lang/kernel_impl.py:634
      │  ├─ 0.134 func__  taichi/lang/kernel_impl.py:485
      │  │  ├─ 0.123 [self]  
      │  │  ├─ 0.005 current_cfg  taichi/lang/impl.py:906
      │  │  │  └─ 0.005 PyCapsule.current_compile_config  <built-in>:0
      │  │  └─ 0.003 match_ext_arr  taichi/lang/kernel_impl.py:619
      │  ├─ 0.056 ensure_compiled  taichi/lang/kernel_impl.py:626
      │  │  ├─ 0.043 lookup  taichi/lang/kernel_impl.py:311
      │  │  │  ├─ 0.034 extract  taichi/lang/kernel_impl.py:305
      │  │  │  │  ├─ 0.024 extract_arg  taichi/lang/kernel_impl.py:257
      │  │  │  │  │  ├─ 0.013 [self]  
      │  │  │  │  │  ├─ 0.005 dtype  taichi/lang/_ndarray.py:53
      │  │  │  │  │  └─ 0.004 shape  taichi/lang/_ndarray.py:251
      │  │  │  │  └─ 0.009 [self]  
      │  │  │  ├─ 0.006 [self]  
      │  │  │  └─ 0.003 __hash__  enum.py:774
      │  │  └─ 0.011 materialize  taichi/lang/kernel_impl.py:430
      │  │     └─ 0.010 materialize  taichi/lang/impl.py:355
      │  │        ├─ 0.007 materialize_root_fb  taichi/lang/impl.py:303
      │  │        │  ├─ 0.004 __getattr__  taichi/lang/impl.py:544
      │  │        │  └─ 0.003 [self]  
      │  │        └─ 0.003 [self]  
      │  └─ 0.008 [self]  
      └─ 0.005 [self]  

Potential hot spots: func__ which executes the kernel (in the [self] time), or ensure_compiled. @ailzhang has commited a fix to remove some property used in Taichi (PR 3910). In addition, we can also check the cost of is_instance(). And also the performance of Matrix/Vector Ndarray, which may expose further bottlenecks.

comments/suggestions are welcome!

Metadata

Metadata

Assignees

No one assigned

    Labels

    pythonPython engineering related

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions