Page 1 of 1

Suoritusnopeuden vertailua

Posted: Sat Jul 02, 2011 10:33 pm
by MetalRain
Raskaat CoolBasic ohjelmat joutuvat usein puristamaan koodista viimeisetkin mehut jotta saavuttavat hyväksyttävän suoritusnopeuden. Siksipä ajattelin että olisi hyvä jakaa enemmänkin tietoa siitä mikä erityisesti CoolBasicilla on tehokasta ja mikä ei.

Vaakasuuntaisen viivan piirto

Code: Select all

SCREEN 800,600

//kuinka monta testiä tehdään
Const kertaus       = 10

//kuinka monta millisekuntia odotetaan testien välissä
Const odotus        = 100

//kuinka monta testattavaa on
Const testattavia   = 3

Dim tulos(kertaus,testattavia) As integer
Dim nimi(testattavia) As String 

//tähän nimi testikoodille
nimi(1) = "lukittu line"
nimi(2) = "line"
nimi(3) = "box"

Global viivoja As integer

Testaa()

//tänne nimeä vastaavaan caseen testikoodi
Function Laskenta(i)
    Select i
        Case 1
            Lock 
                For o=1 To viivoja
                    Line 0,0,100,0
                Next o
            Unlock 
        Case 2
            For o=1 To viivoja
                Line 0,0,100,0
            Next o
        Case 3
            For o=1 To viivoja
                Box 0,0,100,1,1
            Next o
    End Select
End Function 

//tänne testeihin liittyviä muutoksia, jotta testicaset ei
//ole joka kierros samoja.
Function Kierrosmuutos(kierros)
    viivoja=kierros*20000
    Print ""
    Print "Piirretään "+viivoja+" viivaa."
End Function 

//tämä suorittaa itse testit
Function Testaa()

    For o=1 To kertaus
    
        Kierrosmuutos(o)
    
        For u=1 To testattavia

            Wait odotus
        
            tulos(o,u)=Timer()
            
            Laskenta(u)

            tulos(o,u)=Timer()-tulos(o,u)
            
            Print nimi(u)+" "+tulos(o,u)+" ms"
            
            tulos(0,u)=tulos(0,u)+tulos(o,u)
            
        Next u
        
    Next o
    
    Print ""
    Print "--- Keskiarvot ---"
    
    For u=1 To testattavia
        Print nimi(u)+" "+Float(tulos(0,u))/Float(kertaus)+" ms"
    Next u
    
    WaitKey 

End Function
Ruudun lukitseminen Lock komennolla ennen viivojen piirtämistä vauhdittaa piirtoa hurjasti. Box komentokin tuntuu olevan hieman lukitsematonta viivaa nopeampi kunhan määrä pysyy kohtuullisena (<140000).

Pisteen etäisyyden laskeminen origosta

Code: Select all

SCREEN 800,600

//kuinka monta testiä tehdään
Const kertaus       = 10
//kuinka monta millisekuntia odotetaan testien välissä
Const odotus        = 100
//kuinka monta testattavaa on
Const testattavia   = 3

Dim tulos(kertaus,testattavia) As integer
Dim nimi(testattavia) As String 

//tähän nimi testikoodille
nimi(1) = "distance"
nimi(2) = "sqrt+pow"
nimi(3) = "sqrt+mult"

Global fTestNumber1 As Float, fTestNumber2 As Float, iTestAmount As integer 

Testaa()

//tänne nimeä vastaavaan caseen testikoodi
Function Laskenta(i)
    Select i
        Case 1
            For o=1 To iTestAmount
                a=Distance(0,0,fTestNumber1,fTestNumber2)
            Next o
        Case 2
            For o=1 To iTestAmount
                a=Sqrt(fTestNumber1^2+fTestNumber2^2)
            Next o
        Case 3
            For o=1 To iTestAmount
                a=Sqrt(fTestNumber1*fTestNumber1+fTestNumber2*fTestNumber2)
            Next o
    End Select
End Function 

//tänne testeihin liittyviä muutoksia, jotta testicaset ei
//ole joka kierros samoja.
Function Kierrosmuutos(kierros)
    iTestAmount= kierros*200000
    fTestNumber1=Rnd(-100.0,1000.0)
    fTestNumber2=Rnd(-100.0,1000.0)
    Print ""
    Print "Lasketaan pisteen ("+fTestNumber1+","+fTestNumber2+") etäisyys origosta "+iTestAmount+" kertaa."
End Function 

//tämä suorittaa itse testit
Function Testaa()

    For o=1 To kertaus
    
        Kierrosmuutos(o)
    
        For u=1 To testattavia

            Wait odotus
        
            tulos(o,u)=Timer()
            
            Laskenta(u)
            
            tulos(o,u)=Timer()-tulos(o,u)
            
            Print nimi(u)+" "+tulos(o,u)+" ms"
            
            tulos(0,u)=tulos(0,u)+tulos(o,u)
        
        Next u
        
    Next o
    
    Print ""
    Print "--- Keskiarvot ---"
    
    For u=1 To testattavia
        Print nimi(u)+" "+Float(tulos(0,u))/Float(kertaus)+" ms"
    Next u
    
    WaitKey 

End Function 
Distancen käyttö näyttäisi olevan huomattavasti nopeampaa kuin laskea etäisyys neliöjuuren ja kahden potenssin avulla. Kahden potenssin vaihtaminen kertolaskuun tehostaa selvästi muttei aivan yllä distancen tasolle.

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 1:11 am
by MaGetzUb
Distance on n. 57% nopeampi kutsuttaessa sitä 10K kertaa peräkkäin, kuin laskukaava.

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 1:54 pm
by tuhoojabotti
Luuppien vertailua

Code: Select all

SCREEN 800,600

