Instances vs cœurs lors de l'utilisation d'EC2

12

En travaillant sur ce que l'on pourrait souvent appeler des projets de "données moyennes", j'ai pu paralléliser mon code (principalement pour la modélisation et la prédiction en Python) sur un seul système à travers de 4 à 32 cœurs. Maintenant, je cherche à évoluer vers des clusters sur EC2 (probablement avec StarCluster / IPython, mais également ouvert à d'autres suggestions), et j'ai été intrigué par la façon de concilier la distribution du travail entre les cœurs d'une instance et les instances d'un cluster.

Est-il même pratique de paralléliser les instances ainsi que les cœurs sur chaque instance? Dans l'affirmative, quelqu'un peut-il donner un bref aperçu des avantages et inconvénients de l'exécution de nombreuses instances avec peu de cœurs chacune contre quelques instances avec plusieurs cœurs? Existe-t-il une règle de base pour choisir le bon rapport entre les instances et les cœurs par instance?

La bande passante et la RAM sont des préoccupations non triviales dans mes projets, mais il est facile de repérer les goulots d'étranglement et de les réajuster. J'imagine qu'il est beaucoup plus difficile de comparer la bonne combinaison de cœurs à des instances sans tests répétés, et mes projets varient trop pour qu'un seul test s'applique à toutes les circonstances. Merci à l'avance, et si je n'ai pas réussi à google celui-ci correctement, n'hésitez pas à me diriger vers la bonne réponse ailleurs!

Therriault
la source

Réponses:

11

Lorsque vous utilisez IPython, vous n'avez presque pas à vous en soucier (au détriment d'une perte d'efficacité / d'une surcharge de communication accrue). Le plugin IPython parallèle dans StarCluster démarrera par défaut un moteur par cœur physique sur chaque nœud (je crois que c'est configurable mais je ne sais pas où). Vous exécutez simplement ce que vous voulez sur tous les moteurs en utilisant l'API DirectView (map_sync, apply_sync, ...) ou les commandes magiques% px. Si vous utilisez déjà IPython en parallèle sur une machine, son utilisation sur un cluster n'est pas différente.

Répondre à certaines de vos questions spécifiques:

«comment concilier la distribution du travail entre les cœurs d'une instance et les instances d'un cluster» - Vous obtenez un moteur par cœur (au moins); le travail est automatiquement distribué sur tous les cœurs et sur toutes les instances.

"Est-il même pratique de paralléliser les instances ainsi que les cœurs sur chaque instance?" - Oui :) Si le code que vous utilisez est embarrassamment parallèle (exactement le même algo sur plusieurs ensembles de données), vous pouvez surtout ignorer où un moteur particulier est en cours d'exécution. Si le noyau nécessite beaucoup de communication entre les moteurs, vous devez bien sûr le structurer de sorte que les moteurs communiquent principalement avec d'autres moteurs sur la même machine physique; mais ce genre de problème n'est pas idéalement adapté à IPython, je pense.

"Dans l'affirmative, quelqu'un peut-il donner un bref aperçu des avantages et des inconvénients de l'exécution de nombreuses instances avec peu de cœurs chacune contre quelques instances avec de nombreux cœurs? Existe-t-il une règle de base pour choisir le bon rapport entre les instances et les cœurs par instance? " - Utilisez les plus grandes instances c3 pour les problèmes liés au calcul et les plus petites pour les problèmes liés à la bande passante mémoire; pour les problèmes liés à la transmission de messages, utilisez également les instances les plus importantes, mais essayez de partitionner le problème afin que chaque partition s'exécute sur une machine physique et que la plupart des messages transmis se trouvent dans la même partition. Les problèmes qui s'exécuteraient beaucoup plus lentement sur N instances quadruple c3 que sur 2N double c3 sont rares (un exemple artificiel peut exécuter plusieurs filtres simples sur un grand nombre d'images, où vous parcourez toutes les images pour chaque filtre plutôt que tous les filtres pour le même image).

Alex I
la source
1
Je pense que vous devriez noter que pour les processus sur une seule machine, vous pouvez mapper des variables de mémoire avec joblib / Numpy. Vous perdez cette capacité pour les processus sur différentes machines.
gallamine
11

Une règle générale est de ne pas distribuer tant que vous ne le devez pas. Il est généralement plus efficace d'avoir N serveurs d'une certaine capacité que 2N serveurs de la moitié de cette capacité. Une plus grande partie de l'accès aux données sera locale et donc rapide en mémoire et lente sur le réseau.

À un certain moment, la mise à l'échelle d'une machine devient non rentable car le coût des ressources supplémentaires évolue de manière plus que linéaire. Cependant, ce point est toujours incroyablement élevé.

Cependant, sur Amazon en particulier, l'économie de chaque type d'instance peut varier considérablement si vous utilisez des instances de marché au comptant. La tarification par défaut signifie plus ou moins que la même quantité de ressources coûte à peu près la même quel que soit le type d'instance, ce qui peut varier considérablement; les grandes instances peuvent être moins chères que les petites, ou N petites instances peuvent être beaucoup moins chères qu'une grande machine avec des ressources équivalentes.

Une considération massive ici est que le paradigme de calcul peut changer beaucoup lorsque vous passez d'une machine à plusieurs machines. Les compromis induits par la surcharge de communication peuvent vous obliger, par exemple, à adopter un paradigme de données parallèles à l'échelle. Cela signifie un choix différent d'outils et d'algorithme. Par exemple, SGD semble assez différent en mémoire et en Python que sur MapReduce. Il faudrait donc considérer cela avant de paralléliser.

Vous pouvez choisir de répartir le travail sur un cluster, même si un seul nœud et des paradigmes non distribués fonctionnent pour vous, pour plus de fiabilité. Si un seul nœud tombe en panne, vous perdez tout le calcul; un calcul distribué peut potentiellement récupérer et terminer uniquement la partie du calcul qui a été perdue.

Sean Owen
la source
6

Toutes choses étant égales par ailleurs (coût, performances du processeur, etc.), vous pouvez choisir la plus petite instance pouvant contenir tous mes ensembles de données en mémoire et évoluer. De cette façon

  • vous vous assurez de ne pas induire de latences inutiles en raison des communications réseau, et
  • vous avez tendance à maximiser la bande passante mémoire globale disponible pour vos processus.

En supposant que vous exécutez une sorte de schéma de validation croisée pour optimiser certains méta-paramètres de votre modèle, attribuez à chaque cœur une valeur à tester et choisissez autant d'instances que nécessaire pour couvrir tout l'espace des paramètres en aussi peu de tours que vous le souhaitez.

Si vos données ne tiennent pas dans la mémoire d'un système, vous devrez bien sûr les répartir sur plusieurs instances. Ensuite, il s'agit d'équilibrer la latence de la mémoire (mieux avec de nombreuses instances) avec la latence du réseau (mieux avec moins d'instances), mais étant donné la nature d'EC2, je parie que vous préférerez souvent travailler avec peu d'instances volumineuses.

damienfrancois
la source