Esempio n. 1
0
def grad_test(tifunc, npfunc=None):
    npfunc = npfunc or tifunc

    print(
        f'arch={ti.lang.impl.current_cfg().arch} default_fp={ti.lang.impl.current_cfg().default_fp}'
    )
    x = ti.field(ti.lang.impl.current_cfg().default_fp)
    y = ti.field(ti.lang.impl.current_cfg().default_fp)

    ti.root.dense(ti.i, 1).place(x, x.grad, y, y.grad)

    @ti.kernel
    def func():
        for i in x:
            y[i] = tifunc(x[i])

    v = 0.234

    y.grad[0] = 1
    x[0] = v
    func()
    func.grad()

    assert y[0] == test_utils.approx(npfunc(v), rel=1e-4)
    assert x.grad[0] == test_utils.approx(grad(npfunc)(v), rel=1e-4)
Esempio n. 2
0
def test_ad_reduce_fwd():
    N = 16

    x = ti.field(dtype=ti.f32, shape=N)
    loss = ti.field(dtype=ti.f32, shape=())
    ti.root.lazy_dual()

    @ti.kernel
    def func():
        for i in x:
            loss[None] += x[i]**2

    total_loss = 0
    for i in range(N):
        x[i] = i
        total_loss += i * i

    with ti.ad.FwdMode(loss=loss, parameters=x, seed=[1.0 for _ in range(N)]):
        func()

    assert total_loss == test_utils.approx(loss[None])
    sum = 0
    for i in range(N):
        sum += i * 2

    assert loss.dual[None] == test_utils.approx(sum)
Esempio n. 3
0
def _test_polar_decomp(dim, dt):
    m = ti.Matrix.field(dim, dim, dt)
    r = ti.Matrix.field(dim, dim, dt)
    s = ti.Matrix.field(dim, dim, dt)
    I = ti.Matrix.field(dim, dim, dt)
    D = ti.Matrix.field(dim, dim, dt)

    ti.root.place(m, r, s, I, D)

    @ti.kernel
    def polar():
        R, S = ti.polar_decompose(m[None], dt)
        r[None] = R
        s[None] = S
        m[None] = R @ S
        I[None] = R @ R.transpose()
        D[None] = S - S.transpose()

    def V(i, j):
        return i * 2 + j * 7 + int(i == j) * 3

    for i in range(dim):
        for j in range(dim):
            m[None][i, j] = V(i, j)

    polar()

    tol = 5e-5 if dt == ti.f32 else 1e-12

    for i in range(dim):
        for j in range(dim):
            assert m[None][i, j] == test_utils.approx(V(i, j), abs=tol)
            assert I[None][i, j] == test_utils.approx(int(i == j), abs=tol)
            assert D[None][i, j] == test_utils.approx(0, abs=tol)
Esempio n. 4
0
def test_matrix_factories():
    a = ti.Vector.field(3, dtype=ti.i32, shape=3)
    b = ti.Matrix.field(2, 2, dtype=ti.f32, shape=2)
    c = ti.Matrix.field(2, 3, dtype=ti.f32, shape=2)

    @ti.kernel
    def fill():
        b[0] = ti.Matrix.identity(ti.f32, 2)
        b[1] = ti.Matrix.rotation2d(math.pi / 3)
        c[0] = ti.Matrix.zero(ti.f32, 2, 3)
        c[1] = ti.Matrix.one(ti.f32, 2, 3)
        for i in ti.static(range(3)):
            a[i] = ti.Vector.unit(3, i)

    fill()

    for i in range(3):
        for j in range(3):
            assert a[i][j] == int(i == j)

    sqrt3o2 = math.sqrt(3) / 2
    assert b[0].to_numpy() == test_utils.approx(np.eye(2))
    assert b[1].to_numpy() == test_utils.approx(
        np.array([[0.5, -sqrt3o2], [sqrt3o2, 0.5]]))
    assert c[0].to_numpy() == test_utils.approx(np.zeros((2, 3)))
    assert c[1].to_numpy() == test_utils.approx(np.ones((2, 3)))
