Newsgroup: it.comp.lang.visual-basic
Titolo: Ottimizzazioni: Date un'occhiata qui (5K)

Qui sotto c'è un formettino che mi sono fatto per chiarirmi le idee su quali
variabili utilizzare per ottenere le migliori prestazioni durante i calcoli.
Ebbene, posto al NG questo form perché ha sconvolto le mie teorie sulle
ottimizzazioni.
Io ho sempre saputo di dover far attenzione all'uso dei Double, che
diminuiscono le prestazioni. A quanto pare invece, non solo vanno usate, ma
sono più efficienti se i valori delle variabili sono con decimali. Se
infatti si fanno moltiplicazioni tra Double, con valori interi, sembra che
siano trattate come Long (dal Pentium o da VB?) , e che sono più lente!!.
Possibile???
Se a tutto questo c'è una spiegazione....
Fabio Guerrazzi
VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Form1"
   ClientHeight    =   6210
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   7395
   LinkTopic       =   "Form1"
   ScaleHeight     =   6210
   ScaleWidth      =   7395
   StartUpPosition =   3  'Windows Default
   Begin VB.CommandButton Command7
      Caption         =   "Ciclo con contatore double a virg. mobile"
      Height          =   735
      Left            =   300
      TabIndex        =   12
      Top             =   3240
      Width           =   1455
   End
   Begin VB.CommandButton Command6
      Caption         =   "Moltiplicazione di Integer"
      Height          =   855
      Left            =   5400
      TabIndex        =   10
      Top             =   180
      Width           =   1575
   End
   Begin VB.CommandButton Command5
      Caption         =   "Moltiplicazione di Single Interi"
      Height          =   915
      Left            =   3480
      TabIndex        =   7
      Top             =   1560
      Width           =   1575
   End
   Begin VB.CommandButton Command4
      Caption         =   "Moltiplicazione di Single a virgola mobile"
      Height          =   855
      Left            =   3420
      TabIndex        =   6
      Top             =   180
      Width           =   1575
   End
   Begin VB.CommandButton Command3
      Caption         =   "Moltiplicazione di Double Interi"
      Height          =   795
      Left            =   300
      TabIndex        =   4
      Top             =   1620
      Width           =   1395
   End
   Begin VB.CommandButton Command2
      Caption         =   "Moltiplicazione di Long"
      Height          =   855
      Left            =   1980
      TabIndex        =   1
      Top             =   180
      Width           =   1275
   End
   Begin VB.CommandButton Command1
      Caption         =   "Moltiplicazione di Double a virgola mobile"
      Height          =   855
      Left            =   300
      TabIndex        =   0
      Top             =   180
      Width           =   1455
   End
   Begin VB.Label Label7
      Caption         =   "Label7"
      Height          =   195
      Left            =   300
      TabIndex        =   13
      Top             =   4080
      Width           =   1935
   End
   Begin VB.Label Label6
      Caption         =   "Label6"
      Height          =   255
      Left            =   5460
      TabIndex        =   11
      Top             =   1140
      Width           =   1515
   End
   Begin VB.Label Label5
      Caption         =   "Label5"
      Height          =   195
      Left            =   3540
      TabIndex        =   9
      Top             =   2580
      Width           =   1275
   End
   Begin VB.Label Label4
      Caption         =   "Label4"
      Height          =   195
      Left            =   3420
      TabIndex        =   8
      Top             =   1080
      Width           =   1515
   End
   Begin VB.Label Label3
      Caption         =   "Label3"
      Height          =   195
      Left            =   300
      TabIndex        =   5
      Top             =   2520
      Width           =   1335
   End
   Begin VB.Label Label2
      Caption         =   "Label2"
      Height          =   195
      Left            =   2040
      TabIndex        =   3
      Top             =   1140
      Width           =   1635
   End
   Begin VB.Label Label1
      Caption         =   "Label1"
      Height          =   255
      Left            =   360
      TabIndex        =   2
      Top             =   1080
      Width           =   1335
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Sub Command1_Click()
 Dim D As Double
 Dim F As Double
 Label1 = ""
 F = 234.287327743345    ' imposto un valore con decimali
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label1 = Timer - t
End Sub
Private Sub Command2_Click()
 Dim D As Long
 Dim F As Long
 Label2 = ""
 F = 1
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label2 = Timer - t
End Sub
Private Sub Command3_Click()
 Dim D As Double
 Dim F As Double
 Label3 = ""
 F = 2      ' imposto un valore intero, la variabile è sempre Double
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label3 = Timer - t
End Sub
Private Sub Command4_Click()
 Dim D As Single
 Dim F As Single
 Label4 = ""
 F = 32.2873    ' imposto un valore con decimali
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label4 = Timer - t
End Sub
Private Sub Command5_Click()
 Dim D As Single
 Dim F As Single
 Label5 = ""
 F = 1
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label5 = Timer - t
End Sub
Private Sub Command6_Click()
 Dim D As Integer
 Dim F As Integer
 Label6 = ""
 F = 2
 t = Timer
 For i% = 1 To 2500
   For j% = 1 To 2500
      D = F * F
   Next
 Next
 Label6 = Timer - t
