Newsgroup: it.comp.lang.delphi
Titolo: Ottimizzazione: Per Andrea e Unforgiven

Ho pubblicato i miei test su 
http://it.geocities.com/robertomilani2002/dimostr/dimostr.html
Ho compilato con Delphi 6 Enterprise.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Ho compilato con Delphi 6 Enterprise.
E, come temevo, hai pubblicato una baggianata :)
A parte il fatto che non consideri la chiamata a StrToInt e
a @LStrFromChar nel primo caso (codice che occupa spazio e
tempi di elaborazione), nel secondo caso dici che **forse**
il codice e' piu' lento.  Allora dicci su che base pubblichi
questi benchmark, su quale *certezza*.
Le dimensioni del codice sono esattamente le stesse (guarda
il File Size nelle finestrelle di compilazione), quindi qual
e' il parametro di confronto ?
E' chiaro che, mancando la struttura dati a supporto del
codice, nel secondo caso, il codice che si occupa di gestire
il case sia piu' lungo, ma questo non vuol dire
assolutamente nulla.
Tu dici che *forse* e' piu' lento: falso.
Nel secondo caso, e' facile rendersi conto che il
compilatore ha creato una tabella indicizzata di punti del
codice verso cui eseguire un jump incondizionato.
Punti del codice, in cui viene assegnato un valore al
registro "esi" e si salta subito al punto di restituzione
del valore.
Tieni presente che il compilatore spesso e' in grado di
compiere ottimizzazioni, che nessun programmatore potrebbe
fare, solo guardando il codice assembly.
Ricordati una cosa importante, per le prossime volte:
"Premature optimization is the root of all evil."
[Donald Knuth]
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

 fare, solo guardando il codice assembly.
Lo so.


ora dovrebbe essere più veloce di prima.
scusate se mi intrometto: non capisco tutto questo problema
della corsa all'ottimizzazione... Delphi ha un ottimo
compilatore che non ha nulla da invidiare, riguardo ad un
problema cosi banale come quello di cui si sta discutendo
l'ottimizzazione è pressochè inutile.
Ottimizzare serve in ben altri casi, secondo me.
--
Lawrence Oluyede
rhy...@myself.com

che è più lento? è presappoco veloce come nel secondo caso.
E' piu' lento, se ad ogni operazione gli fai compiere una
sottrazione.  Sei intervenuto in un thread, accusando del
codice di essere poco performante, ma proponendo una
soluzione ancor meno performante.  Le ottimizzazioni
lasciale fare al compilatore, perche' altrimenti si finisce
col fare sciocchezze.


 col fare sciocchezze.
beh ci sono ottimizzazioni e ottimizzazioni :) ok va bene nel mio caso 
mi sarò sbagliato però le ottimizzazioni sono importanti, no? ad esempio
fare una free di un puntatore inutilizzato dopo una new... o no?
comunque io non ti accuso niente di niente, c'è stato un programma e io
ho solo espresso il mio punto di vista, non ho mai detto che il
programma
fa cacare (tra l'altro quella che ha posto il problema ha trovato un
altro programma più corto e più semplice) come puoi vedere qui:
"Grazie, lo proverò.
Intanto anch'io ho travato un sorgente simile (con meno linee di codice)
che
funzione benissimo, se credete posso postarlo.
Luisa"
:) ognuno ha i suoi punti di vista!
ciao ciao


altro programma piů corto e piů semplice) come puoi vedere qui:
Di nuovo: non capisco che cosa c'entri questo, onestamente.
Io sto ribattendo alle tue opinioni sulle performance.  
Se, poi, Luisa crede che un codice scritto in meno righe sia
piu' performante o fatto meglio, e' libera di utilizzarlo,
nessuno le dice niente.  Se Open Look mi ribatte sulle
performance con stupidaggini, gli faccio presente che sta
dicendo delle stupidaggini, tutto qui.


fare una free di un puntatore inutilizzato dopo una new... o no?
questa non č ottimizzazione, anzi dovrebbe essere la norma
--
Lawrence Oluyede
rhy...@myself.com

 ora dovrebbe essere pi— veloce di prima.
