Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doc] Replace "tensor" by "field" in documents #1633

Merged
merged 15 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/compilation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ Let's consider the following simple kernel:
.. code-block:: python

@ti.kernel
def add(tensor: ti.template(), delta: ti.i32):
for i in tensor:
tensor[i] += delta
def add(field: ti.template(), delta: ti.i32):
for i in field:
field[i] += delta


We allocate two 1D tensors to simplify discussion:
We allocate two 1D fields to simplify discussion:

.. code-block:: python

x = ti.var(dt=ti.f32, shape=128)
y = ti.var(dt=ti.f32, shape=16)
x = ti.field(dtype=ti.f32, shape=128)
y = ti.field(dtype=ti.f32, shape=16)


Kernel registration
Expand Down
8 changes: 4 additions & 4 deletions docs/debugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ For now, Taichi-scope ``print`` supports string, scalar, vector, and matrix expr

import taichi as ti
ti.init(arch=ti.cpu)
a = ti.var(ti.f32, 4)
a = ti.field(ti.f32, 4)


@ti.kernel
Expand All @@ -104,7 +104,7 @@ It is similar to Python-scope ``print``.

.. code-block:: python

x = ti.var(ti.f32, (2, 3))
x = ti.field(ti.f32, (2, 3))
y = 1

@ti.kernel
Expand Down Expand Up @@ -137,7 +137,7 @@ For performance reason, ``assert`` only works when ``debug`` mode is on, For exa

ti.init(arch=ti.cpu, debug=True)

x = ti.var(ti.f32, 128)
x = ti.field(ti.f32, 128)

@ti.kernel
def do_sqrt_all():
Expand Down Expand Up @@ -166,7 +166,7 @@ For example:

@ti.func
def copy(dst: ti.template(), src: ti.template()):
ti.static_assert(dst.shape == src.shape, "copy() needs src and dst tensors to be same shape")
ti.static_assert(dst.shape == src.shape, "copy() needs src and dst fields to be same shape")
for I in ti.grouped(src):
dst[I] = src[I]
return x % 2 == 1
Expand Down
6 changes: 3 additions & 3 deletions docs/differentiable_programming.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ The `DiffTaichi repo <https://github.com/yuanming-hu/difftaichi>`_ contains 10 d

.. note::
Unlike tools such as TensorFlow where **immutable** output buffers are generated,
the **imperative** programming paradigm adopted in Taichi allows programmers to freely modify global tensors.
the **imperative** programming paradigm adopted in Taichi allows programmers to freely modify global fields.
To make automatic differentiation well-defined under this setting,
we make the following assumption on Taichi programs for differentiable programming:

**Global Data Access Rules:**

