web-dev-qa-db-fra.com

Le multithreading peut-il être implémenté sur un système à processeur unique?

J'ai toujours suivi le concept selon lequel le multithreading ne peut être implémenté que sur plusieurs systèmes de processeurs où il y a plus d'un processeur à affecter à chaque thread et chaque thread peut être exécuté simultanément. Il n'y a pas de planification dans ce cas car chaque thread a des ressources distinctes qui lui sont toutes dédiées. Mais je l'ai lu récemment quelque part que je peux également faire du multithreading sur un système à processeur unique. Est-ce correct? et si oui, alors quelle est la différence entre un seul processeur et plusieurs systèmes de processeur?

57
Ayse

Bien sûr, cela peut être fait sur un système à processeur unique, et en fait, c'est beaucoup plus facile de cette façon. Cela fonctionne de la même manière que l'exécution de plusieurs processus - le noyau, via une interruption de minuterie ou un autre mécanisme similaire, en suspend un, en enregistrant son état machine et en le remplaçant par l'état précédemment enregistré d'un autre - la seule différence étant que deux les threads du même processus partagent le même espace de mémoire virtuelle, ce qui rend le changement de tâche beaucoup plus efficace.

Le multi-threading sur les systèmes multi-processeurs est en réalité beaucoup plus difficile, car vous avez des problèmes d'accès simultané à la mémoire à partir de plusieurs cpus/cœurs, et tous les problèmes de synchronisation de mémoire désagréables qui en découlent.

51
R..

Je l'ai lu récemment quelque part que je peux également faire du multithreading sur un système à processeur unique. Est-ce correct? et si oui, quelle est la différence entre un seul processeur et plusieurs systèmes de processeur?

Oui, vous pouvez faire du multithreading sur un système à processeur unique.

Dans un système multiprocesseur, plusieurs threads s'exécutent, simultanément sur différents cœurs. Par exemple, s'il y a deux threads et deux coeurs, alors chaque thread s'exécutera sur un noyau individuel.

Dans un système à processeur unique, plusieurs threads s'exécutent les uns après les autres ou attendent jusqu'à ce qu'un thread se termine ou soit préempté par le système d'exploitation, en fonction de la priorité du thread et de la stratégie du système d'exploitation, mais les threads en cours d'exécution donnent l'illusion qu'ils s'exécutent simultanément , par rapport au temps de réponse d'application requis de l'application Espace utilisateur.

Comparaison de temps (exemple):

si deux threads prennent 10us chacun pour s'exécuter, alors sur un système à 2 processeurs, le temps net nécessaire est de 10us

si deux threads prennent 10us chacun pour s'exécuter, alors sur un système à 1 processeur, le temps net nécessaire est de 20us

54
Barath Ravikumar

Vous pouvez avoir plus de quatre threads actifs sur un système quad core. Il y a est planification, sauf si vous pouvez garantir que les processus n'essaieront pas de créer plus de threads que de processeurs.

Oui, vous pouvez avoir plusieurs threads sur un ordinateur monocœur.

La différence entre les systèmes à processeur unique et multiprocesseurs est qu'un système multiprocesseur peut en effet faire plus d'une chose à la fois. Il peut faire N choses à la fois, où N est le nombre de cœurs de processeur. Un cœur à processeur unique ne peut faire qu'une seule chose à la fois. Comme l'a dit WhozCraig dans son commentaire, c'est la différence entre la concurrence réelle et perçue.

7
Jim Mischel

Voici un exemple très simplifié. Il s'agit en fait d'un prototype de programme que je construis. Il s'agit d'une implémentation du multitâche coopératif dans un seul thread.

main définit simplement le drapeau quit sur false, remplit un tableau de pointeurs de fonction (les tâches), puis appelle loop.

loop utilise setjmp pour définir un point de retour pour un saut non local (un saut out de la fonction vers un emplacement précédent dans l'exécution) puis procède pour appeler la première tâche (fonction).

Chaque tâche se termine par yield(). Autrement dit, aucune des fonctions de tâche n'est réellement return. Non seulement ils ne contiennent pas de return; (ce qui serait bien car ce sont des fonctions void, c'est-à-dire des procédures), mais elles n'atteindraient pas la return même si elle était là car yield saute de retour à l'appel setjmp, cette fois donnant un 1 à l'instruction if dans loop. L'instruction contrôlée par l'instruction if sélectionne une tâche différente avant de ressaisir la boucle while.

