0/5 (11 avis)
Vue 6 057 fois - Téléchargée 1 685 fois
unit factorielle; //Ecrit par denis bertin stéphane le 25 juillet 2013. //Pour calculer une factorielle sur un ou plusieurs coeurs de calcul. //Ce module utilise un mutex pour synchroniser les différentes tache. //Affiche le temps d'execution et une boucle de temporisation permet de ralentir un peut le calcul. interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TAffichage_factorielle = class(TForm) Label1: TLabel; Edit_nombre: TEdit; Label2: TLabel; Edit_resultat: TEdit; Button1: TButton; Label3: TLabel; Edit_mono: TEdit; Edit_multi: TEdit; Label4: TLabel; result_multi_coeur: TLabel; Edit_result_multi_coeur: TEdit; Label_sur_x_coeur: TLabel; procedure Button1Click(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } end; var Affichage_factorielle: TAffichage_factorielle; implementation {$R *.dfm} uses SyncObjs; const Number_of_process_unit = 31; var ThreadsRunning:integer; var Lock:SyncObjs.TCriticalSection; var Table_thread : array[0..Number_of_process_unit] of extended; type // Objet de gestion des affinités processeur. TCPU = Class Protected FCPUMask : Array[0..Number_of_process_unit] Of Boolean ; // Mapping physique des processeurs autorisés pour le processus courant. FCPUMap : Array[0..Number_of_process_unit] Of Cardinal ; // Mapping logique des processeurs, contient un masque d'affinité. FCPUCount : Cardinal ; // Nombre de processeurs utilisables, conditionne la limite supérieure de CPUMap. // Accesseur "Count". Function GetCPUCount : Cardinal ; Public // Constructeur Constructor Create ; // Récupération du nombre de CPU / coeurs du système. // Les processeurs sont ensuite numérotés de 0 à (Count-1). Property Count : Cardinal Read GetCPUCount ; // Force le thread courant à basculer sur le processeur passé en paramètre. // Lève une exception en cas d'erreur. // Ne lève PAS d'erreur (mais ne fait rien non plus) en cas de numéro de CPU invalide. Procedure SwitchTo ( Const CPUIndex : Cardinal ) ; End Platform ; type TSeulement_Wait = class(TThread) Constructor Create; protected procedure Execute; override; end; type Thread_Factorielle = class(TThread) Constructor Create(un_index,a_int_begin,a_int_ending:integer); Procedure ThreadDone(Sender: TObject); protected procedure Execute; override; {Méthode recouverte en français} Public index,commencement,finissement:integer; {Denis B le 20.7.2013} end; { Cette classe TCPU importé depuis internet le saviez-vous ?} constructor TCPU.Create; begin // Initialisation des structures d'affinité processeur. FCPUCount:=0; FillChar(FCPUMask,SizeOf(FCPUMask),0); FillChar(FCPUMap,SizeOf(FCPUMap),0); // Calcul direct du nombre de CPU. GetCPUCount; end; Function TCPU.GetCPUCount : Cardinal ; Var I, ProcessMask, SystemMask : Cardinal ; Begin // Inutile de tout déclencher si on a déjà le nombre de CPU... If (FCPUCount=0) Then Begin // On va récupérer le nombre de CPU. FCPUCount:=0 ; // On compte les bits d'affinité. Win32Check(GetProcessAffinityMask(GetCurrentProcess,ProcessMask,SystemMask)); // Bon, on a le masque : on va calculer sa taille. For I:=0 To pred(Number_of_process_unit) Do Begin // Explosage du masque binaire vers un tableau de booléens. FCPUMask[I]:=(ProcessMask And (1 Shl I))<>0 ; // On compte les CPU utilisables, et on crée la map d'assignation. // Le contenu de CPUMap, à l'indice donné, est donc le masque d'affinité à utiliser. If FCPUMask[I] Then Begin FCPUMap[FCPUCount]:=(1 Shl I) ; Inc(FCPUCount); End; End; End; // Le nombre de CPU est correct quel que soit le cas, on renvoie donc le résultat. Result:=FCPUCount ; End; Procedure TCPU.SwitchTo ( Const CPUIndex : Cardinal ) ; Begin If (CPUIndex<FCPUCount) Then If (SetThreadAffinityMask(GetCurrentThread,FCPUMap[CPUIndex])=0) Then RaiseLastOSError ; End; Constructor TSeulement_Wait.Create; begin inherited Create(False); self.Priority:=tpLowest; end; {TSeulement_Wait.Create} //Utilisation d'un Mutex pour ne pas décrémenter le compteur deux fois en même temps. Procedure TSeulement_Wait.Execute; var encore:boolean; begin encore:=True; while encore do begin Lock.Enter; encore:=ThreadsRunning<>0; Lock.Leave; end; {While encore} end; {TSeulement_Wait.Execute} Constructor Thread_Factorielle.Create(un_index,a_int_begin,a_int_ending:integer); begin inherited Create(False); self.FreeOnTerminate:=True; self.index:=un_index; self.commencement:=a_int_begin; self.finissement:=a_int_ending; end; procedure Thread_Factorielle.Execute; var i,j:integer; s:extended; begin For i:=self.commencement to self.finissement do begin Table_thread[self.index]:=Table_thread[self.index]*i; //Boucle de temporisation for j:=1 to 20000 do s:=sin(j); end; end; Procedure Thread_Factorielle.ThreadDone(Sender: TObject); begin Lock.Enter; Dec(ThreadsRunning); //Pour que la fin du wait attend que ThreadsRunning=0! Lock.Leave; end; function Convertir_ce_numerique_en_string_separer_par_des_point(a_value:integer):string; var i,j:integer; s,ss:string; begin ss:=''; s:=inttostr(a_value); j:=length(s); for i:=1 to length(s) do begin ss:=ss+char(s[i]); dec(j); if (j mod 3=0) and (j<>0) then ss:=ss+'.'; end; Convertir_ce_numerique_en_string_separer_par_des_point:=ss; end; procedure TAffichage_factorielle.Button1Click(Sender: TObject); var i,j,k,jusqua,ithread:integer; n,s:Extended; time_begin:integer; time_fining:integer; uncpu:TCPU; nombre_de_coeur:integer; un_thread_wait:TSeulement_Wait; modulo,posit_one,posit_two:integer; begin jusqua:=strtoint(Edit_nombre.text); time_begin:=gettickcount; n:=1; for i:=1 to jusqua do begin n:=n*i; //Boucle de temporisation for j:=1 to 20000 do s:=sin(j); end; Edit_resultat.Text:=floattostr(n); time_fining:=gettickcount; Edit_mono.Text:=Convertir_ce_numerique_en_string_separer_par_des_point(time_fining-time_begin)+' Millisecondes'; uncpu:=TCPU.Create; nombre_de_coeur:=uncpu.Count; uncpu.Free; Label_sur_x_coeur.Caption:='sur '+inttostr(nombre_de_coeur)+ ' coeur(s)'; if nombre_de_coeur>1 then begin time_begin:=gettickcount; for i:=1 to nombre_de_coeur do Table_thread[i]:=1; Lock:=TCriticalSection.Create; ThreadsRunning:=nombre_de_coeur; un_thread_wait:=TSeulement_Wait.Create; for ithread:=1 to nombre_de_coeur do begin modulo:=jusqua div nombre_de_coeur; if ithread=1 then posit_one:=1 else posit_one:=modulo*pred(ithread); if ithread=nombre_de_coeur then posit_two:=jusqua else posit_two:=pred(modulo*ithread); with Thread_Factorielle.create( ithread,posit_one,posit_two) do OnTerminate := ThreadDone; end; un_thread_wait.waitfor; Lock.Free; n:=1; for i:=1 to nombre_de_coeur do n:=n*Table_thread[i]; time_fining:=gettickcount; Edit_result_multi_coeur.text:=floattostr(n); Edit_multi.Text:=Convertir_ce_numerique_en_string_separer_par_des_point(time_fining-time_begin)+' Millisecondes'; end else Edit_multi.Text:='Monocoeur'; end; {TAffichage_factorielle.Button1Click} end.
2 août 2013 à 15:51
2 août 2013 à 01:47
Un processeur équipé d'un double coeur permet d'effectuer des programmes dont la fréquence total double. En effet, si pour une action donné, vous pouvez répartir le nombre d'opération sur chacun des coeurs Alors vous obtiendrais une fréquence cumulé égale à la somme des fréquences cumulées des deux coeurs.
2 août 2013 à 01:46
2 août 2013 à 01:38
30 juil. 2013 à 18:35
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.