Comparison QB64 compiled with gcc optimizations and without
#31
CRC-32 : I got this code from the site rosettacode. I added some code to test the processing speed with QB64 compiled with the O3 option and the original version.

6.7x seconds : program compiled with qb64 -O3
17.6x seconds : program compiled with original qb64

here the speed gain is clearly visible.

Code: (Select All)
' Rosetta Code -   CRC-32
Dim tab$(19)
tab$(0) = "malevolently malevolous malexecution malfeasance malfeasant malfeasantly malfeasants malfeasor overwon"
tab$(1) = "malfed malformation malformations malformed malfortune malfunction malfunctioned malfunctioning overwood"
tab$(2) = "malgovernment nonemotionalism nonemotionally verwing overwinning overwinter overwintered overwintering"
tab$(3) = "nonemanating nonemancipation nonemancipative nonembarkation nonembellished nonembellishing overwiped"
tab$(4) = "nonembellishment nonembezzlement nonembryonal nonembryonic nonembryonically nonemendable overwithered"
tab$(5) = "nonemendation nonemergence nonemergent nonemigrant nonemigration nonemission nonemotional overwomanize"
tab$(6) = "overwisdom overwise overwisely overwoman overwomanly overwooded overwoody overword overwords overwore"
tab$(7) = "overwork segreant segregable segregant segregate segregated segregatedly segregatedness segregateness"
tab$(8) = "segregates segregating segregation segregational segregationist segregationists segregative segregator"
tab$(9) = "teleostean teleostei teleosteous teleostomate teleostome teleostomi teleostomian teleostomous teleosts"
tab$(10) = "teleotemporal teleotrocha teleozoic teleozoon telepath telepathy telepathic telepathically telepathies"
tab$(11) = "telepathist telepathize nffroze unfibbed unfibbing unfiber unfibered unfibred unfibrous unfibrously"
tab$(12) = "unfickle unfictitious unfictitiously unfictitiousness unfidelity unfidgeting unfiducial unfielded"
tab$(13) = "unfiend unfiendlike unfierce unfiercely unfiery unfight unfightable unfighting unfigurable unfigured"
tab$(14) = "zulus zumatic zumbooruk zuni zunian zunyite zunis zupanate zurich zurlite zutugil zuurveldt zuza"
tab$(15) = "zwanziger zwieback zwiebacks zwieselite zwinglian zwinglianism zwinglianist zwitter zwitterion"
tab$(16) = "zwitterionic cognovits cogon cogonal cogons cogovernment cogovernor cogracious cograil cogrediency"
tab$(17) = "cogredient cogroad cogs cogswellia coguarantor coguardian cogue cogway cogways cogware cogweel"
tab$(18) = "cogweels cogwheel cogwheels xiphistna xiphisura xiphisuran xiphiura xiphius xiphocostal xiphodynia"
tab$(19) = "xiphodon xiphodontidae xiphoid xyphoid xiphoidal xiphoidian xiphoids xiphopagic xiphopagous xiphopagus"
Color 7: Print "Wait..."
Color 2: Print: Print " generation of test string..."
Dim tabch$(15)
For boucle% = 1 To 15
    chaine$ = ""
    For i = 1 To 10000
        chaine$ = chaine$ + tab$(Rnd * 19)
    Next i
    tabch$(boucle%) = chaine$
Next boucle%
Dim hash$(15)
Color 3: Print: Print " crc calculation 100 times in : ";
start = Timer(.001)
For nbr% = 1 To 100
    For boucle% = 1 To 15
        chaine$ = tabch$(boucle%)
        hash$(boucle%) = Hex$(crc32(chaine$))
    Next boucle%
Next nbr%
Print Timer(.001) - start; "seconds"
Color 14: Print
For boucle% = 1 To 15: Print " "; hash$(boucle%): Next boucle%
Color 7
End

