Différence entre les calculs

Différence entre les calculs - C++ - Programmation

Marsh Posté le 19-12-2012 à 08:29:42    

Bonjour à tous,
 
Je pensais à OCCT dernièrement, et je me demandais comment il arrivais à faire chauffer autant le cpu.
Je me suis amusé à essayer de créer un programme qui fait chauffer pour voir si je pouvais atteindre la même température, et du coup je me demande si certains calculs font chauffer le cpu plus que d'autres.
 
J'ai fais un programme qui calcule le nombre de threads et lance un calcul par thread dispo, j'ai essayé en mettant comme calcul un truc bête à base des 4 opérateurs (par exemple int i = 125 + 48 / 79 * 45) en boucle infinie, et j'ai essayé un truc plus élaboré à base de sin, cos, log, rand et plusieurs conditions, en me disant que si le processeur ne peux "prévoir" la suite du programme il chauffera plus (oui bon on peut s'imagine des choses :o).
 
Il m'a semblé que la chauffe entre les deux était la même.
 
Du coup comment faire, faire des calculs en cache ? Ou autre ? Je n'ai aucune idée de ce qui fait chauffer les cpu :)
 
Merci pour vos éclaircissements  :jap:


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 19-12-2012 à 08:29:42   

Reply

Marsh Posté le 19-12-2012 à 12:02:58    

Ben là, AMHA le compilo optimise direct, s'il n'y a que ça dans ta boucle c'est possible qu'il la vire et qu'il fasse le calcul (ça n'invoque aucune variable ton calcul de i) avant de compiler.
 
Et tu cherches à faire quoi au juste ?


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 19-12-2012 à 18:57:02    

Rien de spécial, je cherchais juste à voir si il y avait certains calculs qui font plus chauffer le processeur, curiosité simple ^^

 

Après j'ai juste fait un petit programme multithreads pour voir la différence de température atteinte.

 

J'ai lu un truc sur les caches, si les données à utiliser ne sont pas stockées dans le cache, il va chercher dans la RAM et pendant ce temps le processeur ne fait rien. Du coup si on veut chauffer il faudrait utiliser seulement le cache non ?


Message édité par Ganon551 le 19-12-2012 à 19:00:21

---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 19-12-2012 à 19:18:09    

Bah, il faudrait déjà savoir ce qui fait chauffer le plus ton CPU, si faire des transferts entre cache et registres a un impact et ce genre de subtilités.
 
Si ton CPU est hyperthreadé, tu voudras sans doute avoir deux threads par core qui font des traitements sur des unités différentes (genre un qui fait des calculs entiers et l'autre du SSE)
 
Normalement, si tu travailles sur des données aléatoires (à coup de random, donc), tu dois effectivement pouvoir te débrouiller pour que ton compilo n'optimise pas tes calculs. Evite simplement les calculs sur constantes et les expressions simplifiables mathématiquement.


---------------
last.fm
Reply

Marsh Posté le 19-12-2012 à 22:18:13    

Comment fais-tu des transferts entre registre et cache en pratique ?

 

En fait mon calcul comporte au début un rand(), et après je traite le rand avec une condition, si le rand est inférieur à 5000 (par exemple), il fait un calcul, si il est supérieur à 5000 il en fait un autre.

 

Mon calcul utilise ensuite un nombre qu'on appellera 'e', qui est un rand. Suite à ça j'ouvre une boucle infinie et je traite le 'e' en condition, selon les valeurs qu'il prend je lui applique une série de sin(cos(log())) et j'intervertis les cos sin et log selon la condition.

 

Maintenant je ne sais pas si les opérations sont simplifiables, qu'entends tu par là ?

 

Dans le cas actuel des choses il me semble difficile pour le processeur de prévoir la suite du calcul et donc d'optimiser.

 


EDIT : Bon j'ai ajoutéune boucle infinie de calculs SSE. Je crée un array de floats d'une taille de 100 000, je le remplis en utilisant cos et sin selon un pattern conditionnel qui se base sur un rand, donc difficile à prévoir. Une fois le tableau crée je fais 3 opérations (_mm_mul_ps, _mm_add_ps et _mm_sqrt_ps) sur les membres du tableau, puis on recommence le tout.

 

Du coup ça chauffe un peu plus, en 30s je passe de 47° à 74°, contre 70° avant.


Message édité par Ganon551 le 20-12-2012 à 02:50:17

---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 20-12-2012 à 13:28:36    

Evite les conditions : si ton processeur se vautre dans la prédiction, ca va faire un stall et c'est pas garanti que pendant le flush du piepline, y'aie pas quelques unités qui se tournent les pouces.


---------------
last.fm
Reply

Marsh Posté le 20-12-2012 à 20:38:20    

Ah ok, je vais essayer sans conditions alors, merci.


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 20-12-2012 à 21:20:35    

Cela dit, en y pensant, peut-être que l'unité de branchement va plus faire chauffer ...
Bref, y'a pas de réponse parfaite, et pire : probablement que la méthode qui fait le plus chauffer un processeur d'une marque et génération donnée n'est pas celle qui fera le plus chauffer un processeur d'une autre marque ou d'une autre génération.


---------------
last.fm
Reply

Marsh Posté le 20-12-2012 à 23:24:34    

J'ai essayé sans les conditions mais ca ne faisait pas plus chauffer. En revanche j'ai imbriqué trois boucles par thread et il chauffe bien avec ça. Les instructions SSE font bien chauffer.


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 21-12-2012 à 01:42:56    

Et donc, tu as essayé avec un thread sur deux qui fait du calcul sur entier et l'autre qui fait du calcul en sse ? Ce sont des unités indépendantes. Si tu as un Core i3 ou Core i7, tu peux essayer avec 4 ou 8 threads avec cette répartition de tâches.


---------------
last.fm
Reply

Marsh Posté le 21-12-2012 à 01:42:56   

Reply

Marsh Posté le 21-12-2012 à 06:48:11    

Ah non tous mes threads font du float, je vais essayer en entier.

 

Au passage j'ai une autre question qui peut paraître stupide. Dans un logiciel de bench comme sandra ou autre, je vois des calculs "FPU" et "APU". A quoi correspondent-ils en pratique ?

 

Merci pour ton aide et ta patience :)

 

