Деякі нотатки про погані справи
Фактори, що впливають на швидкість виконання Python
Інтерпретатор Python
Альтернативні інтерпретатори:
- Перепишіть код у вигляді C-розширень або використовуйте Cython, який дозволяє писати швидкі розширення за синтаксисом, схожим на Python.
- Використовуйте PyPy для компіляції Just-In-Time (JIT), що може значно пришвидшити роботу довготривалих додатків.
Версія має значення:
- Завжди використовуйте останню стабільну версію Python для найкращих оптимізацій.
Віртуальне середовище
- Допомагає уникнути конфліктів залежностей.
- Запобігає впливу глобальних змінних на продуктивність бібліотек.
- Забезпечує використання конкретних версій бібліотек для кращої продуктивності та стабільності.
Бенчмаркінг
- Використовуйте інструменти, як-от
timeit
,cProfile
абоline_profiler
, щоб визначити "вузькі місця". - Орієнтуйте зусилля з оптимізації на найповільніші частини вашого коду.
Техніки оптимізації швидкості
Оптимізації синтаксису
Вбудовані функції та бібліотеки
- Вбудовані функції (наприклад,
map
) працюють швидше за цикли Python, оскільки вони реалізовані на C.
# Повільніший цикл
newlist = [word.upper() for word in wordlist]
# Швидше
newlist = map(str.upper, wordlist)
Множинні присвоєння
- Поєднуйте присвоєння в один рядок, щоб заощадити час на інтерпретації.
# Повільніше
firstName = "John"
lastName = "Henry"
city = "Manchester"
# Швидше
firstName, lastName, city = "John", "Henry", "Manchester"
Спискові вирази
- Використовуйте спискові вирази замість циклів для більш компактного та швидшого коду.
# Повільніший цикл
newlist = []
for i in range(1, 100):
if i % 2 == 0:
newlist.append(i**2)
# Швидше
newlist = [i**2 for i in range(1, 100) if i % 2 == 0]
Примусове визначення типів
- Явно перетворюйте типи даних, щоб забезпечити ефективне виконання операцій.
x = y.astype(int)
Операції зі строками
- Використовуйте
join()
для об'єднання рядків замість оператора+
.
# Повільніше
output = "Programming" + " is " + "fun"
# Швидше
output = " ".join(["Programming", "is", "fun"])
Оптимізація пам'яті
Попереднє виділення пам'яті
- Виділяйте пам'ять один раз і повторно її використовуйте, щоб уникнути повторних виділень.
buffer = np.zeros((1000, 3)) # Попереднє виділення
for i in range(1000):
buffer[i] = [1, 2, 3] # Оновлення на місці
Операції на місці
- Змініть дані без створення нових копій.
# За межами місця
y = x + 1 # Виділяється нова пам'ять
# На місці
x.add_(1) # Модифікує x безпосередньо
Зменшення передачі даних між CPU та GPU
- Мінімізуйте передачу даних між CPU та GPU, обробляючи операції пакетами і зберігаючи дані на GPU.
x_gpu = x.to('cuda') # Перенесення на GPU
Ефективні імпорти
- Уникайте непотрібних імпортів і використовуйте специфічні імпорти для часто використовуваних функцій.
# Повільніше
import math
value = math.sqrt(50)
# Швидше
from math import sqrt
value = sqrt(50)
Оптимізація логіки та потоку
Умовні оператори
- Уникайте непотрібних гілок (наприклад,
if
), щоб зменшити затримки в сучасних процесорах.
Попередньо обчислювана логіка
- Кешуйте результати дорогих обчислень за допомогою
functools.lru_cache
.
from functools import lru_cache
@lru_cache
def expensive_computation(x):
return x**2
Конкурентність і паралелізм
Асинхронні операції
- Використовуйте
asyncio
для задач, пов'язаних з I/O, таких як HTTP-запити.
import asyncio
import httpx
async def fetch(url):
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.text
asyncio.run(fetch("https://example.com"))
Паралелізм
- Використовуйте
concurrent.futures
для паралельного виконання в задачах, пов'язаних з процесором.
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
results = list(executor.map(func, data))
Оптимізація HTTP-запитів
Постійні з'єднання
- Повторно використовуйте з'єднання за допомогою
requests.Session()
абоhttpx.Client()
.
Пакетні запити
- Групуйте кілька API-запитів в один пакет, коли це можливо.
Використання WebSockets
- Замініть повторювані опитування WebSockets для реального часу.
## Розширені інструменти та техніки
Numba
- Прискорюйте числові обчислення за допомогою Numba.
from numba import jit
@jit
def fast_function(x):
return x**2
Cython
- Перетворюйте код Python у C для критичних за продуктивністю ділянок коду.
Оптимізація апаратного забезпечення
- Використовуйте Linux для кращої продуктивності порівняно з Windows.
- Увімкніть режим продуктивності процесора в операційній системі.
- Розгортайте додатки ближче до цільових серверів, щоб зменшити затримку.
Перекладено з: How to Make My Python Run Faster