← Назад к вопросам
Что будешь использовать для вычислительной задачи?
2.0 Middle🔥 191 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Выбор инструмента для вычислительных задач
Выбор зависит от типа задачи, требуемой производительности и доступных ресурсов. Вот мой подход к принятию решения.
Первый вопрос: что это за вычисления?
Нужно разобраться в типе задачи:
Вычислительная задача?
├─ Математические операции (Numpy, Cython)
├─ Машинное обучение (PyTorch, TensorFlow)
├─ Обработка данных (Pandas, Polars, Dask)
├─ Граф обработка (NetworkX, DGL)
└─ Универсальные вычисления (multiprocessing, asyncio)
Решение 1: Если это численные вычисления → Numpy
Для математических операций Numpy — золотой стандарт:
import numpy as np
import time
# Неоптимально: Python loop
def python_calculation(n):
result = 0
for i in range(n):
result += i ** 2
return result
# Оптимально: Numpy (в 100+ раз быстрее)
def numpy_calculation(n):
arr = np.arange(n)
return np.sum(arr ** 2)
# Бенчмарк
start = time.time()
python_calculation(10_000_000)
print(f"Python: {time.time() - start:.3f}s")
start = time.time()
numpy_calculation(10_000_000)
print(f"Numpy: {time.time() - start:.3f}s")
# Python: 2.500s
# Numpy: 0.020s
Решение 2: Машинное обучение → PyTorch / TensorFlow
Для ML использую специализированные фреймворки:
import torch
import numpy as np
# Матричные вычисления
matrix_a = torch.randn(1000, 1000)
matrix_b = torch.randn(1000, 1000)
# На GPU (если доступен)
if torch.cuda.is_available():
matrix_a = matrix_a.cuda()
matrix_b = matrix_b.cuda()
result = torch.matmul(matrix_a, matrix_b)
print(f"Result shape: {result.shape}")
Преимущества:
- Оптимизированы для GPU
- Автоматическое дифференцирование
- Параллельные вычисления из коробки
Решение 3: Обработка больших данных → Pandas / Dask
Для работы с датафреймами:
import pandas as pd
import dask.dataframe as dd
# Маленькие данные → Pandas
df = pd.read_csv('data.csv')
result = df.groupby('category')['value'].mean()
# Большие данные (не влезает в память) → Dask
ddf = dd.read_csv('large_*.csv')
result = ddf.groupby('category')['value'].mean().compute()
Решение 4: Если нужен максимум производительности → Cython
Для критичных по производительности функций:
# fibonacci_cy.pyx (Cython)
cpdef int fibonacci(int n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("fibonacci_cy.pyx")
)
# Использование
from fibonacci_cy import fibonacci
result = fibonacci(35) # намного быстрее чем Python
Решение 5: Параллельные вычисления → Multiprocessing
Для CPU-bound задач на нескольких ядрах:
from concurrent.futures import ProcessPoolExecutor
import numpy as np
def compute_chunk(chunk):
# Тяжелые вычисления
return np.sum(chunk ** 2)
# Данные
data = np.arange(100_000_000).reshape(4, -1)
# Параллельная обработка
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(compute_chunk, data))
total = sum(results)
print(f"Total: {total}")
Решение 6: Асинхронность → asyncio (только для I/O!)
ВАЖНО: asyncio НЕ для вычислений, только для I/O:
import asyncio
# ✅ Правильно: I/O-bound операция
async def fetch_data(url):
# network request
await asyncio.sleep(1)
return "data"
async def main():
results = await asyncio.gather(
fetch_data("url1"),
fetch_data("url2"),
fetch_data("url3")
)
print(results)
# ❌ НЕПРАВИЛЬНО: CPU-bound операция
async def cpu_bound():
return sum(i ** 2 for i in range(100_000_000))
# asyncio не поможет! Используй multiprocessing
Решение 7: Распределенные вычисления → Spark / Ray
Для огромных объемов данных на кластере:
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("BigCompute").getOrCreate()
df = spark.read.csv("huge_file.csv")
result = df.groupBy("category").agg({"value": "mean"}).collect()
Или с Ray:
import ray
@ray.remote
def compute(data):
return sum(i ** 2 for i in data)
ray.init()
results = ray.get([compute.remote(chunk) for chunk in chunks])
Матрица выбора
| Задача | Рекомендация | Зачем |
|---|---|---|
| Математика 10K чисел | Numpy | 100x быстрее Python |
| ML модель | PyTorch/TensorFlow | GPU поддержка, autodiff |
| Big Data (GB) | Pandas | Удобный API |
| Big Data (TB) | Dask/Spark | Параллельная обработка |
| Критичная функция | Cython | 10-100x ускорение |
| Множество задач на CPU | multiprocessing | Использование всех ядер |
| I/O операции | asyncio | Коротор переключения |
| Кластер обработка | Spark/Ray | Масштабируемость |
Реальный пример: обработка изображений
import numpy as np
from PIL import Image
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path
def process_image(path: str) -> np.ndarray:
"""Обработка одного изображения"""
img = Image.open(path)
# Фильтр, трансформация и т.д.
data = np.array(img)
# Numpy для быстрых вычислений
result = np.convolve(data.flatten(), [1, 2, 1], mode='same')
return result
def process_images(image_dir: str, num_workers: int = 4) -> list:
"""Обработка множества изображений параллельно"""
paths = list(Path(image_dir).glob("*.jpg"))
with ProcessPoolExecutor(max_workers=num_workers) as executor:
# multiprocessing для CPU-bound
results = list(executor.map(process_image, paths))
return results
Мой алгоритм выбора
- Профилирование — найди узкие места (
cProfile,line_profiler) - Анализ — что именно медленно?
- Выбор — используй таблицу выше
- Тестирование — оцени прирост производительности
- Оптимизация — повтори для других узких мест
Главное правило: не оптимизируй раньше, чем профилируешь.