[RUBY] Comment utiliser le multicœur du point de vue de plusieurs langues

Comment utiliser le multicœur du point de vue de plusieurs langues

introduction

Ces dernières années, le multi-cœur avec plusieurs cœurs montés sur un seul processeur est devenu courant. Cependant, avec le langage de programmation actuel, il est difficile pour les ingénieurs de créer des programmes multicœurs sans en être conscients. Par conséquent, je vais vous expliquer comment utiliser le multicœur à partir de différentes langues.

Processus et threads

Un processus est un programme en cours d'exécution tel qu'une application, et un thread est une unité d'utilisation du processeur. Un processus a un ou plusieurs threads comme indiqué ci-dessous et peut traiter autant de threads que de cœurs de processeur. (Ces dernières années, [SMT](https://ja.wikipedia.org/wiki/%E5%90%8C%E6%99%82%E3%83%9E%E3%83%AB%E3%83% 81% E3% 82% B9% E3% 83% AC% E3% 83% 83% E3% 83% 87% E3% 82% A3% E3% 83% B3% E3% 82% B0) Le noyau peut gérer plusieurs threads, comme 2 threads. C'est comme 2 noyaux et 4 threads.) スレッドとプロセス.png スレッドとプロセスとCPU.png Afin d'utiliser efficacement le multicœur et d'exécuter un programme, il est nécessaire de générer un nombre approprié de threads côté programme pour le nombre de cœurs pouvant être traités par la CPU. Il est possible de créer plus de threads que le nombre de cœurs, mais le processeur ne peut traiter autant de threads qu'il y a de cœurs, et il existe un problème de ralentissement du traitement en raison du changement de thread à exécuter.

Parallèle et parallèle

Il existe des termes similaires, parallèles et concurrents, mais ils sont différents. Parallèle est un cas où plusieurs processus sont traités en même temps et plusieurs threads sont traités par plusieurs cœurs. (Plusieurs processus ne peuvent pas être exécutés en même temps avec un seul cœur, donc le parallèle ne peut pas être réalisé.) 並列.png Concurrent signifie que plusieurs processus sont commutés et exécutés en même temps, de sorte qu'un thread peut basculer et exécuter plusieurs processus. 並行.png Puisqu'il est possible d'exécuter tout en commutant le traitement en plusieurs threads, il est également possible de réaliser des parallèles et des parallèles.

Problème C10K

Apache, un serveur Web, utilise une méthode pour générer un processus pour chaque requête utilisateur, et lorsque le nombre de clients atteint environ 10 000, les performances de réponse diminuent considérablement même si les performances matérielles du serveur Web ont une marge. Un problème est survenu avec le C10K. (La cause spécifique du problème C10K était facile à comprendre dans cet article.) Par conséquent, dans nginx et Node.js, nous avons essayé de résoudre le problème C10K en traitant en parallèle en traitant les E / S asynchrones avec un seul thread.

Node.js Comme mentionné ci-dessus, Node.js fonctionne dans un seul thread, et l'approche consiste à effectuer un traitement en parallèle avec un traitement asynchrone tel que async / await. Comme le montre la figure ci-dessous, l'image est telle que lors de l'accès à une API externe, un autre traitement est effectué jusqu'à ce que le résultat soit renvoyé, et lorsque le résultat est obtenu, le traitement se poursuit. (Pour plus de détails, cet article était facile à comprendre.) 非同期.png Par conséquent, lors de l'exécution d'un traitement asynchrone standard, il n'est pas possible de faire ressortir les performances du multicœur. Par conséquent, dans Node.js, utilisez Cluster pour créer plusieurs processus (https://postd.cc/setting-up-a-node-js). Vous devez soit -cluster /), soit créer plusieurs threads à l'aide de worker_threads. Pour utiliser le cœur multicœur de cette manière, il est nécessaire de créer plusieurs processus ou threads du côté programme, et en multi-thread, vous pouvez partager la valeur des variables, mais en multi-processus, l'espace mémoire est séparé. [Avantages et inconvénients] de ne pas pouvoir partager la valeur des variables (https://stackoverflow.com/questions/56656498/how-is-cluster-and-worker-threads-work-in-node-js) Existe.

GIL qui se produit en Ruby et Python

Dans Node.js, j'ai pu profiter du multicœur en créant plusieurs processus ou threads. Cependant, dans Ruby et Python, [Global Interpolator Lock (GIL)](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AD%E3%83%BC%E3%83% 90% E3% 83% AB% E3% 82% A4% E3% 83% B3% E3% 82% BF% E3% 83% 97% E3% 83% AA% E3% 82% BF% E3% 83% AD% Il y a quelque chose appelé E3% 83% 83% E3% 82% AF), et même si vous créez plusieurs threads, ils ne peuvent pas être exécutés en parallèle. (Pour être exact, c'est le cas de CPython et CRuby implémentés en langage C, mais il est omis ici.) Par conséquent, si vous essayez de tirer parti du multi-cœur dans ces langages, cela ne peut pas être réalisé par le multi-threading et vous devez créer plusieurs processus.

Goroutine en langue Go

Dans le langage Go, le traitement asynchrone est réalisé en parallèle et en parallèle en utilisant quelque chose appelé goroutine, et par défaut le nombre de cœurs de processeur est défini sur GOMAX PROCS. Autant de threads que cette valeur sont préparés, et la goroutine de thread léger est exécutée dans les threads. La figure ci-dessous est une image lorsque le nombre de cœurs de processeur est de 4 et GOMAX PROCS = 4. goroutine.png En utilisant goroutine de cette manière, vous pouvez exécuter des programmes en parallèle et en parallèle en tirant parti du multi-core. (Pour la raison pour laquelle la goroutine est légère, cet article était facile à comprendre.)

