l0n0lc 0.8.4__py3-none-any.whl → 1.0.0__py3-none-any.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.
Files changed (47) hide show
  1. l0n0lc/Py/350/275/254Cpp/350/275/254/350/257/221/345/231/250.py +579 -0
  2. l0n0lc/__init__.py +75 -6
  3. l0n0lc/aot/347/274/226/350/257/221.py +679 -0
  4. l0n0lc/ast/350/256/277/351/227/256/350/200/205.py +599 -0
  5. l0n0lc/cpp/347/261/273/345/236/213.py +330 -0
  6. l0n0lc/cpp/347/274/226/350/257/221/345/231/250.py +317 -0
  7. l0n0lc/simd/344/274/230/345/214/226.py +260 -0
  8. l0n0lc/std_map.py +153 -0
  9. l0n0lc/std_set.py +185 -0
  10. l0n0lc/std_vector.py +96 -0
  11. l0n0lc//344/273/243/347/240/201/344/274/230/345/214/226.py +302 -0
  12. l0n0lc//344/273/243/347/240/201/347/224/237/346/210/220.py +546 -0
  13. l0n0lc//344/276/235/350/265/226/346/263/250/345/205/245.py +155 -0
  14. l0n0lc//345/215/263/346/227/266/347/274/226/350/257/221.py +192 -0
  15. l0n0lc//345/217/230/351/207/217/347/256/241/347/220/206/345/231/250.py +123 -0
  16. l0n0lc//345/237/272/347/241/200/346/230/240/345/260/204.py +103 -0
  17. l0n0lc//345/237/272/347/241/200/346/267/267/345/205/245.py +147 -0
  18. l0n0lc//345/256/271/345/231/250/346/236/204/345/273/272/345/231/250.py +214 -0
  19. l0n0lc//345/267/245/345/205/267.py +285 -0
  20. l0n0lc//345/271/266/350/241/214/347/274/226/350/257/221/345/231/250.py +412 -0
  21. l0n0lc//345/274/202/345/270/270.py +474 -0
  22. l0n0lc//346/225/260/347/273/204/345/257/271/350/261/241/346/261/240.py +248 -0
  23. l0n0lc//346/226/207/344/273/266/347/256/241/347/220/206/345/231/250.py +286 -0
  24. l0n0lc//346/227/245/345/277/227/345/267/245/345/205/267.py +152 -0
  25. l0n0lc//347/261/273/345/236/213/346/216/250/346/226/255/345/267/245/345/205/267.py +352 -0
  26. l0n0lc//347/261/273/345/236/213/350/275/254/346/215/242.py +210 -0
  27. l0n0lc//347/261/273/346/224/257/346/214/201.py +372 -0
  28. l0n0lc//347/274/226/350/257/221/344/270/212/344/270/213/346/226/207.py +132 -0
  29. l0n0lc//347/274/226/350/257/221/347/256/241/347/220/206/345/231/250.py +171 -0
  30. l0n0lc//350/241/250/350/276/276/345/274/217/345/244/204/347/220/206.py +462 -0
  31. l0n0lc//350/275/254/350/257/221/345/231/250/345/267/245/345/205/267.py +49 -0
  32. l0n0lc//350/277/220/350/241/214/346/227/266/345/212/240/350/275/275.py +217 -0
  33. l0n0lc//351/200/232/347/224/250/345/267/245/345/205/267.py +149 -0
  34. l0n0lc-1.0.0.dist-info/METADATA +363 -0
  35. l0n0lc-1.0.0.dist-info/RECORD +39 -0
  36. {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/WHEEL +1 -1
  37. l0n0lc-1.0.0.dist-info/entry_points.txt +2 -0
  38. {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/licenses/LICENSE +0 -0
  39. l0n0lc/StdList.py +0 -24
  40. l0n0lc/StdMap.py +0 -21
  41. l0n0lc/c/345/237/272/347/241/200/345/244/204/347/220/206.py +0 -207
  42. l0n0lc/jit.py +0 -604
  43. l0n0lc//347/274/226/350/257/221.py +0 -58
  44. l0n0lc//351/200/232/347/224/250.py +0 -134
  45. l0n0lc-0.8.4.dist-info/METADATA +0 -241
  46. l0n0lc-0.8.4.dist-info/RECORD +0 -12
  47. {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,679 @@
1
+ """
2
+ AOT (Ahead-Of-Time) 预编译模块
3
+
4
+ 允许用户在运行前批量预编译所有 @jit 装饰的函数,
5
+ 从而消除首次调用时的编译延迟。
6
+ """
7
+
8
+ import os
9
+ import ast
10
+ import sys
11
+ import argparse
12
+ import inspect
13
+ import importlib.util
14
+ from pathlib import Path
15
+ from typing import List, Dict, Set, Tuple, Optional, Callable, Any
16
+ from concurrent.futures import ProcessPoolExecutor, as_completed
17
+
18
+ from .Py转Cpp转译器 import Py转Cpp转译器
19
+ from .cpp编译器 import Cpp编译器
20
+ from .工具 import 全局上下文
21
+ from .日志工具 import 日志, 日志级别
22
+
23
+
24
+ class JIT函数信息:
25
+ """存储 JIT 函数的元信息"""
26
+
27
+ def __init__(
28
+ self,
29
+ 函数名: str,
30
+ 函数对象: Callable,
31
+ 模块名: str,
32
+ 源文件路径: str,
33
+ 行号: int,
34
+ 装饰器参数: Optional[Dict[str, Any]] = None
35
+ ):
36
+ self.函数名 = 函数名
37
+ self.函数对象 = 函数对象
38
+ self.模块名 = 模块名
39
+ self.源文件路径 = 源文件路径
40
+ self.行号 = 行号
41
+ self.装饰器参数 = 装饰器参数 or {}
42
+
43
+ def __repr__(self):
44
+ return f"JIT函数信息({self.模块名}.{self.函数名} @ {self.源文件路径}:{self.行号})"
45
+
46
+
47
+ class 包扫描器:
48
+ """
49
+ 扫描 Python 包,提取所有 @jit 装饰的函数
50
+ """
51
+
52
+ def __init__(self, 根目录: str):
53
+ """
54
+ 初始化包扫描器
55
+
56
+ Args:
57
+ 根目录: 要扫描的根目录(包的根目录)
58
+ """
59
+ self.根目录 = Path(根目录).resolve()
60
+ if not self.根目录.exists():
61
+ raise ValueError(f"目录不存在: {根目录}")
62
+
63
+ def 扫描目录(
64
+ self,
65
+ 递归: bool = True,
66
+ 排除目录: Optional[Set[str]] = None,
67
+ 包含测试: bool = False
68
+ ) -> List[JIT函数信息]:
69
+ """
70
+ 扫描目录下所有 Python 文件,提取 JIT 函数
71
+
72
+ Args:
73
+ 递归: 是否递归扫描子目录
74
+ 排除目录: 要排除的目录名集合
75
+ 包含测试: 是否包含测试文件(test_*.py)
76
+
77
+ Returns:
78
+ JIT 函数信息列表
79
+ """
80
+ 排除目录 = 排除目录 or {
81
+ "__pycache__",
82
+ ".git",
83
+ ".venv",
84
+ "venv",
85
+ "env",
86
+ "build",
87
+ "dist",
88
+ ".eggs",
89
+ "*.egg-info",
90
+ }
91
+
92
+ jit函数列表 = []
93
+
94
+ # 查找所有 Python 文件
95
+ 模式 = "**/*.py" if 递归 else "*.py"
96
+ for py文件 in self.根目录.rglob(模式):
97
+ # 检查是否应该跳过此文件
98
+ if not self._应该包含文件(py文件, 排除目录, 包含测试):
99
+ continue
100
+
101
+ # 从文件中提取 JIT 函数
102
+ 文件函数 = self._扫描文件(str(py文件))
103
+ jit函数列表.extend(文件函数)
104
+
105
+ 日志.信息(f"扫描完成,找到 {len(jit函数列表)} 个 JIT 函数")
106
+ return jit函数列表
107
+
108
+ def _应该包含文件(
109
+ self,
110
+ 文件路径: Path,
111
+ 排除目录: Set[str],
112
+ 包含测试: bool
113
+ ) -> bool:
114
+ """判断文件是否应该被扫描"""
115
+ # 检查文件名
116
+ if not 包含测试 and 文件路径.name.startswith("test_"):
117
+ return False
118
+
119
+ # 检查父目录是否在排除列表中
120
+ for 父目录 in 文件路径.parents:
121
+ if 父目录.name in 排除目录:
122
+ return False
123
+
124
+ return True
125
+
126
+ def _扫描文件(self, 文件路径: str) -> List[JIT函数信息]:
127
+ """
128
+ 扫描单个 Python 文件,提取 JIT 函数
129
+
130
+ Args:
131
+ 文件路径: Python 文件路径
132
+
133
+ Returns:
134
+ JIT 函数信息列表
135
+ """
136
+ try:
137
+ with open(文件路径, "r", encoding="utf-8") as f:
138
+ 源代码 = f.read()
139
+ except Exception as e:
140
+ 日志.警告(f"无法读取文件 {文件路径}: {e}")
141
+ return []
142
+
143
+ try:
144
+ 树 = ast.parse(源代码, filename=文件路径)
145
+ except SyntaxError as e:
146
+ 日志.警告(f"文件 {文件路径} 语法错误: {e}")
147
+ return []
148
+
149
+ jit函数列表 = []
150
+ 模块名 = Path(文件路径).stem
151
+
152
+ for 节点 in ast.walk(树):
153
+ if isinstance(节点, ast.FunctionDef):
154
+ # 检查是否使用了 @jit 或 @即时编译 装饰器
155
+ if self._是jit函数(节点):
156
+ # 尝试从实际模块中导入函数对象
157
+ 函数对象 = self._导入函数(文件路径, 节点.name)
158
+
159
+ 装饰器参数 = self._提取装饰器参数(节点)
160
+
161
+ 信息 = JIT函数信息(
162
+ 函数名=节点.name,
163
+ 函数对象=函数对象, # type: ignore
164
+ 模块名=模块名,
165
+ 源文件路径=文件路径,
166
+ 行号=节点.lineno,
167
+ 装饰器参数=装饰器参数
168
+ )
169
+ jit函数列表.append(信息)
170
+
171
+ return jit函数列表
172
+
173
+ def _是jit函数(self, 函数节点: ast.FunctionDef) -> bool:
174
+ """检查函数是否使用了 @jit 或 @即时编译 装饰器"""
175
+ for 装饰器 in 函数节点.decorator_list:
176
+ # 检查 @jit
177
+ if isinstance(装饰器, ast.Name) and 装饰器.id in ("jit", "即时编译"):
178
+ return True
179
+ # 检查 @lc.jit() 形式
180
+ if isinstance(装饰器, ast.Call):
181
+ if isinstance(装饰器.func, ast.Attribute):
182
+ if 装饰器.func.attr in ("jit", "即时编译"):
183
+ return True
184
+ elif isinstance(装饰器.func, ast.Name):
185
+ if 装饰器.func.id in ("jit", "即时编译"):
186
+ return True
187
+ return False
188
+
189
+ def _提取装饰器参数(
190
+ self, 函数节点: ast.FunctionDef
191
+ ) -> Dict[str, Any]:
192
+ """
193
+ 从装饰器中提取参数
194
+
195
+ Returns:
196
+ 装饰器参数字典
197
+ """
198
+ 参数 = {}
199
+
200
+ for 装饰器 in 函数节点.decorator_list:
201
+ if isinstance(装饰器, ast.Call):
202
+ 尝试从调用提取参数(装饰器, 参数)
203
+
204
+ return 参数
205
+
206
+ def _导入函数(self, 文件路径: str, 函数名: str) -> Optional[Callable]:
207
+ """
208
+ 从文件中导入函数对象
209
+
210
+ 注意:这可能需要正确设置 Python 路径
211
+ """
212
+ try:
213
+ # 获取文件的目录和模块名
214
+ 文件目录 = os.path.dirname(文件路径)
215
+ 模块名 = Path(文件路径).stem
216
+
217
+ # 添加目录到 sys.path
218
+ 原路径 = sys.path[:]
219
+ if 文件目录 not in sys.path:
220
+ sys.path.insert(0, 文件目录)
221
+
222
+ try:
223
+ # 动态导入模块
224
+ spec = importlib.util.spec_from_file_location(模块名, 文件路径)
225
+ if spec and spec.loader:
226
+ 模块 = importlib.util.module_from_spec(spec)
227
+ spec.loader.exec_module(模块)
228
+
229
+ # 获取函数对象(可能是 Py转Cpp转译器 对象)
230
+ if hasattr(模块, 函数名):
231
+ 对象 = getattr(模块, 函数名)
232
+ # 如果是 JIT 装饰器返回的转译器对象,提取原始函数
233
+ if isinstance(对象, Py转Cpp转译器):
234
+ return 对象.目标函数
235
+ return 对象
236
+ finally:
237
+ # 恢复 sys.path
238
+ sys.path[:] = 原路径
239
+
240
+ except Exception as e:
241
+ 日志.调试(f"无法导入函数 {文件路径}:{函数名}: {e}")
242
+
243
+ return None
244
+
245
+
246
+ def 尝试从调用提取参数(装饰器: ast.Call, 参数字典: Dict[str, Any]):
247
+ """尝试从装饰器调用中提取参数"""
248
+ for 关键字 in 装饰器.keywords:
249
+ if isinstance(关键字.value, ast.Constant):
250
+ 参数字典[关键字.arg] = 关键字.value.value # type: ignore
251
+ elif isinstance(关键字.value, ast.NameConstant):
252
+ 参数字典[关键字.arg] = 关键字.value.value # type: ignore
253
+ elif isinstance(关键字.value, ast.Name):
254
+ 参数字典[关键字.arg] = 关键字.value.id # type: ignore
255
+ elif isinstance(关键字.value, ast.Str):
256
+ 参数字典[关键字.arg] = 关键字.value.s # type: ignore
257
+ elif isinstance(关键字.value, ast.Num):
258
+ 参数字典[关键字.arg] = 关键字.value.n # type: ignore
259
+
260
+
261
+ class AOT编译器:
262
+ """
263
+ AOT (Ahead-Of-Time) 编译器
264
+
265
+ 批量预编译多个 JIT 函数,消除首次调用延迟
266
+ """
267
+
268
+ def __init__(
269
+ self,
270
+ 优化级别: str = "O2",
271
+ 启用并行编译: bool = True,
272
+ 最大进程数: Optional[int] = None,
273
+ 启用LTO: bool = False,
274
+ 启用向量化: bool = False,
275
+ SIMD指令集: Optional[str] = None
276
+ ):
277
+ """
278
+ 初始化 AOT 编译器
279
+
280
+ Args:
281
+ 优化级别: 编译优化级别(O0/O1/O2/O3/Os/Ofast/Og/Oz)
282
+ 启用并行编译: 是否启用并行编译
283
+ 最大进程数: 最大并行进程数
284
+ 启用LTO: 是否启用链接时优化(LTO)
285
+ 启用向量化: 是否启用 SIMD 向量化优化
286
+ SIMD指令集: 指定 SIMD 指令集(None 表示自动检测)
287
+ """
288
+ self.优化级别 = 优化级别
289
+ self.启用并行编译 = 启用并行编译
290
+ self.最大进程数 = 最大进程数
291
+ self.启用LTO = 启用LTO
292
+ self.启用向量化 = 启用向量化
293
+ self.SIMD指令集 = SIMD指令集
294
+ self.编译结果: List[Dict[str, Any]] = []
295
+
296
+ def 编译函数列表(
297
+ self,
298
+ 函数列表: List[JIT函数信息],
299
+ 显示进度: bool = True
300
+ ) -> Dict[str, Any]:
301
+ """
302
+ 批量编译 JIT 函数列表
303
+
304
+ Args:
305
+ 函数列表: JIT 函数信息列表
306
+ 显示进度: 是否显示编译进度
307
+
308
+ Returns:
309
+ 编译统计信息
310
+ """
311
+ 总数 = len(函数列表)
312
+ 成功数 = 0
313
+ 失败数 = 0
314
+ 跳过数 = 0 # 缓存命中
315
+ 结果列表 = []
316
+
317
+ 日志.信息(f"开始 AOT 编译 {总数} 个函数...")
318
+
319
+ for 索引, 信息 in enumerate(函数列表, 1):
320
+ if 显示进度:
321
+ 日志.信息(f"[{索引}/{总数}] 编译 {信息.模块名}.{信息.函数名}...")
322
+
323
+ 结果 = self._编译单个函数(信息)
324
+ 结果列表.append(结果)
325
+
326
+ if 结果["状态"] == "成功":
327
+ 成功数 += 1
328
+ if 显示进度 and 结果.get("使用缓存"):
329
+ 日志.信息(f" ✓ 缓存命中")
330
+ elif 显示进度:
331
+ 日志.信息(f" ✓ 编译成功")
332
+ elif 结果["状态"] == "跳过":
333
+ 跳过数 += 1
334
+ if 显示进度:
335
+ 日志.信息(f" - 跳过({结果.get('原因', '未知原因')})")
336
+ else: # 失败
337
+ 失败数 += 1
338
+ 日志.错误(f" ✗ 编译失败: {结果.get('错误', '未知错误')}")
339
+
340
+ 统计 = {
341
+ "总数": 总数,
342
+ "成功": 成功数,
343
+ "失败": 失败数,
344
+ "跳过": 跳过数,
345
+ "结果列表": 结果列表
346
+ }
347
+
348
+ 日志.信息(
349
+ f"AOT 编译完成: {成功数} 成功, {失败数} 失败, {跳过数} 跳过"
350
+ )
351
+
352
+ return 统计
353
+
354
+ def _编译单个函数(self, 信息: JIT函数信息) -> Dict[str, Any]:
355
+ """
356
+ 编译单个 JIT 函数
357
+
358
+ Returns:
359
+ 编译结果字典
360
+ """
361
+ if 信息.函数对象 is None:
362
+ return {
363
+ "函数名": 信息.函数名,
364
+ "模块名": 信息.模块名,
365
+ "状态": "跳过",
366
+ "原因": "无法导入函数对象"
367
+ }
368
+
369
+ # 如果传入的是已装饰的转译器对象,提取原始函数
370
+ 原始函数 = 信息.函数对象
371
+ if isinstance(原始函数, Py转Cpp转译器):
372
+ 原始函数 = 原始函数.目标函数
373
+
374
+ try:
375
+ # 创建编译器实例,传入 LTO 和向量化设置
376
+ 编译器实例 = Cpp编译器(
377
+ 优化级别=self.优化级别,
378
+ 启用LTO=self.启用LTO,
379
+ 启用向量化=self.启用向量化,
380
+ SIMD指令集=self.SIMD指令集
381
+ )
382
+
383
+ # 创建转译器实例
384
+ 转译器实例 = Py转Cpp转译器(
385
+ 原始函数,
386
+ 编译器实例,
387
+ 可执行文件名=信息.装饰器参数.get("可执行文件名"),
388
+ 总是重编=False, # AOT 不强制重编,利用缓存
389
+ 启用并行编译=self.启用并行编译,
390
+ 最大进程数=self.最大进程数
391
+ )
392
+
393
+ # 检查是否已有缓存
394
+ 库文件名 = 转译器实例.获取库文件名()
395
+ 库路径 = os.path.join(全局上下文.工作目录, 库文件名)
396
+ 使用缓存 = os.path.exists(库路径)
397
+
398
+ if not 使用缓存:
399
+ # 执行编译
400
+ 转译器实例.编译()
401
+
402
+ return {
403
+ "函数名": 信息.函数名,
404
+ "模块名": 信息.模块名,
405
+ "源文件": 信息.源文件路径,
406
+ "行号": 信息.行号,
407
+ "状态": "成功",
408
+ "使用缓存": 使用缓存,
409
+ "库文件": 库文件名
410
+ }
411
+
412
+ except Exception as e:
413
+ return {
414
+ "函数名": 信息.函数名,
415
+ "模块名": 信息.模块名,
416
+ "状态": "失败",
417
+ "错误": str(e)
418
+ }
419
+
420
+
421
+ def 编译包(
422
+ 根目录: str,
423
+ 递归: bool = True,
424
+ 排除目录: Optional[Set[str]] = None,
425
+ 包含测试: bool = False,
426
+ 优化级别: str = "O2",
427
+ 启用并行编译: bool = True,
428
+ 最大进程数: Optional[int] = None,
429
+ 启用LTO: bool = False,
430
+ 启用向量化: bool = False,
431
+ SIMD指令集: Optional[str] = None,
432
+ 显示进度: bool = True
433
+ ) -> Dict[str, Any]:
434
+ """
435
+ 扫描并编译包中的所有 JIT 函数
436
+
437
+ Args:
438
+ 根目录: 包的根目录
439
+ 递归: 是否递归扫描子目录
440
+ 排除目录: 要排除的目录名集合
441
+ 包含测试: 是否包含测试文件
442
+ 优化级别: 编译优化级别
443
+ 启用并行编译: 是否启用并行编译
444
+ 最大进程数: 最大并行进程数
445
+ 启用LTO: 是否启用链接时优化(LTO)
446
+ 启用向量化: 是否启用 SIMD 向量化优化
447
+ SIMD指令集: 指定 SIMD 指令集(None 表示自动检测)
448
+ 显示进度: 是否显示编译进度
449
+
450
+ Returns:
451
+ 编译统计信息
452
+ """
453
+ 扫描器 = 包扫描器(根目录)
454
+ jit函数列表 = 扫描器.扫描目录(递归, 排除目录, 包含测试)
455
+
456
+ if not jit函数列表:
457
+ 日志.警告("未找到任何 JIT 函数")
458
+ return {"总数": 0, "成功": 0, "失败": 0, "跳过": 0, "结果列表": []}
459
+
460
+ 编译器 = AOT编译器(优化级别, 启用并行编译, 最大进程数, 启用LTO, 启用向量化, SIMD指令集)
461
+ return 编译器.编译函数列表(jit函数列表, 显示进度)
462
+
463
+
464
+ def 编译函数列表(
465
+ 函数列表: List[Callable],
466
+ 优化级别: str = "O2",
467
+ 启用并行编译: bool = True,
468
+ 最大进程数: Optional[int] = None,
469
+ 启用LTO: bool = False,
470
+ 启用向量化: bool = False,
471
+ SIMD指令集: Optional[str] = None,
472
+ 显示进度: bool = True
473
+ ) -> Dict[str, Any]:
474
+ """
475
+ 编译给定的函数列表
476
+
477
+ Args:
478
+ 函数列表: 要编译的函数列表(可以是普通函数或 JIT 装饰后的转译器对象)
479
+ 优化级别: 编译优化级别
480
+ 启用并行编译: 是否启用并行编译
481
+ 最大进程数: 最大并行进程数
482
+ 启用LTO: 是否启用链接时优化(LTO)
483
+ 启用向量化: 是否启用 SIMD 向量化优化
484
+ SIMD指令集: 指定 SIMD 指令集(None 表示自动检测)
485
+ 显示进度: 是否显示编译进度
486
+
487
+ Returns:
488
+ 编译统计信息
489
+ """
490
+ jit函数信息列表 = []
491
+
492
+ for 函数 in 函数列表:
493
+ # 处理 Py转Cpp转译器 对象(已通过 @jit 装饰的函数)
494
+ if isinstance(函数, Py转Cpp转译器):
495
+ try:
496
+ # 从转译器中获取原始函数信息
497
+ 原始函数 = 函数.目标函数
498
+ 信息 = JIT函数信息(
499
+ 函数名=函数.函数名,
500
+ 函数对象=原始函数, # 使用原始函数对象进行编译
501
+ 模块名=原始函数.__module__,
502
+ 源文件路径=inspect.getfile(原始函数),
503
+ 行号=inspect.getsourcelines(原始函数)[1]
504
+ )
505
+ jit函数信息列表.append(信息)
506
+ except Exception as e:
507
+ 日志.警告(f"无法获取转译器 {函数.函数名} 的信息: {e}")
508
+ continue
509
+
510
+ # 处理普通函数(未通过 @jit 装饰)
511
+ if not callable(函数):
512
+ continue
513
+
514
+ try:
515
+ 信息 = JIT函数信息(
516
+ 函数名=函数.__name__,
517
+ 函数对象=函数,
518
+ 模块名=函数.__module__,
519
+ 源文件路径=inspect.getfile(函数),
520
+ 行号=inspect.getsourcelines(函数)[1]
521
+ )
522
+ jit函数信息列表.append(信息)
523
+ except Exception as e:
524
+ 日志.警告(f"无法获取函数 {函数} 的信息: {e}")
525
+
526
+ 编译器 = AOT编译器(优化级别, 启用并行编译, 最大进程数, 启用LTO, 启用向量化, SIMD指令集)
527
+ return 编译器.编译函数列表(jit函数信息列表, 显示进度)
528
+
529
+
530
+ def main():
531
+ """CLI 入口点"""
532
+ parser = argparse.ArgumentParser(
533
+ description="l0n0lc AOT 预编译工具 - 批量预编译 JIT 函数",
534
+ formatter_class=argparse.RawDescriptionHelpFormatter,
535
+ epilog="""
536
+ 示例:
537
+ # 编译当前目录下的所有 JIT 函数
538
+ l0n0lc-aot-compile
539
+
540
+ # 编译指定目录
541
+ l0n0lc-aot-compile --path /path/to/project
542
+
543
+ # 使用 O3 优化级别
544
+ l0n0lc-aot-compile --optimization O3
545
+
546
+ # 启用链接时优化(LTO)
547
+ l0n0lc-aot-compile --enable-lto
548
+
549
+ # 启用 SIMD 向量化优化
550
+ l0n0lc-aot-compile --enable-vectorize
551
+
552
+ # 指定 SIMD 指令集
553
+ l0n0lc-aot-compile --enable-vectorize --simd AVX2
554
+
555
+ # 包含测试文件
556
+ l0n0lc-aot-compile --include-tests
557
+
558
+ # 禁用并行编译
559
+ l0n0lc-aot-compile --no-parallel
560
+
561
+ # 组合多个优化选项
562
+ l0n0lc-aot-compile --optimization O3 --enable-lto --enable-vectorize
563
+ """
564
+ )
565
+
566
+ parser.add_argument(
567
+ "--path", "-p",
568
+ default=".",
569
+ help="要扫描的目录路径(默认为当前目录)"
570
+ )
571
+
572
+ parser.add_argument(
573
+ "--optimization", "-O",
574
+ choices=["O0", "O1", "O2", "O3", "Os", "Ofast", "Og", "Oz"],
575
+ default="O2",
576
+ help="编译优化级别(默认为 O2)"
577
+ )
578
+
579
+ parser.add_argument(
580
+ "--no-parallel",
581
+ action="store_true",
582
+ help="禁用并行编译"
583
+ )
584
+
585
+ parser.add_argument(
586
+ "--max-processes",
587
+ type=int,
588
+ default=None,
589
+ help="最大并行进程数(默认为 CPU 核心数)"
590
+ )
591
+
592
+ parser.add_argument(
593
+ "--include-tests",
594
+ action="store_true",
595
+ help="包含测试文件(test_*.py)"
596
+ )
597
+
598
+ parser.add_argument(
599
+ "--exclude",
600
+ action="append",
601
+ help="要排除的目录名(可多次使用)"
602
+ )
603
+
604
+ parser.add_argument(
605
+ "--enable-lto",
606
+ action="store_true",
607
+ help="启用链接时优化(LTO),可提升运行时性能 10-30%%,但会增加编译时间"
608
+ )
609
+
610
+ parser.add_argument(
611
+ "--enable-vectorize",
612
+ action="store_true",
613
+ help="启用 SIMD 向量化优化,可提升数组操作性能 2-8x"
614
+ )
615
+
616
+ parser.add_argument(
617
+ "--simd",
618
+ choices=["SSE2", "SSE4_2", "AVX", "AVX2", "AVX512F", "NEON"],
619
+ default=None,
620
+ help="指定 SIMD 指令集(默认为自动检测)"
621
+ )
622
+
623
+ parser.add_argument(
624
+ "--quiet", "-q",
625
+ action="store_true",
626
+ help="静默模式,减少输出"
627
+ )
628
+
629
+ parser.add_argument(
630
+ "--version", "-v",
631
+ action="version",
632
+ version="l0n0lc AOT 编译器 v0.3.0"
633
+ )
634
+
635
+ args = parser.parse_args()
636
+
637
+ # 设置日志级别
638
+ if args.quiet:
639
+ 日志.设置级别(日志级别.警告)
640
+
641
+ # 构建排除目录集合
642
+ 默认排除目录 = {
643
+ "__pycache__",
644
+ ".git",
645
+ ".venv",
646
+ "venv",
647
+ "env",
648
+ "build",
649
+ "dist",
650
+ ".eggs",
651
+ "*.egg-info",
652
+ }
653
+ if args.exclude:
654
+ 默认排除目录.update(args.exclude)
655
+
656
+ # 执行编译
657
+ 统计 = 编译包(
658
+ 根目录=args.path,
659
+ 递归=True,
660
+ 排除目录=默认排除目录,
661
+ 包含测试=args.include_tests,
662
+ 优化级别=args.optimization,
663
+ 启用并行编译=not args.no_parallel,
664
+ 最大进程数=args.max_processes,
665
+ 启用LTO=args.enable_lto,
666
+ 启用向量化=args.enable_vectorize,
667
+ SIMD指令集=args.simd,
668
+ 显示进度=not args.quiet
669
+ )
670
+
671
+ # 返回适当的退出码
672
+ if 统计["失败"] > 0:
673
+ sys.exit(1)
674
+ else:
675
+ sys.exit(0)
676
+
677
+
678
+ if __name__ == "__main__":
679
+ main()