End Sub
Private Sub Command7_Click()
 Dim D As Double
 Dim F As Double
 Dim i As Double, j As Double
 Label7 = ""
 F = 3432.213543213
 t = Timer
 For i = 1.1 To 2500.1 Step 1.1
   For j = 1.1 To 2500.1 Step 1.1
      D = F * F
   Next
 Next
 Label7 = Timer - t
End Sub


Non ho capito l'ultima frase... comunque,
a partire dai Pentium (per non parlare di Pentium II-III, Athlon, Xeon,
ecc.)
la FPU del processore, ora integrata, è diventata molto più efficiente,
tanto che la penalità nell'uso di Double invece che Long o Integer è
molto minore (per alcune applicazioni trascurabile)
Ciò tuttavia non toglie il fatto che utilizzare il tipo di dati corretto è
comunque una pratica programmatoria corretta (cioè, se devo
fare For i=0 to 1000, è più corretto dichiarare i come Integer  o
come Long. Long è meglio di Integer poichè è il formato di dati
naturale per processori 32bit come i Pentium e derivati).
Poi, visto il tuo codice, un loop di 2500 iterazioni non produce
alcun "benchmark" significativo su processori moderni, in quanto
viene "esaurito" in circa 100 - 200ms.
Data la granulartà del multitasking di Windows 9x e la particolare
inaccuratezza del timer utilizzato (risultati migliori si ottengono
sfruttando i timer multimediali), le piccole differenze dei tempi
di esecuzione sono più dovuti al resto del codice che non
a differenze effettivamente rilevate nei tempi di calcolo.
Se vuoi effettuare dei test comparativi "seri" (con tutte le
limitazioni derivanti dall'utilizzo di VB per questo tipo di
applicazione) dovresti considerare dei loop di almeno
10^7 .. 10^8 cicli. Allora la differenza nei tempi di esecuzione
di operazioni intere o floating point si dovrebbe cominciare
a vedere (un Pentium 200MHz esegue 200 milioni di operazioni
"singolo clock" al secondo. Se non ricordo male operazioni
Long+Long o Double+Double sono eseguite entrambi in un unico ciclo
di clock (o poco più...) pertanto un loop di 2500 iterazioni viene
completato in pochissimi millisecondi. Avendo in mano il
manuale ASM del processore utilizzato il conto è
anche (abbastanza - operation reordering e
speculative execution permettendo) semplice da fare.)
Saluti, Massimo.

Non hai capito l'ultima frase? vuol dire: se a questo c'č una spiegazione
.... la gradirei.
Comunque hai dato un'ottima spiegazione, molto chiara e ben documentata. Ti
ringrazio. Perň non
hai provato il programma, il loop non č di 2500 iterazioni, ma di 2500*2500
(6250000). Il mio P133 impiega  intorno ai 5 secondi a test. So bene che i
benkmark  sono algoritmi ben studiati, ma questo voleva essere solo una cosa
per la verifica di quello che chiedevo. Quello che mi ha stupito č che il
test sulla moltiplicazione tra Double risulta piů veloce rispetto ai Long,
Double = 5.23993 secondi
Long    =  5,70993 secondi
Comunque sia,da quello che hai detto   mi sembra di capire  che nonostante
lo stile
corretto sull'uso di variabili, č abbastanza ininfluente, in termini di
prestazioni, la scelta di una piuttosto che un'altra.
Grazie ancora.
Fabio Guerrazzi