EDIT : Bon j'ai essayé avec des entiers mais ça chauffe moins. Toutefois je ne sais pas trop quoi faire comme calcul lourd en utilisant seulement des entiers, additions, soustractions, etc, c'est pas bien lourd :)

Message cité 1 fois
Message édité par Ganon551 le 21-12-2012 à 07:07:54

---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 21-12-2012 à 10:12:58    

Ganon551 a écrit :

Ah non tous mes threads font du float, je vais essayer en entier.
 
Au passage j'ai une autre question qui peut paraître stupide. Dans un logiciel de bench comme sandra ou autre, je vois des calculs "FPU" et "APU". A quoi correspondent-ils en pratique ?
 
Merci pour ton aide et ta patience :)
 
EDIT : Bon j'ai essayé avec des entiers mais ça chauffe moins. Toutefois je ne sais pas trop quoi faire comme calcul lourd en utilisant seulement des entiers, additions, soustractions, etc, c'est pas bien lourd :)


 
MUL et DIV sont des opérations qui prennent pas mal de cycles chacune. J'insiste sur l'utilisation d'entiers ET de floats (enfin, de SSE) parce que FPU et ALU peuvent tourner en parallèle (c'est là l'intérêt de l'hyper threading), donc le but reste de les alimenter constamment les deux et ce sur chacun de tes cores.
 
Par APU, je ne sais pas ce que tu veux dire, tu parlais peut-être de ca au-dessus, ou alors si c'est vraiment APU, ca peut sous entendre que tu veux faire bosser le GPU intégré à ton CPU, ce qui peut aussi avoir du sens, oui, si tu en as un. Là, il va falloir t'orienter vers du GPGPU j'imagine, avec de l'OpenCL probablement (ou peut-être un truc équivalent sous DirectX11, je crois que c'est Direct Compute)


---------------
last.fm
Reply

Marsh Posté le 21-12-2012 à 17:59:23    

Oui je parlais d'ALU désolé je savais bien qu'APU n'était pas correct ici.
 
Du coup fpu c'est floating point, et alu les entiers ?
 
Quand je dis que j'ai essayé les entiers je parle en parallèle des floats, mais la chauffe était moindre, du coup peut être essayer avec des divisions et un floor ou ceil pour retourner sur l'entier.
 


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 21-12-2012 à 21:55:13    

ALU il me semble que c'est arithmetic & logic unit, donc les entier oui.


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 23-12-2012 à 18:03:11    

Bon je reprend mon topic pour une autre question, j'ai trouvé un semblant de réponse sur le fofo mais je n'arrive pas à l'appliquer.
 
Je voudrais créer un vector de vector<bool>.
 
Je fais donc comme suis :
 
vector< vector<bool> > array;
 
Maintenant mon problème, je voudrais ajouter 4 tableaux à ce premier vector, puis remplir ces 4 tableaux de 250.000 bits chacun. Comment accéder aux vector<bool> ?
 
Merci :)


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 23-12-2012 à 20:25:19    

pour utiliser des tableaux de bits tu as les containers bitset.
Là ça fait 1Byte/valeurs


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 23-12-2012 à 20:30:44    

