Vous voyez cette phrase ou similaire lancée de temps en temps, se référant généralement à un programme qui prétend qu'ils n'ont pas été conçus pour tirer pleinement parti des processeurs multicœurs. Ceci est courant en particulier avec la programmation de jeux vidéo. (bien sûr, de nombreux programmes n'ont pas de simultanéité et n'en ont pas besoin, comme les scripts de base, etc.).
Comment se peut-il? De nombreux programmes (en particulier les jeux) utilisent intrinsèquement la concurrence, et puisque le système d'exploitation est en charge de la planification des tâches sur le CPU, ces programmes ne tirent-ils pas intrinsèquement parti des multiples cœurs disponibles? Que signifierait dans ce contexte "profiter de plusieurs cœurs"? Ces développeurs interdisent-ils réellement la planification des tâches du système d'exploitation et forcent-ils l'affinité ou leur propre planification? (Cela ressemble à un problème majeur de stabilité).
Je suis un programmeur Java, alors peut-être que je n'ai pas eu à faire face à cela en raison d'abstractions ou de tout ça.
la source
Réponses:
Une bonne concurrence nécessite beaucoup plus que de jeter quelques fils dans une application et d'espérer le meilleur. Il existe une gamme dans la façon dont un programme peut passer simultanément d'un parallèle embarrassant à un séquentiel pur. Tout programme donné peut utiliser la loi d' Amdahl pour exprimer à quel point un problème ou un algorithme est évolutif. Quelques qualifications pour une candidature parallèle embarrassante seraient:
Il existe d'autres qualifications, mais avec seulement ces deux, nous pouvons comprendre pourquoi les jeux en particulier ne sont pas aussi faciles que vous pourriez penser pour tirer parti de plusieurs cœurs. D'une part, le modèle du monde qui sera rendu doit être partagé car différentes fonctions calculent la physique, le mouvement, appliquent l'intelligence artificielle, etc. Deuxièmement, chaque image de ce modèle de jeu doit être rendue à l'écran avec une carte graphique.
Pour être juste, de nombreux fabricants de jeux utilisent des moteurs de jeux produits par des tiers. Cela a pris du temps, mais ces moteurs de jeux tiers sont maintenant beaucoup plus parallèles qu'auparavant.
Il existe de plus grands défis architecturaux pour gérer une concurrence efficace
La concurrence peut prendre plusieurs formes, de l'exécution de tâches en arrière-plan à une prise en charge architecturale complète de la concurrence. Certaines langues vous offrent des fonctionnalités de concurrence très puissantes telles que ERLANG , mais cela vous oblige à penser très différemment à la façon dont vous construisez votre application.
Tous les programmes n'ont pas vraiment besoin de la complexité d'un support multicœur complet. Un tel exemple est le logiciel d'impôt, ou toute application pilotée par formulaire. Lorsque la plupart de votre temps est consacré à attendre que l'utilisateur fasse quelque chose, la complexité des applications multithreads n'est tout simplement pas très utile.
Certaines applications se prêtent à une solution parallèle plus embarrassante, comme les applications Web. Dans ce cas, la plate-forme démarre de manière embarrassante en parallèle et c'est à vous de ne pas avoir à imposer de conflit de thread.
En bout de ligne:
Toutes les applications ne sont pas vraiment blessées en ne profitant pas de plusieurs threads (et donc des cœurs). Pour ceux qui en souffrent, parfois les calculs ne sont pas adaptés au traitement parallèle ou le surcoût pour le coordonner rendrait l'application plus fragile. Malheureusement, le traitement parallèle n'est toujours pas aussi facile qu'il devrait l'être pour bien faire.
la source
Non, en fait c'est l'inverse. La plupart des applications sont écrites dans un seul état d'esprit, et le ou les développeurs n'ont jamais apporté les modifications nécessaires pour prendre en charge la concurrence.
En C, C ++ et C #, vous devez indiquer explicitement à l'application de démarrer de nouveaux threads et / ou processus.
Je pense que vous vous concentrez trop sur la planification des threads et pas assez sur la gestion des données dans les threads potentiels. Le partage de données entre des threads et / ou des processus nécessite une certaine forme de synchronisation. Si vous modifiez une application pour utiliser plusieurs threads mais que cette synchronisation n'est pas en place, vous verrez probablement beaucoup de difficultés à détecter les bogues dans le code.
Pour les applications multi-thread sur lesquelles j'ai travaillé, je ne me suis généralement jamais soucié de la répartition et seulement de la synchronisation des données. Les seules fois où je devais me soucier de la répartition, c'était lorsque je cherchais les conditions de course en raison d'une mauvaise synchronisation des données.
Généralement, lorsqu'une application dit qu'elle ne peut pas utiliser plusieurs cœurs, cela signifie qu'elle n'a pas la synchronisation en place pour protéger la manipulation des données.
la source
Il ne s'agit pas tant de plusieurs cœurs que de plusieurs threads. Le système d'exploitation peut planifier l'exécution d'un thread sur le cœur qu'il souhaite, et cette planification est transparente pour le programme en cours de planification. Cependant, de nombreux programmes ne sont pas écrits à l'aide de plusieurs threads, ils ne peuvent donc s'exécuter que sur un seul cœur à la fois.
Pourquoi devrais-je écrire un programme monothread? Ils sont plus faciles à écrire et à déboguer: une chose se produit après l'autre (au lieu de plusieurs choses se produisant à la fois et pouvant se gêner mutuellement). Ou votre programme ne cible peut-être pas les machines multicœurs (comme c'était le cas avec les anciens jeux). Dans certains cas, un programme multithread peut même fonctionner plus lentement qu'une version monothread si la surcharge des commutateurs de contexte et de la communication entre les threads l'emporte sur la vitesse gagnée par l'exécution parallèle (certaines parties du programme peuvent ne pas être parallélisables).
la source
Ce n'est pas une réponse complète. C'est un récit édifiant.
Un jour, j'ai pensé montrer aux étudiants de mon cours de programmation concurrente un tri rapide parallèle. Quicksort devrait bien paralléliser, je pensais. J'ai utilisé deux fils. Je l'ai exécuté sur mon ordinateur monocœur. Les résultats ont été:
C'était à peu près ce à quoi je m'attendais.
Ensuite, je l'ai essayé sur une machine dual-core plus récente.
Les deux threads partageaient une file d'attente des tâches restantes. Il semble que les champs de l'objet de file d'attente soient mélangés d'avant en arrière entre le cache d'un cœur et celui de l'autre.
la source