Author Topic: Holy speed daemon, Batman!  (Read 3142 times)

0 Members and 1 Guest are viewing this topic.

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Holy speed daemon, Batman!
« on: June 20, 2021, 05:13:49 pm »
Two things happened in close succession: (1) got a BIOS update from Dell, for my Core i7 6700, and (2) installed the latest QB64 development build, which does something different with numbers. Whatever the cause, the speed measured by my number-crunching speed test went way the heck up. Any ideas?

Original speed, for the three groups of tests, using the 64-bit QB64, averaged roughly 1.0. 1.8, and 2.3 seconds.

Then Dell updated the BIOS, to defend against a couple of viruses whose names I forget. Weird names. We were warned that this BIOS update would reduce performance. Now the times averaged something like 1.5, 2.3, and 3.4. Disappointing, in that this is what the 32-bit QB64 had measured previously, more or less.

So last night, after the new BIOS and new QB64 64-bit development build, I said hey, let's measure again. Imagine my surprise, when the speeds now measured about 0.12, 0.22, and 0.33 seconds! Whoa. Wha'happened? An order of magnitude faster?

In case you want to do the test yourselves, this is the program I used. It's a program to compute prime numbers, repurposed as a number-crunching speed test. Just really curious to know what changed.

Code: [Select]
Rem                   PRIME NUMBER GENERATOR SPEED TEST
Rem
Rem  The program bypasses 2, starting with 3 as the first prime. It then
Rem  increments the number (num) by 2 each iteration, and tests if it's a
Rem  prime.
Rem
Rem  The prime test consists of trying to divide the number, num, by all odd
Rem  numbers beginning with 3 (ptest). This works because by starting with
Rem  the smallest odd numbers, all primes factors less than ptest will
Rem  already have been tested when a larger non-prime number is used in
Rem  ptest. For example, ptest = 3 will have been attempted before ptest = 9.
Rem  ptest = 3 would have divided evenly into num before ptest = 9 is tried.
Rem
Rem -------
Dim Shared i As _Float, num As _Float, ptest As _Float, prime As _Float, PrimeOld As _Float
Dim Shared MaxPrime As _Float, TimeStart As _Float, TimeEnd As _Float, TestNo, restart
Call init
TestNo = 1
3 If TestNo >= 1 And TestNo <= 5 Then MaxPrime = 100000
If TestNo > 5 And TestNo <= 10 Then MaxPrime = 150000
If TestNo > 10 And TestNo <= 15 Then MaxPrime = 200000
If TestNo >= 16 Then End
Call ReTest
1 Call StopRun
If restart = 1 GoTo 3
Rem -------
Rem  If ptest > sqr(num), and no successful integer division came before, num
Rem  must be prime. Increment num and start again with ptest = 3.
Rem -------
quot = num / ptest
If ptest > Sqr(num) Then
    prime = num
    Call PrintOut
    num = num + 2
    ptest = 3
    GoTo 1
End If
Rem -------
Rem  If ptest divides evenly into num, then num cannot be prime. Increment
Rem  num and start again with ptest = 3.
Rem -------
If quot = Int(quot) Then
    num = num + 2
    ptest = 3
    GoTo 1
End If
Rem -------
Rem  As long as num / ptest is not integer and ptest <= sqr(num), continue
Rem  trying with larger odd values of ptest.
Rem -------
ptest = ptest + 2
GoTo 1
End

Sub init
    _Title "Prime Number Speed Test"
    Screen _NewImage(120, 43, 0)
    Color 1, 7
    Cls
    Print "                          SPEED TEST"
    Print
    Print "Speed test uses prime number generator program. Generator starts with 3."
    Print "Max value of prime to be generated limits test duration. For this speed"
    Print "test, the first 5 tests limit the max prime attempted to the first prime"
    Print "past 100,000, the next 5 tests limit to the first prime past 150,000,"
    Print "the last 5 tests limit to the first prime past 200,000."
    Print
    Print "While program is running, you can press <esc> to stop program."
    Print
End Sub

Sub ReTest
    restart = 0
    TimeStart = Timer
    prime = 1
    num = 3
    PrimeOld = 1
    i = 2
    ptest = 3
End Sub