Esempio n. 5
0
def _test_closing_offline_cache_for_a_kernel(curr_arch, kernel, args, result):
    count_of_cache_file = len(listdir(tmp_offline_cache_file_path()))

    ti.init(arch=curr_arch,
            enable_fallback=False,
            offline_cache=False,
            offline_cache_file_path=tmp_offline_cache_file_path())
    res1 = kernel(*args)
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == get_expected_num_cache_files()

    ti.init(arch=curr_arch,
            enable_fallback=False,
            offline_cache=False,
            offline_cache_file_path=tmp_offline_cache_file_path())
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == get_expected_num_cache_files()
    res2 = kernel(*args)

    assert res1 == test_utils.approx(result) and res1 == test_utils.approx(
        res2)

    ti.reset()
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == get_expected_num_cache_files()
Esempio n. 6
0
    def helper():
        x = ti.field(dtype=ti.f32, shape=())
        y = ti.field(dtype=ti.f32, shape=())

        x[None] = 3.14
        y[None] = 4.14
        assert x[None] == test_utils.approx(3.14)
        assert y[None] == test_utils.approx(4.14)

        x[None] = 6.28
        y[None] = 7.28
        assert x[None] == test_utils.approx(6.28)
        assert y[None] == test_utils.approx(7.28)
Esempio n. 7
0
def test_precision():
    u = ti.field(ti.f64, shape=())
    v = ti.field(ti.f64, shape=())
    w = ti.field(ti.f64, shape=())

    @ti.kernel
    def forward():
        v[None] = ti.sqrt(ti.cast(u[None] + 3.25, ti.f64))
        w[None] = ti.cast(u[None] + 7, ti.f64) / ti.cast(u[None] + 3, ti.f64)

    forward()
    assert v[None]**2 == test_utils.approx(3.25, abs=1e-12)
    assert w[None] * 3 == test_utils.approx(7, abs=1e-12)
Esempio n. 8
0
def test_unary_op():
    dtype = ti.f16
    x = ti.field(dtype, shape=())
    y = ti.field(dtype, shape=())

    @ti.kernel
    def foo():
        x[None] = -y[None]
        x[None] = ti.floor(x[None])
        y[None] = ti.ceil(y[None])

    y[None] = -1.4
    foo()
    assert (x[None] == test_utils.approx(1, rel=1e-3))
    assert (y[None] == test_utils.approx(-1, rel=1e-3))
Esempio n. 9
0
def test_expr_dict_basic():
    @ti.kernel
    def func(u: int, v: float) -> float:
        x = {'foo': 2 + u, 'bar': 3 + v}
        return x['foo'] * 100 + x['bar']

    assert func(2, 0.1) == test_utils.approx(403.1)
Esempio n. 10
0
def _test_svd(dt, n):
    print(
        f'arch={ti.lang.impl.current_cfg().arch} default_fp={ti.lang.impl.current_cfg().default_fp} fast_math={ti.lang.impl.current_cfg().fast_math} dim={n}'
    )
    A = ti.Matrix.field(n, n, dtype=dt, shape=())
    A_reconstructed = ti.Matrix.field(n, n, dtype=dt, shape=())
    U = ti.Matrix.field(n, n, dtype=dt, shape=())
    UtU = ti.Matrix.field(n, n, dtype=dt, shape=())
    sigma = ti.Matrix.field(n, n, dtype=dt, shape=())
    V = ti.Matrix.field(n, n, dtype=dt, shape=())
    VtV = ti.Matrix.field(n, n, dtype=dt, shape=())

    @ti.kernel
    def run():
        U[None], sigma[None], V[None] = ti.svd(A[None], dt)
        UtU[None] = U[None].transpose() @ U[None]
        VtV[None] = V[None].transpose() @ V[None]
        A_reconstructed[None] = U[None] @ sigma[None] @ V[None].transpose()

    if n == 3:
        A[None] = [[1, 1, 3], [9, -3, 2], [-3, 4, 2]]
    else:
        A[None] = [[1, 1], [2, 3]]

    run()

    tol = 1e-5 if dt == ti.f32 else 1e-12

    assert mat_equal(UtU.to_numpy(), np.eye(n), tol=tol)
    assert mat_equal(VtV.to_numpy(), np.eye(n), tol=tol)
    assert mat_equal(A_reconstructed.to_numpy(), A.to_numpy(), tol=tol)
    for i in range(n):
        for j in range(n):
            if i != j:
                assert sigma[None][i, j] == test_utils.approx(0)