//kuinka monta testiä tehdään
Const kertaus       = 20
//kuinka monta millisekuntia odotetaan testien välissä
Const odotus        = 100
//kuinka monta testattavaa on
Const testattavia   = 3

Dim tulos(kertaus,testattavia) As integer
Dim nimi(testattavia) As String 

//tähän nimi testikoodille
nimi(1) = "for"
nimi(2) = "while"
nimi(3) = "repeat"

Global fTestNumber1 As Float, fTestNumber2 As Float, iTestAmount As Integer 

Testaa()

//tänne nimeä vastaavaan caseen testikoodi
Function Laskenta(i)
    Select i
        Case 1
            For o=0 To iTestAmount
                t = fTestNumber1 * fTestNumber2
            Next o
            Print "f "+o
        Case 2
            o = 0
            ton = iTestAmount + 1 // optimization!
            While o < ton
                t = fTestNumber1 * fTestNumber2
                o + 1
            Wend
            Print "w "+o
        Case 3
            o = 0
            Repeat
                t = fTestNumber1 * fTestNumber2
                o + 1
            Until o > iTestAmount
            Print "r "+o
    End Select
End Function 

//tänne testeihin liittyviä muutoksia, jotta testicaset ei
//ole joka kierros samoja.
Function Kierrosmuutos(kierros)
    fTestNumber1 = Rnd (-1000, 1000)
    fTestNumber2 = Rnd (-1000, 1000)
    iTestAmount  = kierros * 200000
    Print ""
    Print "Luupataan... "+fTestNumber1+" x "+fTestNumber2
End Function

//tämä suorittaa itse testit
Function Testaa()

    For o=1 To kertaus
    
        Kierrosmuutos(o)
    
        For u=1 To testattavia

            Wait odotus
        
            tulos(o,u)=Timer()
            
            Laskenta(u)
            
            tulos(o,u)=Timer()-tulos(o,u)
            
            Print nimi(u)+" "+tulos(o,u)+" ms"
            
            tulos(0,u)=tulos(0,u)+tulos(o,u)
        
        Next u
        
    Next o
    
    Print ""
    Print "--- Keskiarvot ---"
    
    For u=1 To testattavia
        Print nimi(u)+" "+Float(tulos(0,u))/Float(kertaus)+" ms"
    Next u
    
    WaitKey 

End Function
Repeat on nopein!1!!!11 :P En kyllä tiedä teinkö oikein, mutta tuommosta. :D

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 7:07 pm
by MaGetzUb
En tiedä sitten.. mutta tämä on varmaan parempi testaustyyli:

Code: Select all

timr1 = Timer()
Repeat 
    a = a + 1
    If a > 100000 Then Exit
Forever 
timr1 = Timer() - timr1

timr2 = Timer()
While True
    b = b + 1
    If b > 100000 Then Exit 
Wend
timr2 = Timer() - timr2

timr3 = Timer()
For i = 0 To i+1
    c = c + 1
    If c > 100000 Then Exit
Next i
timr3 = Timer() - timr3

//MaGetzUb's invented
timr4 = Timer()
Loop:
    e = e + 1
    If e > 100000 Then Goto out
Goto Loop
out:
timr4 = Timer()-timr4

Print "Repeat - Until/Forever took: "+timr1+"ms"
Print "While - Wend took: "+timr2+"ms"
Print "ForTo - Next took: "+timr3+"ms"
Print "Goto loop took: "+timr4+"ms"
WaitKey 
EDIT:

Oma keksintöni "goto loop" on kaikista nopein ainakin minun koneellani. Muilla loopeilla ottaa yli 30ms, mutta Goto loop otti 25ms kun testasin. :D


Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 8:01 pm
by Kille
Minun koneella nopein oli repeat(12ms), whileWend ja Goto 14ms ja ForTo 23 ms.

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 8:24 pm
by MaGetzUb
Kille wrote:Minun koneella nopein oli repeat(12ms), whileWend ja Goto 14ms ja ForTo 23 ms.
Näyttäisi olevan aika pitkälti konekohtaista.. :)

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 9:49 pm
by Latexi95
Minulla Repeat/Forever ja Goto toimivat aivan yhtä nopeasti(13ms). Ne olivat noin 13% nopeampia kuin While/Wend ja melkein kaksi kertaa nopeampia kuin For/Next.

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 9:54 pm
by valscion
Enpä usko että nuo looppien nopeudet kuitenkaan ovat millään tavalla ratkaisevia, joten jos voisitte keskittyä tarkkailemaan jotain oikeasti merkitseviä nopeuseroja?

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 10:34 pm
by Latexi95
MIelenkiintoista... Lock+Putpixel2+Unlock tuntuu olevan minulla aina nopeampi kuin Putpixel, vaikka piirrettäisiin vain yksi pikseli. Eli siis vaikka piirtäisit vain yhden pikselin kannattaa käyttää Putpixel2:sta...

Re: Suoritusnopeuden vertailua

Posted: Sun Jul 03, 2011 11:09 pm
by esa94
Latexi95 wrote:MIelenkiintoista... Lock+Putpixel2+Unlock tuntuu olevan minulla aina nopeampi kuin Putpixel, vaikka piirrettäisiin vain yksi pikseli. Eli siis vaikka piirtäisit vain yhden pikselin kannattaa käyttää Putpixel2:sta...
Riippuu kuinka kauan lukitseminen kestää

Re: Suoritusnopeuden vertailua

Posted: Mon Jul 04, 2011 12:40 am
by Latexi95
esa94 wrote: Riippuu kuinka kauan lukitseminen kestää
Ai niin... Totta. Tein testini vakio ruudunkoolla suoraan ruudulle. Silloin lukitseminen oli melkein kaksi kertaa nopeampi tapa(lukittu noin 420ms ja lukitsematon 750ms).