π Free-threaded Python ΡΠ±ΡΠ°Π» GIL, Π½ΠΎ NumPy Π²ΡΡ ΡΠ°Π²Π½ΠΎ ΡΠΏΠΈΡΠ°Π»ΡΡ Π²ΠΎ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ
ΠΠ°Π·Π°Π»ΠΎΡΡ Π±Ρ, Python 3.13+ Π±Π΅Π· GIL Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠ°ΠΌ ΠΎΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΡΠΈΡΠ»Π΅Π½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.
ΠΠΎ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΠ΅
Π NumPy 2.5 ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΡΡΡΠ°Π½ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΊΠ»ΡΡΠ΅Π²ΡΡ ΡΠ·ΠΊΠΈΡ ΠΌΠ΅ΡΡ:
- ΡΠ°Π±Π»ΠΈΡΡ Π΄ΠΈΡΠΏΠ΅ΡΡΠ΅ΡΠΈΠ·Π°ΡΠΈΠΈ
- ΡΠ°ΡΡΡ ΠΎΠ±ΡΠΈΡ ΡΠ»ΡΠΆΠ΅Π±Π½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΡΠ΄Π΅Π»Π°Π»ΠΈ Β«Π±Π΅ΡΡΠΌΠ΅ΡΡΠ½ΡΠΌΠΈΒ», ΡΠ½ΠΈΠ·ΠΈΠ² ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠΈΡ ΠΏΡΠΈ ΠΏΠΎΠ΄ΡΡΡΡΠ΅ ΡΡΡΠ»ΠΎΠΊ;
- Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΏΠ°ΠΌΡΡΠΈ ΠΏΠ΅ΡΠ΅Π²Π΅Π»ΠΈ Π½Π°
Π’Π΅ΠΏΠ΅ΡΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ±ΡΡΠ½ΡΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ°ΠΌΠΈ:
ΠΠ»Π°Π²Π½ΠΎΠ΅ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²ΠΎ ΠΏΠ΅ΡΠ΅Π΄
ΠΠΎΡΠΎΠΊΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π² ΠΎΠ΄Π½ΠΎΠΌ Π°Π΄ΡΠ΅ΡΠ½ΠΎΠΌ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅, ΠΏΠΎΡΡΠΎΠΌΡ ΠΌΠΎΠ³ΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½Π΅Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΌΠ½ΠΎΠ³ΠΎΡΠ΄Π΅ΡΠ½ΡΠΉ CPU ΠΈ ΠΎΠ±ΡΡΡ ΠΏΠ°ΠΌΡΡΡ.
ΠΠΎ Π΅ΡΡΡ Π²Π°ΠΆΠ½Π°Ρ ΠΎΠ³ΠΎΠ²ΠΎΡΠΊΠ°:
free-threaded Π½Π΅ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ thread-safe.
ΠΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ
ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½Π΅Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ:
- ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ ΠΌΠ°ΡΡΠΈΠ² Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ worker;
- ΠΎΠ±ΡΠΈΠΉ ΠΌΠ°ΡΡΠΈΠ² ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ;
- ΡΠ²Π½ΡΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΈ Π·Π°ΠΏΠΈΡΠΈ.
Π£Π΄Π°Π»ΠΈΡΡ GIL ΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ. Π§ΡΠΎΠ±Ρ Python Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°Π»ΡΡ ΠΏΠΎ ΡΠ΄ΡΠ°ΠΌ, ΠΏΡΠΈΡΠ»ΠΎΡΡ ΠΏΠ΅ΡΠ΅ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΠΈ Π²Π½ΡΡΡΠ΅Π½Π½ΠΎΡΡΠΈ NumPy.
ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅:
https://labs.quansight.org/blog/scaling-numpy-on-free-threaded-python
ΠΠ°Π·Π°Π»ΠΎΡΡ Π±Ρ, Python 3.13+ Π±Π΅Π· GIL Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠ°ΠΌ ΠΎΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΡΠΈΡΠ»Π΅Π½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.
ΠΠΎ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΠ΅
ufunc Π½Π°ΡΠΈΠ½Π°Π»ΠΈ ΠΊΠΎΠ½ΠΊΡΡΠΈΡΠΎΠ²Π°ΡΡ Π·Π° Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠ΅ ΡΡΡΡΠΊΡΡΡΡ NumPy, ΡΡΡΡΡΠΈΠΊΠΈ ΡΡΡΠ»ΠΎΠΊ ΠΈ Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΏΠ°ΠΌΡΡΠΈ.Π NumPy 2.5 ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΡΡΡΠ°Π½ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΊΠ»ΡΡΠ΅Π²ΡΡ ΡΠ·ΠΊΠΈΡ ΠΌΠ΅ΡΡ:
- ΡΠ°Π±Π»ΠΈΡΡ Π΄ΠΈΡΠΏΠ΅ΡΡΠ΅ΡΠΈΠ·Π°ΡΠΈΠΈ
ufunc Π·Π°ΠΌΠ΅Π½ΠΈΠ»ΠΈ Π½Π° lock-free concurrent hash map;- ΡΠ°ΡΡΡ ΠΎΠ±ΡΠΈΡ ΡΠ»ΡΠΆΠ΅Π±Π½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΡΠ΄Π΅Π»Π°Π»ΠΈ Β«Π±Π΅ΡΡΠΌΠ΅ΡΡΠ½ΡΠΌΠΈΒ», ΡΠ½ΠΈΠ·ΠΈΠ² ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠΈΡ ΠΏΡΠΈ ΠΏΠΎΠ΄ΡΡΡΡΠ΅ ΡΡΡΠ»ΠΎΠΊ;
- Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΏΠ°ΠΌΡΡΠΈ ΠΏΠ΅ΡΠ΅Π²Π΅Π»ΠΈ Π½Π°
PyMem_RawMalloc ΠΈ PyMem_RawFree.Π’Π΅ΠΏΠ΅ΡΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ±ΡΡΠ½ΡΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ°ΠΌΠΈ:
from concurrent.futures import ThreadPoolExecutor
import numpy as np
arrays = [
np.random.rand(5_000_000)
for _ in range(8)
]
with ThreadPoolExecutor(max_workers=8) as pool:
results = list(pool.map(np.sin, arrays))
ΠΠ»Π°Π²Π½ΠΎΠ΅ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²ΠΎ ΠΏΠ΅ΡΠ΅Π΄
multiprocessing - ΠΌΠ°ΡΡΠΈΠ²Ρ Π½Π΅ Π½ΡΠΆΠ½ΠΎ ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΈ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΠΌΠ΅ΠΆΠ΄Ρ ΠΏΡΠΎΡΠ΅ΡΡΠ°ΠΌΠΈ.ΠΠΎΡΠΎΠΊΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π² ΠΎΠ΄Π½ΠΎΠΌ Π°Π΄ΡΠ΅ΡΠ½ΠΎΠΌ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅, ΠΏΠΎΡΡΠΎΠΌΡ ΠΌΠΎΠ³ΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½Π΅Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΌΠ½ΠΎΠ³ΠΎΡΠ΄Π΅ΡΠ½ΡΠΉ CPU ΠΈ ΠΎΠ±ΡΡΡ ΠΏΠ°ΠΌΡΡΡ.
ΠΠΎ Π΅ΡΡΡ Π²Π°ΠΆΠ½Π°Ρ ΠΎΠ³ΠΎΠ²ΠΎΡΠΊΠ°:
free-threaded Π½Π΅ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ thread-safe.
ΠΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ
ndarray ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
ΠΏΠΎΡΠΎΠΊΠΎΠ² Π²ΡΡ Π΅ΡΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ²Π΅ΡΡΠΈ ΠΊ Π³ΠΎΠ½ΠΊΠ°ΠΌ, ΠΏΠΎΠ²ΡΠ΅ΠΆΠ΄ΡΠ½Π½ΡΠΌ Π΄Π°Π½Π½ΡΠΌ ΠΈ ΠΏΠ°Π΄Π΅Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠ°ΡΠΎΡΠ°.ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½Π΅Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ:
- ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ ΠΌΠ°ΡΡΠΈΠ² Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ worker;
- ΠΎΠ±ΡΠΈΠΉ ΠΌΠ°ΡΡΠΈΠ² ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ;
- ΡΠ²Π½ΡΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΈ Π·Π°ΠΏΠΈΡΠΈ.
Π£Π΄Π°Π»ΠΈΡΡ GIL ΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ. Π§ΡΠΎΠ±Ρ Python Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΠΎΠ²Π°Π»ΡΡ ΠΏΠΎ ΡΠ΄ΡΠ°ΠΌ, ΠΏΡΠΈΡΠ»ΠΎΡΡ ΠΏΠ΅ΡΠ΅ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΠΈ Π²Π½ΡΡΡΠ΅Π½Π½ΠΎΡΡΠΈ NumPy.
ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅:
https://labs.quansight.org/blog/scaling-numpy-on-free-threaded-python