Merci pour ta réponse.
 
Je sais que ce type n'est pas adapté, mais en fait c'est juste pour tester quelque chose avant de l'implémenter dans un autre programme avec les optimisations nécessaires.
 
Enfin au final je n'ai plus besoin de faire ça avec les tableaux.
 
Par contre si quelqu'un ici connaît bien pthread, je veux bien de l'aide. Soit par MP soit sur le fofo, j'aimerais reproduire avec pthread le comportement de la lib omp, particulièrement la commande qui permet de paralléliser une boucle for.
 
En fait j'ai une boucle for qui prend un vector et le remplit de 0 et de 1 (je fais un modulo 2, si c'est égal à 0 je met 1, sinon je met 0).
 
J'aimerais paralléliser cette boucle for, j'ai essayé avec pthread mais comme tous les threads accèdent au même tableau, ça plante.
 
J'ai donc ajouté un mutex mais du coup les performances sont pires qu'en monothread.
 
Donc si quelqu'un ici connaît bien pthread, je veux bien un peu d'aide :)
 
Merci beaucoup


---------------
Mon btag : ganon551#2549
Reply

Marsh Posté le 24-12-2012 à 14:52:20    

Terminapor a écrit :

pour utiliser des tableaux de bits tu as les containers bitset.
Là ça fait 1Byte/valeurs


 
Certaines implémentations font un cas particulier pour les vecteurs de booléens et allouent bien seulement un bit par élément.
 
 
Pour la question de threading, je vois pas trop ton souci. Ca ne me semble pas relever de pthread spécifiquement.
Normalement, oui, il faut éviter que tes threads changent le conteneur chacun de leur côté. Si c'est ce que tu fais dans ta boucle, je vois très mal ce qu'omp pourrait t'apporter.
A nouveau, c'est difficile de te donner des conseils sur la manière de faire les choses, vu que tu n'as pas vraiment d'objectif fonctionnel.


---------------
last.fm
Reply

Marsh Posté le 24-12-2012 à 19:29:07    

Merci de ta réponse.

 

Ici j'ai bien un objectif, même si ça ne sers pas à grand chose. Il y a trois ans à peu près j'avais programmé pour m'entraîner un petit calculateur de nombres premiers en C++ et Qt. J'avais donc simplement implémenté le crible d'Eratosthène. Ensuite à mes heures perdues je me suis amusé à l'optimiser pour calculer les nombres premiers jusqu'à 1 milliard le plus rapidement possible.

 

Mais je n'ai jamais réussi à paralléliser le calcul. Et hier je suis tombé sur un article de quelqu'un qui avait utilisé openMP pour paralléliser les boucles for et qui avait de bons résultats. Du coup je m'y suis remis et j'espérais pouvoir utiliser pthread.

 


Je vais donner un exemple, ce sera mieux. Je n'ai pas mon code ici, celui avec Qt, qui est beaucoup plus avancé et utilise les types qu'il faut, pour les tests je me suis juste recrée un petit programme qui fait un crible pas très optimisé :

 
Code :
  1. bitset<1000000> array;
  2.     int i;
  3.     array[0] = 0;
  4.     array[1] = 0;
  5.     array[2] = 1;
  6.     array[3] = 1;
  7.     #pragma omp parallel for
  8.     for(i = 4; i < 1000000; i+=2)
  9.     {
  10.             array[i] = 0;
  11.             array[i+1] = 1;
  12.     }
  13.     int racine = floor(sqrt(1000000));
  14.     #pragma omp parallel for
  15.     for(int j = 3; j <= racine;j+=2)
  16.     {
  17.         if(array[j] == 0)
  18.         continue;
  19.         #pragma omp parallel for
  20.         for(int k = j;k <= 1000000/j;k+=2)
  21.         {
  22.             array[j*k] = 0;
  23.         }
  24.     }
  25.     int compteur = 0;
  26.     for(int l = 1;l < 1000000; l+=2)
  27.     {
  28.         if(array[l] == 1)
  29.         compteur++;
  30.     }
  31.     cout << compteur << endl;
 

J'ai pris bitset, sur ma version la plus avancée j'utilise les QVector ça marche bien.

 

Bon c'est vraiment un code très simple, les performances sont vraiment mauvaises, mais c'est pour vous donner une idée de ce que je cherche à paralléliser. Et je tiens à préciser que les lignes openMP ici me font vraiment gagner en performances, du coup je me disais que peut être pthread pouvait le faire aussi.

 

Du coup il n'y a aucun moyen de modifier le même array en mêem temps pour deux threads différents ?


Message édité par Ganon551 le 24-12-2012 à 19:41:05

---------------
Mon btag : ganon551#2549
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed