|
-
Feb 2nd, 2011, 08:41 PM
#1
Thread Starter
Addicted Member
[VB.NET 4.0] Can you speed up this function? :)
I have some code for calculating a "polytrope" (a good model for some types of star). I was reading some optimisation threads on this forum today and it made me curious enough to try to make it faster. It was already probably the most efficient program I'd made since it was my first truly multithreaded application (that actually benefited hugely from it).
Moving "Math.PI" into a constant so it's only called once didn't make any measurable difference in the time taken. However, replacing two occurrences of "r ^ 2" with a new variable initialised to "r ^ 2", which was then used twice, improved the speed of the code by 35%!
I don't actually need this code as it's from an old program but I'm just curious to see if there are any other efficiency improvements one could make?
P.S. This is running in 64-bit mode so I don't think changing any of the Doubles into Singles will improve speed.
VB Code:
Public Const G As Double = 0.00000000006674 'gravitational constant Public Const Pi As Double = Math.PI 'Pi Public Function CalculatePolytrope(ByVal n As Double, ByVal StepSize As Double, ByVal Rho As Double, ByVal P As Double) As Double() Dim K As Double = P / (Rho ^ ((n + 1) / n)) 'constant of polytrope model Dim m As Double = 0 'mass Dim r As Double = 0 - StepSize 'radius Dim dP_dr As Double 'dP/dr Dim dm_dr As Double 'dm/dr Dim rSquared As Double 'r^2 'Process loop until Rho or P are equal to (or less than) zero: Do 'Increment r r += StepSize 'This prevents dP/dr and dm/dr becoming NaN ("not a number") when r = 0 If r = 0 Then dP_dr = 0 dm_dr = 0 Else rSquared = r ^ 2 dP_dr = -(G * m * Rho) / rSquared dm_dr = 4 * Pi * Rho * rSquared End If 'Calculate new mass and pressure m += StepSize * dm_dr P += StepSize * dP_dr 'This prevents square rooting a minus number, which would make Rho NaN ("not a number") If P > 0 Then Rho = (P / K) ^ (n / (n + 1)) Else Rho = 0 End If Loop Until Rho <= 0 OrElse P <= 0 'Create an array of doubles to hold our final M and R then return them to the calling subroutine. Dim Results() As Double = {m, r} Return Results End Function
Last edited by DragonQ; Feb 2nd, 2011 at 09:08 PM.
-
Feb 3rd, 2011, 05:52 AM
#2
Re: [VB.NET 4.0] Can you speed up this function? :)
A minor improvement would be to alter lines 19 to 30, because m and p will only be altered if r is not 0. As such, you could use this to get the same behaviour:
Code:
If r <> 0 Then
rSquared = r ^ 2
dP_dr = -(G * m * Rho) / rSquared
dm_dr = 4 * Pi * Rho * rSquared
'Calculate new mass and pressure
m += StepSize * dm_dr
P += StepSize * dP_dr
End If
...and maybe even eliminate dP_dr and dm_dr.
While storing Pi didn't do you much good, storing 4*Pi (which is what you actually use) is likely to be better.
As n doesn't change inside the loop, it would be a good idea to store (n / (n + 1)) to a variable too.
Due to the conditions/values used in lines 32 to 38, you could simplify that a bit too, eg:
Code:
'This prevents square rooting a minus number, which would make Rho NaN ("not a number")
If P <= 0 Then Exit Do
Rho = (P / K) ^ (n / (n + 1))
Loop Until Rho <= 0
-
Feb 4th, 2011, 08:17 PM
#3
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Thanks for the suggestions! I've read that using >= or <= is slower than > or < so I've tried to avoid using them in this new version. By setting Rho to -1 instead of 0 if "P > 0" is false, I can change the loop condition to "Rho < 0", which should be a bit quicker.
Below is what I have now. This version is 4% faster (averaged over 5 tests) than the version I posted above (which was in turn 35% faster than the code I started with):
VB Code:
'
Public Const G As Double = 0.00000000006674 'gravitational constant
Public Const Pi_x4 As Double = Math.PI * 4 '4 Pi
Public Function CalculatePolytrope(ByVal n As Double, ByVal StepSize As Double, ByVal Rho As Double, ByVal P As Double) As Double()
Dim PolytropeIndex As Double = n / (n + 1) 'n / (n + 1)
Dim K As Double = P / (Rho ^ (1 / PolytropeIndex)) 'constant of polytrope model
Dim m As Double = 0 'mass
Dim r As Double = 0 - StepSize 'radius
Dim dP_dr As Double 'dP/dr
Dim dm_dr As Double 'dm/dr
Dim rSquared As Double 'r^2
'Process loop until Rho or P are equal to (or less than) zero:
Do
'Increment r
r += StepSize
'This prevents dP/dr and dm/dr becoming NaN ("not a number") when r = 0
If r = 0 Then
dP_dr = 0
dm_dr = 0
Else
rSquared = r ^ 2
dP_dr = -(G * m * Rho) / rSquared
dm_dr = Pi_x4 * Rho * rSquared
End If
'Calculate new mass and pressure
m += StepSize * dm_dr
P += StepSize * dP_dr
'This prevents square rooting a minus number, which would make Rho NaN ("not a number")
If P > 0 Then
Rho = (P / K) ^ PolytropeIndex
Else
Rho = -1
End If
Loop Until Rho < 0
'Create an array of doubles to hold our final M and R then return them to the calling subroutine.
Dim Results() As Double = {m, r}
Return Results
End Function
Here's a couple of other things I've tried without measurable effect:
- Making the "G" variable negative so it doesn't need to be made negative each time dP_dr is calculated.
- Moving the negative sign from the dP_dr calculation to the "P += ..." line (change to "P -= ...")
And here's some more things I've tried that all make the code slower (bizzarly):
- Changing the "If r = 0" condition to "If r <> 0" or "If r > 0" or "If Not r = 0" and swapping the If/Else sections around.
- Changing "Rho = -1" to "Exit Do".
- Putting the "m += ..." and "P += ..." lines inside the Else section of the "If r = 0" condition.
- Getting rid of dP_dr and dm_dr in conjunction with the previous change.
- Commenting out the unneeded "dP_dr = 0" and "dm_dr = 0" lines.
Strange...
-
Feb 4th, 2011, 08:54 PM
#4
Frenzied Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Instead of initializing a variable to return, you can return directly:
Code:
Return New Double() {m, r}
Instead of try(ya I know it's minor)
-
Feb 4th, 2011, 09:13 PM
#5
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Woah...replacing "r ^ 2" with "r * r" improved speed by a further 69%! Ridiculous. That means compared to what I started with, the code is now ~140% faster (~2.4x). 
EDIT: After some further trial-and-error, the fastest I can get so far is a ~165% improvement (2.65x). Here's the code for this:
VB Code:
' Public Const G As Double = 0.00000000006674 'gravitational constant Public Const Pi_x4 As Double = Math.PI * 4 '4π Public Function CalculatePolytrope(ByVal n As Double, ByVal StepSize As Double, ByVal Rho As Double, ByVal P As Double) As Double() Dim PolytropeIndex As Double = n / (n + 1) 'n / (n + 1) Dim K As Double = P / (Rho ^ (1 / PolytropeIndex)) 'constant of polytrope model Dim m As Double = 0 'mass Dim r As Double = 0 - StepSize 'radius Dim dP_dr As Double 'dP/dr (excluding Rho term) Dim rSquared As Double 'r^2 Dim StepSize_x_Rho As Double 'StepSize x Rho 'Process loop until Rho or P are equal to (or less than) zero: Do 'Increment r r += StepSize 'This prevents dP/dr and dm/dr becoming NaN ("not a number") when r = 0 If r > 0 Then rSquared = r * r dP_dr = (G * m) / rSquared StepSize_x_Rho = StepSize * Rho 'Calculate new mass and pressure m += (StepSize_x_Rho * Pi_x4 * rSquared) P -= (StepSize_x_Rho * dP_dr) End If 'This prevents square rooting a minus number, which would make Rho NaN ("not a number") If P > 0 Then Rho = (P / K) ^ PolytropeIndex Else Rho = -1 End If Loop Until Rho < 0 'Create an array of doubles to hold our final M and R then return them to the calling subroutine. Return {m, r} End Function
Last edited by DragonQ; Feb 4th, 2011 at 09:59 PM.
-
Feb 5th, 2011, 06:02 AM
#6
Re: [VB.NET 4.0] Can you speed up this function? :)
Is it possible for the the Rho value to ever be 0 or less from the calculation? If so are you sure that your loop exit condition is apt?
In terms of speed I suspect the quickest code for it would be Loop Until Rho = 0 , but that could lead to a change in behaviour.
-
Feb 5th, 2011, 09:29 AM
#7
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
That is true, the condition could be changed to "Rho = 0" without a change in behaviour. It doesn't improve speed though, unfortunately.
The original program managed to perform the calculation with a range of input values that I originally made the code for in 414 s (5000 runs, 8 threads at a time, i7 920 @ 3.8 GHz). The current version (post 5) does it in 154 s.
-
Mar 15th, 2011, 05:10 PM
#8
Re: [VB.NET 4.0] Can you speed up this function? :)
I don't know if this does anything for speed, but stop initializing variables to 0, and replace 0 - stepSize with just -stepSize, it looks better 
At the end instead of setting Rho to -1 you could use GoTo and maybe take out the loop, I wonder how that would work?
For conciseness, take out all those unnecessary parentheses (like around Stepsize_x_Rho * Pi_x4 * rSquared and G * m and Stepsize_x_Rho * dp_dr).
-
Mar 15th, 2011, 09:13 PM
#9
Re: [VB.NET 4.0] Can you speed up this function? :)
 Originally Posted by minitech