Premessi che non ho controllato l'esattezza del codice...
*Dovrebbe* essere più veloce?
Hai migliorato il tempo medio di esecuzione di circa 15 volte!!!
Riguardo al tuo test che hai pubblicato.. mi dispiace dirti che non e' 
molto serio giudicare la *velocità* del codice dal numero di linee asm 
generate.. basta pensare non solo ai diversi cicli macchina impiegati per 
istruzioni diverse... ma, soprattuto in questo caso, al numero di 
istruzioni EFFETTIVAMENTE eseguite.
Detto questo, come faccio a dire che hai migliorato la velocità di 15 
volte? Semplice... ho fatto un mio bench.
I risultati sono stati:
*************************************************************
Test di velocita', premere invio per iniziare...
Soluzione Laforgia...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 1382ms
Tempo medio per CICLO UTILE : 0,001382ms
Premere invio per continuare...
Soluzione Open Look...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 490ms
Tempo medio per CICLO UTILE : 0,00049ms
Premere invio per uscire
*************************************************************
Rifacendo il test più volte e invertendo anche l'ordine di esecuzione o 
separando in due programmi distinti i due test, i risultati sono sempre 
allineati nell'ordine di +/- 20ms
Il codice del test è il seguente:
**************************************************************
program Test;
{$APPTYPE CONSOLE}
uses
  Windows, SysUtils;
const
  numeri: array [0..9] of integer =
   (10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
  lettere: array ['A'..'Z'] of integer =
   (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26);
Function Calcola_OpenLook (C:Char) : Integer;
Begin
  case C of
    '0'..'9': result := numeri[ShortInt(C)-ShortInt('1')];
//    '0'..'9': result := numeri[StrToInt(C)];
    'A'..'Z': result := lettere[C];
  else
  Result := -1;
  end;
End;
Function Calcola_Laforgia (C:Char) : Integer;
Begin
  case C of
    '0': result := 10;
    '1': result := 20;
    '2': result := 30;
    '3': result := 40;
    '4': result := 50;
    '5': result := 60;
    '6': result := 70;
    '7': result := 10;
    '8': result := 10;
    '9': result := 10;
    'A': result := 1;
    'B': result := 2;
    'C': result := 3;
    'D': result := 4;
    'E': result := 5;
    'F': result := 6;
    'G': result := 7;
    'H': result := 8;
    'I': result := 9;
    'L': result := 10;
    'M': result := 11;
    'N': result := 12;
    'O': result := 13;
    'P': result := 14;
    'Q': result := 15;
    'R': result := 16;
    'S': result := 17;
    'T': result := 18;
    'U': result := 19;
    'V': result := 20;
    'Z': result := 21;
  else result := -1;
  end;
End;
const
 n:integer = 1000000;
var
 timeFirst, timeLast : integer;
 timecycle : double;
 i : integer;
 c : char;
begin
  writeln ('Test di velocita'', premere invio per iniziare...');
  readln;
  writeln ('Soluzione Laforgia...');
  timeFirst := GetTickCount();
  for i := 1 to n do begin
    Calcola_Laforgia (#0);
    for c := '0' to '9' do
      Calcola_Laforgia (c);
    for c := 'A' to 'Z' do
      Calcola_Laforgia (c);
  end;
  timeLast := GetTickCount();
  timecycle := (timelast - timefirst) / n;
  writeln ( 'Numero di CICLI UTILI eseguiti: ' + IntToStr (N));
  writeln ( 'Tempo TOTALE: ' + IntToStr (timelast - timefirst) +'ms');
  writeln ( 'Tempo medio per CICLO UTILE : ' + FloatToStr (timecycle)
+'ms');
  writeln;
  writeln ('Premere invio per continuare...');
  readln;
  writeln;
  writeln ('Soluzione Open Look...');
  timeFirst := GetTickCount();
  for i := 1 to n do begin
    Calcola_OpenLook (#0);
    for c := '0' to '9' do
      Calcola_OpenLook (c);
    for c := 'A' to 'Z' do
      Calcola_OpenLook (c);
  end;
  timeLast := GetTickCount();
  timecycle := (timelast - timefirst) / n;
  writeln ( 'Numero di CICLI UTILI eseguiti: ' + IntToStr (N));
  writeln ( 'Tempo TOTALE: ' + IntToStr (timelast - timefirst)+'ms');
  writeln ( 'Tempo medio per CICLO UTILE : ' + FloatToStr (timecycle)
+'ms');
  writeln;
  writeln ('Premere invio per uscire');
  readln;
End.
**************************************************************
Questo è un bench già più serio, che mette comunque in luce la maggiore 
velocità di esecuzione nella soluzione di Open Look.
Ciao a tutti,
Davide DG.
-- 
All resistance is futile! Prepare to be disassembled !

 (p.s. ShortInt esisteva nel Borland Pascal 7.0 non so in Delphi)




I risultati sono stati:


Premere invio per continuare...





uses
  Windows, SysUtils;



  case C of
    '0'..'9': result := numeri[ShortInt(C)-ShortInt('1')];


Hai migliorato il tempo medio di esecuzione di circa 15 volte!!!
Effettivamente, con questa seconda versione, il
miglioramento c'e', ma non e' di 15 volte, almeno non sulla
mia macchina, dove la differenza si riduce a 2 volte (segno
del fatto che benchmark di questo tipo sono affidabili fino
a un certo punto).  Ho provato il codice anch'io ed
effettivamente e' piu' veloce il codice di Open Look
(mediamente) di quasi 2 volte:
Test di velocita', premere invio per iniziare...
Soluzione Laforgia...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 1352ms
Tempo medio per CICLO UTILE : 0,001352ms
Premere invio per continuare...
Soluzione Open Look...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 732ms
Tempo medio per CICLO UTILE : 0,000732ms
Premere invio per uscire
Ho comunque dovuto modificare il codice perche' risultasse
corretto, difatti la sottrazione giusta e' :
ShortInt(C)-ShortInt('0')
cosi' come bisogna contemplare anche i casi J, K, W, X, Y,
nel mio codice (che sono compresi in 'A'..'Z').
Giusto a titolo di cronaca, il codice pubblicato da Open
Look e' effettivamente piu' lento:
Test di velocita', premere invio per iniziare...
Soluzione Laforgia...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 1392ms
Tempo medio per CICLO UTILE : 0,001392ms
Premere invio per continuare...
Soluzione Open Look...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 9664ms
Tempo medio per CICLO UTILE : 0,009664ms
Premere invio per uscire
Non ho avuto modo di osservare, comunque, quanto incida
l'uso del cast ShortInt sul codice assembly generato.


 l'uso del cast ShortInt sul codice assembly generato.
Io penso che non incida perchč il valore Char č in effetti a 8 bit su BP
7.0 e 16 bit (credo) su Delphi, stessi di ShortInt sui rispettivi
compilatori. Il compilatore che fa? Nulla! Prende direttamente il valore
cosě com'č... una specie di MOV AX, (puntatore a C o come la fa il
compilatore!)
comunque che bello sapere che il mio codice era piů veloce e devo
ringraziare Davide e Andrea per i benchmark :)
comunque a me non importa essere "il piů bravo di tutti". A me importa
solo conoscere nuovi modi per miglirore i programmi in ogni aspetto :)
Ciao