Asynchroniser / attendre dans Rust

Dans Rust, le traitement asynchrone peut être effectué en utilisant async / await. À ce stade, vous pouvez sélectionner la méthode d'allocation d'exécution pour les threads de traitement asynchrones en fonction du runtime utilisé. Un runtime populaire est tokio. Dans tokio, les threads sont créés pour le nombre de cœurs et le traitement asynchrone est passé à ces threads, ce qui est similaire à la façon dont goroutine utilise le multi-core. (Pour les autres méthodes d'allocation et le traitement asynchrone dans Rust, cet article était facile à comprendre. Surtout [À propos du modèle d'exécution ici](https://tech-blog.optim.co.jp/entry/2019/11/08/163000#%E5%AE%9F%E8%A1%8C%E3%83% A2% E3% 83% 87% E3% 83% AB) est facile à comprendre.)

enfin

En Ruby et Python, il est difficile de le rendre multi-thread en raison du mécanisme, et le traitement asynchrone de Node.js ne pouvait pas utiliser le multi-core tel quel. Cependant, dans le langage Go et Rust, qui sont populaires ces dernières années, en appelant le traitement asynchrone, le traitement parallèle et parallèle peut être effectué sans que l'ingénieur en soit conscient, et le multi-cœur peut être utilisé. Il est compréhensible que le langage Go et Rust soient populaires à l'ère actuelle, lorsque les processeurs multicœurs sont devenus monnaie courante.

référence

[Illustration] Différences entre les cœurs de processeur, les threads et les processus, les commutateurs de contexte et le multi-threading Se rapprocher de la compréhension complète asynchrone Unity en connaissant la différence entre les processus, les threads et les tâches J'ai étudié les E / S asynchrones de Node.js Node.js je n'entends plus J'ai étudié GIL que vous devriez savoir si vous effectuez un traitement parallèle avec Python Pourquoi la goroutine est légère [Programmation asynchrone principale de Rust](https://tech-blog.optim.co.jp/entry/2019/11/08/163000#%E3%83%A9%E3%83%B3%E3%82 % BF% E3% 82% A4% E3% 83% A0% E3% 81% A7% E9% 9D% 9E% E5% 90% 8C% E6% 9C% 9F% E3% 82% BF% E3% 82% B9 % E3% 82% AF% E3% 82% 92% E8% B5% B7% E5% 8B% 95% E3% 81% 99% E3% 82% 8B)

Recommended Posts

Comment utiliser le multicœur du point de vue de plusieurs langues
[Pepper] Comment l'utiliser?
Comment découper un bloc de plusieurs tableaux à partir d'un multiple en Python
Comment utiliser SWIG de WAF
Comment lancer Explorer à partir de WSL
Comment accéder à wikipedia depuis python
Comment convertir .mgz en .nii.gz
Comment créer un clone depuis Github
Comment titrer plusieurs figures avec matplotlib
Comment convertir facilement le format de Markdown
Comment mettre à jour Google Sheets à partir de Python
[TF] Comment utiliser Tensorboard de Keras
Comment accéder à RDS depuis Lambda (python)
Comment faire fonctionner Linux depuis la console
Comment créer un référentiel à partir d'un média
Comment accéder à la banque de données de l'extérieur
Comment attribuer plusieurs valeurs à la barre de couleurs Matplotlib
Je souhaite me connecter à PostgreSQL à partir de plusieurs langues
Comment ouvrir un navigateur Web à partir de python
Comment faire un traitement parallèle multicœur avec python
Comment créer un objet fonction à partir d'une chaîne
Comment obtenir les résultats de l'identifiant dans Celery
[Python] Comment lire les données de CIFAR-10 et CIFAR-100
Comment générer un objet Python à partir de JSON
Somme de 1 à 10
Comment appeler l'API Cloud à partir de GCP Cloud Functions
Comment faire fonctionner Linux depuis l'extérieur Procédure
Comment bien gérer les commandes Linux à partir de Python
Comment extraire le coefficient de la formule minute
Comment mesurer la vitesse de la ligne depuis le terminal
Comment Git GSR à partir de Jupyter Lab de GCP
[Astuces Python] Comment récupérer plusieurs clés avec la valeur maximale du dictionnaire
Apprenez à gonfler des images à partir du code TensorFlow
[Java] Comment basculer entre plusieurs versions de Java
Comment cloner un référentiel distant Github depuis Atom
Comment renvoyer plusieurs index avec la méthode d'index
[Python] Comment supprimer les valeurs en double de la liste
Comment créer un article à partir de la ligne de commande
Comment "mettre en cache" l'accès à la mémoire FPGA à partir de Linux
Comment obtenir plusieurs objets de modèle au hasard dans Django
Comment utiliser Keras ~ De la simple génération de modèle à CNN ~
Comment écrire une concaténation de chaînes sur plusieurs lignes en Python
Comment récupérer des données d'image de Flickr avec Python
Comment utiliser le stockage Azure Table de Django (PTVS)
Backtrader Comment importer un indicateur depuis un autre fichier
Comment afficher plusieurs images d'une galaxie en tuiles
Comment lancer instantanément Jupyter Notebook à partir du terminal
Comment télécharger des fichiers depuis Selenium of Python dans Chrome
Comment modifier le répertoire statique par défaut dans Flask
Exécuter la fonction Python à partir de Powershell (comment passer des arguments)
Comment récupérer plusieurs tableaux à l'aide de slice en python.
Comment publier un ticket depuis l'API Shogun
Comment prendre une image capturée à partir d'une vidéo (OpenCV)
[Python] Comment appeler une fonction de c depuis python (édition ctypes)
Résumé de la façon de partager l'état avec plusieurs fonctions
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Grattage 2 Comment gratter