Esempio n. 11
0
def test_ad_frac():
    @ti.func
    def frac(x):
        fractional = x - ti.floor(x) if x > 0. else x - ti.ceil(x)
        return fractional

    @ti.kernel
    def ti_frac(input_field: ti.template(), output_field: ti.template()):
        for i in input_field:
            output_field[i] = frac(input_field[i])**2

    @ti.kernel
    def calc_loss(input_field: ti.template(), loss: ti.template()):
        for i in input_field:
            loss[None] += input_field[i]

    n = 10
    field0 = ti.field(dtype=ti.f32, shape=(n, ), needs_grad=True)
    randoms = np.random.randn(10).astype(np.float32)
    field0.from_numpy(randoms)
    field1 = ti.field(dtype=ti.f32, shape=(n, ), needs_grad=True)
    loss = ti.field(dtype=ti.f32, shape=(), needs_grad=True)

    with ti.Tape(loss):
        ti_frac(field0, field1)
        calc_loss(field1, loss)

    grads = field0.grad.to_numpy()
    expected = np.modf(randoms)[0] * 2
    for i in range(n):
        assert grads[i] == test_utils.approx(expected[i], rel=1e-4)
Esempio n. 12
0
def test_expr_list_basic():
    @ti.kernel
    def func(u: int, v: float) -> float:
        x = [2 + u, 3 + v]
        return x[0] * 100 + x[1]

    assert func(1, 1.1) == test_utils.approx(304.1)
Esempio n. 13
0
def test_scalar_argument():
    @ti.kernel
    def add(a: ti.f32, b: ti.f32) -> ti.f32:
        a = a + b
        return a

    assert add(1.0, 2.0) == test_utils.approx(3.0)
Esempio n. 14
0
def test_vector_float():
    n = 8
    A = ti.Vector([1.4, 3.7, 13.2, 4.5, 5.6, 6.1, 7.2, 2.6])
    res = ti.ndarray(ti.f32, shape=(1, ))
    graph = build_graph_vector(n, dtype=ti.f32)
    graph.run({"mat": A, "res": res})
    assert res.to_numpy()[0] == test_utils.approx(57.5, rel=1e-5)
Esempio n. 15
0
def test_matrix_float():
    n = 4
    A = ti.Matrix([4.2, 5.7] * n)
    res = ti.ndarray(ti.f32, shape=(1))
    graph = build_graph_matrix(n, dtype=ti.f32)
    graph.run({"mat": A, "res": res})
    assert res.to_numpy()[0] == test_utils.approx(39.6, rel=1e-5)
