Guide de Performance

Ketu utilise la vectorisation NumPy pure pour obtenir des améliorations de performance massives par rapport à la version précédente.

Benchmarks

Calculs de séries temporelles

Pour calculer les positions planétaires sur 365 jours :

  • 208x plus rapide que l’approche par boucles

  • De ~3.2s à ~15ms pour une année complète

Calculs d’aspects

Pour détecter tous les aspects entre planètes :

  • 14.55x plus rapide avec vectorisation

  • De ~120ms à ~8ms par date

Calculs de positions uniques

Pour calculer les positions de planètes individuelles :

  • 67x plus rapide pour les planètes extérieures

  • 59x plus rapide pour les calculs lunaires

  • Le solveur d’équation de Kepler utilise l’itération Newton-Raphson avec tolérance adaptive :

Fonctions Vectorisées

Calculs de Positions par Batch

import numpy as np
from ketu.ephemeris.time import utc_to_julian
from ketu.ephemeris.planets import calc_planet_position_batch
from datetime import datetime, timedelta

# Calculate Sun positions for a year
dates = [datetime(2025, 1, 1) + timedelta(days=i) for i in range(365)]
jd_array = np.array([utc_to_julian(d) for d in dates])

# Use vectorized batch calculation
positions = calc_planet_position_batch(jd_array, planet_id=0)  # Sun

# Extract components
longitudes = positions[:, 0]
latitudes = positions[:, 1]
distances = positions[:, 2]

Détection d’aspects vectorisée

from ketu.aspects import calculate_aspects
from ketu.ephemeris.time import utc_to_julian
from datetime import datetime, timedelta
import numpy as np

# Build a Julian Day array
dates = [datetime(2025, 1, 1) + timedelta(days=i) for i in range(30)]
jd_array = np.array([utc_to_julian(d) for d in dates])

# Calculate aspects for each date
for jd in jd_array:
    aspects = calculate_aspects(jd)

Techniques d’optimisation

Cache LRU

La bibliothèque utilise functools.lru_cache avec des tailles de cache optimales :

from functools import lru_cache

@lru_cache(maxsize=1024)
def body_properties(jdate, body):
    # Cached for repeated calculations
    # 6.7x speedup vs no cache
    ...

Broadcasting NumPy

Tous les calculs de distance et d’angle utilisent le broadcasting NumPy pour des opérations efficaces sur les tableaux.

def distance(pos1, pos2):
    # Works with both scalars and arrays
    import numpy as np
    angle = np.abs(pos2 - pos1)
    return np.where(angle <= 180, angle, 360 - angle)

Solveur de Kepler optimisé

Le solveur d’équation de Kepler utilise l’itération Newton-Raphson avec tolérance adaptative :

  • Convergence typique en 3-5 itérations

  • Epsilon adaptatif basé sur l’excentricité

  • Vectorisé pour les calculs batch

Efficacité mémoire

Tableaux structurés

Les résultats d’aspects utilisent des tableaux NumPy structurés pour un stockage efficace :

import numpy as np

# Compact storage with named fields
dtype = [('body1', 'i4'), ('body2', 'i4'),
         ('i_asp', 'i4'), ('orb', 'f8')]
aspects = np.zeros(num_aspects, dtype=dtype)

Opérations en place

La plupart des calculs utilisent des opérations NumPy en place pour minimiser l’allocation mémoire.

Bonnes Pratiques

Utiliser les Fonctions Batch

Pour l’analyse de séries temporelles :

from ketu.ephemeris.planets import calc_planet_position_batch

# Good: Use batch functions
positions = calc_planet_position_batch(jd_array, planet_id)

# Avoid: Individual calls in a loop
# positions = [calc_planet_position(jd, planet_id) for jd in jd_array]

Pré-allouer les tableaux

Pour les calculs à grande échelle :

import numpy as np
from ketu.ephemeris.planets import calc_planet_position_batch

# Pre-allocate result array
results = np.zeros((len(dates), 6))

# Fill with batch calculation
results = calc_planet_position_batch(jd_array, planet_id)

Mettre en cache les conversions de dates juliennes

import numpy as np
from ketu.ephemeris.time import utc_to_julian
from ketu.ephemeris.planets import calc_planet_position_batch

# Convert dates once
jd_array = np.array([utc_to_julian(d) for d in dates])

# Reuse for multiple calculations
sun_pos  = calc_planet_position_batch(jd_array, 0)
moon_pos = calc_planet_position_batch(jd_array, 1)

Conseils de performance

  1. Utiliser les fonctions vectorisées pour les opérations en masse

  2. Mettre en cache les dates juliennes lors du calcul de plusieurs corps

  3. Pré-allouer les tableaux pour les grands ensembles de données

  4. Éviter les boucles Python sur les dates - utiliser les tableaux NumPy

  5. Réutiliser les calculs - exploiter le cache LRU

Profiler votre code

Pour identifier les goulots d’étranglement :

import cProfile
import pstats
from ketu.calculations import positions

profiler = cProfile.Profile()
profiler.enable()

# Your ketu code here
lons = positions(jday)

profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(10)