---- file Form1.frm -----------------------
VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Test"
   ClientHeight    =   4650
   ClientLeft      =   1815
   ClientTop       =   1515
   ClientWidth     =   4500
   LinkTopic       =   "Form1"
   ScaleHeight     =   4650
   ScaleWidth      =   4500
   Begin VB.CommandButton btnTest7
      Caption         =   "Ciclo con contatore double a virg. mobile"
      Height          =   735
      Left            =   120
      TabIndex        =   12
      Top             =   3720
      Width           =   1455
   End
   Begin VB.CommandButton btnTest1
      Caption         =   "Integer"
      Height          =   375
      Left            =   120
      TabIndex        =   10
      Top             =   120
      Width           =   1455
   End
   Begin VB.CommandButton btnTest3
      Caption         =   "Single (interi)"
      Height          =   375
      Left            =   120
      TabIndex        =   7
      Top             =   1320
      Width           =   1455
   End
   Begin VB.CommandButton btnTest4
      Caption         =   "Single (decimali)"
      Height          =   375
      Left            =   120
      TabIndex        =   6
      Top             =   1920
      Width           =   1455
   End
   Begin VB.CommandButton btnTest5
      Caption         =   "Double (interi)"
      Height          =   375
      Left            =   120
      TabIndex        =   4
      Top             =   2520
      Width           =   1455
   End
   Begin VB.CommandButton btnTest2
      Caption         =   "Long"
      Height          =   375
      Left            =   120
      TabIndex        =   1
      Top             =   720
      Width           =   1455
   End
   Begin VB.CommandButton btnTest6
      Caption         =   "Double (decimali)"
      Height          =   375
      Left            =   120
      TabIndex        =   0
      Top             =   3120
      Width           =   1455
   End
   Begin VB.Label Label7
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label7"
      Height          =   195
      Left            =   1800
      TabIndex        =   13
      Top             =   3720
      Width           =   480
   End
   Begin VB.Label Label1
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label1"
      Height          =   195
      Left            =   1800
      TabIndex        =   11
      Top             =   120
      Width           =   480
   End
   Begin VB.Label Label5
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label5"
      Height          =   195
      Left            =   1800
      TabIndex        =   9
      Top             =   2520
      Width           =   480
   End
   Begin VB.Label Label4
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label4"
      Height          =   195
      Left            =   1800
      TabIndex        =   8
      Top             =   1920
      Width           =   480
   End
   Begin VB.Label Label3
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label3"
      Height          =   195
      Left            =   1800
      TabIndex        =   5
      Top             =   1320
      Width           =   480
   End
   Begin VB.Label Label2
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label2"
      Height          =   195
      Left            =   1800
      TabIndex        =   3
      Top             =   720
      Width           =   480
   End
   Begin VB.Label Label6
      AutoSize        =   -1  'True
      BackStyle       =   0  'Transparent
      Caption         =   "Label6"
      Height          =   195
      Left            =   1800
      TabIndex        =   2
      Top             =   3120
      Width           =   480
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Const TEST_LOOPS_LONG As Long = 100000000
Const TEST_LOOPS_DOUBLE As Double = 100000000.1
Dim t As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Sub btnTest1_Click()
    Dim i1 As Integer, i2 As Integer
    Dim lCounter As Long
    Label1 = "<running>"
    i1 = 2
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        i2 = i1 * i1
    Next
    Label1 = GetTickCount - t
End Sub
Private Sub btnTest2_Click()
    Dim l1 As Long, l2 As Long
    Dim lCounter As Long
    Label2 = "<running>"
    l1 = 1
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        l2 = l1 * l1
    Next
    Label2 = GetTickCount - t
End Sub
Private Sub btnTest3_Click()
    Dim s1 As Single, s2 As Single
    Dim lCounter As Long
    Label3 = "<running>"
    s1 = 1
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        s2 = s1 * s1
    Next
    Label3 = GetTickCount - t
End Sub
Private Sub btnTest4_Click()
    Dim s1 As Single, s2 As Single
    Dim lCounter As Long
    Label4 = "<running>"
    s1 = 1.2873    ' imposto un valore con decimali
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        s2 = s1 * s1
    Next
    Label4 = GetTickCount - t
End Sub
Private Sub btnTest5_Click()
    Dim d1 As Double, d2 As Double
    Dim lCounter As Long
    Label5 = "<running>"
    d1 = 2      ' imposto un valore intero, la variabile č sempre Double
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        d2 = d1 * d1
    Next
    Label5 = GetTickCount - t
End Sub
Private Sub btnTest6_Click()
    Dim d1 As Double, d2 As Double
    Dim lCounter As Long
    Label6 = "<running>"
    d1 = 234.287327743345    ' imposto un valore con decimali
    t = GetTickCount
    For lCounter = 1 To TEST_LOOPS_LONG
        d2 = d1 * d1
    Next
    Label6 = GetTickCount - t
End Sub
Private Sub btnTest7_Click()
    Dim d1 As Double, d2 As Double
    Dim dCounter As Double
    Label7 = "<running>"
    d1 = 3432.213543213
    t = GetTickCount
    For dCounter = 1.1 To TEST_LOOPS_DOUBLE Step 1.1
        d2 = d1 * d1
    Next
    Label7 = GetTickCount - t
End Sub

Ti ringrazio. Io il test l'ho fatto sull' IDE di VB, non ho provato come
EXE. Evidentemente, come dici, i risultati sono molto diversi. Cosa che
ovviamente supponevo (i tempi dell'exe dovrebbero essere inferiori) ma
pensavo che in percentuale sarebbero abbassati tutti, mantenendo comunque le
stesse discordanze. Proverò e ti farò sapere se a me da gli stessi
risultati.
Fabio

ecco perchè il Bubble Short(esercizio di scuola) andava cosi lento!!!
GRAZIE!!! Ho imparato qualcosa....