Si les données ne tiennent pas en mémoire. Méthodes les plus simples


Femelle Aardvark avec cub. Photo: Scotto Bear , CC BY-SA 2.0

Vous écrivez un programme de traitement de données, il passe parfaitement le test sur un petit fichier, mais il se bloque à une charge réelle.

Le problème est insuffisant. Si vous avez 16 gigaoctets de RAM, vous ne pourrez pas y télécharger une centaine de gigaoctets. À un moment donné, le système d'exploitation manquera de mémoire, il ne pourra pas en allouer de nouveau et le programme se bloquera.

Que faire

Eh bien, vous pouvez déployer un cluster Big Data, simplement:

  • Trouvez un cluster d'ordinateurs.
  • Configurez-le en une semaine.
  • Apprenez la nouvelle API et réécrivez votre code.

C'est cher et désagréable. Heureusement, ce n'est souvent pas nécessaire.

Nous avons besoin d'une solution simple et facile: traiter les données sur un seul ordinateur, avec une configuration minimale et une utilisation maximale des bibliothèques déjà connectées. Cela est presque toujours possible à l'aide de méthodes simples, parfois appelées «calculs hors cœur».

Dans cet article, nous discutons:

  • Pourquoi avons-nous besoin de RAM?
  • Le moyen le plus simple de traiter des données qui ne tiennent pas en mémoire est de dépenser un peu d'argent.
  • Trois méthodes logicielles principales pour traiter des quantités excessives de données: compression, blocage et indexation.

Les prochains articles montreront en pratique comment appliquer ces méthodes avec des bibliothèques spécifiques telles que NumPy et Pandas. Mais d'abord, la théorie.

Pourquoi la RAM est-elle nécessaire?


Avant d'entrer dans la discussion des solutions, clarifions pourquoi ce problème existe. Vous pouvez écrire des données dans la mémoire vive (RAM), mais aussi sur le disque dur, alors pourquoi avez-vous besoin de RAM? Un disque est moins cher, il n'a généralement aucun problème de manque d'espace, pourquoi ne pas vous limiter à lire et à écrire sur un disque?

Théoriquement, cela pourrait fonctionner. Mais même les SSD rapides modernes fonctionnent beaucoup, beaucoup plus lentement que la RAM:

  • Lecture à partir du SSD: ~ 16 000 nanosecondes
  • Lecture à partir de la RAM: ~ 100 nanosecondes

Pour des calculs rapides, nous n'avons pas le choix: les données doivent être écrites en RAM, sinon le code ralentira 150 fois.

La solution la plus simple: plus de RAM


La solution la plus simple au problème de manquer de RAM est de dépenser de l'argent. Vous pouvez acheter un ordinateur puissant, un serveur ou louer une machine virtuelle avec beaucoup de mémoire. En novembre 2019, une recherche rapide et une comparaison de prix très brève donnent les options suivantes:

  • Achetez la Thinkpad M720 Tower avec 6 cœurs et 64 Go de RAM pour 1074 $
  • Louez une machine virtuelle dans le cloud avec 64 cœurs et 432 Go de RAM pour 3,62 $ / heure

Ce ne sont que des chiffres après une recherche rapide. Après avoir fait une bonne recherche, vous trouverez sûrement de meilleures offres.

Dépenser un peu d'argent en matériel pour intégrer les données dans la RAM est souvent la solution la moins chère. Après tout, notre temps est cher. Mais parfois, cela ne suffit pas.

Par exemple, si vous effectuez de nombreuses tâches de traitement de données sur une période de temps, le cloud computing peut être une solution naturelle, mais il peut également être coûteux. Dans l'un de nos projets, ces coûts informatiques auraient consommé tous les revenus projetés du produit, y compris les revenus les plus importants nécessaires pour payer mon salaire.

Si l'achat / la location d'une grande quantité de RAM ne résout pas le problème ou n'est pas possible, l'étape suivante consiste à optimiser l'application elle-même afin qu'elle consomme moins de mémoire.

Technique numéro 1. Compression


La compression vous permet de mettre les mêmes données dans moins de mémoire. Il existe deux formes de compression:

  • Sans perte : après compression, exactement les mêmes informations sont enregistrées que dans les données d'origine.
  • Avec perte : les données stockées perdent certains détails, mais idéalement cela n'affecte pas grandement les résultats du calcul.