Function crc32~& (buf As String)
    Static table(255) As _Unsigned Long
    Static have_table As _Byte
    Dim crc As _Unsigned Long, k As _Unsigned Long
    Dim i As Long, j As Long

    If have_table = 0 Then
        For i = 0 To 255
            k = i
            For j = 0 To 7
                If (k And 1) Then
                    k = _SHR(k, 1)
                    k = k Xor &HEDB88320
                Else
                    k = _SHR(k, 1)
                End If
                table(i) = k
            Next
        Next
        have_table = -1
    End If

    crc = Not crc ' crc = &Hffffffff

    For i = 1 To Len(buf)
        crc = (_SHR(crc, 8)) Xor table((crc And &HFF) Xor Asc(buf, i))
    Next

    crc32~& = Not crc
End Function
Reply
#32
I can see you are busy running tests and comparing the results of the different compiler options. 

Do you think you can take all this knowledge gained and put it into an FAQ or "best practices" doc of some kind?
This could benefit all the QB64 users who would be interested in learning to compile their programs optimized for speed...
Reply
#33
(05-19-2022, 02:18 PM)madscijr Wrote: I can see you are busy running tests and comparing the results of the different compiler options. 

Do you think you can take all this knowledge gained and put it into an FAQ or "best practices" doc of some kind?
This could benefit all the QB64 users who would be interested in learning to compile their programs optimized for speed...

Hi @madscijr. That's a good idea. I'll think about it.
Reply
#34
i discover day by day interesting features in qb64. today it's about _Deflate (compression) and _Inflate (decompression) functions. i wanted to test them. here is the result :

program compiled with qb64 -O3 :

Function _Deflate : 10.1x seconds
Function _Inflate : 1.2x seconds

program compiled with original qb64 :

Function _Deflate : 10.1x seconds
Function _Inflate : 1.2x seconds

the result of the comparison is almost zero in terms of processing speed. i examined the compilation directives of the original version of qb64. it turns out that the compression and decompression module is compiled with the -O3 option. nothing surprising to this result.

on character strings, compression is very efficient and decompression is very fast. this should allow to reduce efficiently the disk space occupied by text data...

Code: (Select All)
Dim tab$(19)
tab$(0) = "malevolently malevolous malexecution malfeasance malfeasant malfeasantly malfeasants malfeasor overwon"
tab$(1) = "malfed malformation malformations malformed malfortune malfunction malfunctioned malfunctioning overwood"
tab$(2) = "malgovernment nonemotionalism nonemotionally verwing overwinning overwinter overwintered overwintering"
tab$(3) = "nonemanating nonemancipation nonemancipative nonembarkation nonembellished nonembellishing overwiped"
tab$(4) = "nonembellishment nonembezzlement nonembryonal nonembryonic nonembryonically nonemendable overwithered"
tab$(5) = "nonemendation nonemergence nonemergent nonemigrant nonemigration nonemission nonemotional overwomanize"
tab$(6) = "overwisdom overwise overwisely overwoman overwomanly overwooded overwoody overword overwords overwore"
tab$(7) = "overwork segreant segregable segregant segregate segregated segregatedly segregatedness segregateness"
tab$(8) = "segregates segregating segregation segregational segregationist segregationists segregative segregator"
tab$(9) = "teleostean teleostei teleosteous teleostomate teleostome teleostomi teleostomian teleostomous teleosts"
tab$(10) = "teleotemporal teleotrocha teleozoic teleozoon telepath telepathy telepathic telepathically telepathies"
tab$(11) = "telepathist telepathize nffroze unfibbed unfibbing unfiber unfibered unfibred unfibrous unfibrously"
tab$(12) = "unfickle unfictitious unfictitiously unfictitiousness unfidelity unfidgeting unfiducial unfielded"
tab$(13) = "unfiend unfiendlike unfierce unfiercely unfiery unfight unfightable unfighting unfigurable unfigured"
tab$(14) = "zulus zumatic zumbooruk zuni zunian zunyite zunis zupanate zurich zurlite zutugil zuurveldt zuza"
tab$(15) = "zwanziger zwieback zwiebacks zwieselite zwinglian zwinglianism zwinglianist zwitter zwitterion"
tab$(16) = "zwitterionic cognovits cogon cogonal cogons cogovernment cogovernor cogracious cograil cogrediency"
tab$(17) = "cogredient cogroad cogs cogswellia coguarantor coguardian cogue cogway cogways cogware cogweel"
tab$(18) = "cogweels cogwheel cogwheels xiphistna xiphisura xiphisuran xiphiura xiphius xiphocostal xiphodynia"
tab$(19) = "xiphodon xiphodontidae xiphoid xyphoid xiphoidal xiphoidian xiphoids xiphopagic xiphopagous xiphopagus"
Color 7: Print "Wait..."
Color 2: Print: Print " generation of test string..."
Dim tabch$(15)
For boucle% = 1 To 15
    chaine$ = ""
    For nbr% = 1 To 10000
        chaine$ = chaine$ + tab$(Rnd * 19)
    Next nbr%
    tabch$(boucle%) = chaine$