Ainsi, chaque fonction de tâche s'exécute plusieurs fois, ce qui donne le répartiteur (le if(setjmp... instruction) qui sélectionne une nouvelle tâche à exécuter.

#include <stdio.h> 
#include <setjmp.h> 

jmp_buf dispatch; 
int ntasks; 
void (*task[10])(void); 
int quit; 

void yield(void) { 
    longjmp(dispatch, 1); 
} 

void loop() { 
    static int i = 0; 
    if(setjmp(dispatch)) 
        i = (i+1) % ntasks; 
    while(!quit) 
        task[i](); 
} 

int acc = 0; 

void a(void) { 
    if (acc > 10) quit = 1; 
    printf("A\n"); 
    yield(); 
} 
void b(void) { 
    acc *= 2; 
    printf("B\n"); 
    yield(); 
} 
void c(void) { 
    acc += 1; 
    printf("C\n"); 
    yield(); 
} 

int main() { 
    quit = 0; 
    ntasks = 3; 
    task[0] = a; 
    task[1] = b; 
    task[2] = c; 
    loop(); 
    return 0; 
} 

La différence entre cet exemple et un système informatique multitâche à processeur unique est que le véritable processeur prend en charge l'interruption d'une tâche en cours d'exécution et sa reprise plus tard à partir du même endroit. Ce n'est pas vraiment possible dans une simulation C avec des tâches en tant que fonctions uniques. Cependant, les tâches pourraient être composées d'une séquence de fonctions C qui cèdent chacune au répartiteur (un tableau de pointeurs de fonction, peut-être, ou une liste chaînée).

5
luser droog

Oui, c'est tout à fait possible. Il y a un certain temps (Win 95?), Nous sommes passés du multitâche coopératif au multithreading, parce que quelqu'un a toujours foiré la partie coopérative. Chaque programme sur votre ordinateur a au moins un thread. Peut-être plus. Et le CPU continue de basculer entre tous ces threads comme des fous quelques millions de fois par seconde. Si aucun d'entre eux n'a rien à faire, cela pourrait même rester inactif pendant un certain temps.

Les systèmes multicœurs signifient uniquement que deux ou plusieurs de ces threads peuvent s'exécuter en parallèle.

Cependant, cela vous en apporte beaucoup moins. Tout ce que vous pouvez faire avec le multithreading sur une machine monocœur est de simuler le multitâche.

Le multitâche suffit pour empêcher le thread GUI de se bloquer en raison d'une opération de longue durée. Cependant, il est généralement compliqué à implémenter, à moins que vous n'ayez de l'aide du compilateur ou de Langauge (comme C # async ... attendez). En conséquence, de nombreux programmeurs GUI ont simplement utilisé le multithreading et l'invocation pour simuler le multitâche. Si ce code s'exécute sur un ou plusieurs cœurs, cela n'a pas d'importance.

Plus important encore, le multitâche n'est PAS adapté aux opérations liées au processeur. Mais 95% de tous les problèmes Async ne sont pas liés au CPU. Ils sont liés au réseau ou au disque. Sur un ordinateur monocœur, le multithreading n'aide pas non plus avec les éléments liés au processeur. Si vous avez deux threads qui nécessitent tous les deux 100% de temps CPU (même programme ou un autre) mais un seul cœur pour les exécuter, le CPU devra simplement basculer entre les deux à 49% et utiliser les 2% restants pour tous ceux d'autres threads qui ne font qu'un petit peu.

Enfin, très peu de problèmes peuvent réellement être multithread. Essayez simplement de multithreader la séquence de Fibonacci (un thread pour chaque paire) sans la rendre plus lente, plus gourmande en mémoire et plus complexe.

tl; dr; Vous avez besoin du multithreading et d'un ordinateur multicœur pour les problèmes liés au processeur. La plupart des problèmes asynchrones ne sont pas liés au processeur. Le multitâche est bien suffisant. Et vous pouvez totalement effectuer plusieurs tâches à l'aide de threads, même sur une seule machine.

3
Christopher