Pour plus de clarté, il ne s'agit pas de fichiers zip ou gzip lorsque les données sont compressées sur le disque . Pour traiter les données d'un fichier ZIP, vous devez généralement le décompresser, puis charger les fichiers en mémoire. Donc, cela n'aidera pas.

Nous avons besoin d'une compression de la représentation des données en mémoire .

Supposons que vos données ne stockent que deux valeurs possibles, et rien d'autre: "AVAILABLE" et "UNAVAILABLE" . Au lieu de stocker des chaînes de 10 octets ou plus par enregistrement, vous pouvez les enregistrer en tant que valeurs booléennes True ou False , qui sont codées sur un seul octet. Vous pouvez même compresser les informations sur un bit, réduisant ainsi la consommation de mémoire de huit fois.

Technique n ° 2. Division en blocs, chargement des données un bloc à la fois


La fragmentation est utile dans les situations où les données ne doivent pas être chargées en même temps. Au lieu de cela, nous pouvons les charger en plusieurs parties, en traitant un fragment à la fois (ou, comme nous le verrons dans l'article suivant, plusieurs parties en parallèle).

Supposons que vous vouliez trouver le plus gros mot d'un livre. Vous pouvez charger toutes les données en mémoire à la fois:

 largest_word = "" for word in book.get_text().split(): if len(word) > len(largest_word): largest_word = word 

Mais si le livre ne tient pas en mémoire, vous pouvez le charger page par page:

 largest_word = "" for page in book.iterpages(): for word in page.get_text().split(): if len(word) > len(largest_word): largest_word = word 

Cela réduit considérablement la consommation de mémoire car une seule page d'un livre est chargée à la fois. Dans ce cas, le résultat sera la même réponse.

Technique n ° 3. Indexation lorsqu'un seul sous-ensemble de données est requis


L'indexation est utile si vous souhaitez utiliser uniquement un sous-ensemble de données et que vous allez charger différents sous-ensembles à des moments différents.

En principe, dans une telle situation, vous pouvez filtrer la partie nécessaire et éliminer l'inutile. Mais le filtrage est lent et n'est pas optimal, car vous devez d'abord charger beaucoup de données supplémentaires en mémoire avant de les supprimer.

Si vous n'avez besoin que d'une partie des données, au lieu de la fragmentation, il est préférable d'utiliser un index - une compression des données qui indique leur emplacement réel.

Imaginez que vous souhaitez lire uniquement des fragments d'un livre mentionnant aardvark (un mammifère mignon sur la photo au début de l'article). Si vous vérifiez toutes les pages tour à tour, le livre entier sera chargé en parties, page par page, à la recherche de aardvarks - et cela prendra beaucoup de temps.

Ou vous pouvez immédiatement ouvrir l'index alphabétique à la fin du livre - et trouver le mot «aardvark». Il indique que le mot est mentionné aux pages 7, 19 et 120-123. Vous pouvez maintenant lire ces pages, et seulement elles, ce qui est beaucoup plus rapide.

Il s'agit d'une méthode efficace car l'index est beaucoup plus petit que l'ensemble du livre, il est donc beaucoup plus facile de charger uniquement l'index en mémoire pour trouver les données pertinentes.

La méthode d'indexation la plus simple


L'indexation la plus simple et la plus courante consiste à nommer des fichiers dans un répertoire:

 mydata/ 2019-Jan.csv 2019-Feb.csv 2019-Mar.csv 2019-Apr.csv ... 

Si vous avez besoin de données pour mars 2019, il vous suffit de télécharger le fichier 2019-Mar.csv - il n'est pas nécessaire de télécharger les données pour février, juillet ou tout autre mois.

Suivant: appliquer ces méthodes


Le problème du manque de RAM est plus facile à résoudre avec de l'argent, après avoir acheté de la RAM. Mais si cela n'est pas possible ou pas suffisant, vous utiliserez quand même la compression, la fragmentation ou l'indexation.

Les mêmes méthodes sont utilisées dans divers progiciels et outils . Même les systèmes Big Data hautes performances sont construits sur eux: par exemple, le traitement parallèle de fragments de données individuels.

Dans les articles suivants, nous verrons comment appliquer ces méthodes dans des bibliothèques et des outils spécifiques, y compris NumPy et Pandas.

Source: https://habr.com/ru/post/fr479282/


All Articles