Next boucle%
Dim chcompress$(15)
Color 3: Print: Print " compress string 100 times in : ";
start = Timer(.001)
For nbr% = 1 To 100
    For boucle% = 1 To 15
        chaine$ = tabch$(boucle%)
        chcompress$(boucle%) = _Deflate$(chaine$)
    Next boucle%
Next nbr%
Print Timer(.001) - start; "seconds"
Color 14: Print
For boucle% = 1 To 15
    Print " len string original : "; Len(tabch$(boucle%)); " -->  Compressed : "; Len(chcompress$(boucle%))
Next boucle%
Color 3: Print: Print " Decompress string 100 times in : ";
start = Timer(.001)
For nbr% = 1 To 100
    For boucle% = 1 To 15
        chaine$ = chcompress$(boucle%)
        tabch$(boucle%) = _Inflate$(chaine$)
    Next boucle%
Next nbr%
Print Timer(.001) - start; "seconds"
Color 7
End
Reply
#35
(05-19-2022, 06:13 PM)Coolman Wrote:
(05-19-2022, 02:18 PM)madscijr Wrote: I can see you are busy running tests and comparing the results of the different compiler options. 

Do you think you can take all this knowledge gained and put it into an FAQ or "best practices" doc of some kind?
This could benefit all the QB64 users who would be interested in learning to compile their programs optimized for speed...

Hi @madscijr. That's a good idea. I'll think about it.

How did all these tests turn out? 
Any final results?
Reply
#36
hello @madscijr, i think i've done the trick. compiled with option O3, qb64 is much faster than the original version in calculations, sorting algorithms, string manipulations. the speed gain is very important. the console programs i've made for personal use are quite efficient although not as fast as freebasic. qb64 allows to develop very quickly like quickbasic. it's a definite advantage. you can concentrate on the essential. i didn't notice any visible problem. it would be necessary to make more tests to validate the compilation in O3 and eventually to propose an optimized version of qb64. but this decision is up to the maintainers of qb64.

frankly, I had not considered using qb64 at the beginning. I tested many very interesting basic interpreter, I thought that the speed of development and the instantaneous execution of the programs is an important criterion, finally the speed of execution is more important when it is necessary to make many treatments. I will thus use qb64 intensively. I would continue to use freebasic equally.
Reply
#37
"frankly, I had not considered using qb64 at the beginning. I tested many very interesting basic interpreter, I thought that the speed of development and the instantaneous execution of the programs is an important criterion, finally the speed of execution is more important when it is necessary to make many treatments. I will thus use qb64 intensively. I would continue to use freebasic equally."

It does take some practice to appreciate the full scope of what QB64 IDE offers. What you lose in the little bit of compile time before execution of new code is more than made up for avoiding typo's and syntax errors, fast lookup of keywords and a host of things you wont get from a third party editor IMHO. Don't look at compile time, execution time is way more important because you only compile once to make an exe. I would say that development time is at least as important as execution time (maybe more so when turning one proggie after another :-)) It use to be space for memory and length of programs but now it's about time, humans' more so than computers.
b = b + ...
Reply
#38
(06-08-2022, 03:11 PM)bplus Wrote: It use to be space for memory and length of programs but now it's about time, humans' more so than computers.

I wholeheartedly agree! 
Let the machines do the work - saving humans time was always the promise and the whole point of using computers to begin with ;-)
Reply
#39
just for testing

