Suoritusnopeuden vertailua

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
User avatar
MetalRain
Active Member
Posts: 188
Joined: Sun Mar 21, 2010 12:17 pm
Location: Espoo

Suoritusnopeuden vertailua

Post by MetalRain » Sat Jul 02, 2011 10:33 pm

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.

User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Suoritusnopeuden vertailua

Post by MaGetzUb » Sun Jul 03, 2011 1:11 am

Distance on n. 57% nopeampi kutsuttaessa sitä 10K kertaa peräkkäin, kuin laskukaava.
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
tuhoojabotti
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 3:53 pm
Location: Suomi, Finland
Contact:

Re: Suoritusnopeuden vertailua

Post by tuhoojabotti » Sun Jul 03, 2011 1:54 pm

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
Imagedev.tuhoojabotti.com — “Programmer (noun): An organism that turns caffeine into code.”

User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Suoritusnopeuden vertailua

Post by MaGetzUb » Sun Jul 03, 2011 7:07 pm

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

Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
Kille
Active Member
Posts: 249
Joined: Wed Aug 26, 2009 3:50 pm
Location: Juankoski

Re: Suoritusnopeuden vertailua

Post by Kille » Sun Jul 03, 2011 8:01 pm

Minun koneella nopein oli repeat(12ms), whileWend ja Goto 14ms ja ForTo 23 ms.
ZEPPELIN
Jatkoa tulossa... tällä kertaa lataus ei kestä viikkoa

User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: Suoritusnopeuden vertailua

Post by MaGetzUb » Sun Jul 03, 2011 8:24 pm

Kille wrote:Minun koneella nopein oli repeat(12ms), whileWend ja Goto 14ms ja ForTo 23 ms.
Näyttäisi olevan aika pitkälti konekohtaista.. :)
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Suoritusnopeuden vertailua

Post by Latexi95 » Sun Jul 03, 2011 9:49 pm

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.

User avatar
valscion
Moderator
Moderator
Posts: 1588
Joined: Thu Dec 06, 2007 8:46 pm
Location: Espoo
Contact:

Re: Suoritusnopeuden vertailua

Post by valscion » Sun Jul 03, 2011 9:54 pm

Enpä usko että nuo looppien nopeudet kuitenkaan ovat millään tavalla ratkaisevia, joten jos voisitte keskittyä tarkkailemaan jotain oikeasti merkitseviä nopeuseroja?
cbEnchanted, uudelleenkirjoitettu runtime. Uusin versio: 0.4.1 — Nyt myös sorsat GitHubissa!
NetMatch - se kunnon nettimättö-deathmatch! Avoimella lähdekoodilla varustettu
vesalaakso.com

User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Suoritusnopeuden vertailua

Post by Latexi95 » Sun Jul 03, 2011 10:34 pm

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...

User avatar
esa94
Guru
Posts: 1855
Joined: Tue Sep 04, 2007 5:35 pm

Re: Suoritusnopeuden vertailua

Post by esa94 » Sun Jul 03, 2011 11:09 pm

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ää

User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Suoritusnopeuden vertailua

Post by Latexi95 » Mon Jul 04, 2011 12:40 am

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).

Post Reply