Author Topic: This two codes do the same thing...  (Read 5594 times)

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
This two codes do the same thing...
« on: February 09, 2013, 10:52:55 AM »
(had to tone it down a little to make it more presentable :p)

Numsgil, correct me if I am wrong on this:

Code: [Select]
'calculates difference between two angles (A)
Private Function angle_compare(ByVal ang1 As Double, ByVal ang2 As Double) As Double
'A dot B = |A| * |B| * cos(angle between them)
'(A dot B) / (|A| * |B|) = cos(angle between them)
'-(A cross B) / (|A| * |B|) = sin(angle between them)
Ay = Sin(ang1 / 180 * pi)
Ax = Cos(ang1 / 180 * pi)
By = Sin(ang2 / 180 * pi)
Bx = Cos(ang2 / 180 * pi)
mydotproduct = Ax * Bx + Ay * By
resultingcos = mydotproduct
mycrossproduct = Ax * By - Ay * Bx
resultingsin = -mycrossproduct

k = angle(resultingcos, resultingsin, 0, 0) / pi * 180
If k > 180 Then k = k - 360
angle_compare = k
End Function

'calculates difference between two angles (B)
Public Function AngDiff(ByVal a1 As Double, ByVal a2 As Double) As Double
a1 = a1 / 180 * pi
a2 = a2 / 180 * pi
  Dim r As Double
  r = a1 - a2
  If r > pi Then
    r = -(2 * pi - r)
  End If
  If r < -pi Then
    r = r + 2 * pi
  End If
  AngDiff = r * 180 / pi
End Function

I am actually preferring version B for several reasons:

1.) Smaller
2.) Less CPU intensive
3.) It is already build in (I need this for a function I am planning in DarwinBots)
4.) It does not make sense for me to use Sin, Cos and ArcTangent if I can avoid them.

Don't get me wrong, it is still a very cool formula. And, probably still useful in other applications.
« Last Edit: February 13, 2013, 11:42:12 AM by Botsareus »

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Re: This two codes do the same thing...
« Reply #1 on: February 11, 2013, 02:50:24 AM »
It's weird that the first function is converting from angles to vectors and then back, yeah.  As to whether they do the same thing or not... What happens in the second one if one of the inputs is > 4pi?  Also, why are you converting to radians, and then converting back to degrees at the end?

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #2 on: February 11, 2013, 03:14:54 PM »
Quote
What happens in the second one if one of the inputs is > 4pi?

Well, it is always used together with 'angnorm' :

Code: [Select]
' normalizes angle in 0,2pi
Public Function angnorm(ByVal an As Single) As Single
  While an < 0
    an = an + 2 * PI
  Wend
  While an > 2 * PI
    an = an - 2 * PI
  Wend
  angnorm = an
End Function

Quote
Also, why are you converting to radians, and then converting back to degrees at the end?

Ah, no that's for my personal experiments. I guess I learned trig originally using degrees and just prefer that over radians, this has nothing to do with DarwinBots but I do use this in my personal projects. -I did not want to bother modify the version B  function too much. Just corrected it for the values my system uses in my personal experiment and checked it against version (A) I was very surprised when I found out it worked perfectly, here is the full source, maybe when you have time you can check it out:

Code: [Select]
Private Const pi = 3.14159265358979
Dim ang1 As Double
Dim ang2 As Double

Dim a As Double

Dim i As Byte

Private Sub Form_Load()
ang2 = 180
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
sx = ScaleWidth / 2
sy = ScaleHeight / 2
cang1 = ang1 / 180 * pi
cang2 = ang2 / 180 * pi
If Sqr((X - Cos(cang1 + pi) * sx / 1.5 - sx) ^ 2 + (Y - Sin(cang1 + pi) * sy / 1.5 - sy) ^ 2) < 200 Then
i = 1
ElseIf Sqr((X - Cos(cang2 + pi) * sx / 1.5 - sx) ^ 2 + (Y - Sin(cang2 + pi) * sy / 1.5 - sy) ^ 2) < 200 Then
i = 2
End If
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
sx = ScaleWidth / 2
sy = ScaleHeight / 2
If i = 1 Then
ang1 = angle(sx, sy, X, Y) * 180 / pi
End If
If i = 2 Then
ang2 = angle(sx, sy, X, Y) * 180 / pi
End If
End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
i = 0
End Sub

Private Sub Timer1_Timer() 'enabled = true; interval = 1
Dim cang1 As Double
Dim cang2 As Double