Code: (Select All)
_Title "n-body"

'http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=gcc&id=1
' The Computer Language Benchmarks Game
' http://benchmarksgame.alioth.debian.org/

' contributed by Christoph Bauer
'
' translated to QB64 by Jack
' modified a bit to avoid using pointer to array

declare FUNCTION main# (n AS LONG)

Print Str$(main(50000000)) + " seconds"
End

Const pi = 3.141592653589793
Const solar_mass = (4 * pi) * pi
Const days_per_year = 365.24

Type planet
    x As Double
    y As Double
    z As Double
    vx As Double
    vy As Double
    vz As Double
    mass As Double
End Type

Sub advance (nbodies As Long, bodies() As planet, dt As Double)
    Dim i As Long, j As Long
    Dim dx As Double, dy As Double, dz As Double, distance As Double, mag As Double
    For i = 0 To nbodies - 1
        For j = i + 1 To nbodies - 1
            dx = bodies(i).x - bodies(j).x
            dy = bodies(i).y - bodies(j).y
            dz = bodies(i).z - bodies(j).z
            distance = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
            mag = dt / ((distance * distance) * distance)
            bodies(i).vx = bodies(i).vx - (dx * bodies(j).mass) * mag
            bodies(i).vy = bodies(i).vy - (dy * bodies(j).mass) * mag
            bodies(i).vz = bodies(i).vz - (dz * bodies(j).mass) * mag
            bodies(j).vx = bodies(j).vx + (dx * bodies(i).mass) * mag
            bodies(j).vy = bodies(j).vy + (dy * bodies(i).mass) * mag
            bodies(j).vz = bodies(j).vz + (dz * bodies(i).mass) * mag
        Next
    Next
    For i = 0 To nbodies - 1
        bodies(i).x = bodies(i).x + dt * bodies(i).vx
        bodies(i).y = bodies(i).y + dt * bodies(i).vy
        bodies(i).z = bodies(i).z + dt * bodies(i).vz
    Next
End Sub

Function energy# (nbodies As Long, bodies() As planet)
    Dim i As Long, j As Long
    Dim e As Double, dx As Double, dy As Double, dz As Double, distance As Double, mag As Double
    e = 0.0
    For i = 0 To nbodies - 1
        e = e + (0.5 * bodies(i).mass) * (((bodies(i).vx * bodies(i).vx) + (bodies(i).vy * bodies(i).vy)) + (bodies(i).vz * bodies(i).vz))
        For j = i + 1 To nbodies - 1
            dx = bodies(i).x - bodies(j).x
            dy = bodies(i).y - bodies(j).y
            dz = bodies(i).z - bodies(j).z
            distance = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
            e = e - (bodies(i).mass * bodies(j).mass) / distance
        Next
    Next
    energy# = e
End Function

Sub offset_momentum (nbody As Long, bodies() As planet)
    Dim px As Double, py As Double, pz As Double
    Dim I As Long
    For I = 0 To nbody - 1
        px = px + bodies(I).vx * bodies(I).mass
        py = py + bodies(I).vy * bodies(I).mass
        pz = pz + bodies(I).vz * bodies(I).mass
    Next
    bodies(0).vx = (-px) / ((4 * pi) * pi)
    bodies(0).vy = (-py) / ((4 * pi) * pi)
    bodies(0).vz = (-pz) / ((4 * pi) * pi)
End Sub


