Skip to main content
Version: v1.0.4

Premiers Pas

Target audience

Bienvenue sur la documentation pour le langage Taichi!

Pour commencer à utiliser Taichi, simplement l'installer avec pip:

Pour les développeurs qui sont intéressés par le compilateur, les graphismes informatiques ou l'informatique haute performance, et aimerait contribuer à de nouvelles fonctionnalités ou à des corrections de bugs dans le langage de programmation Taïchi, voir l'installation de Développeur pour plus d'informations sur la construction de Taichi à partir de la source.

:::

Prerequisites

Python

D'autres étapes sont requises en fonction du système d'exploitation utilisé :

note

Pour introduire le langage de programmation Taichi, nous allons créer ensemble un exemple simple de fractal.

Champs

Plongons dans ce programme Taichi.

plateformeCPUCUDAOpenGLMetalC source
WindowsOKOKOKN/AOK
LinuxOKOKOKN/AOK
macOSOKN/AN/AOKOK
  • ✔️: supported;
  • N/A: not available

Installation

Taichi est un langage dédié (domain-specific language) intégré dans Python.

python3 -m pip install taichi

D'autres étapes sont requises en fonction du système d'exploitation utilisé :

On Arch Linux, you need to install ncurses5-compat-libs package from the Arch User Repository: yaourt -S ncurses5-compat-libs

See the Installation Troubleshooting if you run into any issues when installing Taichi.

Hello, world!

Pour introduire le langage de programmation Taichi, nous allons créer ensemble un exemple simple de fractal.

Running the Taichi code below using either python3 fractal.py or ti example fractal (you can find more information about the Taichi CLI in the Command line utilities section) will give you an animation of Julia set:

image

fractal.py
import taichi as ti

ti.init(arch=ti.gpu)

n = 320
pixels = ti.field(dtype=float, shape=(n * 2, n))

@ti.func
def complex_sqr(z):
return ti.Vector([z[0]**2 - z[1]**2, z[1] * z[0] * 2])

@ti.kernel
def paint(t: float):
for i, j in pixels: # Parallelized over all pixels
c = ti.Vector([-0.8, ti.cos(t) * 0.2])
z = ti.Vector([i / n - 1, j / n - 0.5]) * 2
iterations = 0
while z.norm() < 20 and iterations < 50:
z = complex_sqr(z) + c
iterations += 1
pixels[i, j] = 1 - iterations * 0.02

gui = ti.GUI("Julia Set", res=(n * 2, n))

i = 0
while gui.running:
paint(i * 0.03)
gui.set_image(pixels)
gui.show()
i = i + 1

Plongons dans ce programme Taichi.

import taichi as ti

Taichi est un langage dédié (domain-specific language) intégré dans Python.

To make Taichi as easy-to-use as a Python package, we have done heavy engineering with this goal in mind - letting every Python programmer write Taichi programs with minimal learning effort.

You can even use your favorite Python package management system, Python IDEs and other Python packages together with Taichi.

# Initialize Taichi and run it on CPU (default)
# - `arch=ti.gpu`: Run Taichi on GPU and has Taichi automatically detect the suitable backend
# - `arch=ti.cuda`: For the NVIDIA CUDA backend
# - `arch=ti.metal`: [macOS] For the Apple Metal backend
# - `arch=ti.opengl`: For the OpenGL backend
# - `arch=ti.vulkan`: For the Vulkan backend
# - `arch=ti.dx11`: For the DX11 backend
ti.init(arch=ti.cpu)
info
  • Avec arch=ti.gpu, Taichi essaiera d'abord de s'exécuter avec CUDA. Si CUDA n'est pas pris en charge sur votre machine, Taichi se repliera sur Metal ou OpenGL.
  • note

    Pour le moment, Taichi supporte seulement Python 3.6/3.7/3.8/3.9 (64-bit).

note

When running on the CUDA backend on Windows or ARM devices (for example NVIDIA Jetson), Taichi allocates 1 GB GPU memory for field storage by default.

To override this behavior, do either of the following:

  • Initialize Taichi using ti.init(arch=ti.cuda, device_memory_GB=3.4) to allocate 3.4 GB GPU memory,
  • Initialize Taichi using ti.init(arch=ti.cuda, device_memory_fraction=0.3) to allocate 30% of the GPU memory.