Look e' effettivamente piu' lento:
Si', quello originale (con StrToInt) era molto piů lento (difatti l'ho 
lasciato commentato in Calcola_OpenLook proprio per rendersene conto).
Ad ogni modo ho postato non certo per fare da arbitro in qualche gara... ma 
per esporre il mio punto di vista sulla questione benchmark (velocita' non 
e' proporzionale alla lunghezza del codice asm, figurarsi a quella del 
codice pascal)
Ciao, buona domenica a tutti,


Pubblico anch'io i test fatti su 2 computer:
1° COMPUTER Pentium III 700 - Windows Millenium
Test di velocita', premere invio per iniziare...
Soluzione Laforgia...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 1827ms
Tempo medio per CICLO UTILE : 0.001827ms
Premere invio per continuare...
Soluzione Open Look...
Numero di CICLI UTILI eseguiti: 1000000
Tempo TOTALE: 1158ms
Tempo medio per CICLO UTILE : 0.001158ms
Premere invio per uscire
2° COMPUTER Celeron 450 - Windows Millenium
est di velocita', premere invio per iniziare...
oluzione Laforgia...
umero di CICLI UTILI eseguiti: 1000000
empo TOTALE: 2479ms
empo medio per CICLO UTILE : 0,002479ms
remere invio per continuare...
oluzione Open Look...
umero di CICLI UTILI eseguiti: 1000000
empo TOTALE: 1561ms
empo medio per CICLO UTILE : 0,001561ms
remere invio per uscire
questi benchmark tengono conto a colui che definiva le mie affermazioni
come idiozie o stupidaggine. non ho bisogno di fare nessun commento.


 Ho compilato con Delphi 6 Enterprise.
In un problema come quello del Codice Fiscale dove in genere si 
utilizza una tabella contenente tutti i comuni d'Italia (che dubito
abbiate utilizzato per fare le vostre prove) mi preoccuperei di piu 
della struttura e della corretta indicizzazione degli archivi.
Per quanto riguarda il codice, se non è strettamente necessario alla 
velocità di esecuzione preferirei una buona manutenibilità (leggasi
: codice leggibile).
Scusate la mia tapina opinione, ma in questo particolare problema
mi sembra ci abbiate voluto "pensare un pò troppo", perdendo di vista
il problema reale: un banale calcolo del codice fiscale.
Saluti a tutti quanti.




D'accordissimo. Però, ogni tanto, una bella discussione puramente
accademica, se resta nel confronto civile (come è stato), può anche
essere divertente e interessante.
Massimo.
-- 
Ore 18.30: premo invio.