Esempio n. 16
0
def test_constant_matrices():
    assert ti.cos(math.pi / 3) == test_utils.approx(0.5)
    assert np.allclose((-ti.Vector([2, 3])).to_numpy(), np.array([-2, -3]))
    assert ti.cos(ti.Vector([2, 3])).to_numpy() == test_utils.approx(
        np.cos(np.array([2, 3])))
    assert ti.max(2, 3) == 3
    res = ti.max(4, ti.Vector([3, 4, 5]))
    assert np.allclose(res.to_numpy(), np.array([4, 4, 5]))
    res = ti.Vector([2, 3]) + ti.Vector([3, 4])
    assert np.allclose(res.to_numpy(), np.array([5, 7]))
    res = ti.atan2(ti.Vector([2, 3]), ti.Vector([3, 4]))
    assert res.to_numpy() == test_utils.approx(
        np.arctan2(np.array([2, 3]), np.array([3, 4])))
    res = ti.Matrix([[2, 3], [4, 5]]) @ ti.Vector([2, 3])
    assert np.allclose(res.to_numpy(), np.array([13, 23]))
    v = ti.Vector([3, 4])
    w = ti.Vector([5, -12])
    r = ti.Vector([1, 2, 3, 4])
    s = ti.Matrix([[1, 2], [3, 4]])
    assert v.normalized().to_numpy() == test_utils.approx(np.array([0.6, 0.8]))
    assert v.cross(w) == test_utils.approx(-12 * 3 - 4 * 5)
    w.y = v.x * w[0]
    r.x = r.y
    r.y = r.z
    r.z = r.w
    r.w = r.x
    assert np.allclose(w.to_numpy(), np.array([5, 15]))
    assert ti.select(ti.Vector([1, 0]), ti.Vector([2, 3]),
                     ti.Vector([4, 5])) == ti.Vector([2, 5])
    s[0, 1] = 2
    assert s[0, 1] == 2

    @ti.kernel
    def func(t: ti.i32):
        m = ti.Matrix([[2, 3], [4, t]])
        print(m @ ti.Vector([2, 3]))
        m += ti.Matrix([[3, 4], [5, t]])
        print(m @ v)
        print(r.x, r.y, r.z, r.w)
        s = w.transpose() @ m
        print(s)
        print(m)

    func(5)
Esempio n. 17
0
def test_grouped_static_for_cast():
    @ti.kernel
    def foo() -> ti.f32:
        ret = 0.
        for I in ti.static(ti.grouped(ti.ndrange((4, 5), (3, 5), 5))):
            tmp = I.cast(float)
            ret += tmp[2] / 2
        return ret

    assert foo() == test_utils.approx(10)
Esempio n. 18
0
def test_image_resize_sum(resx, resy, comp, scale):
    shape = (resx, resy)
    if comp != 1:
        shape = shape + (comp, )
    old_img = np.random.rand(*shape).astype(np.float32)
    if resx == resy:
        new_img = ti.imresize(old_img, resx * scale)
    else:
        new_img = ti.imresize(old_img, resx * scale, resy * scale)
    assert np.sum(old_img) * scale**2 == test_utils.approx(np.sum(new_img))
Esempio n. 19
0
def test_random_vector_dup_eval():
    a = ti.Vector.field(2, ti.f32, ())

    @ti.kernel
    def func():
        a[None] = ti.Vector([ti.random(), 1]).normalized()

    for i in range(4):
        func()
        assert a[None].norm_sqr() == test_utils.approx(1)
Esempio n. 20
0
def test_expr_dict_field():
    a = ti.field(ti.f32, shape=(4, ))

    @ti.kernel
    def func() -> float:
        x = {'foo': 2 + a[0], 'bar': 3 + a[1]}
        return x['foo'] * 100 + x['bar']

    a[0] = 2
    a[1] = 0.1
    assert func() == test_utils.approx(403.1)
Esempio n. 21
0
def test_func_random_argument_dup_eval():
    @ti.func
    def func(a):
        return ti.Vector([ti.cos(a), ti.sin(a)])

    @ti.kernel
    def kern() -> ti.f32:
        return func(ti.random()).norm_sqr()

    for i in range(4):
        assert kern() == test_utils.approx(1.0, rel=5e-5)
Esempio n. 22
0
def test_arg_f16():
    dtype = ti.f16
    x = ti.field(dtype, shape=())
    y = ti.field(dtype, shape=())

    @ti.kernel
    def foo(a: ti.f16):
        x[None] = y[None] + a

    y[None] = -0.3
    foo(1.2)
    assert (x[None] == test_utils.approx(0.9, rel=1e-3))