Sub PrintOut
    i = i + 1
    PrimeOld = prime
End Sub

Sub StopRun
    If InKey$ = Chr$(27) Then End
    If prime >= MaxPrime Then
        TimeEnd = Timer
        ElapsedTime = Abs(TimeEnd - TimeStart)
        Print "Test #"; TestNo; "  Highest prime reached"; prime; "  Seconds to reach value ="; ElapsedTime
        restart = 1
        TestNo = TestNo + 1
        If TestNo = 6 Then Print
        If TestNo = 11 Then Print
    End If
End Sub

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Holy speed daemon, Batman!
« Reply #1 on: June 20, 2021, 05:19:42 pm »
A change to the floating point math processors we use was introduced recently.  That might be changing your performance speeds.  (Only thing I can think of that might do it.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #2 on: June 20, 2021, 05:30:19 pm »
If that's it, then wow, what a good change! I thought maybe the BIOS update might have done something too. At the time when they reduced the performance, I read that future BIOS updates might try to increase efficiency again. Still, what I'm measuring would be way more than I would expect from a BIOS update.

So, hey thanks, guys!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Holy speed daemon, Batman!
« Reply #3 on: June 20, 2021, 05:50:30 pm »
If you want to test it, grab the routines from here: https://www.qb64.org/forum/index.php?topic=3636.msg129794#msg129794

Toggle between normal and double precision and see if the change makes much of a different in your speed testing.  If so, then I'd say the recent changes are making a good improvement with your benchmarks.  If not, then it must be the BIOS update that did it.   ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #4 on: June 20, 2021, 06:04:27 pm »
It chokes. Can't find your custom library.

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #5 on: June 20, 2021, 07:50:04 pm »
Just for grins, I ran the same speed test on my laptop, with Intel Core i5 10310U processor. The speed is a little slower than the desktop Core i7, but still much faster than before.

On the laptop, I get about 0.16, 0.27, and 0.38 seconds. Compared with 0.12, 0.22, and 0.33 seconds on the desktop. On the laptop, as on the desktop, that's about a 10X speed increase, compared with before.

Since both the desktop and the laptop have brand new BIOSs, and running the same development build of QB64 64-bit, still not positive what caused the improvement. Significant improvement, for number crunching anyway, no matter how you describe it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #6 on: June 20, 2021, 08:26:07 pm »
Here is something a little faster:
Code: QB64: [Select]
  1. ' 6 wheel sieve.bas for QB64 fork (B+=MGA) 2017-08-30 copy and trans to QB64
  2. 'translated from: First Factors.bas for SmallBASIC 11/27/14 (bpf.org post)
  3.  
  4. 'topN = 1000000, primes 78,498, .17 secs, 8169 twins last 999959,  999961
  5. 'topN = 10000000, primes 664,579, 1.85 secs, 58,980 twins last 9999971,  9999973
  6. 'topN = 100000000, primes 5,761,455, 20.69 secs, 440,312 twins last 99999587,  99999589
  7. ' out of memory for 1 billion
  8.  
  9. 'compare to 30 wheel
  10.  
  11. 'topN = 1000000, primes 78,498, .15 secs, 8169 twins last 999959,  999961
  12. 'topN = 10000000, primes 664,579, 1.81 secs, 58,980 twins last 9999971,  9999973
  13. 'topN = 100000000, primes 5,761,455, 19.65 secs, 440,312 twins last 99999587,  99999589
  14. ' out of memory for 1 billion
  15.  
  16. 'compare to 2310 wheel sieve   WOW the 30 wheel is faster!
  17.  
  18. 'QB64 results from 2310 wheel
  19. 'topN = 1000000, primes 78,498, .18 secs, 8169 twins last 999959,  999961
  20. 'topN = 10000000, primes 664,579, 1.98 secs, 58,980 twins last 9999971,  9999973
  21. 'topN = 100000000, primes 5,761,455, 21.57 secs, 440,312 twins last 99999587,  99999589
  22. ' out of memory for 1 billion
  23.  
  24.  
  25. Common Shared ff(), topN
  26. topN = 1223 'first 200 primes test
  27. topN = 200000
  28. testlimitN = Sqr(topN)
  29.  
  30. 'First Factors array is 0 for prime number or contains the numbers lowest factor
  31. Dim ff(topN + 6)
  32.  
  33. tStart# = Timer(.001)
  34.  
  35. For i = 0 To topN Step 6
  36.     ff(i + 2) = 2: ff(i + 3) = 3: ff(i + 4) = 2: ff(i + 6) = 2
  37.  
  38. ff(2) = 0: ff(3) = 0 'fix first 2 factors
  39. For pcand = 5 To testlimitN Step 2
  40.     If ff(pcand) = 0 Then
  41.         For i = pcand * pcand To topN Step 2 * pcand
  42.             If ff(i) = 0 Then ff(i) = pcand
  43.         Next
  44.     End If
  45.  
  46. 'count primes
  47. For i = 2 To topN
  48.     If ff(i) = 0 Then p = p + 1
  49. tStop# = Timer(.001)
  50. tTime# = tStop# - tStart#
  51. Print "For "; topN; " numbers there are "; p; " primes in "; tTime#; " secs."
  52.  
  53. If 0 Then ' <<<<< uncomment this as needed
  54.  
  55.     'file twin primes data
  56.  
  57.     Open "Twin primes.txt" For Output As #1
  58.     lastp = -1
  59.     For i = 2 To topN
  60.         If ff(i) = 0 Then
  61.             If i - lastp = 2 Then
  62.                 Print #1, Str$(lastp) + ", " + Str$(i) + " Middle/6 = " + Str$((i - 1) / 6) + ": " + factors$((i - 1) / 6)
  63.                 tCount = tCount + 1
  64.             End If
  65.             lastp = i
  66.         End If
  67.     Next
  68.     Close #1
  69.     Print "Found "; tCount; " Twin Primes in first "; topN; " integers."
  70.  
  71. End If ' <<<<<<<<<<<<< uncomment this as needed
  72.  
  73. 'test some factoring of numbers
  74. factorMe = 10
  75. While factorMe > 1
  76.     Input "Enter a number to factor, 0 quits "; factorMe
  77.     If factorMe < 2 Then Exit While Else Print factors$(factorMe)
  78.  
  79. Function factors$ (n)
  80.     If n > topN Then factors$ = "Error: too high a number.": Exit Function
  81.     f$ = ""
  82.     While ff(n) <> 0
  83.         f$ = f$ + Str$(ff(n)) + " "
  84.         n = n / ff(n)
  85.     Wend
  86.     factors$ = f$ + Str$(n)
  87.  
  88.  
  89.  
  90.  

Plus you can factor numbers after it's done finding primes.

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #7 on: June 20, 2021, 10:30:50 pm »
Not to ignore bplus' one-upmanship, :),  but to get back to Steve's suggestion, I re-dimensioned the variables as Double, instead of _Float. It increased the speed in the Core i5 to about where it was with _Float, in the Core i7, although less consistent in each group of tests.

I'm not clear, though, whether such a test proves anything. Not sure what goes on under the hood, when we dimension variables as Double as opposed to _Float. If floating point is truly not being used, then that would imply that the significant speed boost is caused by the updated BIOS. Which seems surprising to me.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Holy speed daemon, Batman!
« Reply #8 on: June 21, 2021, 03:46:49 am »
It chokes. Can't find your custom library.

It’s there at the bottom of that post,  You just need to download the fpp.h and put it in your QB64 folder.

(Or, copy the following and save it as fpp.h)

Code: [Select]
void set_dpfpu() { unsigned int mode = 0x37F; asm ("fldcw %0" : : "m" (*&mode));}
void set_qbfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));}

Then, with the declare library, you can toggle between the old math and new math, which we swapped out, under the hood.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: Holy speed daemon, Batman!
« Reply #9 on: June 21, 2021, 04:55:56 pm »
Ah, right, there it was. Thanks.

So, first I confirmed that the new scheme fixes the math problem, just using your program and toggling back and forth. It works fine.

Then, I copied it to the top of my test program, toggled to the old floating point scheme, ran the test, and it didn't make a lick of difference to the results.

Sure am impressed with these latest BIOS versions, then. You can tell immediately, when running the test, how much faster it flies by than it used to. Incroyable.