gstaichi 0.1.25.dev0__cp310-cp310-macosx_15_0_arm64.whl → 2.0.0__cp310-cp310-macosx_15_0_arm64.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.
- gstaichi/CHANGELOG.md +6 -0
- gstaichi/__init__.py +1 -1
- gstaichi/_lib/core/gstaichi_python.cpython-310-darwin.so +0 -0
- gstaichi/_lib/core/gstaichi_python.pyi +11 -41
- gstaichi/_test_tools/__init__.py +18 -0
- gstaichi/_test_tools/dataclass_test_tools.py +36 -0
- gstaichi/_test_tools/textwrap2.py +6 -0
- gstaichi/_version.py +1 -1
- gstaichi/examples/minimal.py +1 -1
- gstaichi/lang/__init__.py +1 -1
- gstaichi/lang/_dataclass_util.py +31 -0
- gstaichi/lang/_fast_caching/__init__.py +3 -0
- gstaichi/lang/_fast_caching/args_hasher.py +110 -0
- gstaichi/lang/_fast_caching/config_hasher.py +30 -0
- gstaichi/lang/_fast_caching/fast_caching_types.py +21 -0
- gstaichi/lang/_fast_caching/function_hasher.py +57 -0
- gstaichi/lang/_fast_caching/hash_utils.py +11 -0
- gstaichi/lang/_fast_caching/python_side_cache.py +52 -0
- gstaichi/lang/_fast_caching/src_hasher.py +75 -0
- gstaichi/lang/_kernel_impl_dataclass.py +212 -0
- gstaichi/lang/_template_mapper.py +16 -20
- gstaichi/lang/_wrap_inspect.py +27 -1
- gstaichi/lang/ast/ast_transformer.py +7 -2
- gstaichi/lang/ast/ast_transformer_utils.py +18 -13
- gstaichi/lang/ast/ast_transformers/call_transformer.py +73 -16
- gstaichi/lang/ast/ast_transformers/function_def_transformer.py +102 -118
- gstaichi/lang/field.py +0 -38
- gstaichi/lang/impl.py +25 -24
- gstaichi/lang/kernel_arguments.py +28 -30
- gstaichi/lang/kernel_impl.py +154 -200
- gstaichi/lang/matrix.py +0 -46
- gstaichi/lang/struct.py +0 -45
- gstaichi/lang/util.py +11 -80
- gstaichi/types/annotations.py +10 -5
- gstaichi/types/compound_types.py +1 -20
- gstaichi/types/ndarray_type.py +31 -11
- gstaichi/types/utils.py +0 -2
- {gstaichi-0.1.25.dev0.dist-info → gstaichi-2.0.0.dist-info}/METADATA +2 -1
- gstaichi-2.0.0.dist-info/RECORD +177 -0
- gstaichi/__main__.py +0 -5
- gstaichi/_main.py +0 -545
- gstaichi/lang/argpack.py +0 -411
- gstaichi-0.1.25.dev0.dist-info/RECORD +0 -168
- gstaichi-0.1.25.dev0.dist-info/entry_points.txt +0 -2
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/GLFW/glfw3.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/GLFW/glfw3native.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv-tools/instrument.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv-tools/libspirv.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv-tools/libspirv.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv-tools/linker.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv-tools/optimizer.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/GLSL.std.450.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cfg.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_common.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cpp.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross_c.h +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross_containers.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross_error_handling.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross_parsed_ir.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_cross_util.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_glsl.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_hlsl.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_msl.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_parser.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/include/spirv_cross/spirv_reflect.hpp +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsTarget-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsTarget.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffTargets-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffTargets.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkTargets-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkTargets.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintTargets-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintTargets.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optTargets-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optTargets.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceTarget-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceTarget.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/glfw3/glfw3Config.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/glfw3/glfw3ConfigVersion.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/glfw3/glfw3Targets-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/cmake/glfw3/glfw3Targets.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/lib/libSPIRV-Tools-shared.dylib +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_c/cmake/spirv_cross_cConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_c/cmake/spirv_cross_cConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_core/cmake/spirv_cross_coreConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_core/cmake/spirv_cross_coreConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_cpp/cmake/spirv_cross_cppConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_cpp/cmake/spirv_cross_cppConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_glsl/cmake/spirv_cross_glslConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_glsl/cmake/spirv_cross_glslConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_hlsl/cmake/spirv_cross_hlslConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_hlsl/cmake/spirv_cross_hlslConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_msl/cmake/spirv_cross_mslConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_msl/cmake/spirv_cross_mslConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_reflect/cmake/spirv_cross_reflectConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_reflect/cmake/spirv_cross_reflectConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_util/cmake/spirv_cross_utilConfig-release.cmake +0 -0
- {gstaichi-0.1.25.dev0.data → gstaichi-2.0.0.data}/data/share/spirv_cross_util/cmake/spirv_cross_utilConfig.cmake +0 -0
- {gstaichi-0.1.25.dev0.dist-info → gstaichi-2.0.0.dist-info}/WHEEL +0 -0
- {gstaichi-0.1.25.dev0.dist-info → gstaichi-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {gstaichi-0.1.25.dev0.dist-info → gstaichi-2.0.0.dist-info}/top_level.txt +0 -0
gstaichi/_main.py
DELETED
@@ -1,545 +0,0 @@
|
|
1
|
-
# type: ignore
|
2
|
-
|
3
|
-
import argparse
|
4
|
-
import math
|
5
|
-
import os
|
6
|
-
import runpy
|
7
|
-
import shutil
|
8
|
-
import subprocess
|
9
|
-
import sys
|
10
|
-
import timeit
|
11
|
-
from collections import defaultdict
|
12
|
-
from functools import wraps
|
13
|
-
from pathlib import Path
|
14
|
-
|
15
|
-
import rich
|
16
|
-
from colorama import Fore
|
17
|
-
from rich.console import Console
|
18
|
-
|
19
|
-
from gstaichi._lib import core as _ti_core
|
20
|
-
from gstaichi._lib import utils
|
21
|
-
from gstaichi.lang import impl
|
22
|
-
from gstaichi.tools import diagnose
|
23
|
-
|
24
|
-
|
25
|
-
def timer(func):
|
26
|
-
"""Function decorator to benchmark a function running time."""
|
27
|
-
|
28
|
-
@wraps(func)
|
29
|
-
def wrapper(*args, **kwargs):
|
30
|
-
start = timeit.default_timer()
|
31
|
-
result = func(*args, **kwargs)
|
32
|
-
elapsed = timeit.default_timer() - start
|
33
|
-
print(f">>> Running time: {elapsed:.2f}s")
|
34
|
-
return result
|
35
|
-
|
36
|
-
return wrapper
|
37
|
-
|
38
|
-
|
39
|
-
def registerableCLI(cls):
|
40
|
-
"""Class decorator to register methods with @register into a set."""
|
41
|
-
cls.registered_commands = set([])
|
42
|
-
for name in dir(cls):
|
43
|
-
method = getattr(cls, name)
|
44
|
-
if hasattr(method, "registered"):
|
45
|
-
cls.registered_commands.add(name)
|
46
|
-
return cls
|
47
|
-
|
48
|
-
|
49
|
-
def register(func):
|
50
|
-
"""Method decorator to register CLI commands."""
|
51
|
-
func.registered = True
|
52
|
-
return func
|
53
|
-
|
54
|
-
|
55
|
-
@registerableCLI
|
56
|
-
class GsTaichiMain:
|
57
|
-
def __init__(self, test_mode: bool = False):
|
58
|
-
self.banner = f"\n{'*' * 43}\n** GsTaichi Programming Language **\n{'*' * 43}"
|
59
|
-
print(self.banner)
|
60
|
-
|
61
|
-
print(self._get_friend_links())
|
62
|
-
|
63
|
-
parser = argparse.ArgumentParser(description="GsTaichi CLI", usage=self._usage())
|
64
|
-
parser.add_argument("command", help="command from the above list to run")
|
65
|
-
|
66
|
-
# Flag for unit testing
|
67
|
-
self.test_mode = test_mode
|
68
|
-
|
69
|
-
self.main_parser = parser
|
70
|
-
|
71
|
-
@timer
|
72
|
-
def __call__(self):
|
73
|
-
# Print help if no command provided
|
74
|
-
if len(sys.argv[1:2]) == 0:
|
75
|
-
self.main_parser.print_help()
|
76
|
-
return 1
|
77
|
-
|
78
|
-
# Parse the command
|
79
|
-
args = self.main_parser.parse_args(sys.argv[1:2])
|
80
|
-
|
81
|
-
if args.command not in self.registered_commands: # pylint: disable=E1101
|
82
|
-
# TODO: do we really need this?
|
83
|
-
if args.command.endswith(".py"):
|
84
|
-
GsTaichiMain._exec_python_file(args.command)
|
85
|
-
else:
|
86
|
-
print(f"{args.command} is not a valid command!")
|
87
|
-
self.main_parser.print_help()
|
88
|
-
return 1
|
89
|
-
|
90
|
-
return getattr(self, args.command)(sys.argv[2:])
|
91
|
-
|
92
|
-
@staticmethod
|
93
|
-
def _get_friend_links():
|
94
|
-
return (
|
95
|
-
"\n"
|
96
|
-
"Docs: https://docs.taichi-lang.org/\n"
|
97
|
-
"GitHub: https://github.com/taichi-dev/gstaichi/\n"
|
98
|
-
"Forum: https://forum.gstaichi.graphics/\n"
|
99
|
-
)
|
100
|
-
|
101
|
-
def _usage(self) -> str:
|
102
|
-
"""Compose deterministic usage message based on registered_commands."""
|
103
|
-
# TODO: add some color to commands
|
104
|
-
msg = "\n"
|
105
|
-
space = 20
|
106
|
-
for command in sorted(self.registered_commands): # pylint: disable=E1101
|
107
|
-
msg += f" {command}{' ' * (space - len(command))}|-> {getattr(self, command).__doc__}\n"
|
108
|
-
return msg
|
109
|
-
|
110
|
-
@staticmethod
|
111
|
-
def _exec_python_file(filename: str):
|
112
|
-
"""Execute a Python file based on filename."""
|
113
|
-
# TODO: do we really need this?
|
114
|
-
subprocess.call([sys.executable, filename] + sys.argv[1:])
|
115
|
-
|
116
|
-
@staticmethod
|
117
|
-
def _get_examples_dir() -> Path:
|
118
|
-
"""Get the path to the examples directory."""
|
119
|
-
|
120
|
-
root_dir = utils.package_root
|
121
|
-
examples_dir = Path(root_dir) / "examples"
|
122
|
-
return examples_dir
|
123
|
-
|
124
|
-
@staticmethod
|
125
|
-
def _get_available_examples() -> set:
|
126
|
-
"""Get a set of all available example names."""
|
127
|
-
examples_dir = GsTaichiMain._get_examples_dir()
|
128
|
-
all_examples = examples_dir.rglob("*.py")
|
129
|
-
all_example_names = {f.stem: f.parent for f in all_examples}
|
130
|
-
return all_example_names
|
131
|
-
|
132
|
-
@staticmethod
|
133
|
-
def _example_choices_type(choices):
|
134
|
-
def support_choice_with_dot_py(choice):
|
135
|
-
if choice.endswith(".py") and choice.split(".")[0] in choices:
|
136
|
-
# try to find and remove python file extension
|
137
|
-
return choice.split(".")[0]
|
138
|
-
return choice
|
139
|
-
|
140
|
-
return support_choice_with_dot_py
|
141
|
-
|
142
|
-
@register
|
143
|
-
def example(self, arguments: list = sys.argv[2:]):
|
144
|
-
"""Run an example by name (or name.py)"""
|
145
|
-
|
146
|
-
def colormap(index, name):
|
147
|
-
from colorsys import hls_to_rgb # pylint: disable=C0415
|
148
|
-
|
149
|
-
x = (ord(name[0].upper()) - 64.0) / 26.0
|
150
|
-
r, g, b = hls_to_rgb(x, 0.4, 1.0)
|
151
|
-
r = hex(int(r * 255) % 16)[2:]
|
152
|
-
g = hex(int(g * 255) % 16)[2:]
|
153
|
-
b = hex(int(b * 255) % 16)[2:]
|
154
|
-
return f"{index}: [#{r}{r}{g}{g}{b}{b}]{name}"
|
155
|
-
|
156
|
-
console = Console()
|
157
|
-
table = rich.table.Table(
|
158
|
-
box=rich.box.HORIZONTALS,
|
159
|
-
show_header=False,
|
160
|
-
header_style="bold #2070b2",
|
161
|
-
title="[bold][#3fdda4]GSTAICHI[#f8e020] EXAMPLES",
|
162
|
-
)
|
163
|
-
|
164
|
-
ncols = 3
|
165
|
-
choices = GsTaichiMain._get_available_examples()
|
166
|
-
nrows, rem = divmod(len(choices), ncols)
|
167
|
-
if rem > 0:
|
168
|
-
nrows += 1
|
169
|
-
names = sorted(choices.keys())
|
170
|
-
for k in range(nrows):
|
171
|
-
table.add_row(*[colormap(j, names[j]) for j in range(k, len(choices), nrows)])
|
172
|
-
|
173
|
-
parser = argparse.ArgumentParser(prog="ti example", description=f"{self.example.__doc__}")
|
174
|
-
parser.add_argument(
|
175
|
-
"name",
|
176
|
-
type=GsTaichiMain._example_choices_type(choices.keys()),
|
177
|
-
choices=sorted(choices.keys()),
|
178
|
-
help=console.print(table),
|
179
|
-
nargs="?",
|
180
|
-
default=None,
|
181
|
-
metavar="name",
|
182
|
-
)
|
183
|
-
parser.add_argument(
|
184
|
-
"-p",
|
185
|
-
"--print",
|
186
|
-
required=False,
|
187
|
-
dest="print",
|
188
|
-
action="store_true",
|
189
|
-
help="Print example source code instead of running it",
|
190
|
-
)
|
191
|
-
parser.add_argument(
|
192
|
-
"-P",
|
193
|
-
"--pretty-print",
|
194
|
-
required=False,
|
195
|
-
dest="pretty_print",
|
196
|
-
action="store_true",
|
197
|
-
help="Like --print, but print in a rich format with line numbers",
|
198
|
-
)
|
199
|
-
parser.add_argument(
|
200
|
-
"-s",
|
201
|
-
"--save",
|
202
|
-
required=False,
|
203
|
-
dest="save",
|
204
|
-
action="store_true",
|
205
|
-
help="Save source code to current directory instead of running it",
|
206
|
-
)
|
207
|
-
|
208
|
-
# TODO: Pass the arguments to downstream correctly(#3216).
|
209
|
-
args = parser.parse_args(arguments)
|
210
|
-
|
211
|
-
examples_dir = GsTaichiMain._get_examples_dir()
|
212
|
-
example_name = args.name
|
213
|
-
if example_name is None:
|
214
|
-
try:
|
215
|
-
index = input(f"Please input the example index (between 0 and {len(names)}): ")
|
216
|
-
while not index.isdigit() or int(index) >= len(names):
|
217
|
-
index = input(f"Example [{index}] does not exist. Please try again: ")
|
218
|
-
example_name = names[int(index)]
|
219
|
-
except KeyboardInterrupt as e:
|
220
|
-
print("\nCancelled by user, exiting...")
|
221
|
-
return 1
|
222
|
-
|
223
|
-
target = str((examples_dir / choices[example_name] / f"{example_name}.py").resolve())
|
224
|
-
# path for examples needs to be modified for implicit relative imports
|
225
|
-
sys.path.append(str((examples_dir / choices[example_name]).resolve()))
|
226
|
-
|
227
|
-
# Short circuit for testing
|
228
|
-
if self.test_mode:
|
229
|
-
return args
|
230
|
-
|
231
|
-
if args.save:
|
232
|
-
print(f"Saving example {example_name} to current directory...")
|
233
|
-
shutil.copy(target, ".")
|
234
|
-
return 0
|
235
|
-
|
236
|
-
if args.pretty_print:
|
237
|
-
syntax = rich.syntax.Syntax.from_path(target, line_numbers=True)
|
238
|
-
console = Console()
|
239
|
-
console.print(syntax)
|
240
|
-
return 0
|
241
|
-
|
242
|
-
if args.print:
|
243
|
-
with open(target) as f:
|
244
|
-
print(f.read())
|
245
|
-
return 0
|
246
|
-
|
247
|
-
print(f"Running example {example_name} ...")
|
248
|
-
|
249
|
-
runpy.run_path(target, run_name="__main__")
|
250
|
-
|
251
|
-
@staticmethod
|
252
|
-
@register
|
253
|
-
def changelog(arguments: list = sys.argv[2:]):
|
254
|
-
"""Display changelog of current version"""
|
255
|
-
changelog_md = os.path.join(utils.package_root, "CHANGELOG.md")
|
256
|
-
with open(changelog_md) as f:
|
257
|
-
print(f.read())
|
258
|
-
|
259
|
-
@staticmethod
|
260
|
-
@register
|
261
|
-
def release(arguments: list = sys.argv[2:]):
|
262
|
-
"""Make source code release"""
|
263
|
-
raise RuntimeError("TBD")
|
264
|
-
|
265
|
-
@staticmethod
|
266
|
-
@register
|
267
|
-
def doc(arguments: list = sys.argv[2:]):
|
268
|
-
"""Build documentation"""
|
269
|
-
raise RuntimeError("TBD")
|
270
|
-
|
271
|
-
@staticmethod
|
272
|
-
@register
|
273
|
-
def format(arguments: list = sys.argv[2:]):
|
274
|
-
"""Reformat modified source files"""
|
275
|
-
raise RuntimeError("Please run `pre-commit run -a` instead")
|
276
|
-
|
277
|
-
@staticmethod
|
278
|
-
@register
|
279
|
-
def format_all(arguments: list = sys.argv[2:]):
|
280
|
-
"""Reformat all source files"""
|
281
|
-
raise RuntimeError("Please run `pre-commit run -a` instead")
|
282
|
-
|
283
|
-
@staticmethod
|
284
|
-
def _display_benchmark_regression(xd, yd, args):
|
285
|
-
def parse_dat(file):
|
286
|
-
_dict = {}
|
287
|
-
with open(file) as f:
|
288
|
-
for line in f.readlines():
|
289
|
-
try:
|
290
|
-
a, b = line.strip().split(":")
|
291
|
-
except:
|
292
|
-
continue
|
293
|
-
b = float(b)
|
294
|
-
if abs(b % 1.0) < 1e-5: # codegen_*
|
295
|
-
b = int(b)
|
296
|
-
_dict[a.strip()] = b
|
297
|
-
return _dict
|
298
|
-
|
299
|
-
def parse_name(file):
|
300
|
-
if file[0:5] == "test_":
|
301
|
-
return file[5:-4].replace("__test_", "::", 1)
|
302
|
-
if file[0:10] == "benchmark_":
|
303
|
-
return "::".join(reversed(file[10:-4].split("__arch_")))
|
304
|
-
raise Exception(f"bad benchmark file name {file}")
|
305
|
-
|
306
|
-
def get_dats(directory):
|
307
|
-
_list = []
|
308
|
-
for x in os.listdir(directory):
|
309
|
-
if x.endswith(".dat"):
|
310
|
-
_list.append(x)
|
311
|
-
_dict = {}
|
312
|
-
for x in _list:
|
313
|
-
name = parse_name(x)
|
314
|
-
path = os.path.join(directory, x)
|
315
|
-
_dict[name] = parse_dat(path)
|
316
|
-
return _dict
|
317
|
-
|
318
|
-
spec = args.files
|
319
|
-
single_line = spec and len(spec) == 1
|
320
|
-
xs, ys = get_dats(xd), get_dats(yd)
|
321
|
-
scatter = defaultdict(list)
|
322
|
-
for name in reversed(sorted(set(xs.keys()).union(ys.keys()))):
|
323
|
-
file, func = name.split("::")
|
324
|
-
u, v = xs.get(name, {}), ys.get(name, {})
|
325
|
-
ret = ""
|
326
|
-
for key in set(u.keys()).union(v.keys()):
|
327
|
-
if spec and key not in spec:
|
328
|
-
continue
|
329
|
-
a, b = u.get(key, 0), v.get(key, 0)
|
330
|
-
if a == 0:
|
331
|
-
if b == 0:
|
332
|
-
res = 1.0
|
333
|
-
else:
|
334
|
-
res = math.inf
|
335
|
-
else:
|
336
|
-
res = b / a
|
337
|
-
scatter[key].append(res)
|
338
|
-
if res == 1:
|
339
|
-
continue
|
340
|
-
if not single_line:
|
341
|
-
ret += f"{key:<30}"
|
342
|
-
res -= 1
|
343
|
-
color = Fore.RESET
|
344
|
-
if res > 0:
|
345
|
-
color = Fore.RED
|
346
|
-
elif res < 0:
|
347
|
-
color = Fore.GREEN
|
348
|
-
if isinstance(a, float):
|
349
|
-
a = f"{a:>7.2}"
|
350
|
-
else:
|
351
|
-
a = f"{a:>7}"
|
352
|
-
if isinstance(b, float):
|
353
|
-
b = f"{b:>7.2}"
|
354
|
-
else:
|
355
|
-
b = f"{b:>7}"
|
356
|
-
ret += f"{Fore.MAGENTA}{a}{Fore.RESET} -> "
|
357
|
-
ret += f"{Fore.CYAN}{b} {color}{res:>+9.1%}{Fore.RESET}\n"
|
358
|
-
if ret != "":
|
359
|
-
print(f'{file + "::" + func:_<58}', end="")
|
360
|
-
if not single_line:
|
361
|
-
print("")
|
362
|
-
print(ret, end="")
|
363
|
-
if not single_line:
|
364
|
-
print("")
|
365
|
-
|
366
|
-
@staticmethod
|
367
|
-
def _get_benchmark_baseline_dir():
|
368
|
-
return os.path.join(_ti_core.get_repo_dir(), "benchmarks", "baseline")
|
369
|
-
|
370
|
-
@staticmethod
|
371
|
-
def _get_benchmark_output_dir():
|
372
|
-
return os.path.join(_ti_core.get_repo_dir(), "benchmarks", "output")
|
373
|
-
|
374
|
-
@register
|
375
|
-
def regression(self, arguments: list = sys.argv[2:]):
|
376
|
-
"""Display benchmark regression test result"""
|
377
|
-
parser = argparse.ArgumentParser(prog="ti regression", description=f"{self.regression.__doc__}")
|
378
|
-
parser.add_argument("files", nargs="*", help="Test file(s) to be run for benchmarking")
|
379
|
-
args = parser.parse_args(arguments)
|
380
|
-
|
381
|
-
# Short circuit for testing
|
382
|
-
if self.test_mode:
|
383
|
-
return args
|
384
|
-
|
385
|
-
baseline_dir = GsTaichiMain._get_benchmark_baseline_dir()
|
386
|
-
output_dir = GsTaichiMain._get_benchmark_output_dir()
|
387
|
-
GsTaichiMain._display_benchmark_regression(baseline_dir, output_dir, args)
|
388
|
-
|
389
|
-
return None
|
390
|
-
|
391
|
-
@register
|
392
|
-
def baseline(self, arguments: list = sys.argv[2:]):
|
393
|
-
"""Archive current benchmark result as baseline"""
|
394
|
-
parser = argparse.ArgumentParser(prog="ti baseline", description=f"{self.baseline.__doc__}")
|
395
|
-
args = parser.parse_args(arguments)
|
396
|
-
|
397
|
-
# Short circuit for testing
|
398
|
-
if self.test_mode:
|
399
|
-
return args
|
400
|
-
|
401
|
-
baseline_dir = GsTaichiMain._get_benchmark_baseline_dir()
|
402
|
-
output_dir = GsTaichiMain._get_benchmark_output_dir()
|
403
|
-
shutil.rmtree(baseline_dir, True)
|
404
|
-
shutil.copytree(output_dir, baseline_dir)
|
405
|
-
print(f"[benchmark] baseline data saved to {baseline_dir}")
|
406
|
-
|
407
|
-
return None
|
408
|
-
|
409
|
-
@staticmethod
|
410
|
-
@register
|
411
|
-
def test(self, arguments: list = sys.argv[2:]):
|
412
|
-
raise RuntimeError("ti test is deprecated. Please run `python tests/run_tests.py` instead.")
|
413
|
-
|
414
|
-
@register
|
415
|
-
def run(self, arguments: list = sys.argv[2:]):
|
416
|
-
"""Run a single script"""
|
417
|
-
parser = argparse.ArgumentParser(prog="ti run", description=f"{self.run.__doc__}")
|
418
|
-
parser.add_argument(
|
419
|
-
"filename",
|
420
|
-
help="A single (Python) script to run with GsTaichi, e.g. render.py",
|
421
|
-
)
|
422
|
-
args = parser.parse_args(arguments)
|
423
|
-
|
424
|
-
# Short circuit for testing
|
425
|
-
if self.test_mode:
|
426
|
-
return args
|
427
|
-
|
428
|
-
runpy.run_path(args.filename)
|
429
|
-
|
430
|
-
return None
|
431
|
-
|
432
|
-
@register
|
433
|
-
def debug(self, arguments: list = sys.argv[2:]):
|
434
|
-
"""Debug a single script"""
|
435
|
-
parser = argparse.ArgumentParser(prog="ti debug", description=f"{self.debug.__doc__}")
|
436
|
-
parser.add_argument(
|
437
|
-
"filename",
|
438
|
-
help="A single (Python) script to run with debugger, e.g. render.py",
|
439
|
-
)
|
440
|
-
args = parser.parse_args(arguments)
|
441
|
-
|
442
|
-
# Short circuit for testing
|
443
|
-
if self.test_mode:
|
444
|
-
return args
|
445
|
-
|
446
|
-
_ti_core.set_core_trigger_gdb_when_crash(True)
|
447
|
-
os.environ["TI_DEBUG"] = "1"
|
448
|
-
|
449
|
-
runpy.run_path(args.filename, run_name="__main__")
|
450
|
-
|
451
|
-
return None
|
452
|
-
|
453
|
-
@staticmethod
|
454
|
-
@register
|
455
|
-
def diagnose(arguments: list = sys.argv[2:]):
|
456
|
-
"""System diagnose information"""
|
457
|
-
diagnose.main()
|
458
|
-
|
459
|
-
@staticmethod
|
460
|
-
@register
|
461
|
-
def repl(arguments: list = sys.argv[2:]):
|
462
|
-
"""Start GsTaichi REPL / Python shell with 'import gstaichi as ti'"""
|
463
|
-
|
464
|
-
def local_scope():
|
465
|
-
try:
|
466
|
-
import IPython # pylint: disable=C0415
|
467
|
-
|
468
|
-
IPython.embed()
|
469
|
-
except ImportError:
|
470
|
-
import code # pylint: disable=C0415
|
471
|
-
|
472
|
-
__name__ = "__console__" # pylint: disable=W0622
|
473
|
-
code.interact(local=locals())
|
474
|
-
|
475
|
-
local_scope()
|
476
|
-
|
477
|
-
@staticmethod
|
478
|
-
@register
|
479
|
-
def lint(arguments: list = sys.argv[2:]):
|
480
|
-
"""Run pylint checker for the Python codebase of GsTaichi"""
|
481
|
-
# TODO: support arguments for lint specific files
|
482
|
-
# parser = argparse.ArgumentParser(prog='ti lint', description=f"{self.lint.__doc__}")
|
483
|
-
# args = parser.parse_args(arguments)
|
484
|
-
|
485
|
-
options = [os.path.dirname(__file__)]
|
486
|
-
|
487
|
-
from multiprocessing import cpu_count # pylint: disable=C0415
|
488
|
-
|
489
|
-
threads = min(8, cpu_count())
|
490
|
-
options += ["-j", str(threads)]
|
491
|
-
|
492
|
-
# http://pylint.pycqa.org/en/latest/user_guide/run.html
|
493
|
-
# TODO: support redirect output to lint.log
|
494
|
-
import pylint # pylint: disable=C0415
|
495
|
-
|
496
|
-
pylint.lint.Run(options)
|
497
|
-
|
498
|
-
@staticmethod
|
499
|
-
@register
|
500
|
-
def cache(arguments: list = sys.argv[2:]):
|
501
|
-
"""Manage the offline cache files manually"""
|
502
|
-
|
503
|
-
def clean(cmd_args, parser):
|
504
|
-
parser.add_argument(
|
505
|
-
"-p",
|
506
|
-
"--offline-cache-file-path",
|
507
|
-
dest="offline_cache_file_path",
|
508
|
-
default=impl.default_cfg().offline_cache_file_path,
|
509
|
-
)
|
510
|
-
args = parser.parse_args(cmd_args)
|
511
|
-
path = os.path.abspath(args.offline_cache_file_path)
|
512
|
-
count = _ti_core.clean_offline_cache_files(path)
|
513
|
-
print(f"Deleted {count} offline cache files in {path}")
|
514
|
-
|
515
|
-
# TODO(PGZXB): Provide more tools to manage the offline cache files
|
516
|
-
subcmds_map = {"clean": (clean, "Clean all offline cache files in given path")}
|
517
|
-
|
518
|
-
def print_help():
|
519
|
-
print("usage: ti cache <command> [<args>]")
|
520
|
-
for name, value in subcmds_map.items():
|
521
|
-
_, description = value
|
522
|
-
print(f"\t{name}\t|-> {description}")
|
523
|
-
|
524
|
-
if not arguments:
|
525
|
-
print_help()
|
526
|
-
return
|
527
|
-
|
528
|
-
subcmd = arguments[0]
|
529
|
-
if subcmd not in subcmds_map:
|
530
|
-
print(f"'ti cache {subcmd}' is not a valid command!")
|
531
|
-
print_help()
|
532
|
-
return
|
533
|
-
|
534
|
-
func, description = subcmds_map[subcmd]
|
535
|
-
parser = argparse.ArgumentParser(prog=f"ti cache {subcmd}", description=description)
|
536
|
-
func(cmd_args=arguments[1:], parser=parser)
|
537
|
-
|
538
|
-
|
539
|
-
def main():
|
540
|
-
cli = GsTaichiMain()
|
541
|
-
return cli()
|
542
|
-
|
543
|
-
|
544
|
-
if __name__ == "__main__":
|
545
|
-
sys.exit(main())
|