Function main# (n As Long)
    Const NBODIES = 5
    Dim bodies(0 To 4) As planet
    bodies(0).x = 0: bodies(0).y = 0: bodies(0).z = 0: bodies(0).vx = 0: bodies(0).vy = 0: bodies(0).vz = 0: bodies(0).mass = (4 * pi) * pi
    bodies(1).x = 4.84143144246472090D+00: bodies(1).y = -1.16032004402742839D+00: bodies(1).z = -1.03622044471123109D-01: bodies(1).vx = 1.66007664274403694D-03 * days_per_year: bodies(1).vy = 7.69901118419740425D-03 * days_per_year: bodies(1).vz = (-6.90460016972063023D-05) * days_per_year: bodies(1).mass = 9.54791938424326609D-04 * ((4 * pi) * pi)
    bodies(2).x = 8.34336671824457987D+00: bodies(2).y = 4.12479856412430479D+00: bodies(2).z = -4.03523417114321381D-01: bodies(2).vx = (-2.76742510726862411D-03) * days_per_year: bodies(2).vy = 4.99852801234917238D-03 * days_per_year: bodies(2).vz = 2.30417297573763929D-05 * days_per_year: bodies(2).mass = 2.85885980666130812D-04 * ((4 * pi) * pi)
    bodies(3).x = 1.28943695621391310D+01: bodies(3).y = -1.51111514016986312D+01: bodies(3).z = -2.23307578892655734D-01: bodies(3).vx = 2.96460137564761618D-03 * days_per_year: bodies(3).vy = 2.37847173959480950D-03 * days_per_year: bodies(3).vz = (-2.96589568540237556D-05) * days_per_year: bodies(3).mass = 4.36624404335156298D-05 * ((4 * pi) * pi)
    bodies(4).x = 1.53796971148509165D+01: bodies(4).y = -2.59193146099879641D+01: bodies(4).z = 1.79258772950371181D-01: bodies(4).vx = 2.68067772490389322D-03 * days_per_year: bodies(4).vy = 1.62824170038242295D-03 * days_per_year: bodies(4).vz = (-9.51592254519715870D-05) * days_per_year: bodies(4).mass = 5.15138902046611451D-05 * ((4 * pi) * pi)

    Dim i As Long
    Dim t As Double
    t = Timer
    Call offset_momentum(NBODIES, bodies())
    Print Using "##.#########"; energy#(NBODIES, bodies())
    For i = 1 To n
        Call advance(NBODIES, bodies(), 0.01)
    Next
    Print Using "##.#########"; energy#(NBODIES, bodies())
    main# = Timer - t
End Function
Reply
#40
(06-10-2022, 02:41 AM)Jack Wrote: just for testing

Code: (Select All)
_Title "n-body"

'http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=gcc&id=1
' The Computer Language Benchmarks Game
' http://benchmarksgame.alioth.debian.org/

' contributed by Christoph Bauer
'
' translated to QB64 by Jack
' modified a bit to avoid using pointer to array

declare FUNCTION main# (n AS LONG)

Print Str$(main(50000000)) + " seconds"
End

Const pi = 3.141592653589793
Const solar_mass = (4 * pi) * pi
Const days_per_year = 365.24

Type planet
    x As Double
    y As Double
    z As Double
    vx As Double
    vy As Double
    vz As Double
    mass As Double
End Type

Sub advance (nbodies As Long, bodies() As planet, dt As Double)
    Dim i As Long, j As Long
    Dim dx As Double, dy As Double, dz As Double, distance As Double, mag As Double
    For i = 0 To nbodies - 1
        For j = i + 1 To nbodies - 1
            dx = bodies(i).x - bodies(j).x
            dy = bodies(i).y - bodies(j).y
            dz = bodies(i).z - bodies(j).z
            distance = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
            mag = dt / ((distance * distance) * distance)
            bodies(i).vx = bodies(i).vx - (dx * bodies(j).mass) * mag
            bodies(i).vy = bodies(i).vy - (dy * bodies(j).mass) * mag
            bodies(i).vz = bodies(i).vz - (dz * bodies(j).mass) * mag
            bodies(j).vx = bodies(j).vx + (dx * bodies(i).mass) * mag
            bodies(j).vy = bodies(j).vy + (dy * bodies(i).mass) * mag
            bodies(j).vz = bodies(j).vz + (dz * bodies(i).mass) * mag
        Next
    Next
    For i = 0 To nbodies - 1
        bodies(i).x = bodies(i).x + dt * bodies(i).vx
        bodies(i).y = bodies(i).y + dt * bodies(i).vy
        bodies(i).z = bodies(i).z + dt * bodies(i).vz
    Next
End Sub