On platforms other than Windows or ARM devices, Taichi relies on its on-demand memory allocator to allocate memory adaptively.

Champs

Taichi is a data-oriented programming language where dense or spatially-sparse fields are the first-class citizens.

In the code above, pixels = ti.field(dtype=float, shape=(n * 2, n)) allocates a 2D dense field named pixels of size (640, 320) and element data type float.

Fonctions et noyaux

Le calcul réside dans les noyaux de Taichi et les fonctions de Taichi.

Les noyaux Taïchi sont définis avec le décorateur @ti.kernel. They can be called from Python to perform computation. Kernel arguments must be type-hinted (if any).

Les noyaux Taïchi sont définis avec le décorateur @ti.func. They can only be called by Taichi kernels or other Taichi functions.

See syntax for more details about Taichi kernels and functions.

The language used in Taichi kernels and functions looks exactly like Python, yet the Taichi frontend compiler converts it into a language that is compiled, statically-typed, lexically-scoped, parallel and differentiable.

info

Taichi scope vs. Python scope:

Everything decorated with @ti.kernel and @ti.func is in the Taichi scope and hence will be compiled by the Taichi compiler. Everything else is in the Python scope. C'est simplement du code natif Python.

caution
  • Les noyaux de Taichi doivent être appelés à partir du scope Python.
  • Pour ceux qui vienne de CUDA, ti.func correspond à __device__ et ti.kernel correspond à __global__.
tip

Pour ceux qui vienne de CUDA, ti.func correspond à __device__ et ti.kernel correspond à __global__.

note
  • Les noyaux imbriqués ne sont pas pris en charge.
  • Les fonctions imbriquées sont prises en charge.
  • Recursive functions are not supported for now.

Interagir avec d'autres paquets Python

For loops at the outermost scope in a Taichi kernel is automatically parallelized. For loops can have two forms:

  • range-for loops
  • struct-for loops.

Range-for loops are no different from the Python for loops, except that they are parallelized when used at the outermost scope. Range-for loops can be nested.

@ti.kernel
def fill():
for i in range(10): # Parallelized
x[i] += i
s = 0
for j in range(5): # Serialized in each parallel thread
s += j
y[i] = s

@ti.kernel
def fill_3d():
# Parallelized for all 3 <= i < 8, 1 <= j < 6, 0 <= k < 9
for i, j, k in ti.ndrange((3, 8), (1, 6), 9):
x[i, j, k] = i + j + k
note

C'est la boucle à la portée ultrapériphérique qui est parallélisée, pas la boucle ultrapériphérique.

@ti.kernel
def foo():
for i in range(10): # En parallèles:-)
...

@ti.kernel
def bar(k: ti.i32):
if k > 42:
for i in range(10): # En série :-(
...

Struct-for loops are particularly useful when iterating over (sparse) field elements. In the fractal.py above, for i, j in pixels loops over all the pixel coordinates, i.e.,(0, 0), (0, 1), (0, 2), ... , (0, 319), (1, 0), ..., (639, 319).

note

Struct-for is the key to sparse computation in Taichi, as it will only loop over active elements in a sparse field. In dense fields, all elements are active.

WARNING

Struct-for loops must live at the outer-most scope of kernels. It is the loop at the outermost scope that gets parallelized, not the outermost loop.

x = [1, 2, 3]

@ti.kernel
def foo():
for i in x: # Parallelized :-)
...

@ti.kernel
def bar(k: ti.i32):
# The outermost scope is a `if` statement
if k > 42:
for i in x: # Pas permis. Struct-fors must live in the outermost scope.
...
WARNING

break is not supported in parallel loops:

@ti.kernel
def foo():
for i in x:
...
break # Erreur!

for i in range(10):
...
break # Erreur!

@ti.kernel
def foo():
for i in x:
for j in range(10):
...
break # OK!

GUI system

Taichi provides a CPU-based GUI system for you to render your results on the screen.

gui = ti.GUI("Julia Set", res=(n * 2, n))

for i in range(1000000):
paint(i * 0.03)
gui.set_image(pixels)
gui.show()

J'ai encore des problèmes?

Si vous rencontrez un problème qui n'est pas abordé ici, n'hésitez pas à le signaler en ouvrant un problème sur GitHub et en incluant les détails. Nous sommes là pour vous aider!