- If a global tensor element is written more than once, then starting from the second write, the
- If a global field element is written more than once, then starting from the second write, the
write **must** come in the form of an atomic add (“accumulation", using ``ti.atomic_add`` or simply ``+=``).
- No read accesses happen to a global tensor element, until its accumulation is done.
- No read accesses happen to a global field element, until its accumulation is done.

**Kernel Simplicity Rule:** Kernel body consists of multiple `simply nested` for-loops.
I.e., each for-loop can either contain exactly one (nested) for-loop (and no other statements), or a group of statements without loops.
Expand Down
20 changes: 10 additions & 10 deletions docs/export_results.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Export images using ``ti.GUI.show``

ti.init()

pixels = ti.var(ti.u8, shape=(512, 512, 3))
pixels = ti.field(ti.u8, shape=(512, 512, 3))

@ti.kernel
def paint():
Expand Down Expand Up @@ -57,7 +57,7 @@ To save images without invoking ``ti.GUI.show(filename)``, use ``ti.imwrite(file

ti.init()

pixels = ti.var(ti.u8, shape=(512, 512, 3))
pixels = ti.field(ti.u8, shape=(512, 512, 3))

@ti.kernel
def set_pixels():
Expand All @@ -69,15 +69,15 @@ To save images without invoking ``ti.GUI.show(filename)``, use ``ti.imwrite(file
ti.imwrite(pixels.to_numpy(), filename)
print(f'The image has been saved to {filename}')

- ``ti.imwrite`` can export Taichi tensors (``ti.Matrix``, ``ti.Vector``, ``ti.var``) and numpy tensors ``np.ndarray``.
- ``ti.imwrite`` can export Taichi fields (``ti.Matrix.field``, ``ti.Vector.field``, ``ti.field``) and numpy tensors ``np.ndarray``.
- Same as above ``ti.GUI.show(filename)``, the image format (``png``, ``jpg`` and ``bmp``) is also controlled by the suffix of ``filename`` in ``ti.imwrite(filename)``.
- Meanwhile, the resulted image type (grayscale, RGB, or RGBA) is determined by **the number of channels in the input tensor**, i.e., the length of the third dimension (``tensor.shape[2]``).
- In other words, a tensor that has shape ``(w, h)`` or ``(w, h, 1)`` will be exported as a grayscale image.
- If you want to export ``RGB`` or ``RGBA`` images instead, the input tensor should have a shape ``(w, h, 3)`` or ``(w, h, 4)`` respectively.
- Meanwhile, the resulted image type (grayscale, RGB, or RGBA) is determined by **the number of channels in the input field**, i.e., the length of the third dimension (``field.shape[2]``).
- In other words, a field that has shape ``(w, h)`` or ``(w, h, 1)`` will be exported as a grayscale image.
- If you want to export ``RGB`` or ``RGBA`` images instead, the input field should have a shape ``(w, h, 3)`` or ``(w, h, 4)`` respectively.

.. note::

All Taichi tensors have their own data types, such as ``ti.u8`` and ``ti.f32``. Different data types can lead to different behaviors of ``ti.imwrite``. Please check out :ref:`gui` for more details.
All Taichi fields have their own data types, such as ``ti.u8`` and ``ti.f32``. Different data types can lead to different behaviors of ``ti.imwrite``. Please check out :ref:`gui` for more details.

- Taichi offers other helper functions that read and show images in addition to ``ti.imwrite``. They are also demonstrated in :ref:`gui`.

Expand All @@ -96,7 +96,7 @@ Export videos

ti.init()

pixels = ti.var(ti.u8, shape=(512, 512, 3))
pixels = ti.field(ti.u8, shape=(512, 512, 3))

@ti.kernel
def paint():
Expand Down Expand Up @@ -190,8 +190,8 @@ Export PLY files
ti.init(arch=ti.cpu)

num_vertices = 1000
pos = ti.Vector(3, dt=ti.f32, shape=(10, 10, 10))
rgba = ti.Vector(4, dt=ti.f32, shape=(10, 10, 10))
pos = ti.Vector.field(3, dtype=ti.f32, shape=(10, 10, 10))
rgba = ti.Vector.field(4, dtype=ti.f32, shape=(10, 10, 10))


@ti.kernel
Expand Down
14 changes: 7 additions & 7 deletions docs/external.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Interacting with external arrays

**External arrays** refer to ``numpy.ndarray`` or ``torch.Tensor``.

Conversion between Taichi tensors and external arrays
-----------------------------------------------------
Conversion between Taichi fields and external arrays
----------------------------------------------------

Use ``to_numpy``/``from_numpy``/``to_torch``/``from_torch``:

Expand All @@ -20,10 +20,10 @@ Use ``to_numpy``/``from_numpy``/``to_torch``/``from_torch``:
n = 4
m = 7

# Taichi tensors
val = ti.var(ti.i32, shape=(n, m))
vec = ti.Vector(3, dt=ti.i32, shape=(n, m))
mat = ti.Matrix(3, 4, dt=ti.i32, shape=(n, m))
# Taichi fields
val = ti.field(ti.i32, shape=(n, m))
vec = ti.Vector.field(3, dtype=ti.i32, shape=(n, m))
mat = ti.Matrix.field(3, 4, dtype=ti.i32, shape=(n, m))

# Scalar
arr = np.ones(shape=(n, m), dtype=np.int32)
Expand Down Expand Up @@ -74,7 +74,7 @@ Note that struct-for's on external arrays are not supported.
n = 4
m = 7

val = ti.var(ti.i32, shape=(n, m))
val = ti.field(ti.i32, shape=(n, m))

@ti.kernel
def test_numpy(arr: ti.ext_arr()):
Expand Down
10 changes: 5 additions & 5 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Frequently asked questions
for i in range(100): # This loop will not be parallelized
...

**Q:** What's the most convenient way to load images / textures into Taichi tensors?
**Q:** What's the most convenient way to load images / textures into Taichi fields?

**A:** Simply use ``tensor.from_numpy(ti.imread('filename.png'))``.
**A:** Simply use ``field.from_numpy(ti.imread('filename.png'))``.

**Q:** Can Taichi co-operate with **other Python packages** like ``matplotlib``?

Expand All @@ -41,10 +41,10 @@ Frequently asked questions
**A:** You may export it with :ref:`export_ply_files` so that you could view it in Houdini or Blender.
Or make use the extension library `Taichi THREE <https://github.com/taichi-dev/taichi_glsl>`_ to render images and update to GUI in real-time.

**Q:** How do I declare a tensor with **dynamic length**?
**Q:** How do I declare a field with **dynamic length**?

**A:** What you want may be the ``dynamic`` SNode, a kind of sparse tensor, see :ref:`dynamic`.
Or simply allocate a dense tensor large enough, and another 0-D tensor ``tensor_len[None]`` for length record.
**A:** What you want may be the ``dynamic`` SNode, a kind of sparse field, see :ref:`dynamic`.
Or simply allocate a dense field large enough, and another 0-D field ``field_len[None]`` for length record.
But in fact, the ``dynamic`` SNode could be slower than the latter solution, due to the cost of maintaining the sparsity information.

**Q:** Can a user iterate over irregular topologies (e.g., graphs or tetrahedral meshes) instead of regular grids?
Expand Down
2 changes: 1 addition & 1 deletion docs/global_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Compilation
Runtime
*******

- Restart the entire Taichi system (destroy all tensors and kernels): ``ti.reset()``.
- Restart the entire Taichi system (destroy all fields and kernels): ``ti.reset()``.
- To start program in debug mode: ``ti.init(debug=True)`` or ``ti debug your_script.py``.
- To disable importing torch on start up: ``export TI_ENABLE_TORCH=0``.

Expand Down
26 changes: 13 additions & 13 deletions docs/gui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Paint on a window
.. function:: gui.set_image(img)

:parameter gui: (GUI) the window object
:parameter img: (np.array or Tensor) tensor containing the image, see notes below
:parameter img: (np.array or ti.field) field containing the image, see notes below

Set an image to display on the window.

Expand All @@ -63,11 +63,11 @@ Paint on a window

If the window size is ``(x, y)``, then ``img`` must be one of:

* ``ti.var(shape=(x, y))``, a grey-scale image
* ``ti.field(shape=(x, y))``, a grey-scale image

* ``ti.var(shape=(x, y, 3))``, where `3` is for ``(r, g, b)`` channels
* ``ti.field(shape=(x, y, 3))``, where `3` is for ``(r, g, b)`` channels

* ``ti.Vector(3, shape=(x, y))`` (see :ref:`vector`)
* ``ti.Vector.field(3, shape=(x, y))`` (see :ref:`vector`)

* ``np.ndarray(shape=(x, y))``

Expand Down Expand Up @@ -427,11 +427,11 @@ Image I/O
:parameter img: (Matrix or Expr) the image you want to export
:parameter filename: (string) the location you want to save to

Export a ``np.ndarray`` or Taichi tensor (``ti.Matrix``, ``ti.Vector``, or ``ti.var``) to a specified location ``filename``.
Export a ``np.ndarray`` or Taichi field (``ti.Matrix.field``, ``ti.Vector.field``, or ``ti.field``) to a specified location ``filename``.

Same as ``ti.GUI.show(filename)``, the format of the exported image is determined by **the suffix of** ``filename`` as well. Now ``ti.imwrite`` supports exporting images to ``png``, ``img`` and ``jpg`` and we recommend using ``png``.

Please make sure that the input image has **a valid shape**. If you want to export a grayscale image, the input shape of tensor should be ``(height, weight)`` or ``(height, weight, 1)``. For example:
Please make sure that the input image has **a valid shape**. If you want to export a grayscale image, the input shape of field should be ``(height, weight)`` or ``(height, weight, 1)``. For example:

.. code-block:: python

Expand All @@ -441,7 +441,7 @@ Image I/O

shape = (512, 512)
type = ti.u8
pixels = ti.var(dt=type, shape=shape)
pixels = ti.field(dtype=type, shape=shape)

@ti.kernel
def draw():
Expand All @@ -452,13 +452,13 @@ Image I/O

ti.imwrite(pixels, f"export_u8.png")

Besides, for RGB or RGBA images, ``ti.imwrite`` needs to receive a tensor which has shape ``(height, width, 3)`` and ``(height, width, 4)`` individually.
Besides, for RGB or RGBA images, ``ti.imwrite`` needs to receive a field which has shape ``(height, width, 3)`` and ``(height, width, 4)`` individually.

Generally the value of the pixels on each channel of a ``png`` image is an integar in [0, 255]. For this reason, ``ti.imwrite`` will **cast tensors** which has different datatypes all **into integars between [0, 255]**. As a result, ``ti.imwrite`` has the following requirements for different datatypes of input tensors:
Generally the value of the pixels on each channel of a ``png`` image is an integar in [0, 255]. For this reason, ``ti.imwrite`` will **cast fields** which has different datatypes all **into integars between [0, 255]**. As a result, ``ti.imwrite`` has the following requirements for different datatypes of input fields:

- For float-type (``ti.f16``, ``ti.f32``, etc) input tensors, **the value of each pixel should be float between [0.0, 1.0]**. Otherwise ``ti.imwrite`` will first clip them into [0.0, 1.0]. Then they are multiplied by 256 and casted to integaters ranging from [0, 255].
- For float-type (``ti.f16``, ``ti.f32``, etc) input fields, **the value of each pixel should be float between [0.0, 1.0]**. Otherwise ``ti.imwrite`` will first clip them into [0.0, 1.0]. Then they are multiplied by 256 and casted to integaters ranging from [0, 255].

- For int-type (``ti.u8``, ``ti.u16``, etc) input tensors, **the value of each pixel can be any valid integer in its own bounds**. These integers in this tensor will be scaled to [0, 255] by being divided over the upper bound of its basic type accordingly.
- For int-type (``ti.u8``, ``ti.u16``, etc) input fields, **the value of each pixel can be any valid integer in its own bounds**. These integers in this field will be scaled to [0, 255] by being divided over the upper bound of its basic type accordingly.

Here is another example:

Expand All @@ -471,7 +471,7 @@ Image I/O
shape = (512, 512)
channels = 3
type = ti.f32
pixels = ti.Matrix(channels, dt=type, shape=shape)
pixels = ti.Matrix.field(channels, dtype=type, shape=shape)

@ti.kernel
def draw():
Expand All @@ -493,7 +493,7 @@ Image I/O

This function loads an image from the target filename and returns it as a ``np.ndarray(dtype=np.uint8)``.

Each value in this returned tensor is an integer in [0, 255].
Each value in this returned field is an integer in [0, 255].

.. function:: ti.imshow(img, windname)

Expand Down
28 changes: 14 additions & 14 deletions docs/hello.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Running the Taichi code below (``python3 fractal.py`` or ``ti example fractal``)
ti.init(arch=ti.gpu)

n = 320
pixels = ti.var(dt=ti.f32, shape=(n * 2, n))
pixels = ti.field(dtype=ti.f32, shape=(n * 2, n))


@ti.func
Expand Down Expand Up @@ -95,19 +95,19 @@ Taichi programs run on either CPUs or GPUs. Initialize Taichi according to your
.. note::

When used with the CUDA backend on Windows or ARM devices (e.g. NVIDIA Jetson),
Taichi by default allocates 1 GB GPU memory for tensor storage. You can override this behavior by initializing with
Taichi by default allocates 1 GB GPU memory for field storage. You can override this behavior by initializing with
``ti.init(arch=ti.cuda, device_memory_GB=3.4)`` to allocate ``3.4`` GB GPU memory, or
``ti.init(arch=ti.cuda, device_memory_fraction=0.3)`` to allocate ``30%`` of the total GPU memory.

On other platforms, Taichi will make use of its on-demand memory allocator to adaptively allocate memory.

(Sparse) tensors
----------------
(Sparse) fields
---------------

Taichi is a data-oriented programming language where dense or spatially-sparse tensors are the first-class citizens.
See :ref:`sparse` for more details on sparse tensors.
Taichi is a data-oriented programming language where dense or spatially-sparse fields are the first-class citizens.
See :ref:`sparse` for more details on sparse fields.

In the code above, ``pixels = ti.var(dt=ti.f32, shape=(n * 2, n))`` allocates a 2D dense tensor named ``pixels`` of
In the code above, ``pixels = ti.field(dtype=ti.f32, shape=(n * 2, n))`` allocates a 2D dense field named ``pixels`` of
size ``(640, 320)`` and element data type ``ti.f32`` (i.e. ``float`` in C).

Functions and kernels
Expand Down Expand Up @@ -178,12 +178,12 @@ when used at the outermost scope. Range-for loops can be nested.
for i in range(10): # Serial :-(
...

**Struct-for loops** are particularly useful when iterating over (sparse) tensor elements.
**Struct-for loops** are particularly useful when iterating over (sparse) field elements.
In the code 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 :ref:`sparse` in Taichi, as it will only loop over active elements in a sparse tensor. In dense tensors, all elements are active.
Struct-for is the key to :ref:`sparse` in Taichi, as it will only loop over active elements in a sparse field. In dense fields, all elements are active.

.. warning::

Expand Down Expand Up @@ -241,13 +241,13 @@ Python-scope data access
++++++++++++++++++++++++

Everything outside Taichi-scopes (``ti.func`` and ``ti.kernel``) is simply Python code.
In Python-scopes, you can access Taichi tensor elements using plain indexing syntax.
In Python-scopes, you can access Taichi field elements using plain indexing syntax.
For example, to access a single pixel of the rendered image in Python-scope, simply use:

.. code-block:: python

import taichi as ti
pixels = ti.var(ti.f32, (1024, 512))
pixels = ti.field(ti.f32, (1024, 512))

pixels[42, 11] = 0.7 # store data into pixels
print(pixels[42, 11]) # prints 0.7
Expand All @@ -256,17 +256,17 @@ For example, to access a single pixel of the rendered image in Python-scope, sim
Sharing data with other packages
++++++++++++++++++++++++++++++++

Taichi provides helper functions such as ``from_numpy`` and ``to_numpy`` for transfer data between Taichi tensors and NumPy arrays,
Taichi provides helper functions such as ``from_numpy`` and ``to_numpy`` for transfer data between Taichi fields and NumPy arrays,
So that you can also use your favorite Python packages (e.g. ``numpy``, ``pytorch``, ``matplotlib``) together with Taichi. e.g.:

.. code-block:: python

import taichi as ti
pixels = ti.var(ti.f32, (1024, 512))
pixels = ti.field(ti.f32, (1024, 512))

import numpy as np
arr = np.random.rand(1024, 512)
pixels.from_numpy(arr) # load numpy data into taichi tensors
pixels.from_numpy(arr) # load numpy data into taichi fields

import matplotlib.pyplot as plt
arr = pixels.to_numpy() # store taichi data into numpy arrays
Expand Down
Loading