Esempio n. 23
0
def test_extra_unary_promote():
    dtype = ti.f16
    x = ti.field(dtype, shape=())
    y = ti.field(dtype, shape=())

    @ti.kernel
    def foo():
        x[None] = abs(y[None])

    y[None] = -0.3
    foo()
    assert (x[None] == test_utils.approx(0.3, rel=1e-3))
Esempio n. 24
0
def test_binary_extra_promote():
    x = ti.field(dtype=ti.f16, shape=())
    y = ti.field(dtype=ti.f16, shape=())
    z = ti.field(dtype=ti.f16, shape=())

    @ti.kernel
    def foo():
        y[None] = x[None]**2
        z[None] = ti.atan2(y[None], 0.3)

    x[None] = 0.1
    foo()
    assert (z[None] == test_utils.approx(math.atan2(0.1**2, 0.3), rel=1e-3))
Esempio n. 25
0
def _test_offline_cache_for_a_kernel(curr_arch, kernel, args, result):
    count_of_cache_file = len(listdir(tmp_offline_cache_file_path()))

    ti.init(arch=curr_arch,
            enable_fallback=False,
            **current_thread_ext_options())
    res1 = kernel(*args)
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == 0 * cache_files_num_per_kernel

    ti.init(arch=curr_arch,
            enable_fallback=False,
            **current_thread_ext_options())
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == 1 * cache_files_num_per_kernel
    res2 = kernel(*args)
    assert res1 == test_utils.approx(result) and res1 == test_utils.approx(
        res2)

    ti.reset()
    assert len(listdir(tmp_offline_cache_file_path())
               ) - count_of_cache_file == 1 * cache_files_num_per_kernel
Esempio n. 26
0
def test_const_func_ret():
    ti.init()

    @ti.kernel
    def func1() -> ti.f32:
        return 3

    @ti.kernel
    def func2() -> ti.i32:
        return 3.3  # return type mismatch, will be auto-casted into ti.i32

    assert func1() == test_utils.approx(3)
    assert func2() == 3
Esempio n. 27
0
def test_ad_reduce():
    N = 16

    x = ti.field(dtype=ti.f32, shape=N, needs_grad=True)
    loss = ti.field(dtype=ti.f32, shape=(), needs_grad=True)

    @ti.kernel
    def func():
        for i in x:
            loss[None] += x[i]**2

    total_loss = 0
    for i in range(N):
        x[i] = i
        total_loss += i * i

    loss.grad[None] = 1
    func()
    func.grad()

    assert total_loss == test_utils.approx(loss[None])
    for i in range(N):
        assert x.grad[i] == test_utils.approx(i * 2)
Esempio n. 28
0
def test_minimization():
    from taichi.examples.autodiff.minimization import (L, gradient_descent, n,
                                                       reduce, x, y)

    for i in range(n):
        x[i] = random.random()
        y[i] = random.random()

    for k in range(100):
        with ti.Tape(loss=L):
            reduce()
        gradient_descent()

    for i in range(n):
        assert x[i] == test_utils.approx(y[i], rel=1e-2)
Esempio n. 29
0
def test_diag():
    m1 = ti.Matrix.field(3, 3, dtype=ti.f32, shape=())

    @ti.kernel
    def fill():
        m1[None] = ti.Matrix.diag(dim=3, val=1.4)

    fill()

    for i in range(3):
        for j in range(3):
            if i == j:
                assert m1[None][i, j] == test_utils.approx(1.4)
            else:
                assert m1[None][i, j] == 0.0
Esempio n. 30
0
def test_random_independent_product():
    n = 1024
    x = ti.field(ti.f32, shape=n * n)

    @ti.kernel
    def fill():
        for i in range(n * n):
            a = ti.random()
            b = ti.random()
            x[i] = a * b

    fill()
    X = x.to_numpy()
    for i in range(4):
        assert X.mean() == test_utils.approx(1 / 4, rel=1e-2)