Actually, r ^ 2 = r * r. Sorry.
Yeah, I tried explaining it but I wrote the equation incorrectly thinking r*r*r = r ^2 when it was meant to be r *r = r ^2. I deleted my original post because it was too long-winded and confusing. Although, the above still doesn't seem to explain why r*r would be faster than r^2?
Edit:
Maybe the fact that DragonQ had rSquared dimmed as double had something to do with it.
Last edited by Nightwalker83; Mar 15th, 2011 at 09:16 PM.
Reason: Adding more!
when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
https://get.cryptobrowser.site/30/4111672
-
Mar 15th, 2011, 09:17 PM
#10
Re: [VB.NET 4.0] Can you speed up this function? :)
^ is an operator that implicitly uses Doubles on both sides and performs a multitude of completely unnecessary operations to accomodate decimal and negative powers. Multiplication, being a fundamental binary operation, is much faster.
-
Mar 20th, 2011, 09:17 AM
#11
Re: [VB.NET 4.0] Can you speed up this function? :)
@Dragon - post sample data in the following format please
Code:
Dim smplData() As Double = New Double() {n, StepSize, Rho, P, M_answer, R_answer, _
n, StepSize, Rho, P, M_answer, R_answer, _
n, StepSize, Rho, P, M_answer, R_answer}
replacing the variables with the actual values. Two or three sets should be good, more if you want.
-
Mar 20th, 2011, 09:59 AM
#12
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Code:
Dim smplData() As Double = New Double() {1, 1000, 4.6E+1, 4.4E+10, 2.005282E+028, 6.995690E+008, _
1, 1000, 4.6E+3, 4.4E+12, 2.005340E+027, 6.995200E+007, _
1, 1000, 4.6E+5, 4.4E+14, 2.005925E+026, 6.991000E+006}
-
Mar 20th, 2011, 11:37 AM
#13
Re: [VB.NET 4.0] Can you speed up this function? :)
Maybe a little better, but it is hard to tell...
Code:
Private Sub Button2_Click(sender As System.Object, _
e As System.EventArgs) Handles Button2.Click
Dim sd() As Double = New Double() {1, 1000, 46.0, 44000000000.0, 2.0052816957994727E+28, 699569000.0, _
1, 1000, 4600.0, 4400000000000.0, 2.0053401856028196E+27, 69952000.0, _
1, 1000, 460000.0, 440000000000000.0, 2.0059251372079435E+26, 6991000.0}
Dim stpw As New Stopwatch
stpw.Start()
For y As Integer = 1 To 20
For x As Integer = 0 To sd.Length - 1 Step 6
Dim ans() As Double = CalculatePolytrope(sd(x), sd(x + 1), sd(x + 2), sd(x + 3))
If ans(0) = sd(x + 4) AndAlso ans(1) = sd(x + 5) Then
'Debug.WriteLine("m={0} r={1}", ans(0), ans(1))
Else
Stop
End If
Next
Next y
stpw.Stop()
'Debug.WriteLine(stpw.ElapsedMilliseconds.ToString("n0"))
TextBox1.Text = stpw.ElapsedMilliseconds.ToString("n0")
End Sub
Public Const G As Double = 0.00000000006674# 'gravitational constant
Public Const Pi_x4 As Double = Math.PI * 4 '4π
Public Function CalculatePolytrope(ByVal n As Double, _
ByVal StepSize As Double, _
ByVal Rho As Double, _
ByVal P As Double) As Double()
Dim PolytropeIndex As Double = n / (n + 1) 'n / (n + 1)
Dim K As Double = P / (Rho ^ (1 / PolytropeIndex)) 'constant of polytrope model
Dim m As Double 'mass
Dim r As Double = -StepSize 'radius
Dim dP_dr As Double 'dP/dr (excluding Rho term)
Dim rSquared As Double 'r^2
Dim StepSize_x_Rho As Double 'StepSize x Rho
'Process loop until Rho or P are equal to (or less than) zero:
Do
'Increment r
r += StepSize
'This prevents dP/dr and dm/dr becoming NaN ("not a number") when r = 0
If r > 0 Then
rSquared = r * r
dP_dr = (G * m) / rSquared
StepSize_x_Rho = StepSize * Rho
'Calculate new mass and pressure
m += (StepSize_x_Rho * Pi_x4 * rSquared)
P -= (StepSize_x_Rho * dP_dr)
If P <= 0 Then Exit Do
End If
Rho = (P / K) ^ PolytropeIndex
Loop Until Rho < 0
'Create an array of doubles to hold our final M and R then return them to the calling subroutine.
Return {m, r}
End Function
-
Mar 20th, 2011, 11:50 AM
#14
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Nice try but it's no quicker. 
It's probably a good idea to give you the settings used for my benchmark which gives me 4.10-4.15 seconds with my current code (the slowest of the 9 original calculations the program was intended for):
vb Code:
'
Dim StartTime as DateTime = DateTime.Now
Dim Results As Double() = CalculatePolytrope(1, 1000, 46.0, 440000000000000.0)
Dim TimeElapsed As TimeSpan = DateTime.Now.Subtract(StartTime)
txtTimeElapsed.Text = Format((TimeElapsed.TotalMilliseconds / 1000), "##0.00").ToString & " s"
-
Apr 4th, 2011, 01:50 AM
#15
Re: [VB.NET 4.0] Can you speed up this function? :)
(a/b)^x same as a^x / b^x
K ^ PolytropeIndex is a constant
-
Apr 4th, 2011, 04:58 AM
#16
Thread Starter
Addicted Member
Re: [VB.NET 4.0] Can you speed up this function? :)
Good suggestion but again that idea ends up slowing the program down (4.25-4.30 s vs 4.10-4.15 s).
-
Apr 4th, 2011, 05:36 AM
#17
Re: [VB.NET 4.0] Can you speed up this function? :)
I see.
I'm curious though why you didn't use a formula based on dM/dr since you are after mass anyway. isn't it possible? Maybe the algorithm and computation would be more efficient with that approach.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|