zonza/moteur/__init__.py
Ralph Mayola 5f83e4c6a3 La sonde CUDA reconnait aussi les DLL Windows
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:10:23 +02:00

63 lines
2.5 KiB
Python

"""Choisit le moteur de transcription d'après le matériel."""
import ctypes
import platform
import sys
def nom_moteur_pour(plateforme, machine, cuda_disponible):
"""Décide du moteur. Fonction PURE : aucune interrogation de la machine ici,
ce qui rend les quatre configurations testables depuis un seul poste."""
if plateforme.startswith("darwin") and machine in ("arm64", "aarch64"):
return "mlx"
return "faster-gpu" if cuda_disponible else "faster-cpu"
def detecter_moteur():
"""Interroge la machine, puis délègue la décision à `nom_moteur_pour`."""
return nom_moteur_pour(sys.platform, platform.machine(), _cuda_disponible())
# Le nom de la bibliothèque partagée CUDA diffère radicalement par plateforme ET
# par version : `libcudart.so` (parfois suffixé `.12`, `.11.0`...) sous Linux/macOS,
# mais `cudart64_12.dll`, `cudart64_110.dll`... sous Windows, où le numéro de version
# est ENCODÉ DANS LE NOM du fichier. `ctypes.util.find_library` ne résout pas ces DLL
# versionnées de façon fiable — il cherche un nom canonique qui n'existe pas pour
# CUDA sous Windows. On essaie donc une liste explicite de noms candidats, du plus
# récent au plus ancien, et on s'arrête au premier qui charge.
_NOMS_CUDART_WINDOWS = [
"cudart64_12.dll",
"cudart64_110.dll",
"cudart64_101.dll",
"cudart64_100.dll",
]
_NOMS_CUDART_UNIX = [
"libcudart.so",
"libcudart.so.12",
"libcudart.so.11.0",
]
def _cuda_disponible(plateforme=None, charger=None):
"""Sonde la présence du runtime CUDA en tentant de charger sa bibliothèque
partagée. `plateforme` et `charger` sont injectables : ça rend la sonde
testable avec une doublure, sans dépendre d'une vraie machine CUDA ni d'un
vrai Windows. Ne lève jamais — dans le doute, on rend False."""
plateforme = plateforme if plateforme is not None else sys.platform
charger = charger if charger is not None else ctypes.CDLL
noms = _NOMS_CUDART_WINDOWS if plateforme.startswith("win") else _NOMS_CUDART_UNIX
for nom in noms:
try:
charger(nom)
return True
except Exception:
continue
return False
def choisir_transcripteur(nom, modele, langue, amorce):
"""Rend l'implémentation du contrat Transcripteur portant ce nom."""
if nom == "mlx":
from moteur.mlx import TranscripteurMLX
return TranscripteurMLX(modele, langue, amorce)
raise NotImplementedError(f"Moteur non pris en charge à cette étape : {nom}")