Skip to content

Commit

Permalink
[skip ci] Merge branch 'master' into ti-chain-compare-support-python-…
Browse files Browse the repository at this point in the history
…scope
  • Loading branch information
archibate committed Jul 2, 2020
2 parents 5fbcf16 + 8faf2b2 commit c7284d8
Show file tree
Hide file tree
Showing 59 changed files with 997 additions and 189 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/persubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
matrix:
os: [ubuntu-latest]
python: [3.6, 3.7, 3.8]
with_cc: [OFF]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
Expand All @@ -30,7 +31,7 @@ jobs:
export TAICHI_REPO_DIR=`pwd`
export PATH=$TAICHI_REPO_DIR/taichi-llvm/bin/:$PATH
export CXX=clang++
export CI_SETUP_CMAKE_ARGS=-DTI_WITH_OPENGL:BOOL=OFF
export CI_SETUP_CMAKE_ARGS="-DTI_WITH_OPENGL:BOOL=OFF -DTI_WITH_CC:BOOL=${{matrix.with_cc}}"
# GLFW dependencies:
#export CI_SETUP_CMAKE_ARGS=-DTI_WITH_OPENGL:BOOL=ON
#sudo apt-get install libx11-dev libxcursor-dev libxi-dev
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
*.swp
*.swo
/.vs
/tags
/.*_localrc
/Debug
*.sdf
/x64
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ project(taichi)

SET(TI_VERSION_MAJOR 0)
SET(TI_VERSION_MINOR 6)
SET(TI_VERSION_PATCH 14)
SET(TI_VERSION_PATCH 15)

