
Ray : L’informatique distribuée pour tous, partie 2
épisode de ma série en deux parties sur la bibliothèque Ray, un framework Python créé par AnyScale pour l’informatique distribuée et parallèle. La première partie explique comment paralléliser les tâches Python gourmandes en CPU sur votre PC local en répartissant la charge de travail sur tous les cœurs disponibles, ce qui entraîne des améliorations marquées du temps d’exécution. Je laisserai un lien vers la partie 1 à la fin de cet article.
Cette partie traite d’un thème similaire, sauf que nous faisons passer la distribution des charges de travail Python au niveau supérieur en utilisant Ray pour les paralléliser sur des clusters multi-serveurs dans le cloud.
Si vous en êtes arrivé là sans avoir lu la première partie, le TL;DR de Ray est qu’il s’agit d’un source ouverte cadre informatique distribué conçu pour le faire facile à mettre à l’échelle Programmes Python depuis un ordinateur portable vers un cluster avec un minimum de modifications de code. Nous espérons que cela suffira à lui seul à susciter votre intérêt. Dans mon propre test, sur mon ordinateur de bureau, j’ai pris un programme Python simple et relativement simple qui trouve des nombres premiers et j’ai réduit son temps d’exécution d’un facteur 10 en ajoutant seulement quatre lignes de code.
Où pouvez-vous exécuter des clusters Ray ?
Les clusters de rayons peuvent être configurés sur les éléments suivants :
- AWS et GCP Cloud, bien que des intégrations non officielles existent également pour d’autres fournisseurs, comme Azure
- AnyScale, une plateforme entièrement gérée développée par les créateurs de Ray.
- Kubernetes peut également être utilisé via le projet KubeRay officiellement pris en charge.
Conditions préalables
Pour suivre mon processus, vous aurez besoin de quelques éléments configurés au préalable. J’utiliserai AWS pour ma démo, car j’y ai déjà un compte ; cependant, je m’attends à ce que la configuration des autres fournisseurs et plates-formes cloud soit très similaire. Vous devriez avoir :
- Identifiants configurés pour exécuter les commandes Cloud CLI du fournisseur de votre choix.
- Un VPC par défaut et au moins un sous-réseau public qui lui est associé et qui possède une adresse IP accessible publiquement.
- Un fichier de paire de clés SSH (.pem) que vous pouvez télécharger sur votre système local afin que Ray (et vous) puissiez vous connecter aux nœuds de votre cluster
- Vous disposez de suffisamment de quotas pour satisfaire le nombre demandé de nœuds et de processeurs virtuels dans le cluster que vous configurez.
Si vous souhaitez effectuer des tests locaux de votre code Ray avant de le déployer sur un cluster, vous devrez également installer la bibliothèque Ray. Nous pouvons le faire en utilisant pip.
$ pip install ray
Je vais tout exécuter à partir d’un shell Ubuntu WSL2 sur mon bureau Windows.
Pour vérifier que Ray a été correctement installé, vous devriez pouvoir utiliser son interpréteur de ligne de commande. Dans une fenêtre de terminal, tapez la commande suivante.
$ ray --help
Usage: ray [OPTIONS] COMMAND [ARGS]...
Options:
--logging-level TEXT The logging level threshold, choices=['debug',
'info', 'warning', 'error', 'critical'],
default='info'
--logging-format TEXT The logging format.
default="%%(asctime)s\t%%(levelname)s
%%(filename)s:%%(lineno)s -- %%(message)s"
--version Show the version and exit.
--help Show this message and exit.
Commands:
attach Create or attach to a SSH session to a Ray cluster.
check-open-ports Check open ports in the local Ray cluster.
cluster-dump Get log data from one or more nodes.
...
...
...
Si vous ne voyez pas cela, quelque chose s’est mal passé et vous devez revérifier le résultat de votre commande d’installation.
En supposant que tout va bien, nous sommes prêts à partir.
Un dernier point important cependant. Création de ressources, telles que des clusters de calcul, sur un fournisseur de cloud comme AWS entraînera des fraisil est donc essentiel que vous gardiez cela à l’esprit. La bonne nouvelle est que Ray dispose d’une commande intégrée qui détruira toute infrastructure que vous créez, mais pour être sûr, vous devez vérifier qu’aucun service inutilisé et potentiellement coûteux ne reste. « allumé » par erreur.
Notre exemple de code Python
La première étape consiste à modifier notre code Ray existant de la partie 1 pour l’exécuter sur un cluster. Voici le code original pour votre référence. Rappelez-vous que nous essayons de compter le nombre de nombres premiers dans une plage numérique spécifique.
import math
import time
# -----------------------------------------
# Change No. 1
# -----------------------------------------
import ray
ray.init()
def is_prime(n: int) -> bool:
if n < 2: return False
if n == 2: return True
if n % 2 == 0: return False
r = int(math.isqrt(n)) + 1
for i in range(3, r, 2):
if n % i == 0:
return False
return True
# -----------------------------------------
# Change No. 2
# -----------------------------------------
@ray.remote(num_cpus=1) # pure-Python loop → 1 CPU per task
def count_primes(a: int, b: int) -> int:
c = 0
for n in range(a, b):
if is_prime(n):
c += 1
return c
if __name__ == "__main__":
A, B = 10_000_000, 20_000_000
total_cpus = int(ray.cluster_resources().get("CPU", 1))
# Start "chunky"; we can sweep this later
chunks = max(4, total_cpus * 2)
step = (B - A) // chunks
print(f"nodes={len(ray.nodes())}, CPUs~{total_cpus}, chunks={chunks}")
t0 = time.time()
refs = []
for i in range(chunks):
s = A + i * step
e = s + step if i < chunks - 1 else B
# -----------------------------------------
# Change No. 3
# -----------------------------------------
refs.append(count_primes.remote(s, e))
# -----------------------------------------
# Change No. 4
# -----------------------------------------
total = sum(ray.get(refs))
print(f"total={total}, time={time.time() - t0:.2f}s")
Quelles modifications sont nécessaires pour l’exécuter sur un cluster ? La réponse est que juste un changement mineur est requis.
Change
ray.init()
to
ray.init(address=auto)
C’est l’une des beautés de Ray. Le même code s’exécute presque sans modification sur votre PC local et partout où vous souhaitez l’exécuter, y compris les grands clusters cloud multi-serveurs.
Mise en place de notre cluster
Sur le cloud, un cluster Ray se compose d’un nœud principal et d’un ou plusieurs nœuds de travail. Dans AWS, tous ces nœuds sont simplement des instances EC2. Les clusters Ray peuvent être de taille fixe ou évoluer automatiquement vers le haut ou vers le bas en fonction des ressources demandées par les applications exécutées sur le cluster. Le nœud principal est démarré en premier et les nœuds de travail sont configurés avec l’adresse du nœud principal pour former le cluster. Si la mise à l’échelle automatique est activée, les nœuds de travail augmentent ou diminuent automatiquement en fonction de la charge de l’application et diminueront après une période spécifiée par l’utilisateur (5 minutes par défaut).
Ray utilise des fichiers YAML pour configurer des clusters. Un fichier YAML est simplement un fichier texte brut avec une syntaxe de type JSON utilisée pour la configuration du système.
Voici le fichier YAML que j’utiliserai pour configurer mon cluster. J’ai découvert que l’instance EC2 la plus proche de mon ordinateur de bureau, en termes de nombre de cœurs de processeur et de performances, était une c7g.8xlarge.. Pour plus de simplicité, je fais en sorte que le nœud principal soit du même type de serveur que tous les travailleurs, mais vous pouvez mélanger et faire correspondre différents types EC2 si vous le souhaitez.
cluster_name: ray_test
provider:
type: aws
region: eu-west-1
availability_zone: eu-west-1a
auth:
# For Amazon Linux AMIs the SSH user is 'ec2-user'.
# If you switch to an Ubuntu AMI, change this to 'ubuntu'.
ssh_user: ec2-user
ssh_private_key: ~/.ssh/ray-autoscaler_eu-west-1.pem
max_workers: 10
idle_timeout_minutes: 10
head_node_type: head_node
available_node_types:
head_node:
node_config:
InstanceType: c7g.8xlarge
ImageId: ami-06687e45b21b1fca9
KeyName: ray-autoscaler_eu-west-1
worker_node:
min_workers: 5
max_workers: 5
node_config:
InstanceType: c7g.8xlarge
ImageId: ami-06687e45b21b1fca9
KeyName: ray-autoscaler_eu-west-1
InstanceMarketOptions:
MarketType: spot
# =========================
# Setup commands (run on head + workers)
# =========================
setup_commands:
- |
set -euo pipefail
have_cmd() { command -v "$1" >/dev/null 2>&1; }
have_pip_py() {
python3 -c 'import importlib.util, sys; sys.exit(0 if importlib.util.find_spec("pip") else 1)'
}
# 1) Ensure Python 3 is present
if ! have_cmd python3; then
if have_cmd dnf; then
sudo dnf install -y python3
elif have_cmd yum; then
sudo yum install -y python3
elif have_cmd apt-get; then
sudo apt-get update -y
sudo apt-get install -y python3
else
echo "No supported package manager found to install python3." >&2
exit 1
fi
fi
# 2) Ensure pip exists
if ! have_pip_py; then
python3 -m ensurepip --upgrade >/dev/null 2>&1 || true
fi
if ! have_pip_py; then
if have_cmd dnf; then
sudo dnf install -y python3-pip || true
elif have_cmd yum; then
sudo yum install -y python3-pip || true
elif have_cmd apt-get; then
sudo apt-get update -y || true
sudo apt-get install -y python3-pip || true
fi
fi
if ! have_pip_py; then
curl -fsS https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py
python3 /tmp/get-pip.py
fi
# 3) Upgrade packaging tools and install Ray
python3 -m pip install -U pip setuptools wheel
python3 -m pip install -U "ray[default]"
Voici une brève explication de chaque section YAML critique.
cluster_name: Assigns a name to the cluster, allowing Ray to track and manage
it separately from others.
provider: Specifies which cloud to use (AWS here), along with the region and
availability zone for launching instances.
auth: Defines how Ray connects to instances over SSH - the user name and the
private key used for authentication.
max_workers: Sets the maximum number of worker nodes Ray can scale up to when
more compute is needed.
idle_timeout_minutes: Tells Ray how long to wait before automatically terminating
idle worker nodes.
available_node_types: Describes the different node types (head and workers), their
instance sizes, AMI images, and scaling limits.
head_node_type: Identifies which of the node types acts as the cluster's controller
(the head node).
setup_commands: Lists shell commands that run once on each node when it's first
created, typically to install software or set up the environment.
Pour démarrer la création du cluster, utilisez cette commande ray depuis le terminal.
$ ray up -y ray_test.yaml
Ray fera son travail en créant toute l’infrastructure nécessaire, et après quelques minutes, vous devriez voir quelque chose comme ceci dans la fenêtre de votre terminal.
...
...
...
Next steps
To add another node to this Ray cluster, run
ray start --address='10.0.9.248:6379'
To connect to this Ray cluster:
import ray
ray.init()
To submit a Ray job using the Ray Jobs CLI:
RAY_ADDRESS='http://10.0.9.248:8265' ray job submit --working-dir . -- python my_script.py
See https://docs.ray.io/en/latest/cluster/running-applications/job-submission/index.html
for more information on submitting Ray jobs to the Ray cluster.
To terminate the Ray runtime, run
ray stop
To view the status of the cluster, use
ray status
To monitor and debug Ray, view the dashboard at
10.0.9.248:8265
If connection to the dashboard fails, check your firewall settings and network configuration.
Shared connection to 108.130.38.255 closed.
New status: up-to-date
Useful commands:
To terminate the cluster:
ray down /mnt/c/Users/thoma/ray_test.yaml
To retrieve the IP address of the cluster head:
ray get-head-ip /mnt/c/Users/thoma/ray_test.yaml
To port-forward the cluster's Ray Dashboard to the local machine:
ray dashboard /mnt/c/Users/thoma/ray_test.yaml
To submit a job to the cluster, port-forward the Ray Dashboard in another terminal and run:
ray job submit --address http://localhost:<dashboard-port> --working-dir . -- python my_script.py
To connect to a terminal on the cluster head for debugging:
ray attach /mnt/c/Users/thoma/ray_test.yaml
To monitor autoscaling:
ray exec /mnt/c/Users/thoma/ray_test.yaml 'tail -n 100 -f /tmp/ray/session_latest/logs/monitor*'
Exécuter un travail Ray sur un cluster
A ce stade, le cluster est construit et nous sommes prêts à lui soumettre notre travail Ray. Pour donner au cluster quelque chose de plus substantiel avec lequel travailler, j’ai augmenté la plage de recherche principale dans mon code de 10 000 000 à 20 000 000 à 10 000 000 à 60 000 000. Sur mon bureau local, Ray a exécuté cela en 18 secondes.
J’ai attendu un peu de temps que tous les nœuds du cluster s’initialisent complètement, puis j’ai exécuté le code sur le cluster avec cette commande.
$ ray exec ray_test.yaml 'python3 ~/ray_test.py'
Voici ma sortie.
(base) tom@tpr-desktop:/mnt/c/Users/thoma$ ray exec ray_test2.yaml 'python3 ~/primes_ray.py'
2025-11-01 13:44:22,983 INFO util.py:389 -- setting max workers for head node type to 0
Loaded cached provider configuration
If you experience issues with the cloud provider, try re-running the command with --no-config-cache.
Fetched IP: 52.213.155.130
Warning: Permanently added '52.213.155.130' (ED25519) to the list of known hosts.
2025-11-01 13:44:26,469 INFO worker.py:1832 -- Connecting to existing Ray cluster at address: 10.0.5.86:6379...
2025-11-01 13:44:26,477 INFO worker.py:2003 -- Connected to Ray cluster. View the dashboard at http://10.0.5.86:8265
nodes=6, CPUs~192, chunks=384
(autoscaler +2s) Tip: use `ray status` to view detailed cluster status. To disable these messages, set RAY_SCHEDULER_EVENTS=0.
(autoscaler +2s) No available node types can fulfill resource requests {'CPU': 1.0}*160. Add suitable node types to this cluster to resolve this issue.
total=2897536, time=5.71s
Shared connection to 52.213.155.130 closed.
Comme vous pouvez le constater, le temps d’exécution sur le cluster était d’un peu plus de 5 secondes. Ainsi, cinq nœuds de travail ont exécuté le même travail en moins d’un tiers du temps nécessaire sur mon PC local. Pas trop mal.
Lorsque vous avez terminé avec votre cluster, exécutez la commande Ray suivante pour le supprimer.
$ ray down -y ray_test.yaml
Comme je l’ai mentionné précédemment, vous devez toujours revérifier votre compte pour vous assurer que cette commande a fonctionné comme prévu.
Résumé
Cet article, le deuxième d’une série en deux parties, montre comment exécuter du code Python gourmand en CPU sur des clusters basés sur le cloud à l’aide de la bibliothèque Ray. En répartissant la charge de travail sur tous les processeurs virtuels disponibles, Ray garantit que notre code offre des performances et des durées d’exécution rapides.
J’ai décrit et montré comment créer un cluster à l’aide d’un fichier YAML et comment utiliser l’interface de ligne de commande Ray pour soumettre du code à exécuter sur le cluster.
En utilisant AWS comme exemple de plate-forme, j’ai pris le code Ray Python, qui s’exécutait sur mon PC local et je l’ai exécuté – presque inchangé – sur un cluster EC2 à 6 nœuds. Cela a montré des améliorations significatives des performances (3x) par rapport à la durée d’exécution hors cluster.
Enfin, j’ai montré comment utiliser l’outil de ligne de commande Ray pour détruire l’infrastructure de cluster AWS créée par Ray.
Si vous n’avez pas déjà lu mon premier article de cette série, cliquez sur le lien ci-dessous pour le consulter.
Veuillez noter qu’en plus d’être un utilisateur occasionnel de leurs services, je n’ai aucune affiliation avec AnyScale ou AWS ou toute autre organisation mentionnée dans cet article.



