fastpython-native 0.1.0__tar.gz
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.
- fastpython_native-0.1.0/PKG-INFO +108 -0
- fastpython_native-0.1.0/README.md +95 -0
- fastpython_native-0.1.0/fastpython/__init__.py +19 -0
- fastpython_native-0.1.0/fastpython/__main__.py +4 -0
- fastpython_native-0.1.0/fastpython/api.py +185 -0
- fastpython_native-0.1.0/fastpython/auto.py +10 -0
- fastpython_native-0.1.0/fastpython/cli.py +84 -0
- fastpython_native-0.1.0/fastpython/codegen/__init__.py +3 -0
- fastpython_native-0.1.0/fastpython/codegen/transpiler.py +545 -0
- fastpython_native-0.1.0/fastpython/compiler/__init__.py +4 -0
- fastpython_native-0.1.0/fastpython/compiler/cache.py +57 -0
- fastpython_native-0.1.0/fastpython/compiler/toolchain.py +147 -0
- fastpython_native-0.1.0/fastpython/hardware/__init__.py +3 -0
- fastpython_native-0.1.0/fastpython/hardware/cpu.py +209 -0
- fastpython_native-0.1.0/fastpython/importer.py +181 -0
- fastpython_native-0.1.0/fastpython/memory/__init__.py +3 -0
- fastpython_native-0.1.0/fastpython/server/__init__.py +38 -0
- fastpython_native-0.1.0/fastpython/simd/__init__.py +10 -0
- fastpython_native-0.1.0/fastpython_native.egg-info/PKG-INFO +108 -0
- fastpython_native-0.1.0/fastpython_native.egg-info/SOURCES.txt +24 -0
- fastpython_native-0.1.0/fastpython_native.egg-info/dependency_links.txt +1 -0
- fastpython_native-0.1.0/fastpython_native.egg-info/entry_points.txt +2 -0
- fastpython_native-0.1.0/fastpython_native.egg-info/top_level.txt +1 -0
- fastpython_native-0.1.0/pyproject.toml +27 -0
- fastpython_native-0.1.0/setup.cfg +4 -0
- fastpython_native-0.1.0/tests/test_fastpython.py +114 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastpython-native
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AOT Hardware-Adaptive Native Machine Code Compiler for Python
|
|
5
|
+
Author: FastPython Team
|
|
6
|
+
Keywords: compiler,performance,aot,simd,avx2,jit,optimization
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
9
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# FastPython ⚡
|
|
15
|
+
|
|
16
|
+
> **AOT Hardware-Adaptive Native Machine Code Compiler for Python**
|
|
17
|
+
|
|
18
|
+
FastPython erkennt beim Start automatisch die Architektur und Fähigkeiten deiner Host-CPU (AVX2, AVX-512, FMA3, BMI2, Cache & Kerne), analysiert deine Python-Funktionen, übersetzt rechenintensive Schleifen und Algorithmen in optimierten C99/C++ Code und kompiliert diesen **vor dem Start** in hardwarenahen Maschinencode.
|
|
19
|
+
|
|
20
|
+
Beim wiederholten Starten sorgt ein intelligentes SHA-256 Caching dafür, dass keine Kompilierungszeit anfällt und das Modul in **unter 1 Millisekunde** direkt aus dem Cache geladen wird.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚀 Benchmark-Ergebnisse (auf AMD Ryzen 7 5700X, 16 Threads, AVX2, FMA3)
|
|
25
|
+
|
|
26
|
+
| Bereich / Algorithmus | Standard CPython | FastPython (Host AOT) | Beschleunigung |
|
|
27
|
+
| :--- | :---: | :---: | :---: |
|
|
28
|
+
| **Fraktale: Mandelbrot Multi-Core** (250x250, 16 Threads) | 662,7 ms | **1,45 ms** | **⚡ 458,2x schneller** |
|
|
29
|
+
| **Stochastik: Monte Carlo Pi** (3 Mio. Samples) | 4.234,6 ms | **13,7 ms** | **⚡ 308,6x schneller** |
|
|
30
|
+
| **Lineare Algebra: Vector Dot** (1.000.000 Floats SIMD) | 121,5 ms | **0,73 ms** | **⚡ 167,4x schneller** |
|
|
31
|
+
| **Zahlentheorie: Collatz-Suche** (50.000 Zahlen) | 698,3 ms | **7,2 ms** | **⚡ 96,8x schneller** |
|
|
32
|
+
| **Fraktale: Mandelbrot Single-Core** (250x250, AVX2) | 651,4 ms | **8,58 ms** | **⚡ 75,9x schneller** |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🛠️ Verwendung
|
|
37
|
+
|
|
38
|
+
### 1. Zero-Touch Projekt-Beschleunigung (Empfohlen)
|
|
39
|
+
|
|
40
|
+
Füge einfach in deiner `main.py` als erste Zeile hinzu:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import fastpython.auto # Aktiviert automatische Hardware-AOT-Kompilierung für das Projekt
|
|
44
|
+
|
|
45
|
+
# Ab hier: Importiere deine ganz normalen Projektdateien (ohne Decorator oder Änderungen!)
|
|
46
|
+
import simulation
|
|
47
|
+
import math_utils
|
|
48
|
+
|
|
49
|
+
# Alle Funktionen in diesen Dateien laufen jetzt im nativen Maschinencode!
|
|
50
|
+
simulation.run()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Führe dein Skript wie gewohnt mit Python aus:
|
|
54
|
+
```bash
|
|
55
|
+
python main.py
|
|
56
|
+
```
|
|
57
|
+
FastPython fängt alle Projekt-Imports ab, identifiziert rechenintensive Funktionen in allen Projektdateien, kompiliert sie vor der Ausführung in AVX2-Maschinencode und sichert sie im Cache. Bei jedem weiteren Start startet das Programm ohne Verzögerung sofort im nativen Modus.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2. Als gezielter Decorator für einzelne Funktionen
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from fastpython import compile_native
|
|
65
|
+
|
|
66
|
+
@compile_native(fastmath=True, parallel=True)
|
|
67
|
+
def calculate_pi(n: int) -> float:
|
|
68
|
+
acc = 0.0
|
|
69
|
+
sign = 1.0
|
|
70
|
+
for i in range(n):
|
|
71
|
+
denom = 2.0 * float(i) + 1.0
|
|
72
|
+
acc += sign / denom
|
|
73
|
+
sign = -sign
|
|
74
|
+
return 4.0 * acc
|
|
75
|
+
|
|
76
|
+
print(calculate_pi(20_000_000)) # 20 Millionen Iterationen in ~25ms!
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### 3. Über das Command Line Interface (CLI)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Host-Hardware analysieren
|
|
85
|
+
python -m fastpython info
|
|
86
|
+
|
|
87
|
+
# Benchmark-Suite ausführen
|
|
88
|
+
python -m fastpython benchmark
|
|
89
|
+
|
|
90
|
+
# Eigenes Skript mit FastPython starten
|
|
91
|
+
python -m fastpython run dein_skript.py
|
|
92
|
+
|
|
93
|
+
# Cache leeren
|
|
94
|
+
python -m fastpython clear-cache
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## ⚙️ Wie es unter der Haube funktioniert
|
|
100
|
+
|
|
101
|
+
1. **Hardware-Profiling (`fastpython.hardware`)**:
|
|
102
|
+
Liest über Low-Level CPUID und System-APIs ab, welche Befehlssätze dein Prozessor unterstützt (z. B. AVX2, FMA3, NEON).
|
|
103
|
+
2. **AST-Transpiler (`fastpython.codegen`)**:
|
|
104
|
+
Untersucht den Python Abstract Syntax Tree (AST), extrahiert numerische Datentypen (int64_t, double) und entfernt das Python-Objekt-Boxing in inneren Schleifen.
|
|
105
|
+
3. **Host-Compiler (`fastpython.compiler`)**:
|
|
106
|
+
Generiert die native C-Erweiterung und ruft den lokalen Compiler (MSVC BuildTools / Clang / GCC) mit maximalen Hardware-Flags (`/arch:AVX2 /fp:fast /O2 /Oi /Ot`) auf.
|
|
107
|
+
4. **Caching-Layer**:
|
|
108
|
+
Hasht Quellcode + CPU-Fingerprint + Compiler-Flags. Bei erneutem Start wird der kompilierte Maschinencode (`.pyd` / `.so`) sofort eingebunden.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# FastPython ⚡
|
|
2
|
+
|
|
3
|
+
> **AOT Hardware-Adaptive Native Machine Code Compiler for Python**
|
|
4
|
+
|
|
5
|
+
FastPython erkennt beim Start automatisch die Architektur und Fähigkeiten deiner Host-CPU (AVX2, AVX-512, FMA3, BMI2, Cache & Kerne), analysiert deine Python-Funktionen, übersetzt rechenintensive Schleifen und Algorithmen in optimierten C99/C++ Code und kompiliert diesen **vor dem Start** in hardwarenahen Maschinencode.
|
|
6
|
+
|
|
7
|
+
Beim wiederholten Starten sorgt ein intelligentes SHA-256 Caching dafür, dass keine Kompilierungszeit anfällt und das Modul in **unter 1 Millisekunde** direkt aus dem Cache geladen wird.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🚀 Benchmark-Ergebnisse (auf AMD Ryzen 7 5700X, 16 Threads, AVX2, FMA3)
|
|
12
|
+
|
|
13
|
+
| Bereich / Algorithmus | Standard CPython | FastPython (Host AOT) | Beschleunigung |
|
|
14
|
+
| :--- | :---: | :---: | :---: |
|
|
15
|
+
| **Fraktale: Mandelbrot Multi-Core** (250x250, 16 Threads) | 662,7 ms | **1,45 ms** | **⚡ 458,2x schneller** |
|
|
16
|
+
| **Stochastik: Monte Carlo Pi** (3 Mio. Samples) | 4.234,6 ms | **13,7 ms** | **⚡ 308,6x schneller** |
|
|
17
|
+
| **Lineare Algebra: Vector Dot** (1.000.000 Floats SIMD) | 121,5 ms | **0,73 ms** | **⚡ 167,4x schneller** |
|
|
18
|
+
| **Zahlentheorie: Collatz-Suche** (50.000 Zahlen) | 698,3 ms | **7,2 ms** | **⚡ 96,8x schneller** |
|
|
19
|
+
| **Fraktale: Mandelbrot Single-Core** (250x250, AVX2) | 651,4 ms | **8,58 ms** | **⚡ 75,9x schneller** |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🛠️ Verwendung
|
|
24
|
+
|
|
25
|
+
### 1. Zero-Touch Projekt-Beschleunigung (Empfohlen)
|
|
26
|
+
|
|
27
|
+
Füge einfach in deiner `main.py` als erste Zeile hinzu:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import fastpython.auto # Aktiviert automatische Hardware-AOT-Kompilierung für das Projekt
|
|
31
|
+
|
|
32
|
+
# Ab hier: Importiere deine ganz normalen Projektdateien (ohne Decorator oder Änderungen!)
|
|
33
|
+
import simulation
|
|
34
|
+
import math_utils
|
|
35
|
+
|
|
36
|
+
# Alle Funktionen in diesen Dateien laufen jetzt im nativen Maschinencode!
|
|
37
|
+
simulation.run()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Führe dein Skript wie gewohnt mit Python aus:
|
|
41
|
+
```bash
|
|
42
|
+
python main.py
|
|
43
|
+
```
|
|
44
|
+
FastPython fängt alle Projekt-Imports ab, identifiziert rechenintensive Funktionen in allen Projektdateien, kompiliert sie vor der Ausführung in AVX2-Maschinencode und sichert sie im Cache. Bei jedem weiteren Start startet das Programm ohne Verzögerung sofort im nativen Modus.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### 2. Als gezielter Decorator für einzelne Funktionen
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from fastpython import compile_native
|
|
52
|
+
|
|
53
|
+
@compile_native(fastmath=True, parallel=True)
|
|
54
|
+
def calculate_pi(n: int) -> float:
|
|
55
|
+
acc = 0.0
|
|
56
|
+
sign = 1.0
|
|
57
|
+
for i in range(n):
|
|
58
|
+
denom = 2.0 * float(i) + 1.0
|
|
59
|
+
acc += sign / denom
|
|
60
|
+
sign = -sign
|
|
61
|
+
return 4.0 * acc
|
|
62
|
+
|
|
63
|
+
print(calculate_pi(20_000_000)) # 20 Millionen Iterationen in ~25ms!
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### 3. Über das Command Line Interface (CLI)
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Host-Hardware analysieren
|
|
72
|
+
python -m fastpython info
|
|
73
|
+
|
|
74
|
+
# Benchmark-Suite ausführen
|
|
75
|
+
python -m fastpython benchmark
|
|
76
|
+
|
|
77
|
+
# Eigenes Skript mit FastPython starten
|
|
78
|
+
python -m fastpython run dein_skript.py
|
|
79
|
+
|
|
80
|
+
# Cache leeren
|
|
81
|
+
python -m fastpython clear-cache
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## ⚙️ Wie es unter der Haube funktioniert
|
|
87
|
+
|
|
88
|
+
1. **Hardware-Profiling (`fastpython.hardware`)**:
|
|
89
|
+
Liest über Low-Level CPUID und System-APIs ab, welche Befehlssätze dein Prozessor unterstützt (z. B. AVX2, FMA3, NEON).
|
|
90
|
+
2. **AST-Transpiler (`fastpython.codegen`)**:
|
|
91
|
+
Untersucht den Python Abstract Syntax Tree (AST), extrahiert numerische Datentypen (int64_t, double) und entfernt das Python-Objekt-Boxing in inneren Schleifen.
|
|
92
|
+
3. **Host-Compiler (`fastpython.compiler`)**:
|
|
93
|
+
Generiert die native C-Erweiterung und ruft den lokalen Compiler (MSVC BuildTools / Clang / GCC) mit maximalen Hardware-Flags (`/arch:AVX2 /fp:fast /O2 /Oi /Ot`) auf.
|
|
94
|
+
4. **Caching-Layer**:
|
|
95
|
+
Hasht Quellcode + CPU-Fingerprint + Compiler-Flags. Bei erneutem Start wird der kompilierte Maschinencode (`.pyd` / `.so`) sofort eingebunden.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .api import compile_native, accelerate, AcceleratedFunction
|
|
2
|
+
from .hardware.cpu import get_cpu_info, CPUFeatures
|
|
3
|
+
from .importer import auto_accelerate
|
|
4
|
+
from .server import FastWebServer
|
|
5
|
+
from . import simd
|
|
6
|
+
from . import memory
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"compile_native",
|
|
10
|
+
"accelerate",
|
|
11
|
+
"AcceleratedFunction",
|
|
12
|
+
"get_cpu_info",
|
|
13
|
+
"CPUFeatures",
|
|
14
|
+
"auto_accelerate",
|
|
15
|
+
"FastWebServer",
|
|
16
|
+
"simd",
|
|
17
|
+
"memory",
|
|
18
|
+
]
|
|
19
|
+
__version__ = "0.2.0"
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Public API for FastPython.
|
|
3
|
+
Provides decorators and pre-start compilation helpers to turn Python functions
|
|
4
|
+
into hardware-optimized machine code.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import functools
|
|
8
|
+
import inspect
|
|
9
|
+
import time
|
|
10
|
+
from typing import Callable, Dict, Any, Optional
|
|
11
|
+
|
|
12
|
+
from .hardware.cpu import get_cpu_info
|
|
13
|
+
from .compiler.toolchain import CompilerToolchain
|
|
14
|
+
from .compiler.cache import ModuleCache
|
|
15
|
+
from .codegen.transpiler import generate_c_extension_source
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_GLOBAL_TOOLCHAIN: Optional[CompilerToolchain] = None
|
|
19
|
+
_GLOBAL_CACHE: Optional[ModuleCache] = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_toolchain() -> CompilerToolchain:
|
|
23
|
+
global _GLOBAL_TOOLCHAIN
|
|
24
|
+
if _GLOBAL_TOOLCHAIN is None:
|
|
25
|
+
_GLOBAL_TOOLCHAIN = CompilerToolchain()
|
|
26
|
+
return _GLOBAL_TOOLCHAIN
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_cache() -> ModuleCache:
|
|
30
|
+
global _GLOBAL_CACHE
|
|
31
|
+
if _GLOBAL_CACHE is None:
|
|
32
|
+
_GLOBAL_CACHE = ModuleCache()
|
|
33
|
+
return _GLOBAL_CACHE
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AcceleratedFunction:
|
|
37
|
+
"""Wrapper that holds both the original Python function and the compiled native function."""
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
py_func: Callable[..., Any],
|
|
41
|
+
type_hints: Optional[Dict[str, Any]] = None,
|
|
42
|
+
parallel: bool = False,
|
|
43
|
+
fastmath: bool = True,
|
|
44
|
+
verbose: bool = True,
|
|
45
|
+
eager: bool = True,
|
|
46
|
+
source_code: Optional[str] = None
|
|
47
|
+
):
|
|
48
|
+
self.py_func = py_func
|
|
49
|
+
self.func_name = getattr(py_func, "__name__", "anonymous")
|
|
50
|
+
self.type_hints = type_hints or getattr(py_func, "__annotations__", {})
|
|
51
|
+
self.parallel = parallel
|
|
52
|
+
self.fastmath = fastmath
|
|
53
|
+
self.verbose = verbose
|
|
54
|
+
self.source_code = source_code
|
|
55
|
+
self.native_func: Optional[Callable[..., Any]] = None
|
|
56
|
+
self.compilation_time_ms: float = 0.0
|
|
57
|
+
self.is_compiled: bool = False
|
|
58
|
+
|
|
59
|
+
if eager:
|
|
60
|
+
self._compile_or_load()
|
|
61
|
+
|
|
62
|
+
def _compile_or_load(self, sample_args: Optional[tuple] = None):
|
|
63
|
+
if self.is_compiled:
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
toolchain = get_toolchain()
|
|
67
|
+
cache = get_cache()
|
|
68
|
+
cpu = get_cpu_info()
|
|
69
|
+
|
|
70
|
+
# Update type hints from sample_args if not specified
|
|
71
|
+
if sample_args and not self.type_hints:
|
|
72
|
+
sig = inspect.signature(self.py_func)
|
|
73
|
+
inferred = {}
|
|
74
|
+
for param, val in zip(sig.parameters.values(), sample_args):
|
|
75
|
+
if isinstance(val, int):
|
|
76
|
+
inferred[param.name] = "int64_t"
|
|
77
|
+
elif isinstance(val, float):
|
|
78
|
+
inferred[param.name] = "double"
|
|
79
|
+
elif isinstance(val, bool):
|
|
80
|
+
inferred[param.name] = "bool"
|
|
81
|
+
elif hasattr(val, "__len__") and hasattr(val, "__getitem__"):
|
|
82
|
+
inferred[param.name] = "double* __restrict"
|
|
83
|
+
self.type_hints.update(inferred)
|
|
84
|
+
|
|
85
|
+
t0 = time.perf_counter()
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
# Get source code
|
|
89
|
+
if self.source_code:
|
|
90
|
+
raw_source = self.source_code
|
|
91
|
+
else:
|
|
92
|
+
try:
|
|
93
|
+
raw_source = inspect.getsource(self.py_func)
|
|
94
|
+
except Exception:
|
|
95
|
+
raw_source = ""
|
|
96
|
+
|
|
97
|
+
if not raw_source:
|
|
98
|
+
raise ValueError("Could not determine source code for function")
|
|
99
|
+
|
|
100
|
+
# Compute hash from source + settings first
|
|
101
|
+
meta = f"parallel={self.parallel}_fastmath={self.fastmath}_hints={self.type_hints}"
|
|
102
|
+
code_hash = cache.compute_hash(raw_source, meta)
|
|
103
|
+
mod_name = f"native_{self.func_name}_{code_hash}"
|
|
104
|
+
c_path, pyd_path = cache.get_module_paths(mod_name, code_hash)
|
|
105
|
+
|
|
106
|
+
if not cache.is_cached(pyd_path):
|
|
107
|
+
if self.verbose:
|
|
108
|
+
print(f"[FastPython] Compiling '{self.func_name}' for host: {cpu.summary()}...")
|
|
109
|
+
|
|
110
|
+
# Generate C source with matching module name
|
|
111
|
+
c_source = generate_c_extension_source(
|
|
112
|
+
self.py_func,
|
|
113
|
+
module_name=mod_name,
|
|
114
|
+
type_hints=self.type_hints,
|
|
115
|
+
parallel=self.parallel,
|
|
116
|
+
fastmath=self.fastmath,
|
|
117
|
+
source_code=raw_source
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
with open(c_path, "w", encoding="utf-8") as f:
|
|
121
|
+
f.write(c_source)
|
|
122
|
+
|
|
123
|
+
toolchain.compile_extension(
|
|
124
|
+
c_source_path=c_path,
|
|
125
|
+
output_pyd_path=pyd_path,
|
|
126
|
+
fastmath=self.fastmath,
|
|
127
|
+
parallel=self.parallel
|
|
128
|
+
)
|
|
129
|
+
elapsed = (time.perf_counter() - t0) * 1000
|
|
130
|
+
self.compilation_time_ms = elapsed
|
|
131
|
+
if self.verbose:
|
|
132
|
+
print(f"[FastPython] '{self.func_name}' successfully compiled in {elapsed:.1f}ms! Ready for execution.")
|
|
133
|
+
else:
|
|
134
|
+
if self.verbose:
|
|
135
|
+
print(f"[FastPython] Loading cached native binary for '{self.func_name}' [hash={code_hash}]")
|
|
136
|
+
|
|
137
|
+
self.native_func = cache.load_extension(mod_name, pyd_path, self.func_name)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
if self.verbose:
|
|
140
|
+
print(f"[FastPython] Native compilation fallback for '{self.func_name}': {e}. Using pure Python.")
|
|
141
|
+
self.native_func = None
|
|
142
|
+
|
|
143
|
+
self.is_compiled = True
|
|
144
|
+
|
|
145
|
+
def __call__(self, *args, **kwargs):
|
|
146
|
+
if not self.is_compiled:
|
|
147
|
+
self._compile_or_load(sample_args=args)
|
|
148
|
+
|
|
149
|
+
if self.native_func:
|
|
150
|
+
return self.native_func(*args, **kwargs)
|
|
151
|
+
return self.py_func(*args, **kwargs)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def compile_native(
|
|
155
|
+
func: Optional[Callable[..., Any]] = None,
|
|
156
|
+
*,
|
|
157
|
+
types: Optional[Dict[str, Any]] = None,
|
|
158
|
+
parallel: bool = False,
|
|
159
|
+
fastmath: bool = True,
|
|
160
|
+
verbose: bool = True,
|
|
161
|
+
eager: bool = True,
|
|
162
|
+
source_code: Optional[str] = None
|
|
163
|
+
):
|
|
164
|
+
"""
|
|
165
|
+
Decorator that compiles a Python function into host-native machine code before execution.
|
|
166
|
+
"""
|
|
167
|
+
def decorator(fn: Callable[..., Any]) -> AcceleratedFunction:
|
|
168
|
+
wrapper = AcceleratedFunction(
|
|
169
|
+
py_func=fn,
|
|
170
|
+
type_hints=types,
|
|
171
|
+
parallel=parallel,
|
|
172
|
+
fastmath=fastmath,
|
|
173
|
+
verbose=verbose,
|
|
174
|
+
eager=eager,
|
|
175
|
+
source_code=source_code
|
|
176
|
+
)
|
|
177
|
+
functools.update_wrapper(wrapper, fn)
|
|
178
|
+
return wrapper
|
|
179
|
+
|
|
180
|
+
if func is not None:
|
|
181
|
+
return decorator(func)
|
|
182
|
+
return decorator
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
accelerate = compile_native
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastPython Auto-Import Module.
|
|
3
|
+
Simply writing 'import fastpython.auto' at the top of your main script
|
|
4
|
+
automatically accelerates and AOT-compiles all project modules upon import.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .importer import auto_accelerate
|
|
8
|
+
|
|
9
|
+
# Activate automatically when imported
|
|
10
|
+
auto_accelerate()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command Line Interface for FastPython.
|
|
3
|
+
Allows users to:
|
|
4
|
+
- Inspect host hardware CPU features: python -m fastpython info
|
|
5
|
+
- Run benchmarks: python -m fastpython benchmark
|
|
6
|
+
- Execute accelerated scripts: python -m fastpython run <script.py>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
import os
|
|
11
|
+
import argparse
|
|
12
|
+
import runpy
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from .hardware.cpu import get_cpu_info
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
parser = argparse.ArgumentParser(
|
|
19
|
+
prog="fastpython",
|
|
20
|
+
description="FastPython: AOT Hardware-Native Machine Code Acceleration for Python"
|
|
21
|
+
)
|
|
22
|
+
subparsers = parser.add_subparsers(dest="command", help="Available subcommands")
|
|
23
|
+
|
|
24
|
+
# Command: info
|
|
25
|
+
subparsers.add_parser("info", help="Display host CPU architecture, features, and optimization flags")
|
|
26
|
+
|
|
27
|
+
# Command: benchmark
|
|
28
|
+
subparsers.add_parser("benchmark", help="Run the multi-domain FastPython benchmark suite")
|
|
29
|
+
|
|
30
|
+
# Command: run
|
|
31
|
+
run_parser = subparsers.add_parser("run", help="Execute a Python script with FastPython AOT pre-compilation")
|
|
32
|
+
run_parser.add_argument("script", help="Path to Python script to execute")
|
|
33
|
+
run_parser.add_argument("script_args", nargs=argparse.REMAINDER, help="Arguments to pass to script")
|
|
34
|
+
|
|
35
|
+
# Command: clear-cache
|
|
36
|
+
subparsers.add_parser("clear-cache", help="Clear the local .fastpython_cache directory")
|
|
37
|
+
|
|
38
|
+
args = parser.parse_args()
|
|
39
|
+
|
|
40
|
+
if args.command == "info" or args.command is None and len(sys.argv) == 1:
|
|
41
|
+
cpu = get_cpu_info()
|
|
42
|
+
print("=" * 65)
|
|
43
|
+
print(" FastPython Hardware Profiler")
|
|
44
|
+
print("=" * 65)
|
|
45
|
+
print(f" CPU Model: {cpu.brand}")
|
|
46
|
+
print(f" Vendor: {cpu.vendor}")
|
|
47
|
+
print(f" Architecture: {cpu.architecture}")
|
|
48
|
+
print(f" Threads / Cores: {cpu.logical_cores} logical / {cpu.physical_cores} physical")
|
|
49
|
+
print(f" AVX Support: AVX={cpu.has_avx}, AVX2={cpu.has_avx2}, AVX-512={cpu.has_avx512f}")
|
|
50
|
+
print(f" Math Extensions: FMA3={cpu.has_fma}, SSE4.2={cpu.has_sse42}, BMI2={cpu.has_bmi2}")
|
|
51
|
+
print("-" * 65)
|
|
52
|
+
print(f" MSVC Flags: {' '.join(cpu.get_msvc_flags())}")
|
|
53
|
+
print(f" GCC Flags: {' '.join(cpu.get_gcc_flags())}")
|
|
54
|
+
print("=" * 65)
|
|
55
|
+
|
|
56
|
+
elif args.command == "benchmark":
|
|
57
|
+
bench_script = Path(__file__).resolve().parent.parent / "benchmarks" / "run_all_benchmarks.py"
|
|
58
|
+
runpy.run_path(str(bench_script), run_name="__main__")
|
|
59
|
+
|
|
60
|
+
elif args.command == "clear-cache":
|
|
61
|
+
cache_dir = Path.cwd() / ".fastpython_cache"
|
|
62
|
+
if cache_dir.exists():
|
|
63
|
+
import shutil
|
|
64
|
+
shutil.rmtree(cache_dir)
|
|
65
|
+
print(f"Cleared cache at: {cache_dir}")
|
|
66
|
+
else:
|
|
67
|
+
print("No cache directory found.")
|
|
68
|
+
|
|
69
|
+
elif args.command == "run":
|
|
70
|
+
target_script = Path(args.script).resolve()
|
|
71
|
+
if not target_script.exists():
|
|
72
|
+
print(f"Error: Script '{args.script}' not found.")
|
|
73
|
+
sys.exit(1)
|
|
74
|
+
|
|
75
|
+
# Set sys.argv for the target script
|
|
76
|
+
sys.argv = [str(target_script)] + args.script_args
|
|
77
|
+
sys.path.insert(0, str(target_script.parent))
|
|
78
|
+
|
|
79
|
+
# Execute script
|
|
80
|
+
runpy.run_path(str(target_script), run_name="__main__")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
main()
|