2017-02-20 1 views
0

Je souhaite optimiser mon code séquentiel pour créer un dégradé.pourquoi utiliser plus de 2 threads consomment plus de temps?

Le dégradé de calcul principal pour la bordure de l'image et les autres threads calculent chacun le dégradé pour un fragment de l'image, en utilisant 2 threads et le thread principal donne un résultat meilleur que le code séquentiel mais en utilisant plus de 2 threads, mais il consomme de plus et semble pire que le séquentiel.

J'ai essayé ce code pour accélérer le processus gradient:

for (int n = 0; n<iter_outer; n++) 
     { 
      int chunk = 1 + ((row - 1)/num_threads); //ceiling 
      int start=0; 
      int end=0; 
      //Launch a group of threads 
      for (int tid = 0; tid < num_threads; ++tid) 
      { 
       start = tid * chunk; 
       end = start + chunk; 
       t[tid] = thread(gradient, tid, g, vx, vy, row, col, 1, start, end); 

      } 
      //Launched from the main; 
      gradient(1, g, vx, vy, row, col,0, start, end); 
      //Join the threads with the main thread 
      for (int i = 0; i < num_threads; ++i) 
      { 
       t[i].join(); 

      } 

     } 
+1

Combien de noyaux votre machine a-t-elle? Peut-être 2? – NathanOliver

+0

Chaque fois que vous passez d'un thread à l'autre, vous avez besoin de temps pour configurer le nouveau contexte. –

+8

Pour les threads à exécution courte, il y a un point où le temps de création d'un thread (et la commutation entre les contextes) annule le gain de vitesse dû à plusieurs threads. Je soupçonne que votre image est trop petite. –

Répondre

-7

Il semble que votre processeur est dual-core. Donc, en réalité, seulement 2 tâches peuvent être effectuées en parallèle

+4

Complet faux guesstimate. En plus d'un processeur dual-core capable d'exécuter plus de 2 tâches en parallèle (par exemple, Hyper-Threading), le coût réel est probablement la création de threads. Cela devrait être un commentaire au mieux. – IInspectable

+0

ma machine est le noyau i7 –

-1

L'exécution parallèle est un énorme avantage pour les tâches qui sont facilement divisibles et les threads ne dépendront pas d'eux-mêmes, mais la création de threads a un prix. Imaginons qu'un ordinateur ne fasse rien d'autre que d'exécuter votre programme (il n'y a pas d'OS et pas d'autres processus). Le processeur a 2 cœurs, ils sont des processeurs à leur propre compte et peuvent exécuter simultanément n'importe quel code. Dans le cas d'un seul thread, le second noyau est assis et ne fait absolument rien, d'où un potentiel d'accélération. Si vous lancez le second thread (et lui donnez 50% de la tâche), le deuxième noyau fonctionne également et théoriquement l'accélération est de 2 (en ignorant les parties séquentielles et les aspects pratiques). Maintenant, faisons 4 threads. Attendez ... nous avons deux processeurs et 4 threads? Oui, maintenant chaque CPU fait plus d'une chose et avant de changer la tâche sur laquelle elle travaille, le CPU doit changer de contexte (changer les valeurs des registres pour conserver les valeurs de variables appropriées, aller à une section de code différente etc.). Si vous créez trop de threads, cela prendra plus de temps que de faire le travail. Cela peut avoir un impact énorme sur n'importe quelle application threadée et doit être noté avant de décider du nombre de threads à exécuter. Notez que ce poste est aussi simple que de nombreux processeurs modernes peuvent fonctionner efficacement plus d'un thread par cœur (c'est-à-dire HyperThreading).

+0

HyperThreading ne signifie pas qu'un CPU moderne peut efficacement exécuter plus d'un thread par core; seulement qu'ils peuvent exécuter plus d'un thread par cœur à la fois. HyperThreading ne gagne qu'environ 15% de performance ou moins - beaucoup moins qu'un nouveau core - mais plus de zéro. Il est également plus compliqué car de nombreux processeurs multi-cœurs modernes fonctionnent plus rapidement si un seul cœur fonctionne, car il y a moins de risque de surchauffe. –

4

Pour toute exécution parallèle, vous devez prendre en compte Amdahl's law. Il précise que le temps nécessaire pour faire une tâche en parallèle n'échelle pas linéaire avec le nombre de processeurs:

t = ((1-p) + p/n) * T 

T is the time needed for the task when it is done sequentially 
p fraction of time that can be parallelized 
n is the number of processors 

Notez que j'ai utilisé une formulation légèrement différente, mais la déclaration est le même: L'accélération totale que vous obtenez est limitée par 1/(1-p) (par exemple si p=50% votre version parallèle fonctionnera au maximum deux fois plus vite).

En plus de cela, vous devez considérer que l'ajout de parallélisme dans la réalité ajoute également plus de frais généraux (pour la synchronisation, la mise en place des fils, etc), donc une estimation plus réaliste est:

t = ((1-p) + p/n) * T + o*p 
          ^^ overhead 

Ce t comme une fonction du nombre de processeurs p a un minimum pour un certain nombre de processeurs. Ajouter plus de processeurs au problème n'entraînera pas une accélération, mais plutôt un ralentissement, car le temps minimum nécessaire pour faire cette partie est zéro, mais le temps supplémentaire que vous ajoutez en ajoutant plus de processeurs augmente sans limite.Cela n'explique pas pourquoi vous n'obtenez pas d'accélération dans votre cas, mais en général ce n'est pas une grande surprise que d'ajouter simplement plus de processeurs à une tâche n'entraîne pas toujours une accélération.

+0

tout d'abord merci pour votre réponse. J'ai essayé d'accélérer ce code en utilisant cuda et gpu et le résultat est correct et accélère très bien et utilisé beaucoup de threads atteint 256, donc je pense qu'il est bon d'être parralélisé. mais en utilisant des threads sur cpu plus de 2 threads comme 3 ou 4 est pire que séquentiel! donc je demande, est-il normal d'être parrallélisé sur GPU, mais pas bon sur multithreading de CPU? et pourquoi? Si vous avez un exemple, ce serait génial. –

+0

@islamgad Je n'ai aucune expérience avec cuda. S'il vous plaît noter que ma réponse ne décrit que les bases et les détails peuvent être beaucoup plus impliqués. Par exemple, lorsque vous avez une communication entre les processeurs, la surcharge peut être aussi mauvaise que 'p * (p-1)'. En outre, il se peut que votre taille de problème soit trop petite pour être distribuée efficacement. Les threads en attente d'autres peuvent significativement décourager votre accélération. Cependant, la seule façon fiable de comprendre ce qui se passe est de mesurer. – user463035818

+0

Merci pour votre soutien. –