warp-lang 1.5.0__py3-none-manylinux2014_x86_64.whl → 1.6.0__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +5 -0
- warp/autograd.py +414 -191
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +40 -12
- warp/build_dll.py +13 -6
- warp/builtins.py +1124 -497
- warp/codegen.py +261 -136
- warp/config.py +1 -1
- warp/context.py +357 -119
- warp/examples/assets/square_cloth.usd +0 -0
- warp/examples/benchmarks/benchmark_gemm.py +27 -18
- warp/examples/benchmarks/benchmark_interop_paddle.py +3 -3
- warp/examples/benchmarks/benchmark_interop_torch.py +3 -3
- warp/examples/core/example_torch.py +18 -34
- warp/examples/fem/example_apic_fluid.py +1 -0
- warp/examples/fem/example_mixed_elasticity.py +1 -1
- warp/examples/optim/example_bounce.py +1 -1
- warp/examples/optim/example_cloth_throw.py +1 -1
- warp/examples/optim/example_diffray.py +4 -15
- warp/examples/optim/example_drone.py +1 -1
- warp/examples/optim/example_softbody_properties.py +392 -0
- warp/examples/optim/example_trajectory.py +1 -3
- warp/examples/optim/example_walker.py +5 -0
- warp/examples/sim/example_cartpole.py +0 -2
- warp/examples/sim/example_cloth.py +3 -1
- warp/examples/sim/example_cloth_self_contact.py +260 -0
- warp/examples/sim/example_granular_collision_sdf.py +4 -5
- warp/examples/sim/example_jacobian_ik.py +0 -2
- warp/examples/sim/example_quadruped.py +5 -2
- warp/examples/tile/example_tile_cholesky.py +79 -0
- warp/examples/tile/example_tile_convolution.py +2 -2
- warp/examples/tile/example_tile_fft.py +2 -2
- warp/examples/tile/example_tile_filtering.py +3 -3
- warp/examples/tile/example_tile_matmul.py +4 -4
- warp/examples/tile/example_tile_mlp.py +12 -12
- warp/examples/tile/example_tile_nbody.py +180 -0
- warp/examples/tile/example_tile_walker.py +319 -0
- warp/fem/geometry/geometry.py +0 -2
- warp/math.py +147 -0
- warp/native/array.h +12 -0
- warp/native/builtin.h +0 -1
- warp/native/bvh.cpp +149 -70
- warp/native/bvh.cu +287 -68
- warp/native/bvh.h +195 -85
- warp/native/clang/clang.cpp +5 -1
- warp/native/coloring.cpp +5 -1
- warp/native/cuda_util.cpp +91 -53
- warp/native/cuda_util.h +5 -0
- warp/native/exports.h +40 -40
- warp/native/intersect.h +17 -0
- warp/native/mat.h +41 -0
- warp/native/mathdx.cpp +19 -0
- warp/native/mesh.cpp +25 -8
- warp/native/mesh.cu +153 -101
- warp/native/mesh.h +482 -403
- warp/native/quat.h +40 -0
- warp/native/solid_angle.h +7 -0
- warp/native/sort.cpp +85 -0
- warp/native/sort.cu +34 -0
- warp/native/sort.h +3 -1
- warp/native/spatial.h +11 -0
- warp/native/tile.h +1187 -669
- warp/native/tile_reduce.h +8 -6
- warp/native/vec.h +41 -0
- warp/native/warp.cpp +8 -1
- warp/native/warp.cu +263 -40
- warp/native/warp.h +19 -5
- warp/optim/linear.py +22 -4
- warp/render/render_opengl.py +130 -64
- warp/sim/__init__.py +6 -1
- warp/sim/collide.py +270 -26
- warp/sim/import_urdf.py +8 -8
- warp/sim/integrator_euler.py +25 -7
- warp/sim/integrator_featherstone.py +154 -35
- warp/sim/integrator_vbd.py +842 -40
- warp/sim/model.py +134 -72
- warp/sparse.py +1 -1
- warp/stubs.py +265 -132
- warp/tape.py +28 -30
- warp/tests/aux_test_module_unload.py +15 -0
- warp/tests/{test_sim_grad.py → flaky_test_sim_grad.py} +104 -63
- warp/tests/test_array.py +74 -0
- warp/tests/test_assert.py +242 -0
- warp/tests/test_codegen.py +14 -61
- warp/tests/test_collision.py +2 -2
- warp/tests/test_coloring.py +12 -2
- warp/tests/test_examples.py +12 -1
- warp/tests/test_func.py +21 -4
- warp/tests/test_grad_debug.py +87 -2
- warp/tests/test_hash_grid.py +1 -1
- warp/tests/test_ipc.py +116 -0
- warp/tests/test_lerp.py +13 -87
- warp/tests/test_mat.py +138 -167
- warp/tests/test_math.py +47 -1
- warp/tests/test_matmul.py +17 -16
- warp/tests/test_matmul_lite.py +10 -15
- warp/tests/test_mesh.py +84 -60
- warp/tests/test_mesh_query_aabb.py +165 -0
- warp/tests/test_mesh_query_point.py +328 -286
- warp/tests/test_mesh_query_ray.py +134 -121
- warp/tests/test_mlp.py +2 -2
- warp/tests/test_operators.py +43 -0
- warp/tests/test_overwrite.py +47 -2
- warp/tests/test_quat.py +77 -0
- warp/tests/test_reload.py +29 -0
- warp/tests/test_sim_grad_bounce_linear.py +204 -0
- warp/tests/test_smoothstep.py +17 -83
- warp/tests/test_static.py +19 -3
- warp/tests/test_tape.py +25 -0
- warp/tests/test_tile.py +178 -191
- warp/tests/test_tile_load.py +356 -0
- warp/tests/test_tile_mathdx.py +61 -8
- warp/tests/test_tile_mlp.py +17 -17
- warp/tests/test_tile_reduce.py +24 -18
- warp/tests/test_tile_shared_memory.py +66 -17
- warp/tests/test_tile_view.py +165 -0
- warp/tests/test_torch.py +35 -0
- warp/tests/test_utils.py +36 -24
- warp/tests/test_vec.py +110 -0
- warp/tests/unittest_suites.py +29 -4
- warp/tests/unittest_utils.py +30 -13
- warp/thirdparty/unittest_parallel.py +2 -2
- warp/types.py +411 -101
- warp/utils.py +10 -7
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/METADATA +92 -69
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/RECORD +130 -119
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/WHEEL +1 -1
- warp/examples/benchmarks/benchmark_tile.py +0 -179
- warp/native/tile_gemm.h +0 -341
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
import warp as wp
|
|
11
|
+
import warp.optim
|
|
12
|
+
import warp.sim
|
|
13
|
+
import warp.sim.render
|
|
14
|
+
from warp.tests.unittest_utils import *
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@wp.kernel
|
|
18
|
+
def update_trajectory_kernel(
|
|
19
|
+
trajectory: wp.array(dtype=wp.vec3),
|
|
20
|
+
q: wp.array(dtype=wp.transform),
|
|
21
|
+
time_step: wp.int32,
|
|
22
|
+
q_idx: wp.int32,
|
|
23
|
+
):
|
|
24
|
+
trajectory[time_step] = wp.transform_get_translation(q[q_idx])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@wp.kernel
|
|
28
|
+
def trajectory_loss_kernel(
|
|
29
|
+
trajectory: wp.array(dtype=wp.vec3f),
|
|
30
|
+
target_trajectory: wp.array(dtype=wp.vec3f),
|
|
31
|
+
loss: wp.array(dtype=wp.float32),
|
|
32
|
+
):
|
|
33
|
+
tid = wp.tid()
|
|
34
|
+
diff = trajectory[tid] - target_trajectory[tid]
|
|
35
|
+
distance_loss = wp.dot(diff, diff)
|
|
36
|
+
wp.atomic_add(loss, 0, distance_loss)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class BallBounceLinearTest:
|
|
40
|
+
def __init__(self, gravity=True, rendering=False):
|
|
41
|
+
# Ball bouncing scenario inspired by https://github.com/NVIDIA/warp/issues/349
|
|
42
|
+
self.fps = 30
|
|
43
|
+
self.num_frames = 60
|
|
44
|
+
self.sim_substeps = 20 # XXX need to use enough substeps to achieve smooth gradients
|
|
45
|
+
self.frame_dt = 1.0 / self.fps
|
|
46
|
+
self.sim_dt = self.frame_dt / self.sim_substeps
|
|
47
|
+
self.sim_duration = self.num_frames * self.frame_dt
|
|
48
|
+
self.sim_steps = int(self.sim_duration // self.sim_dt)
|
|
49
|
+
|
|
50
|
+
self.target_force_linear = 100.0
|
|
51
|
+
|
|
52
|
+
if gravity:
|
|
53
|
+
builder = wp.sim.ModelBuilder(up_vector=wp.vec3(0, 0, 1))
|
|
54
|
+
else:
|
|
55
|
+
builder = wp.sim.ModelBuilder(gravity=0.0, up_vector=wp.vec3(0, 0, 1))
|
|
56
|
+
|
|
57
|
+
b = builder.add_body(origin=wp.transform((0.5, 0.0, 1.0), wp.quat_identity()), name="ball")
|
|
58
|
+
builder.add_shape_sphere(
|
|
59
|
+
body=b, radius=0.1, density=100.0, ke=2000.0, kd=10.0, kf=200.0, mu=0.2, thickness=0.01
|
|
60
|
+
)
|
|
61
|
+
builder.set_ground_plane(ke=10, kd=10, kf=0.0, mu=0.2)
|
|
62
|
+
self.model = builder.finalize(requires_grad=True)
|
|
63
|
+
|
|
64
|
+
self.time = np.linspace(0, self.sim_duration, self.sim_steps)
|
|
65
|
+
|
|
66
|
+
self.integrator = wp.sim.SemiImplicitIntegrator()
|
|
67
|
+
if rendering:
|
|
68
|
+
self.renderer = wp.sim.render.SimRendererOpenGL(self.model, "ball_bounce_linear")
|
|
69
|
+
else:
|
|
70
|
+
self.renderer = None
|
|
71
|
+
|
|
72
|
+
self.loss = wp.array([0], dtype=wp.float32, requires_grad=True)
|
|
73
|
+
self.states = [self.model.state() for _ in range(self.sim_steps + 1)]
|
|
74
|
+
self.target_states = [self.model.state() for _ in range(self.sim_steps + 1)]
|
|
75
|
+
|
|
76
|
+
self.target_force = wp.array([0.0, 0.0, 0.0, 0.0, self.target_force_linear, 0.0], dtype=wp.spatial_vectorf)
|
|
77
|
+
|
|
78
|
+
self.trajectory = wp.empty(len(self.time), dtype=wp.vec3, requires_grad=True)
|
|
79
|
+
self.target_trajectory = wp.empty(len(self.time), dtype=wp.vec3)
|
|
80
|
+
|
|
81
|
+
def _reset(self):
|
|
82
|
+
self.loss = wp.array([0], dtype=wp.float32, requires_grad=True)
|
|
83
|
+
|
|
84
|
+
def generate_target_trajectory(self):
|
|
85
|
+
for i in range(self.sim_steps):
|
|
86
|
+
curr_state = self.target_states[i]
|
|
87
|
+
next_state = self.target_states[i + 1]
|
|
88
|
+
curr_state.clear_forces()
|
|
89
|
+
if i == 0:
|
|
90
|
+
wp.copy(curr_state.body_f, self.target_force, dest_offset=0, src_offset=0, count=1)
|
|
91
|
+
wp.sim.collide(self.model, curr_state)
|
|
92
|
+
self.integrator.simulate(self.model, curr_state, next_state, self.sim_dt)
|
|
93
|
+
wp.launch(kernel=update_trajectory_kernel, dim=1, inputs=[self.target_trajectory, curr_state.body_q, i, 0])
|
|
94
|
+
|
|
95
|
+
def forward(self, force: wp.array):
|
|
96
|
+
for i in range(self.sim_steps):
|
|
97
|
+
curr_state = self.states[i]
|
|
98
|
+
next_state = self.states[i + 1]
|
|
99
|
+
curr_state.clear_forces()
|
|
100
|
+
if i == 0:
|
|
101
|
+
wp.copy(curr_state.body_f, force, dest_offset=0, src_offset=0, count=1)
|
|
102
|
+
wp.sim.collide(self.model, curr_state)
|
|
103
|
+
self.integrator.simulate(self.model, curr_state, next_state, self.sim_dt)
|
|
104
|
+
wp.launch(kernel=update_trajectory_kernel, dim=1, inputs=[self.trajectory, curr_state.body_q, i, 0])
|
|
105
|
+
|
|
106
|
+
if self.renderer:
|
|
107
|
+
self.renderer.begin_frame(self.time[i])
|
|
108
|
+
self.renderer.render(curr_state)
|
|
109
|
+
self.renderer.end_frame()
|
|
110
|
+
|
|
111
|
+
def step(self, force: wp.array):
|
|
112
|
+
self.tape = wp.Tape()
|
|
113
|
+
self._reset()
|
|
114
|
+
with self.tape:
|
|
115
|
+
self.forward(force)
|
|
116
|
+
wp.launch(
|
|
117
|
+
kernel=trajectory_loss_kernel,
|
|
118
|
+
dim=len(self.trajectory),
|
|
119
|
+
inputs=[self.trajectory, self.target_trajectory, self.loss],
|
|
120
|
+
)
|
|
121
|
+
self.tape.backward(self.loss)
|
|
122
|
+
force_grad = force.grad.numpy()[0, 4]
|
|
123
|
+
self.tape.zero()
|
|
124
|
+
|
|
125
|
+
return self.loss.numpy()[0], force_grad
|
|
126
|
+
|
|
127
|
+
def evaluate(self, num_samples, plot_results=False):
|
|
128
|
+
forces = np.linspace(0, self.target_force_linear * 2, num_samples)
|
|
129
|
+
losses = np.zeros_like(forces)
|
|
130
|
+
grads = np.zeros_like(forces)
|
|
131
|
+
|
|
132
|
+
for i, fx in enumerate(forces):
|
|
133
|
+
force = wp.array([[0.0, 0.0, 0.0, 0.0, fx, 0.0]], dtype=wp.spatial_vectorf, requires_grad=True)
|
|
134
|
+
losses[i], grads[i] = self.step(force)
|
|
135
|
+
if plot_results:
|
|
136
|
+
print(f"Iteration {i + 1}/{num_samples}")
|
|
137
|
+
print(f"Force: {fx:.2f}, Loss: {losses[i]:.6f}, Grad: {grads[i]:.6f}")
|
|
138
|
+
|
|
139
|
+
assert np.isfinite(losses[i])
|
|
140
|
+
assert np.isfinite(grads[i])
|
|
141
|
+
if i > 0:
|
|
142
|
+
assert grads[i] >= grads[i - 1]
|
|
143
|
+
|
|
144
|
+
if plot_results:
|
|
145
|
+
import matplotlib.pyplot as plt
|
|
146
|
+
|
|
147
|
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
|
|
148
|
+
|
|
149
|
+
# Plot the loss curve
|
|
150
|
+
ax1.plot(forces, losses, label="Loss")
|
|
151
|
+
ax1.set_xlabel("Force")
|
|
152
|
+
ax1.set_ylabel("Loss")
|
|
153
|
+
ax1.set_title("Loss vs Force")
|
|
154
|
+
ax1.legend()
|
|
155
|
+
|
|
156
|
+
# Make sure the grads are not too large
|
|
157
|
+
grads = np.clip(grads, -1e4, 1e4)
|
|
158
|
+
|
|
159
|
+
# Plot the gradient curve
|
|
160
|
+
ax2.plot(forces, grads, label="Gradient", color="orange")
|
|
161
|
+
ax2.set_xlabel("Force")
|
|
162
|
+
ax2.set_ylabel("Gradient")
|
|
163
|
+
ax2.set_title("Gradient vs Force")
|
|
164
|
+
ax2.legend()
|
|
165
|
+
|
|
166
|
+
plt.suptitle("Loss and Gradient vs Force")
|
|
167
|
+
plt.tight_layout(rect=[0, 0, 1, 0.95])
|
|
168
|
+
plt.show()
|
|
169
|
+
|
|
170
|
+
return losses, grads
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def test_sim_grad_bounce_linear(test, device):
|
|
174
|
+
with wp.ScopedDevice(device):
|
|
175
|
+
model = BallBounceLinearTest()
|
|
176
|
+
model.generate_target_trajectory()
|
|
177
|
+
|
|
178
|
+
num_samples = 20
|
|
179
|
+
losses, grads = model.evaluate(num_samples=num_samples)
|
|
180
|
+
# gradients must approximate linear behavior with zero crossing in the middle
|
|
181
|
+
test.assertTrue(np.abs(grads[1:] - grads[:-1]).max() < 1.1)
|
|
182
|
+
test.assertTrue(np.all(grads[: num_samples // 2] <= 0.0))
|
|
183
|
+
test.assertTrue(np.all(grads[num_samples // 2 :] >= 0.0))
|
|
184
|
+
# losses must follow a parabolic behavior
|
|
185
|
+
test.assertTrue(np.allclose(losses[: num_samples // 2], losses[num_samples // 2 :][::-1], atol=1.0))
|
|
186
|
+
diffs = losses[1:] - losses[:-1]
|
|
187
|
+
test.assertTrue(np.all(diffs[: num_samples // 2 - 1] <= 0.0))
|
|
188
|
+
test.assertTrue(np.all(diffs[num_samples // 2 - 1 :] >= 0.0))
|
|
189
|
+
# second derivative must be constant positive
|
|
190
|
+
diffs2 = diffs[1:] - diffs[:-1]
|
|
191
|
+
test.assertTrue(np.allclose(diffs2, diffs2[0], atol=1e-2))
|
|
192
|
+
test.assertTrue(np.all(diffs2 >= 0.0))
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class TestSimGradBounceLinear(unittest.TestCase):
|
|
196
|
+
pass
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
devices = get_test_devices("basic")
|
|
200
|
+
add_function_test(TestSimGradBounceLinear, "test_sim_grad_bounce_linear", test_sim_grad_bounce_linear, devices=devices)
|
|
201
|
+
|
|
202
|
+
if __name__ == "__main__":
|
|
203
|
+
wp.clear_kernel_cache()
|
|
204
|
+
unittest.main(verbosity=2, failfast=True)
|
warp/tests/test_smoothstep.py
CHANGED
|
@@ -31,15 +31,7 @@ class TestData:
|
|
|
31
31
|
|
|
32
32
|
TEST_DATA = {
|
|
33
33
|
wp.float32: (
|
|
34
|
-
TestData(
|
|
35
|
-
a=1.0,
|
|
36
|
-
b=2.0,
|
|
37
|
-
t=1.5,
|
|
38
|
-
expected=0.5,
|
|
39
|
-
expected_adj_a=-0.75,
|
|
40
|
-
expected_adj_b=-0.75,
|
|
41
|
-
expected_adj_t=1.5,
|
|
42
|
-
),
|
|
34
|
+
TestData(a=1.0, b=2.0, t=1.5, expected=0.5, expected_adj_a=-0.75, expected_adj_b=-0.75, expected_adj_t=1.5),
|
|
43
35
|
TestData(
|
|
44
36
|
a=-1.0,
|
|
45
37
|
b=2.0,
|
|
@@ -49,24 +41,8 @@ TEST_DATA = {
|
|
|
49
41
|
expected_adj_b=-0.09375,
|
|
50
42
|
expected_adj_t=0.375,
|
|
51
43
|
),
|
|
52
|
-
TestData(
|
|
53
|
-
|
|
54
|
-
b=1.0,
|
|
55
|
-
t=9.9,
|
|
56
|
-
expected=1.0,
|
|
57
|
-
expected_adj_a=0.0,
|
|
58
|
-
expected_adj_b=0.0,
|
|
59
|
-
expected_adj_t=0.0,
|
|
60
|
-
),
|
|
61
|
-
TestData(
|
|
62
|
-
a=0.0,
|
|
63
|
-
b=1.0,
|
|
64
|
-
t=-9.9,
|
|
65
|
-
expected=0.0,
|
|
66
|
-
expected_adj_a=0.0,
|
|
67
|
-
expected_adj_b=0.0,
|
|
68
|
-
expected_adj_t=0.0,
|
|
69
|
-
),
|
|
44
|
+
TestData(a=0.0, b=1.0, t=9.9, expected=1.0, expected_adj_a=0.0, expected_adj_b=0.0, expected_adj_t=0.0),
|
|
45
|
+
TestData(a=0.0, b=1.0, t=-9.9, expected=0.0, expected_adj_a=0.0, expected_adj_b=0.0, expected_adj_t=0.0),
|
|
70
46
|
),
|
|
71
47
|
}
|
|
72
48
|
|
|
@@ -83,72 +59,30 @@ def test_smoothstep(test, device):
|
|
|
83
59
|
|
|
84
60
|
return fn
|
|
85
61
|
|
|
86
|
-
for data_type in TEST_DATA:
|
|
62
|
+
for data_type, test_data_set in TEST_DATA.items():
|
|
87
63
|
kernel_fn = make_kernel_fn(data_type)
|
|
88
64
|
kernel = wp.Kernel(
|
|
89
65
|
func=kernel_fn,
|
|
90
66
|
key=f"test_smoothstep{data_type.__name__}_kernel",
|
|
91
67
|
)
|
|
92
68
|
|
|
93
|
-
for test_data in
|
|
94
|
-
a = wp.array(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
device=device,
|
|
104
|
-
requires_grad=True,
|
|
105
|
-
)
|
|
106
|
-
t = wp.array(
|
|
107
|
-
[test_data.t],
|
|
108
|
-
dtype=float,
|
|
109
|
-
device=device,
|
|
110
|
-
requires_grad=True,
|
|
111
|
-
)
|
|
112
|
-
out = wp.array(
|
|
113
|
-
[0] * wp.types.type_length(data_type),
|
|
114
|
-
dtype=data_type,
|
|
115
|
-
device=device,
|
|
116
|
-
requires_grad=True,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
tape = wp.Tape()
|
|
120
|
-
with tape:
|
|
121
|
-
wp.launch(
|
|
122
|
-
kernel,
|
|
123
|
-
dim=1,
|
|
124
|
-
inputs=[a, b, t, out],
|
|
125
|
-
device=device,
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
assert_np_equal(
|
|
129
|
-
out.numpy(),
|
|
130
|
-
np.array([test_data.expected]),
|
|
131
|
-
tol=1e-6,
|
|
132
|
-
)
|
|
69
|
+
for test_data in test_data_set:
|
|
70
|
+
a = wp.array([test_data.a], dtype=data_type, device=device, requires_grad=True)
|
|
71
|
+
b = wp.array([test_data.b], dtype=data_type, device=device, requires_grad=True)
|
|
72
|
+
t = wp.array([test_data.t], dtype=float, device=device, requires_grad=True)
|
|
73
|
+
out = wp.array([0] * wp.types.type_length(data_type), dtype=data_type, device=device, requires_grad=True)
|
|
74
|
+
|
|
75
|
+
with wp.Tape() as tape:
|
|
76
|
+
wp.launch(kernel, dim=1, inputs=[a, b, t, out], device=device)
|
|
77
|
+
|
|
78
|
+
assert_np_equal(out.numpy(), np.array([test_data.expected]), tol=1e-6)
|
|
133
79
|
|
|
134
80
|
if test_data.check_backwards():
|
|
135
81
|
tape.backward(out)
|
|
136
82
|
|
|
137
|
-
assert_np_equal(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
tol=1e-6,
|
|
141
|
-
)
|
|
142
|
-
assert_np_equal(
|
|
143
|
-
tape.gradients[b].numpy(),
|
|
144
|
-
np.array([test_data.expected_adj_b]),
|
|
145
|
-
tol=1e-6,
|
|
146
|
-
)
|
|
147
|
-
assert_np_equal(
|
|
148
|
-
tape.gradients[t].numpy(),
|
|
149
|
-
np.array([test_data.expected_adj_t]),
|
|
150
|
-
tol=1e-6,
|
|
151
|
-
)
|
|
83
|
+
assert_np_equal(tape.gradients[a].numpy(), np.array([test_data.expected_adj_a]), tol=1e-6)
|
|
84
|
+
assert_np_equal(tape.gradients[b].numpy(), np.array([test_data.expected_adj_b]), tol=1e-6)
|
|
85
|
+
assert_np_equal(tape.gradients[t].numpy(), np.array([test_data.expected_adj_t]), tol=1e-6)
|
|
152
86
|
|
|
153
87
|
|
|
154
88
|
devices = get_test_devices()
|
warp/tests/test_static.py
CHANGED
|
@@ -281,20 +281,20 @@ def test_function_lookup(test, device):
|
|
|
281
281
|
|
|
282
282
|
outputs = wp.empty(2, dtype=wp.float32)
|
|
283
283
|
|
|
284
|
-
for
|
|
284
|
+
for _op, op_func in op_handlers.items():
|
|
285
285
|
|
|
286
286
|
@wp.kernel
|
|
287
287
|
def operate(input: wp.array(dtype=inputs.dtype, ndim=2), output: wp.array(dtype=wp.float32)):
|
|
288
288
|
tid = wp.tid()
|
|
289
289
|
a, b = input[tid, 0], input[tid, 1]
|
|
290
290
|
# retrieve the right function to use for the captured dtype variable
|
|
291
|
-
output[tid] = wp.static(
|
|
291
|
+
output[tid] = wp.static(op_func)(a, b) # noqa: B023
|
|
292
292
|
|
|
293
293
|
wp.launch(operate, dim=2, inputs=[inputs], outputs=[outputs])
|
|
294
294
|
outputs_np = outputs.numpy()
|
|
295
295
|
inputs_np = inputs.numpy()
|
|
296
296
|
for i in range(len(outputs_np)):
|
|
297
|
-
test.assertEqual(outputs_np[i],
|
|
297
|
+
test.assertEqual(outputs_np[i], op_func(float(inputs_np[i][0]), float(inputs_np[i][1])))
|
|
298
298
|
|
|
299
299
|
|
|
300
300
|
def count_ssa_occurrences(kernel: wp.Kernel, ssas: List[str]) -> Dict[str, int]:
|
|
@@ -536,6 +536,21 @@ def test_static_function_hash(test, _):
|
|
|
536
536
|
test.assertEqual(hash1, hash3)
|
|
537
537
|
|
|
538
538
|
|
|
539
|
+
@wp.kernel
|
|
540
|
+
def static_len_query_kernel(v1: wp.vec2):
|
|
541
|
+
v2 = wp.vec3()
|
|
542
|
+
m = wp.identity(n=wp.static(len(v1) + len(v2) + 1), dtype=float)
|
|
543
|
+
wp.expect_eq(wp.ddot(m, m), 6.0)
|
|
544
|
+
|
|
545
|
+
t = wp.transform_identity(float)
|
|
546
|
+
wp.expect_eq(wp.static(len(t)), 7)
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def test_static_len_query(test, _):
|
|
550
|
+
v1 = wp.vec2()
|
|
551
|
+
wp.launch(static_len_query_kernel, 1, inputs=(v1,))
|
|
552
|
+
|
|
553
|
+
|
|
539
554
|
devices = get_test_devices()
|
|
540
555
|
|
|
541
556
|
|
|
@@ -561,6 +576,7 @@ add_function_test(TestStatic, "test_static_if_else_elif", test_static_if_else_el
|
|
|
561
576
|
|
|
562
577
|
add_function_test(TestStatic, "test_static_constant_hash", test_static_constant_hash, devices=None)
|
|
563
578
|
add_function_test(TestStatic, "test_static_function_hash", test_static_function_hash, devices=None)
|
|
579
|
+
add_function_test(TestStatic, "test_static_len_query", test_static_len_query, devices=None)
|
|
564
580
|
|
|
565
581
|
|
|
566
582
|
if __name__ == "__main__":
|
warp/tests/test_tape.py
CHANGED
|
@@ -125,6 +125,30 @@ def test_tape_dot_product(test, device):
|
|
|
125
125
|
assert_np_equal(tape.gradients[y].numpy(), x.numpy())
|
|
126
126
|
|
|
127
127
|
|
|
128
|
+
@wp.kernel
|
|
129
|
+
def assign_chain_kernel(x: wp.array(dtype=float), y: wp.array(dtype=float), z: wp.array(dtype=float)):
|
|
130
|
+
tid = wp.tid()
|
|
131
|
+
y[tid] = x[tid]
|
|
132
|
+
z[tid] = y[tid]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_tape_zero_multiple_outputs(test, device):
|
|
136
|
+
x = wp.array(np.arange(3), dtype=float, device=device, requires_grad=True)
|
|
137
|
+
y = wp.zeros_like(x)
|
|
138
|
+
z = wp.zeros_like(x)
|
|
139
|
+
|
|
140
|
+
tape = wp.Tape()
|
|
141
|
+
with tape:
|
|
142
|
+
wp.launch(assign_chain_kernel, dim=3, inputs=[x, y, z], device=device)
|
|
143
|
+
|
|
144
|
+
tape.backward(grads={y: wp.ones_like(x)})
|
|
145
|
+
assert_np_equal(x.grad.numpy(), np.ones(3, dtype=float))
|
|
146
|
+
tape.zero()
|
|
147
|
+
|
|
148
|
+
tape.backward(grads={z: wp.ones_like(x)})
|
|
149
|
+
assert_np_equal(x.grad.numpy(), np.ones(3, dtype=float))
|
|
150
|
+
|
|
151
|
+
|
|
128
152
|
def test_tape_visualize(test, device):
|
|
129
153
|
dim = 8
|
|
130
154
|
tape = wp.Tape()
|
|
@@ -163,6 +187,7 @@ class TestTape(unittest.TestCase):
|
|
|
163
187
|
add_function_test(TestTape, "test_tape_mul_constant", test_tape_mul_constant, devices=devices)
|
|
164
188
|
add_function_test(TestTape, "test_tape_mul_variable", test_tape_mul_variable, devices=devices)
|
|
165
189
|
add_function_test(TestTape, "test_tape_dot_product", test_tape_dot_product, devices=devices)
|
|
190
|
+
add_function_test(TestTape, "test_tape_zero_multiple_outputs", test_tape_zero_multiple_outputs, devices=devices)
|
|
166
191
|
add_function_test(TestTape, "test_tape_visualize", test_tape_visualize, devices=devices)
|
|
167
192
|
|
|
168
193
|
|