warp-lang 0.10.1__py3-none-win_amd64.whl → 0.11.0__py3-none-win_amd64.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.

Files changed (300) hide show
  1. warp/__init__.py +10 -4
  2. warp/__init__.pyi +1 -0
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +5 -3
  6. warp/build_dll.py +29 -9
  7. warp/builtins.py +868 -507
  8. warp/codegen.py +1074 -638
  9. warp/config.py +3 -3
  10. warp/constants.py +6 -0
  11. warp/context.py +715 -222
  12. warp/fabric.py +326 -0
  13. warp/fem/__init__.py +27 -0
  14. warp/fem/cache.py +389 -0
  15. warp/fem/dirichlet.py +181 -0
  16. warp/fem/domain.py +263 -0
  17. warp/fem/field/__init__.py +101 -0
  18. warp/fem/field/field.py +149 -0
  19. warp/fem/field/nodal_field.py +299 -0
  20. warp/fem/field/restriction.py +21 -0
  21. warp/fem/field/test.py +181 -0
  22. warp/fem/field/trial.py +183 -0
  23. warp/fem/geometry/__init__.py +19 -0
  24. warp/fem/geometry/closest_point.py +70 -0
  25. warp/fem/geometry/deformed_geometry.py +271 -0
  26. warp/fem/geometry/element.py +744 -0
  27. warp/fem/geometry/geometry.py +186 -0
  28. warp/fem/geometry/grid_2d.py +373 -0
  29. warp/fem/geometry/grid_3d.py +435 -0
  30. warp/fem/geometry/hexmesh.py +953 -0
  31. warp/fem/geometry/partition.py +376 -0
  32. warp/fem/geometry/quadmesh_2d.py +532 -0
  33. warp/fem/geometry/tetmesh.py +840 -0
  34. warp/fem/geometry/trimesh_2d.py +577 -0
  35. warp/fem/integrate.py +1616 -0
  36. warp/fem/operator.py +191 -0
  37. warp/fem/polynomial.py +213 -0
  38. warp/fem/quadrature/__init__.py +2 -0
  39. warp/fem/quadrature/pic_quadrature.py +245 -0
  40. warp/fem/quadrature/quadrature.py +294 -0
  41. warp/fem/space/__init__.py +292 -0
  42. warp/fem/space/basis_space.py +489 -0
  43. warp/fem/space/collocated_function_space.py +105 -0
  44. warp/fem/space/dof_mapper.py +236 -0
  45. warp/fem/space/function_space.py +145 -0
  46. warp/fem/space/grid_2d_function_space.py +267 -0
  47. warp/fem/space/grid_3d_function_space.py +306 -0
  48. warp/fem/space/hexmesh_function_space.py +352 -0
  49. warp/fem/space/partition.py +350 -0
  50. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  51. warp/fem/space/restriction.py +160 -0
  52. warp/fem/space/shape/__init__.py +15 -0
  53. warp/fem/space/shape/cube_shape_function.py +738 -0
  54. warp/fem/space/shape/shape_function.py +103 -0
  55. warp/fem/space/shape/square_shape_function.py +611 -0
  56. warp/fem/space/shape/tet_shape_function.py +567 -0
  57. warp/fem/space/shape/triangle_shape_function.py +429 -0
  58. warp/fem/space/tetmesh_function_space.py +292 -0
  59. warp/fem/space/topology.py +295 -0
  60. warp/fem/space/trimesh_2d_function_space.py +221 -0
  61. warp/fem/types.py +77 -0
  62. warp/fem/utils.py +495 -0
  63. warp/native/array.h +147 -44
  64. warp/native/builtin.h +122 -149
  65. warp/native/bvh.cpp +73 -325
  66. warp/native/bvh.cu +406 -23
  67. warp/native/bvh.h +34 -43
  68. warp/native/clang/clang.cpp +13 -8
  69. warp/native/crt.h +2 -0
  70. warp/native/cuda_crt.h +5 -0
  71. warp/native/cuda_util.cpp +15 -3
  72. warp/native/cuda_util.h +3 -1
  73. warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
  74. warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
  75. warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
  76. warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
  77. warp/native/cutlass/tools/library/scripts/library.py +799 -0
  78. warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
  79. warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
  80. warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
  81. warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
  82. warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
  83. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
  84. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
  85. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
  86. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
  87. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
  88. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
  89. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
  90. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
  91. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
  92. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
  93. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
  94. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
  95. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
  96. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
  97. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
  98. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
  99. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
  100. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
  101. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
  102. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
  103. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
  104. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
  105. warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
  106. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
  107. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
  108. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
  109. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
  110. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
  111. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
  112. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
  113. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
  114. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
  115. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  116. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  117. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
  118. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
  119. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
  120. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
  121. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
  122. warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
  123. warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
  124. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
  125. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
  126. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
  127. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
  128. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
  129. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
  130. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
  131. warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
  132. warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
  133. warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
  134. warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
  135. warp/native/cutlass/tools/library/scripts/rt.py +796 -0
  136. warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
  137. warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
  138. warp/native/cutlass_gemm.cu +5 -3
  139. warp/native/exports.h +1240 -952
  140. warp/native/fabric.h +228 -0
  141. warp/native/hashgrid.cpp +4 -4
  142. warp/native/hashgrid.h +22 -2
  143. warp/native/intersect.h +22 -7
  144. warp/native/intersect_adj.h +8 -8
  145. warp/native/intersect_tri.h +1 -1
  146. warp/native/marching.cu +157 -161
  147. warp/native/mat.h +80 -19
  148. warp/native/matnn.h +2 -2
  149. warp/native/mesh.cpp +33 -108
  150. warp/native/mesh.cu +114 -23
  151. warp/native/mesh.h +446 -46
  152. warp/native/noise.h +272 -329
  153. warp/native/quat.h +51 -8
  154. warp/native/rand.h +45 -35
  155. warp/native/range.h +6 -2
  156. warp/native/reduce.cpp +1 -1
  157. warp/native/reduce.cu +10 -12
  158. warp/native/runlength_encode.cu +6 -10
  159. warp/native/scan.cu +8 -11
  160. warp/native/sparse.cpp +4 -4
  161. warp/native/sparse.cu +164 -154
  162. warp/native/spatial.h +2 -2
  163. warp/native/temp_buffer.h +14 -30
  164. warp/native/vec.h +107 -23
  165. warp/native/volume.h +120 -0
  166. warp/native/warp.cpp +560 -30
  167. warp/native/warp.cu +431 -44
  168. warp/native/warp.h +13 -4
  169. warp/optim/__init__.py +1 -0
  170. warp/optim/linear.py +922 -0
  171. warp/optim/sgd.py +92 -0
  172. warp/render/render_opengl.py +335 -119
  173. warp/render/render_usd.py +11 -11
  174. warp/sim/__init__.py +2 -2
  175. warp/sim/articulation.py +385 -185
  176. warp/sim/collide.py +8 -0
  177. warp/sim/import_mjcf.py +297 -106
  178. warp/sim/import_urdf.py +389 -210
  179. warp/sim/import_usd.py +198 -97
  180. warp/sim/inertia.py +17 -18
  181. warp/sim/integrator_euler.py +14 -8
  182. warp/sim/integrator_xpbd.py +158 -16
  183. warp/sim/model.py +795 -291
  184. warp/sim/render.py +3 -3
  185. warp/sim/utils.py +3 -0
  186. warp/sparse.py +640 -150
  187. warp/stubs.py +606 -267
  188. warp/tape.py +61 -10
  189. warp/tests/__main__.py +3 -6
  190. warp/tests/assets/curlnoise_golden.npy +0 -0
  191. warp/tests/assets/pnoise_golden.npy +0 -0
  192. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  193. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  194. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  195. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  196. warp/tests/aux_test_unresolved_func.py +14 -0
  197. warp/tests/aux_test_unresolved_symbol.py +14 -0
  198. warp/tests/disabled_kinematics.py +239 -0
  199. warp/tests/run_coverage_serial.py +31 -0
  200. warp/tests/test_adam.py +103 -106
  201. warp/tests/test_arithmetic.py +128 -74
  202. warp/tests/test_array.py +212 -97
  203. warp/tests/test_array_reduce.py +57 -23
  204. warp/tests/test_atomic.py +64 -28
  205. warp/tests/test_bool.py +99 -0
  206. warp/tests/test_builtins_resolution.py +1292 -0
  207. warp/tests/test_bvh.py +42 -18
  208. warp/tests/test_closest_point_edge_edge.py +54 -57
  209. warp/tests/test_codegen.py +208 -130
  210. warp/tests/test_compile_consts.py +28 -20
  211. warp/tests/test_conditional.py +108 -24
  212. warp/tests/test_copy.py +10 -12
  213. warp/tests/test_ctypes.py +112 -88
  214. warp/tests/test_dense.py +21 -14
  215. warp/tests/test_devices.py +98 -0
  216. warp/tests/test_dlpack.py +75 -75
  217. warp/tests/test_examples.py +277 -0
  218. warp/tests/test_fabricarray.py +955 -0
  219. warp/tests/test_fast_math.py +15 -11
  220. warp/tests/test_fem.py +1271 -0
  221. warp/tests/test_fp16.py +53 -19
  222. warp/tests/test_func.py +187 -86
  223. warp/tests/test_generics.py +194 -49
  224. warp/tests/test_grad.py +178 -109
  225. warp/tests/test_grad_customs.py +176 -0
  226. warp/tests/test_hash_grid.py +52 -37
  227. warp/tests/test_import.py +10 -23
  228. warp/tests/test_indexedarray.py +32 -31
  229. warp/tests/test_intersect.py +18 -9
  230. warp/tests/test_large.py +141 -0
  231. warp/tests/test_launch.py +14 -41
  232. warp/tests/test_lerp.py +64 -65
  233. warp/tests/test_linear_solvers.py +154 -0
  234. warp/tests/test_lvalue.py +493 -0
  235. warp/tests/test_marching_cubes.py +12 -13
  236. warp/tests/test_mat.py +517 -2898
  237. warp/tests/test_mat_lite.py +115 -0
  238. warp/tests/test_mat_scalar_ops.py +2889 -0
  239. warp/tests/test_math.py +103 -9
  240. warp/tests/test_matmul.py +305 -69
  241. warp/tests/test_matmul_lite.py +410 -0
  242. warp/tests/test_mesh.py +71 -14
  243. warp/tests/test_mesh_query_aabb.py +41 -25
  244. warp/tests/test_mesh_query_point.py +140 -22
  245. warp/tests/test_mesh_query_ray.py +39 -22
  246. warp/tests/test_mlp.py +30 -22
  247. warp/tests/test_model.py +92 -89
  248. warp/tests/test_modules_lite.py +39 -0
  249. warp/tests/test_multigpu.py +88 -114
  250. warp/tests/test_noise.py +12 -11
  251. warp/tests/test_operators.py +16 -20
  252. warp/tests/test_options.py +11 -11
  253. warp/tests/test_pinned.py +17 -18
  254. warp/tests/test_print.py +32 -11
  255. warp/tests/test_quat.py +275 -129
  256. warp/tests/test_rand.py +18 -16
  257. warp/tests/test_reload.py +38 -34
  258. warp/tests/test_rounding.py +50 -43
  259. warp/tests/test_runlength_encode.py +168 -20
  260. warp/tests/test_smoothstep.py +9 -11
  261. warp/tests/test_snippet.py +143 -0
  262. warp/tests/test_sparse.py +261 -63
  263. warp/tests/test_spatial.py +276 -243
  264. warp/tests/test_streams.py +110 -85
  265. warp/tests/test_struct.py +268 -63
  266. warp/tests/test_tape.py +39 -21
  267. warp/tests/test_torch.py +118 -89
  268. warp/tests/test_transient_module.py +12 -13
  269. warp/tests/test_types.py +614 -0
  270. warp/tests/test_utils.py +494 -0
  271. warp/tests/test_vec.py +354 -2050
  272. warp/tests/test_vec_lite.py +73 -0
  273. warp/tests/test_vec_scalar_ops.py +2099 -0
  274. warp/tests/test_volume.py +457 -293
  275. warp/tests/test_volume_write.py +124 -134
  276. warp/tests/unittest_serial.py +35 -0
  277. warp/tests/unittest_suites.py +341 -0
  278. warp/tests/unittest_utils.py +568 -0
  279. warp/tests/unused_test_misc.py +71 -0
  280. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  281. warp/thirdparty/appdirs.py +36 -45
  282. warp/thirdparty/unittest_parallel.py +549 -0
  283. warp/torch.py +9 -6
  284. warp/types.py +1089 -366
  285. warp/utils.py +93 -387
  286. warp_lang-0.11.0.dist-info/METADATA +238 -0
  287. warp_lang-0.11.0.dist-info/RECORD +332 -0
  288. {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
  289. warp/tests/test_all.py +0 -219
  290. warp/tests/test_array_scan.py +0 -60
  291. warp/tests/test_base.py +0 -208
  292. warp/tests/test_unresolved_func.py +0 -7
  293. warp/tests/test_unresolved_symbol.py +0 -7
  294. warp_lang-0.10.1.dist-info/METADATA +0 -21
  295. warp_lang-0.10.1.dist-info/RECORD +0 -188
  296. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  297. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  298. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  299. {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/LICENSE.md +0 -0
  300. {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,568 @@
1
+ # Copyright (c) 2022 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 ctypes
9
+ import ctypes.util
10
+ import os
11
+ import sys
12
+ import time
13
+ import unittest
14
+
15
+ import numpy as np
16
+
17
+ import warp as wp
18
+
19
+ try:
20
+ import pxr # noqa: F401
21
+
22
+ USD_AVAILABLE = True
23
+ except ImportError as e:
24
+ USD_AVAILABLE = False
25
+ print(f"Skipping USD tests for reason: {e}")
26
+
27
+ # default test mode (see get_test_devices())
28
+ # "basic" - only run on CPU and first GPU device
29
+ # "unique" - run on CPU and all unique GPU arches
30
+ # "all" - run on all devices
31
+ test_mode = "unique"
32
+
33
+ try:
34
+ if sys.platform == "win32":
35
+ LIBC = ctypes.CDLL("ucrtbase.dll")
36
+ else:
37
+ LIBC = ctypes.CDLL(ctypes.util.find_library("c"))
38
+ except OSError:
39
+ print("Failed to load the standard C library")
40
+ LIBC = None
41
+
42
+
43
+ def get_unique_cuda_test_devices(mode=None):
44
+ """Returns a list of unique CUDA devices according to the CUDA arch.
45
+
46
+ If ``mode`` is ``None``, the ``global test_mode`` value will be used and
47
+ this list will be a subset of the devices returned from ``get_test_devices()``.
48
+ """
49
+
50
+ if mode is None:
51
+ global test_mode
52
+ mode = test_mode
53
+
54
+ if mode == "basic":
55
+ cuda_devices = [wp.get_device("cuda:0")]
56
+ else:
57
+ cuda_devices = wp.get_cuda_devices()
58
+
59
+ unique_cuda_devices = {}
60
+ for d in cuda_devices:
61
+ if d.arch not in unique_cuda_devices:
62
+ unique_cuda_devices[d.arch] = d
63
+
64
+ return list(unique_cuda_devices.values())
65
+
66
+
67
+ def get_test_devices(mode=None):
68
+ """Returns a list of devices based on the mode selected.
69
+
70
+ Args:
71
+ mode (str, optional): The testing mode to specify which devices to include. If not provided or ``None``, the
72
+ ``global test_mode`` value will be used.
73
+ "basic" (default): Returns the CPU and the first GPU device when available.
74
+ "unique": Returns the CPU and all unique GPU architectures.
75
+ "all": Returns all available devices.
76
+ """
77
+ if mode is None:
78
+ global test_mode
79
+ mode = test_mode
80
+
81
+ devices = []
82
+
83
+ # only run on CPU and first GPU device
84
+ if mode == "basic":
85
+ if wp.is_cpu_available():
86
+ devices.append(wp.get_device("cpu"))
87
+ if wp.is_cuda_available():
88
+ devices.append(wp.get_device("cuda:0"))
89
+
90
+ # run on CPU and all unique GPU arches
91
+ elif mode == "unique":
92
+ if wp.is_cpu_available():
93
+ devices.append(wp.get_device("cpu"))
94
+
95
+ devices.extend(get_unique_cuda_test_devices())
96
+
97
+ # run on all devices
98
+ elif mode == "all":
99
+ devices = wp.get_devices()
100
+
101
+ return devices
102
+
103
+
104
+ # redirects and captures all stdout output (including from C-libs)
105
+ class StdOutCapture:
106
+ def begin(self):
107
+ # Flush the stream buffers managed by libc.
108
+ # This is needed at the moment due to Carbonite not flushing the logs
109
+ # being printed out when extensions are starting up.
110
+ if LIBC is not None:
111
+ LIBC.fflush(None)
112
+
113
+ # save original
114
+ self.saved = sys.stdout
115
+ self.target = os.dup(self.saved.fileno())
116
+
117
+ # create temporary capture stream
118
+ import io
119
+ import tempfile
120
+
121
+ self.tempfile = io.TextIOWrapper(
122
+ tempfile.TemporaryFile(buffering=0), encoding="utf-8", errors="replace", newline="", write_through=True
123
+ )
124
+
125
+ os.dup2(self.tempfile.fileno(), self.saved.fileno())
126
+
127
+ sys.stdout = self.tempfile
128
+
129
+ def end(self):
130
+ if sys.platform == "win32":
131
+ # Workaround for what seems to be a Windows-specific bug where
132
+ # the output of CUDA's `printf` is not being immediately flushed
133
+ # despite the context synchronisation.
134
+ time.sleep(0.01)
135
+
136
+ os.dup2(self.target, self.saved.fileno())
137
+ os.close(self.target)
138
+
139
+ self.tempfile.seek(0)
140
+ res = self.tempfile.buffer.read()
141
+ self.tempfile.close()
142
+
143
+ sys.stdout = self.saved
144
+
145
+ return str(res.decode("utf-8"))
146
+
147
+
148
+ class CheckOutput:
149
+ def __init__(self, test):
150
+ self.test = test
151
+
152
+ def __enter__(self):
153
+ # wp.force_load()
154
+
155
+ self.capture = StdOutCapture()
156
+ self.capture.begin()
157
+
158
+ def __exit__(self, exc_type, exc_value, traceback):
159
+ # ensure any stdout output is flushed
160
+ wp.synchronize()
161
+
162
+ s = self.capture.end()
163
+ if s != "":
164
+ print(s.rstrip())
165
+
166
+ # fail if test produces unexpected output (e.g.: from wp.expect_eq() builtins)
167
+ # we allow strings starting of the form "Module xxx load on device xxx"
168
+ # for lazy loaded modules
169
+ if s != "" and not s.startswith("Module"):
170
+ self.test.fail(f"Unexpected output:\n'{s.rstrip()}'")
171
+
172
+
173
+ def assert_array_equal(result: wp.array, expect: wp.array):
174
+ np.testing.assert_equal(result.numpy(), expect.numpy())
175
+
176
+
177
+ def assert_np_equal(result, expect, tol=0.0):
178
+ a = result.flatten()
179
+ b = expect.flatten()
180
+
181
+ if tol == 0.0:
182
+ if not (a == b).all():
183
+ raise AssertionError(f"Unexpected result, got: {a} expected: {b}")
184
+
185
+ else:
186
+ delta = a - b
187
+ err = np.max(np.abs(delta))
188
+ if err > tol:
189
+ raise AssertionError(
190
+ f"Maximum expected error exceeds tolerance got: {a}, expected: {b}, with err: {err} > {tol}"
191
+ )
192
+
193
+
194
+ # if check_output is True any output to stdout will be treated as an error
195
+ def create_test_func(func, device, check_output, **kwargs):
196
+ # pass args to func
197
+ def test_func(self):
198
+ if check_output:
199
+ with CheckOutput(self):
200
+ func(self, device, **kwargs)
201
+ else:
202
+ func(self, device, **kwargs)
203
+
204
+ return test_func
205
+
206
+
207
+ def skip_test_func(self):
208
+ # A function to use so we can tell unittest that the test was skipped.
209
+ self.skipTest("No suitable devices to run the test.")
210
+
211
+
212
+ def sanitize_identifier(s):
213
+ """replace all non-identifier characters with '_'"""
214
+
215
+ s = str(s)
216
+ if s.isidentifier():
217
+ return s
218
+ else:
219
+ import re
220
+
221
+ return re.sub(r"\W|^(?=\d)", "_", s)
222
+
223
+
224
+ def add_function_test(cls, name, func, devices=None, check_output=True, **kwargs):
225
+ if devices is None:
226
+ setattr(cls, name, create_test_func(func, None, check_output, **kwargs))
227
+ elif isinstance(devices, list):
228
+ if not devices:
229
+ # No devices to run this test
230
+ setattr(cls, name, skip_test_func)
231
+ else:
232
+ for device in devices:
233
+ setattr(
234
+ cls,
235
+ name + "_" + sanitize_identifier(device),
236
+ create_test_func(func, device, check_output, **kwargs),
237
+ )
238
+ else:
239
+ setattr(cls, name + "_" + sanitize_identifier(devices), create_test_func(func, devices, check_output, **kwargs))
240
+
241
+
242
+ def add_kernel_test(cls, kernel, dim, name=None, expect=None, inputs=None, devices=None):
243
+ def test_func(self, device):
244
+ args = []
245
+ if inputs:
246
+ args.extend(inputs)
247
+
248
+ if expect:
249
+ # allocate outputs to match results
250
+ result = wp.array(expect, dtype=int, device=device)
251
+ output = wp.zeros_like(result)
252
+
253
+ args.append(output)
254
+
255
+ # force load so that we don't generate any log output during launch
256
+ kernel.module.load(device)
257
+
258
+ with CheckOutput(self):
259
+ wp.launch(kernel, dim=dim, inputs=args, device=device)
260
+
261
+ # check output values
262
+ if expect:
263
+ assert_array_equal(output, result)
264
+
265
+ if name is None:
266
+ name = kernel.key
267
+
268
+ # device is required for kernel tests, so use all devices if none were given
269
+ if devices is None:
270
+ devices = get_test_devices()
271
+
272
+ # register test func with class for the given devices
273
+ for d in devices:
274
+ # use a function to forward the device to the inner test function
275
+ def test_func_wrapper(test, device=d):
276
+ test_func(test, device)
277
+
278
+ setattr(cls, name + "_" + sanitize_identifier(d), test_func_wrapper)
279
+
280
+
281
+ # helper that first calls the test function to generate all kernel permutations
282
+ # so that compilation is done in one-shot instead of per-test
283
+ def add_function_test_register_kernel(cls, name, func, devices=None, **kwargs):
284
+ func(None, None, **kwargs, register_kernels=True)
285
+ add_function_test(cls, name, func, devices=devices, **kwargs)
286
+
287
+
288
+ class TeamCityTestResult(unittest.TextTestResult):
289
+ """This class will report each test result to TeamCity"""
290
+
291
+ def __init__(self, stream, descriptions, verbosity):
292
+ super(TeamCityTestResult, self).__init__(stream, descriptions, verbosity)
293
+
294
+ def addSuccess(self, test):
295
+ super(TeamCityTestResult, self).addSuccess(test)
296
+ self.reportSuccess(test)
297
+
298
+ def addError(self, test, err):
299
+ super(TeamCityTestResult, self).addError(test, err)
300
+ self.reportFailure(test)
301
+
302
+ def addFailure(self, test, err):
303
+ super(TeamCityTestResult, self).addFailure(test, err)
304
+ self.reportFailure(test)
305
+
306
+ def addSkip(self, test, reason):
307
+ super(TeamCityTestResult, self).addSkip(test, reason)
308
+
309
+ def addExpectedFailure(self, test, err):
310
+ super(TeamCityTestResult, self).addExpectedFailure(test, err)
311
+ self.reportSuccess(test)
312
+
313
+ def addUnexpectedSuccess(self, test):
314
+ super(TeamCityTestResult, self).addUnexpectedSuccess(test)
315
+ self.reportFailure(test)
316
+
317
+ def reportSuccess(self, test):
318
+ test_id = test.id()
319
+ print(f"##teamcity[testStarted name='{test_id}']")
320
+ print(f"##teamcity[testFinished name='{test_id}']")
321
+
322
+ def reportFailure(self, test):
323
+ test_id = test.id()
324
+ print(f"##teamcity[testStarted name='{test_id}']")
325
+ print(f"##teamcity[testFailed name='{test_id}']")
326
+ print(f"##teamcity[testFinished name='{test_id}']")
327
+
328
+
329
+ class TeamCityTestRunner(unittest.TextTestRunner):
330
+ """Test runner that will report test results to TeamCity if running in TeamCity"""
331
+
332
+ def __init__(self, **kwargs):
333
+ self.running_in_teamcity = os.environ.get("TEAMCITY_VERSION") is not None
334
+ if self.running_in_teamcity:
335
+ kwargs["resultclass"] = TeamCityTestResult
336
+ super(TeamCityTestRunner, self).__init__(**kwargs)
337
+
338
+ def run(self, test, name):
339
+ if self.running_in_teamcity:
340
+ print(f"##teamcity[testSuiteStarted name='{name}']")
341
+
342
+ result = super(TeamCityTestRunner, self).run(test)
343
+
344
+ if self.running_in_teamcity:
345
+ print(f"##teamcity[testSuiteFinished name='{name}']")
346
+ if not result.wasSuccessful():
347
+ print("##teamcity[buildStatus status='FAILURE']")
348
+
349
+ return result
350
+
351
+
352
+ def write_junit_results(
353
+ outfile: str,
354
+ test_records: list,
355
+ tests_run: int,
356
+ tests_failed: int,
357
+ tests_errored: int,
358
+ tests_skipped: int,
359
+ test_duration: float,
360
+ ):
361
+ """Write a JUnit XML from our report data
362
+
363
+ The report file is needed for GitLab to add test reports in merge requests.
364
+ """
365
+
366
+ import xml.etree.ElementTree as ET
367
+
368
+ root = ET.Element(
369
+ "testsuites",
370
+ name="Warp Tests",
371
+ failures=str(tests_failed),
372
+ errors=str(tests_errored),
373
+ skipped=str(tests_skipped),
374
+ tests=str(tests_run),
375
+ time=f"{test_duration:.3f}",
376
+ )
377
+
378
+ for test_data in test_records:
379
+ test = test_data[0]
380
+ test_duration = test_data[1]
381
+ test_status = test_data[2]
382
+
383
+ test_case = ET.SubElement(
384
+ root, "testcase", classname=test.__class__.__name__, name=test._testMethodName, time=f"{test_duration:.3f}"
385
+ )
386
+
387
+ if test_status == "FAIL":
388
+ failure = ET.SubElement(test_case, "failure", message=str(test_data[3]))
389
+ failure.text = str(test_data[4]) # Stacktrace
390
+ elif test_status == "ERROR":
391
+ error = ET.SubElement(test_case, "error")
392
+ error.text = str(test_data[4]) # Stacktrace
393
+ elif test_status == "SKIP":
394
+ skip = ET.SubElement(test_case, "skipped")
395
+ skip.text = str(test_data[3]) # The skip reason
396
+
397
+ tree = ET.ElementTree(root)
398
+
399
+ if hasattr(ET, "indent"):
400
+ ET.indent(root) # Pretty-printed XML output, Python 3.9 required
401
+
402
+ tree.write(outfile, encoding="utf-8", xml_declaration=True)
403
+
404
+
405
+ class ParallelJunitTestResult(unittest.TextTestResult):
406
+ def __init__(self, stream, descriptions, verbosity):
407
+ stream = type(stream)(sys.stderr)
408
+ self.test_record = []
409
+ super().__init__(stream, descriptions, verbosity)
410
+
411
+ def startTest(self, test):
412
+ if self.showAll:
413
+ self.stream.writeln(f"{self.getDescription(test)} ...")
414
+ self.stream.flush()
415
+ self.start_time = time.perf_counter_ns()
416
+ super(unittest.TextTestResult, self).startTest(test)
417
+
418
+ def _add_helper(self, test, dots_message, show_all_message):
419
+ if self.showAll:
420
+ self.stream.writeln(f"{self.getDescription(test)} ... {show_all_message}")
421
+ elif self.dots:
422
+ self.stream.write(dots_message)
423
+ self.stream.flush()
424
+
425
+ def _record_test(self, test, code, message=None, details=None):
426
+ duration = round((time.perf_counter_ns() - self.start_time) * 1e-9, 3) # [s]
427
+ self.test_record.append((test, duration, code, message, details))
428
+
429
+ def addSuccess(self, test):
430
+ super(unittest.TextTestResult, self).addSuccess(test)
431
+ self._add_helper(test, ".", "ok")
432
+ self._record_test(test, "OK")
433
+
434
+ def addError(self, test, err):
435
+ super(unittest.TextTestResult, self).addError(test, err)
436
+ self._add_helper(test, "E", "ERROR")
437
+ self._record_test(test, "ERROR", str(err[1]), self._exc_info_to_string(err, test))
438
+
439
+ def addFailure(self, test, err):
440
+ super(unittest.TextTestResult, self).addFailure(test, err)
441
+ self._add_helper(test, "F", "FAIL")
442
+ self._record_test(test, "FAIL", str(err[1]), self._exc_info_to_string(err, test))
443
+
444
+ def addSkip(self, test, reason):
445
+ super(unittest.TextTestResult, self).addSkip(test, reason)
446
+ self._add_helper(test, "s", f"skipped {reason!r}")
447
+ self._record_test(test, "SKIP", reason)
448
+
449
+ def addExpectedFailure(self, test, err):
450
+ super(unittest.TextTestResult, self).addExpectedFailure(test, err)
451
+ self._add_helper(test, "x", "expected failure")
452
+ self._record_test(test, "OK", "expected failure")
453
+
454
+ def addUnexpectedSuccess(self, test):
455
+ super(unittest.TextTestResult, self).addUnexpectedSuccess(test)
456
+ self._add_helper(test, "u", "unexpected success")
457
+ self._record_test(test, "FAIL", "unexpected success")
458
+
459
+ def addSubTest(self, test, subtest, err):
460
+ super(unittest.TextTestResult, self).addSubTest(test, subtest, err)
461
+ if err is not None:
462
+ self._add_helper(test, "E", "ERROR")
463
+ # err is (class, error, traceback)
464
+ self._record_test(test, "FAIL", str(err[1]), self._exc_info_to_string(err, test))
465
+
466
+ def printErrors(self):
467
+ pass
468
+
469
+
470
+ def _tc_escape(s):
471
+ """Modifies strings so they can be used in TeamCity log messages."""
472
+ s = s.replace("|", "||")
473
+ s = s.replace("\n", "|n")
474
+ s = s.replace("\r", "|r")
475
+ s = s.replace("'", "|'")
476
+ s = s.replace("[", "|[")
477
+ s = s.replace("]", "|]")
478
+ return s
479
+
480
+
481
+ class ParallelTeamCityTestResult(unittest.TextTestResult):
482
+ def __init__(self, stream, descriptions, verbosity):
483
+ stream = type(stream)(sys.stderr)
484
+ super().__init__(stream, descriptions, verbosity)
485
+ self.test_record = []
486
+
487
+ def startTest(self, test):
488
+ if self.showAll:
489
+ self.stream.writeln(f"{self.getDescription(test)} ...")
490
+ self.stream.flush()
491
+ self.start_time = time.perf_counter_ns()
492
+ super(unittest.TextTestResult, self).startTest(test)
493
+
494
+ def _add_helper(self, test, dots_message, show_all_message):
495
+ if self.showAll:
496
+ self.stream.writeln(f"{self.getDescription(test)} ... {show_all_message}")
497
+ elif self.dots:
498
+ self.stream.write(dots_message)
499
+ self.stream.flush()
500
+
501
+ def addSuccess(self, test):
502
+ super(unittest.TextTestResult, self).addSuccess(test)
503
+ self._add_helper(test, ".", "ok")
504
+ self.reportSuccess(test)
505
+
506
+ def addError(self, test, err):
507
+ super(unittest.TextTestResult, self).addError(test, err)
508
+ self._add_helper(test, "E", "ERROR")
509
+ self.reportFailure(test, err)
510
+
511
+ def addFailure(self, test, err):
512
+ super(unittest.TextTestResult, self).addFailure(test, err)
513
+ self._add_helper(test, "F", "FAIL")
514
+ self.reportFailure(test, err)
515
+
516
+ def addSkip(self, test, reason):
517
+ super(unittest.TextTestResult, self).addSkip(test, reason)
518
+ self._add_helper(test, "s", f"skipped {reason!r}")
519
+ self.reportIgnored(test, reason)
520
+
521
+ def addExpectedFailure(self, test, err):
522
+ super(unittest.TextTestResult, self).addExpectedFailure(test, err)
523
+ self._add_helper(test, "x", "expected failure")
524
+ self.reportSuccess(test)
525
+
526
+ def addUnexpectedSuccess(self, test):
527
+ super(unittest.TextTestResult, self).addUnexpectedSuccess(test)
528
+ self._add_helper(test, "u", "unexpected success")
529
+ self.reportFailure(test, "unexpected success")
530
+
531
+ def addSubTest(self, test, subtest, err):
532
+ super(unittest.TextTestResult, self).addSubTest(test, subtest, err)
533
+ if err is not None:
534
+ self._add_helper(test, "E", "ERROR")
535
+ self.reportSubTestFailure(test, err)
536
+
537
+ def printErrors(self):
538
+ pass
539
+
540
+ def reportIgnored(self, test, reason):
541
+ test_id = test.id()
542
+ self.stream.writeln(f"##teamcity[testIgnored name='{test_id}' message='{_tc_escape(str(reason))}']")
543
+ self.stream.flush()
544
+
545
+ def reportSuccess(self, test):
546
+ duration = round((time.perf_counter_ns() - self.start_time) / 1e6) # [ms]
547
+ test_id = test.id()
548
+ self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
549
+ self.stream.writeln(f"##teamcity[testFinished name='{test_id}' duration='{duration}']")
550
+ self.stream.flush()
551
+
552
+ def reportFailure(self, test, err):
553
+ test_id = test.id()
554
+ self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
555
+ self.stream.writeln(
556
+ f"##teamcity[testFailed name='{test_id}' message='{_tc_escape(str(err[1]))}' details='{_tc_escape(self._exc_info_to_string(err, test))}']"
557
+ )
558
+ self.stream.writeln(f"##teamcity[testFinished name='{test_id}']")
559
+ self.stream.flush()
560
+
561
+ def reportSubTestFailure(self, test, err):
562
+ test_id = test.id()
563
+ self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
564
+ self.stream.writeln(
565
+ f"##teamcity[testFailed name='{test_id}' message='{_tc_escape(str(err[1]))}' details='{_tc_escape(self._exc_info_to_string(err, test))}']"
566
+ )
567
+ self.stream.writeln(f"##teamcity[testFinished name='{test_id}']")
568
+ self.stream.flush()
@@ -0,0 +1,71 @@
1
+ # Copyright (c) 2021 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
+
12
+ wp.init()
13
+
14
+
15
+ @wp.kernel
16
+ def arange(out: wp.array(dtype=int)):
17
+ tid = wp.tid()
18
+ out[tid] = tid
19
+
20
+
21
+ device = "cuda:0"
22
+ cmds = []
23
+
24
+ n = 10
25
+ arrays = []
26
+
27
+ for i in range(5):
28
+ arrays.append(wp.zeros(n, dtype=int, device=device))
29
+
30
+ # setup CUDA graph
31
+ wp.capture_begin()
32
+
33
+ # launch kernels and keep command object around
34
+ for i in range(5):
35
+ cmd = wp.launch(arange, dim=n, inputs=[arrays[i]], device=device, record_cmd=True)
36
+ cmds.append(cmd)
37
+
38
+ graph = wp.capture_end()
39
+
40
+ # ---------------------------------------
41
+
42
+ ref = np.arange(0, n, dtype=int)
43
+ wp.capture_launch(graph)
44
+
45
+ for i in range(5):
46
+ print(arrays[i].numpy())
47
+
48
+
49
+ # ---------------------------------------
50
+
51
+ n = 16
52
+ arrays = []
53
+
54
+ for i in range(5):
55
+ arrays.append(wp.zeros(n, dtype=int, device=device))
56
+
57
+ # update graph params
58
+ for i in range(5):
59
+ cmd.set_dim(n)
60
+ cmd.set_param(arrays[i])
61
+
62
+ cmd.update_graph()
63
+
64
+
65
+ wp.capture_launch(graph)
66
+ wp.synchronize()
67
+
68
+ ref = np.arange(0, n, dtype=int)
69
+
70
+ for i in range(5):
71
+ print(arrays[i].numpy())
@@ -49,10 +49,7 @@
49
49
  #
50
50
  ####################################################################################################
51
51
 
52
- import unittest
53
-
54
52
  import warp as wp
55
- from warp.tests.test_base import *
56
53
 
57
54
  # The init() function prints the directory of the kernel cache which contains the .cpp files
58
55
  # generated from Warp kernels. You can put breakpoints in these C++ files through Visual Studio Code,
@@ -67,7 +64,7 @@ assert wp.context.runtime.core.is_debug_enabled(), "Warp must be built in debug
67
64
 
68
65
 
69
66
  @wp.kernel
70
- def test_breakpoint(n: int):
67
+ def example_breakpoint(n: int):
71
68
  a = int(0)
72
69
 
73
70
  for i in range(0, n):
@@ -83,17 +80,6 @@ def test_breakpoint(n: int):
83
80
  wp.expect_eq(a, 5)
84
81
 
85
82
 
86
- def register(parent):
87
- class TestDebug(parent):
88
- pass
89
-
90
- wp.build.clear_kernel_cache()
91
-
92
- add_kernel_test(TestDebug, name="test_breakpoint", kernel=test_breakpoint, dim=1, inputs=[10], devices=["cpu"])
93
-
94
- return TestDebug
95
-
96
-
97
83
  if __name__ == "__main__":
98
- c = register(unittest.TestCase)
99
- unittest.main(verbosity=2, failfast=True)
84
+ wp.build.clear_kernel_cache()
85
+ wp.launch(example_breakpoint, dim=1, inputs=[10], device="cpu")