cang1 = ang1 / 180 * pi
cang2 = ang2 / 180 * pi
Cls
sx = ScaleWidth / 2
sy = ScaleHeight / 2
'screen
Me.Circle (sx, sy), sx / 1.5, vbWhite
'line1
Me.Line (sx, sy)-(sx - Cos(cang1) * sx / 1.5, sy - Sin(cang1) * sy / 1.5), vbBlue
Me.Circle (sx - Cos(cang1) * sx / 1.5, sy - Sin(cang1) * sy / 1.5), 200, vbBlue
'line2
Me.Line (sx, sy)-(sx - Cos(cang2) * sx / 1.5, sy - Sin(cang2) * sy / 1.5), vbGreen
Me.Circle (sx - Cos(cang2) * sx / 1.5, sy - Sin(cang2) * sy / 1.5), 200, vbGreen

a = (a + 1) Mod 50
res = AngDiff(ang1, ang2)


'line3
lang = cang2 + a / 50 * res / 180 * pi



Me.Line (sx, sy)-(sx - Cos(lang) * sx / 1.5, sy - Sin(lang) * sy / 1.5), vbRed
End Sub

'calculates difference between two angles
Private Function angle_compare(ByVal ang1 As Double, ByVal ang2 As Double) As Double
'A dot B = |A| * |B| * cos(angle between them)
'(A dot B) / (|A| * |B|) = cos(angle between them)
'-(A cross B) / (|A| * |B|) = sin(angle between them)
Ay = Sin(ang1 / 180 * pi)
Ax = Cos(ang1 / 180 * pi)
By = Sin(ang2 / 180 * pi)
Bx = Cos(ang2 / 180 * pi)
mydotproduct = Ax * Bx + Ay * By
resultingcos = mydotproduct
mycrossproduct = Ax * By - Ay * Bx
resultingsin = -mycrossproduct

k = angle(resultingcos, resultingsin, 0, 0) / pi * 180
If k > 180 Then k = k - 360
angle_compare = k
End Function

'calculates difference between two angles
Public Function AngDiff(ByVal a1 As Double, ByVal a2 As Double) As Double
a1 = a1 / 180 * pi
a2 = a2 / 180 * pi
  Dim r As Double
  r = a1 - a2
  If r > pi Then
    r = -(2 * pi - r)
  End If
  If r < -pi Then
    r = r + 2 * pi
  End If
  AngDiff = r * 180 / pi
End Function


Private Function angle(ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single) As Single
        Dim an As Single
        Dim dx As Single
        Dim dy As Single
        dx = x1 - x2
        dy = y1 - y2
        If dx = 0 Then
            'an = 0
            an = pi / 2
            If dy < 0 Then an = pi / 2 * 3
        Else
            an = Math.Atn(dy / dx)
            If dx < 0 Then
                an = an + pi
            End If
        End If
        If an < 0 Then an = an + pi * 2
        angle = an
End Function
« Last Edit: February 11, 2013, 03:25:52 PM by Botsareus »

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #3 on: February 13, 2013, 11:31:51 AM »
Just ran another experiment. 'angnorm' is slowing down version B considerably. So, unless you have angles that perfectly fit in the 0 to 2 pi range, you are better of using the first function I described. Although I would have never thought how computationally inexpensive converting to vectors and then back to angles is, Numsgil is still the god of video game mathematics.  :Headbang: I rest my case.

P.S.

Now I feel a little dumb because I should of ran a test like this in the first place...
« Last Edit: February 15, 2013, 03:37:26 PM by Botsareus »

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #4 on: February 15, 2013, 01:24:18 PM »
Numsgil, please help me figure this out, it is not making much sense:

So, my input is

Code: [Select]
ang1 = (Rnd * 1200 - 400) / 180 * pi 'never converted back to degrees

The function

Code: [Select]
...
e = e + 1
Caption = e & "AngDiff" & angnorm(ang1)
DoEvents
Loop

is faster then

Code: [Select]
...
e = e + 1
Caption = e & "AngComp" & angle(Cos(ang1), Sin(ang1), 0, 0)
DoEvents
Loop

Meanwhile, the function

Code: [Select]
...
e = e + 1
Caption = e & "AngComp2" & angle_compare(ang1, ang2)
DoEvents
Loop

is faster then

Code: [Select]
...
e = e + 1
Caption = e & "AngDiff2" & AngDiff(angnorm(ang1), angnorm(ang2))
DoEvents
Loop

See post above to figure out what 'AngDiff' 'angnorm' 'angle_compare' and 'angle' do

My qustion to you is: Where is my performance loss? Because as far as I can tell

Code: [Select]
angle(Cos(ang1), Sin(ang1), 0, 0)
should be faster then