Function energy# (nbodies As Long, bodies() As planet)
    Dim i As Long, j As Long
    Dim e As Double, dx As Double, dy As Double, dz As Double, distance As Double, mag As Double
    e = 0.0
    For i = 0 To nbodies - 1
        e = e + (0.5 * bodies(i).mass) * (((bodies(i).vx * bodies(i).vx) + (bodies(i).vy * bodies(i).vy)) + (bodies(i).vz * bodies(i).vz))
        For j = i + 1 To nbodies - 1
            dx = bodies(i).x - bodies(j).x
            dy = bodies(i).y - bodies(j).y
            dz = bodies(i).z - bodies(j).z
            distance = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
            e = e - (bodies(i).mass * bodies(j).mass) / distance
        Next
    Next
    energy# = e
End Function

Sub offset_momentum (nbody As Long, bodies() As planet)
    Dim px As Double, py As Double, pz As Double
    Dim I As Long
    For I = 0 To nbody - 1
        px = px + bodies(I).vx * bodies(I).mass
        py = py + bodies(I).vy * bodies(I).mass
        pz = pz + bodies(I).vz * bodies(I).mass
    Next
    bodies(0).vx = (-px) / ((4 * pi) * pi)
    bodies(0).vy = (-py) / ((4 * pi) * pi)
    bodies(0).vz = (-pz) / ((4 * pi) * pi)
End Sub


Function main# (n As Long)
    Const NBODIES = 5
    Dim bodies(0 To 4) As planet
    bodies(0).x = 0: bodies(0).y = 0: bodies(0).z = 0: bodies(0).vx = 0: bodies(0).vy = 0: bodies(0).vz = 0: bodies(0).mass = (4 * pi) * pi
    bodies(1).x = 4.84143144246472090D+00: bodies(1).y = -1.16032004402742839D+00: bodies(1).z = -1.03622044471123109D-01: bodies(1).vx = 1.66007664274403694D-03 * days_per_year: bodies(1).vy = 7.69901118419740425D-03 * days_per_year: bodies(1).vz = (-6.90460016972063023D-05) * days_per_year: bodies(1).mass = 9.54791938424326609D-04 * ((4 * pi) * pi)
    bodies(2).x = 8.34336671824457987D+00: bodies(2).y = 4.12479856412430479D+00: bodies(2).z = -4.03523417114321381D-01: bodies(2).vx = (-2.76742510726862411D-03) * days_per_year: bodies(2).vy = 4.99852801234917238D-03 * days_per_year: bodies(2).vz = 2.30417297573763929D-05 * days_per_year: bodies(2).mass = 2.85885980666130812D-04 * ((4 * pi) * pi)
    bodies(3).x = 1.28943695621391310D+01: bodies(3).y = -1.51111514016986312D+01: bodies(3).z = -2.23307578892655734D-01: bodies(3).vx = 2.96460137564761618D-03 * days_per_year: bodies(3).vy = 2.37847173959480950D-03 * days_per_year: bodies(3).vz = (-2.96589568540237556D-05) * days_per_year: bodies(3).mass = 4.36624404335156298D-05 * ((4 * pi) * pi)
    bodies(4).x = 1.53796971148509165D+01: bodies(4).y = -2.59193146099879641D+01: bodies(4).z = 1.79258772950371181D-01: bodies(4).vx = 2.68067772490389322D-03 * days_per_year: bodies(4).vy = 1.62824170038242295D-03 * days_per_year: bodies(4).vz = (-9.51592254519715870D-05) * days_per_year: bodies(4).mass = 5.15138902046611451D-05 * ((4 * pi) * pi)

    Dim i As Long
    Dim t As Double
    t = Timer
    Call offset_momentum(NBODIES, bodies())
    Print Using "##.#########"; energy#(NBODIES, bodies())
    For i = 1 To n
        Call advance(NBODIES, bodies(), 0.01)
    Next
    Print Using "##.#########"; energy#(NBODIES, bodies())
    main# = Timer - t
End Function

hello @Jack. interesting code. this is where we see the potential of qb64 compiled with O3 optimization. thanks for sharing.

on my computer :

16.7x seconds : program compiled with qb64 -O3
66.8x seconds : program compiled with original qb64
Reply




Users browsing this thread: 1 Guest(s)