execute_process(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@

**Taichi** (太极) is a programming language designed for *high-performance computer graphics*. It is deeply embedded in **Python**, and its **just-in-time compiler** offloads compute-intensive tasks to multi-core CPUs and massively parallel GPUs.

<a href="https://github.com/taichi-dev/taichi/blob/master/examples/fractal.py#L1-L31"> <img src="https://github.com/yuanming-hu/public_files/raw/master/graphics/taichi/fractal_code.png" height="293px"></a> <img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/fractal_small.gif" height="293px">
<a href="https://github.com/taichi-dev/taichi/blob/master/examples/fractal.py#L1-L31"> <img src="https://github.com/yuanming-hu/public_files/raw/master/graphics/taichi/fractal_code.png" height="270px"></a> <img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/fractal_small.gif" height="270px">


Advanced features of Taichi include [spatially sparse computing](https://taichi.readthedocs.io/en/latest/sparse.html) and [differentiable programming](https://taichi.readthedocs.io/en/latest/differentiable_programming.html) [[examples]](https://github.com/yuanming-hu/difftaichi).

## Gallery

<a href="https://github.com/taichi-dev/taichi/blob/master/examples/mpm128.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/mpm128.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/stable_fluid.py"> <img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/stable_fluids.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/sdf_renderer.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/sdf_renderer.jpg" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/taichi_sparse.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/sparse_grids.gif" height="192px"></a>
<a href="https://github.com/taichi-dev/taichi/blob/master/examples/mpm128.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/mpm128.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/stable_fluid.py"> <img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/stable_fluids.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/sdf_renderer.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/sdf_renderer.jpg" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/taichi_sparse.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/sparse_grids.gif" height="192px"></a>

<a href="https://github.com/taichi-dev/taichi/blob/master/examples/mpm_lagrangian_forces.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/lagrangian.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/pbf2d.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/pbf.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/game_of_life.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/game_of_life.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/euler.py"><img src="https://raw.githubusercontent.com/yuanming-hu/public_files/master/graphics/taichi/euler.gif" height="192px"></a>
<a href="https://github.com/taichi-dev/taichi/blob/master/examples/mpm_lagrangian_forces.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/lagrangian.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/pbf2d.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/pbf.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/game_of_life.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/game_of_life.gif" height="192px"></a> <a href="https://github.com/taichi-dev/taichi/blob/master/examples/euler.py"><img src="https://github.com/taichi-dev/public_files/blob/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/euler.gif" height="192px"></a>

## Installation [![Downloads](https://pepy.tech/badge/taichi/month)](https://pepy.tech/project/taichi/month)

Expand Down
22 changes: 20 additions & 2 deletions cmake/TaichiCore.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@ set(CORE_LIBRARY_NAME taichi_core)
option(USE_STDCPP "Use -stdlib=libc++" OFF)
option(TI_WITH_CUDA "Build with the CUDA backend" ON)
option(TI_WITH_OPENGL "Build with the OpenGL backend" ON)
option(TI_WITH_CC "Build with the C backend" OFF)

if (APPLE)
if (TI_WITH_CUDA)
set(TI_WITH_CUDA OFF)
message(WARNING "CUDA not supported on OS X. Setting TI_WITH_CUDA to OFF.")
message(WARNING "CUDA backend not supported on OS X. Setting TI_WITH_CUDA to OFF.")
endif()
if (TI_WITH_OPENGL)
set(TI_WITH_OPENGL OFF)
message(WARNING "OpenGL not supported on OS X. Setting TI_WITH_OPENGL to OFF.")
message(WARNING "OpenGL backend not supported on OS X. Setting TI_WITH_OPENGL to OFF.")
endif()
if (TI_WITH_CC)
set(TI_WITH_CC OFF)
message(WARNING "C backend not supported on OS X. Setting TI_WITH_CC to OFF.")
endif()
endif()

if (WIN32)
if (TI_WITH_CC)
set(TI_WITH_CC OFF)
message(WARNING "C backend not supported on Windows. Setting TI_WITH_CC to OFF.")
endif()
endif()

Expand All @@ -30,6 +42,7 @@ file(GLOB TAICHI_CPU_SOURCE "taichi/backends/cpu/*.cpp" "taichi/backends/cpu/*.h
file(GLOB TAICHI_CUDA_SOURCE "taichi/backends/cuda/*.cpp" "taichi/backends/cuda/*.h")
file(GLOB TAICHI_METAL_SOURCE "taichi/backends/metal/*.h" "taichi/backends/metal/*.cpp" "taichi/backends/metal/shaders/*")
file(GLOB TAICHI_OPENGL_SOURCE "taichi/backends/opengl/*.h" "taichi/backends/opengl/*.cpp" "taichi/backends/opengl/shaders/*")
file(GLOB TAICHI_CC_SOURCE "taichi/backends/cc/*.h" "taichi/backends/cc/*.cpp")

list(REMOVE_ITEM TAICHI_CORE_SOURCE ${TAICHI_BACKEND_SOURCE})

Expand All @@ -56,6 +69,11 @@ if (TI_WITH_OPENGL)
list(APPEND TAICHI_CORE_SOURCE ${TAICHI_GLAD_SOURCE})
endif()

if (TI_WITH_CC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTI_WITH_CC")
list(APPEND TAICHI_CORE_SOURCE ${TAICHI_CC_SOURCE})
endif()

add_library(${CORE_LIBRARY_NAME} SHARED ${TAICHI_CORE_SOURCE} ${PROJECT_SOURCES})

if (APPLE)
Expand Down
25 changes: 13 additions & 12 deletions docs/compilation.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
.. _compilation:

The life of a Taichi kernel
Life of a Taichi kernel
===============================================

Sometimes it is helpful to understand the life cycle of a Taichi kernel.
In short, compilation will only happen on the first invocation of an instance of a kernel.

Life cycle of a Taichi kernel looks like this:
The life cycle of a Taichi kernel has the following stages:

- Kernel registration
- Template instantiation and caching
- Python AST transforms
- Taichi IR compilation, optimization, and binary generation
- Taichi IR compilation, optimization, and executable generation
- Launching

.. image:: life_of_kernel_lowres.jpg
.. image:: https://raw.githubusercontent.com/taichi-dev/public_files/6bd234694270c83baf97ba32e0c6278b8cf37e6e/taichi/life_of_kernel.jpg

Let's consider the following simple kernel:

Expand All @@ -26,7 +26,7 @@ Let's consider the following simple kernel:
tensor[i] += delta
We also allocate two 1D tensors to simplify discussion:
We allocate two 1D tensors to simplify discussion:

.. code-block:: python
Expand All @@ -50,7 +50,7 @@ Template instantiation and caching
When ``add`` is called for the first time, the Taichi frontend compiler will instantiate the kernel.

When you have a second call with the same template signature (explained later), e.g.,
When you have a second call with the same **template signature** (explained later), e.g.,

.. code-block:: python
Expand All @@ -69,12 +69,12 @@ will lead to a new instantiation of **add**.
.. note::
**Template signatures** are what distinguish different instantiations of a kernel template.
The signature of ``add(x, 42)`` is ``(x, ti.i32)``, which is the same as that of ``add(x, 1)``. Therefore, the latter can reuse the previously compiled binary.
The signature of ``add(y, 42)`` is ``(y, ti.i32)``, a different value from the previous signature, therefore a new instantiation and compilation will happen.
The signature of ``add(y, 42)`` is ``(y, ti.i32)``, a different value from the previous signature, hence a new kernel will be instantiated and compiled.

.. note::

Many basic operations in the Taichi standard library is implemented using Taichi kernels for performance,
with more or less metaprogramming tricks. Invoking them will incur **implicit kernel instantiations**
Many basic operations in the Taichi standard library are implemented using Taichi kernels
using metaprogramming tricks. Invoking them will incur **implicit kernel instantiations**.

Examples include ``x.to_numpy()`` and ``y.from_torch(torch_tensor)``. When you invoke these functions,
you will see kernel instantiations, as Taichi kernels will be generated to offload the hard work to multiple CPU cores/GPUs.
Expand All @@ -84,7 +84,7 @@ will lead to a new instantiation of **add**.
Code transformation and optimizations
---------------------------------------

When a new instantiation happens, the Taichi frontend compiler will transform the kernel body AST
When a new instantiation happens, the Taichi frontend compiler (i.e., the ``ASTTransformer`` Python class) will transform the kernel body AST
into a Python script, which, when executed, emits a Taichi frontend AST.
Basically, some patches are applied to the Python AST so that the Taichi frontend can recognize it.

Expand All @@ -103,9 +103,10 @@ which allows a series of further IR passes to happen, such as
The just-in-time (JIT) compilation engine
-----------------------------------------

Finally, the optimized SSA IR is fed into the LLVM IR codegen, and LLVM JIT generates high-performance executable CPU/GPU programs.
Finally, the optimized SSA IR is fed into backend compilers such as LLVM or Apple Metal/OpenGL shader compilers.
The backend compilers then generate high-performance executable CPU/GPU programs.

Kernel launching
----------------

Taichi kernels will be ultimately launched as multi-threaded CPU tasks or CUDA kernels.
Taichi kernels will be ultimately launched as multi-threaded CPU tasks or GPU kernels.
2 changes: 1 addition & 1 deletion docs/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.6.14
0.6.15
4 changes: 2 additions & 2 deletions examples/export_videos.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def paint():

result_dir = "./results"
video_manager = ti.VideoManager(output_dir=result_dir,
framerate=24,
automatic_build=False)
framerate=24,
automatic_build=False)

for i in range(50):
paint()
Expand Down
2 changes: 2 additions & 0 deletions misc/listgen_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
x = ti.var(ti.i32)
ti.root.dense(ti.i, 4).bitmasked(ti.i, 4).place(x)


@ti.kernel
def func():
for i in x:
print(i)


func()
1 change: 1 addition & 0 deletions misc/prtags.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"windows" : "Windows",
"perf" : "Performance improvements",
"ipython" : "IPython and other shells",
"cc" : "C source backend",
"release" : "Release"
}
2 changes: 1 addition & 1 deletion python/taichi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from taichi.misc import *
from taichi.misc.gui import GUI
from taichi.misc.np2ply import PLYWriter
from taichi.misc.image import *
from taichi.misc.image import imread, imwrite, imshow, imdisplay
from taichi.misc.task import Task
from taichi.misc.test import *
from taichi.misc import settings as settings
Expand Down
2 changes: 1 addition & 1 deletion python/taichi/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def import_ti_core(tmp_dir=None):
global ti_core
if get_os_name() != 'win':
old_flags = sys.getdlopenflags()
sys.setdlopenflags(2) # 2 = RTLD_NOW
sys.setdlopenflags(2 | 8) # RTLD_NOW | RTLD_DEEPBIND
else:
pyddir = os.path.join(package_root(), 'lib')
os.environ['PATH'] += ';' + pyddir
Expand Down
5 changes: 4 additions & 1 deletion python/taichi/lang/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
cuda = core.cuda
metal = core.metal
opengl = core.opengl
cc = core.cc
gpu = [cuda, metal, opengl]
cpu = core.host_arch()
kernel_profiler_print = lambda: core.get_current_program(
Expand Down Expand Up @@ -292,14 +293,16 @@ def is_arch_supported(arch):
return core.with_metal()
elif arch == opengl:
return core.with_opengl()
elif arch == cc:
return core.with_cc()
elif arch == cpu:
return True
else:
return False


def supported_archs():
archs = [cpu, cuda, metal, opengl]
archs = [cpu, cuda, metal, opengl, cc]

wanted_archs = os.environ.get('TI_WANTED_ARCHS', '')
want_exclude = wanted_archs.startswith('^')
Expand Down
10 changes: 10 additions & 0 deletions python/taichi/lang/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ def expr_init_func(rhs): # temporary solution to allow passing in tensors as
return expr_init(rhs)


def begin_frontend_struct_for(group, loop_range):
if group.size() != len(loop_range.shape):
raise IndexError(
'Number of struct-for indices does not match loop variable dimensionality '
f'({group.size()} != {len(loop_range.shape)}). Maybe you wanted to '
'use "for I in ti.grouped(x)" to group all indices into a single vector I?'
)
taichi_lang_core.begin_frontend_struct_for(group, loop_range.ptr)


def wrap_scalar(x):
if type(x) in [int, float]:
return Expr(x)
Expand Down
4 changes: 2 additions & 2 deletions python/taichi/lang/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def visit_struct_for(self, node, is_grouped):
___loop_var = 0
{} = ti.make_var_vector(size=len(___loop_var.loop_range().shape))
___expr_group = ti.make_expr_group({})
ti.core.begin_frontend_struct_for(___expr_group, ___loop_var.loop_range().ptr)
ti.begin_frontend_struct_for(___expr_group, ___loop_var.loop_range())
ti.core.end_frontend_range_for()
'''.format(vars, vars)
t = ast.parse(template).body[0]
Expand All @@ -450,7 +450,7 @@ def visit_struct_for(self, node, is_grouped):
{}
___loop_var = 0
___expr_group = ti.make_expr_group({})
ti.core.begin_frontend_struct_for(___expr_group, ___loop_var.loop_range().ptr)
ti.begin_frontend_struct_for(___expr_group, ___loop_var.loop_range())
ti.core.end_frontend_range_for()
'''.format(var_decl, vars)
t = ast.parse(template).body[0]
Expand Down
8 changes: 4 additions & 4 deletions python/taichi/misc/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ def set_image(self, img):
self.img = self.cook_image(img.to_numpy())
else:
# Type matched! We can use an optimized copy kernel.
assert img.shape(
) == self.res, "Image resolution does not match GUI resolution"
assert img.shape \
== self.res, "Image resolution does not match GUI resolution"
from taichi.lang.meta import tensor_to_image
tensor_to_image(img, self.img)
ti.sync()
Expand All @@ -96,8 +96,8 @@ def set_image(self, img):
self.img = self.cook_image(img.to_numpy())
else:
# Type matched! We can use an optimized copy kernel.
assert img.shape(
) == self.res, "Image resolution does not match GUI resolution"
assert img.shape \
== self.res, "Image resolution does not match GUI resolution"
assert img.n in [
3, 4
], "Only greyscale, RGB or RGBA images are supported in GUI.set_image"
Expand Down
48 changes: 42 additions & 6 deletions python/taichi/misc/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import taichi as ti


def imwrite(img, filename):
def cook_image_to_bytes(img):
"""
Takes a NumPy array or Taichi tensor of any type.
Returns a NumPy array of uint8.
This is used by ti.imwrite and ti.imdisplay.
"""
if not isinstance(img, np.ndarray):
img = img.to_numpy()

Expand All @@ -16,19 +21,47 @@ def imwrite(img, filename):
assert len(img.shape) in [2,
3], "Image must be either RGB/RGBA or greyscale"

resx, resy = img.shape[:2]
if len(img.shape) == 2:
comp = 1
img = img.reshape(*img.shape, 1)

assert img.shape[2] in [1, 3,
4], "Image must be either RGB/RGBA or greyscale"

return img.swapaxes(0, 1)[::-1, :]


def imdisplay(img):
"""
Try to display image in interactive shell.
"""
if ti.lang.shell.oinspect.name == ti.lang.shell.ShellType.JUPYTER:
import PIL.Image
from io import BytesIO
import IPython.display
import numpy as np
img = cook_image_to_bytes(img)
with BytesIO() as f:
PIL.Image.fromarray(img).save(f, 'png')
IPython.display.display(IPython.display.Image(data=f.getvalue()))
else:
comp = img.shape[2]
assert comp in [1, 3, 4], "Image must be either RGB/RGBA or greyscale"
ti.imshow(img)


img = np.ascontiguousarray(img.swapaxes(0, 1)[::-1, :])
def imwrite(img, filename):
"""
Save image to a specific file.
"""
img = cook_image_to_bytes(img)
img = np.ascontiguousarray(img)
ptr = img.ctypes.data
resy, resx, comp = img.shape
ti.core.imwrite(filename, ptr, resx, resy, comp)


def imread(filename, channels=0):
"""
Load image from a specific file.
"""
ptr, resx, resy, comp = ti.core.imread(filename, channels)
img = np.ndarray(shape=(resy, resx, comp), dtype=np.uint8)
img = np.ascontiguousarray(img)
Expand All @@ -39,6 +72,9 @@ def imread(filename, channels=0):


def imshow(img, window_name='Taichi'):
"""
Show image in a Taichi GUI.
"""
if not isinstance(img, np.ndarray):
img = img.to_numpy()
assert len(img.shape) in [2,
Expand Down
Loading

0 comments on commit c7284d8

Please sign in to comment.