Code: [Select]
angnorm(ang1)


Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Re: This two codes do the same thing...
« Reply #5 on: February 16, 2013, 01:57:35 AM »
Be careful throwing text operations in to a loop you're trying to time.  It can screw up the timings by adding a lot of noise (eg: cache threashing).

Your best bet is to get a proper profiler.  It can then tell you the exact line that's slowing down code.  I managed to get Darwinbots running in VTune years and years ago.  There might be another profiler you could use.  The trick is to generate the a PDB symbols file with the EXE.  There's an option to do it somewhere.

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #6 on: February 16, 2013, 10:58:52 AM »
Quote
Be careful throwing text operations in to a loop you're trying to time.  It can screw up the timings by adding a lot of noise (eg: cache threashing).

Angdiff is only compared agenst AngComp (both strings are 7 letters long) and Angdiff2 is only compared agenst AngComp2 (both strings are 8 letters long) and all inputs are the same (seed is same).

I am not using threading and just running multiple exes at once. I managed to get windows to load them in different order and still my time difference is about 500 clicks (the first number before "Ang...")

Quote
Your best bet is to get a proper profiler.

VTune is "Try it for 30 days free" and they make you register  :wacko:

How does a profiler work anyway? Does it tell you the milliseconds every line took to execute?

I am getting the feeling you can't tell whats slowing it down and where just by looking at the code segments I submitted. Should I send you the whole code so you can look when you have time? (It is very small and reasonably easily written, although both projects are named the same in different folders)

Can not find any other free vb6 Performance Analyzer programs.

thx for help

The only thing that can make my week better is if the problem is CPU specific  :P
« Last Edit: February 16, 2013, 03:48:04 PM by Botsareus »

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #7 on: February 16, 2013, 03:48:46 PM »
Numsgil has found me a free profiler. It totally worked! Now I just have figure out what the hell I am looking at.

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #8 on: February 24, 2013, 01:19:50 PM »
After running each module 3 times (6 total) results are:

Code: [Select]
angnorm(ang1) got less processor hits then
Code: [Select]
angle(Cos(ang1), Sin(ang1), 0, 0)
And it turns out that
Code: [Select]
AngDiff(angnor1(ang1), angnor2(ang2)) got less processor hits then 
Code: [Select]
angle_compare(ang1, ang2)
So it is indeed faster to use AngDiff in all cases.

Some things I took away from this experience:

1.) Vb6 may have 'phantom code' running. This kind of code eats up CPU time but does not produce any output to the user. You need to do a lot of smart programming to make sure your program does not contain any 'phantom code'

2.) It is sometimes better to distribute your variables instead of using one-liners. It may slow down the program a little but it will make the program allot easier to debug.

3.) Writing text to screen or the window's caption slows down your code considerably. Also, due to inherent instability of CPU usage by the OS it will most likely produce completely un-time-able results.

4.) Funny thing I discovered in vb6. If two functions do exactly the same thing but are named differently, the compiler ignores the second function and automatically makes the compile pointer to point on the first function. I guess it was a way for them to save on the programs size when it is compiled.

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Re: This two codes do the same thing...
« Reply #9 on: February 26, 2013, 03:57:06 AM »
VB6 has some crazy things going on under the hood.  It was definitely an exercise in frustration trying to get anything in it to run efficiently.

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #10 on: March 08, 2013, 02:46:27 PM »
Quote
It was definitely an exercise in frustration trying to get anything in vb6 to run efficiently.

I have a feeling it gotten easyer in .NET, but I still want to know 'how' it is easyer ...

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Re: This two codes do the same thing...
« Reply #11 on: March 09, 2013, 12:16:33 AM »
It's a lot easier, actually.  The JITter that .NET uses is pretty clever and can eliminate a lot of code overhead.  The main downside vs. C or C++ in terms of speed is mainly that you don't really have access to any SIMD commands.  If you're adventurous you can write some wrappers around C functions and call them from C# tho.

Offline Botsareus

  • Society makes it all backwards - there is a good reason for that
  • Bot God
  • *****
  • Posts: 4483
    • View Profile
Re: This two codes do the same thing...
« Reply #12 on: March 09, 2013, 04:38:06 PM »
I guess they got rid of SIMD to keep it sane for the users that prefer VB.NET.

Can I get some kind of picy on how the .NET JITter looks like?

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Re: This two codes do the same thing...
« Reply #13 on: March 09, 2013, 05:29:23 PM »
I think they avoid SIMD to make it easier for the intermediate language to be machine independent.

Google around for C# and JIT, and you should learn more of the details.