Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X
My mathcad worksheet is crazy slow. I have highlighted the problem code in yellow box.
I have named it ProblemDate(d). Once you rename it Date(d) it's gonna slow down a lot.
scroll down slowly and you will see that the equations are now taking more time to compute. Once you hit the first graph it will just go to sleep.
Can anyone tell me how to optimize it. i'm attaching my code. Mathcad 14 only. it contains scripts that mathcad 11 doesn't like.
Solved! Go to Solution.
Richard Jackson wrote:
You can't.
That is not quite correct
Well, with mathcad it's true that almost always one can. In the attached optimization done; also only one script for enabling and not a "vectorization" but a "discretization" for dates failing in the year of the date given by "Num". As bonus, now works in mc11.
Regards. Alvaro.
You can't. Script functions are only for do some few calculations, you can't call vbscript code a lot of times. If you want accelerete the code must to write a dll in c++ or the mathcad functions without scripting.
Without calling the script (ie, without renaming the date function) seems to be now enough quickly. Optimized via "not double eval the same", but just inside each function. It can be optimize more doing the same, but not calling some intermediate functions, and evaluating it inside some "important" functions.
Regards. Alvaro.
But why is it calling the script so many times anyway.
Here is a simple example
F(x):= CallScript(x)
G(x,y):=F(x)+y
Now i plot G(1,y) versus y
I have already fixed the x value. the script should be run once and the result saved. why is it running for every value of y when it doesn't even depend on y.
If i was doing G(x,1) then i can understand why the script will have to run for every value of x.
Ziyad Saeed wrote:
But why is it calling the script so many times anyway.
Here is a simple example
F(x):= CallScript(x)
G(x,y):=F(x)+y
Now i plot G(1,y) versus y
I have already fixed the x value. the script should be run once and the result saved. why is it running for every value of y when it doesn't even depend on y.
If i was doing G(x,1) then i can understand why the script will have to run for every value of x.
I'm afraid you're confused; you're calling F(x) for each value of y. If you know that F(x) is constant, then you should modify G(x,y) to reflect that. Even if you have G(1,y), that's still a call to F(x), by your own function definition.
TTFN
There should be a way to cache the result of of the script in an array. with an if statement i can check if the array already has the required result then return that else run the script.
This should work in theory.
Ziyad Saeed wrote:
But why is it calling the script so many times anyway.
Here is a simple example
F(x):= CallScript(x)
G(x,y):=F(x)+y
Now i plot G(1,y) versus y
I have already fixed the x value. the script should be run once and the result saved. why is it running for every value of y when it doesn't even depend on y.
In your case y is a range variable though. A range variable is an iterator, like a loop variable. It means G(1,y) will be executed once for each value of y. That in turns calls F(x). What you would need to do is this:
Constant:=CallScript(1)
G(y):=Constant+y
Then plot G(y) against y.
If you want to call the script for multiple values do NOT use a range variable. CallScript(x) will be very slow if x is a range variable because it will call the script once for each value of x. On the other hand, if x is a vector of values it will call the script only once. If you want to get an idea of just how much diference that makes run the attached worksheet. On my computer using a vector rather than a range variable is about 700 times faster!
You can't.
That is not quite correct
Script functions are only for do some few calculations, you can't call vbscript code a lot of times. If you want accelerete the code must to write a dll in c++ or the mathcad functions without scripting.
It's true that you don't want to call a function based on a scripted component a lot of times, but it is not true that they are thus only good for a few calculations. It specifically says in the worksheet for date and time functions that calling the component multiple times is very slow, and that the function is therefore written to take a vector of values. To speed it up the worksheet needs to work with vectors, not range variables. I just haven't had time to modify it.
Richard Jackson wrote:
You can't.
That is not quite correct
Well, with mathcad it's true that almost always one can. In the attached optimization done; also only one script for enabling and not a "vectorization" but a "discretization" for dates failing in the year of the date given by "Num". As bonus, now works in mc11.
Regards. Alvaro.
Your attached file is lot faster. Thanks for the optimizations
you have done some changes to other formulas as well they are lot faster now as well.
one questions you have turned variables like MA(d,hrs) to just MA by using the back arrow syntax. Does that optimize code or does it just make stuff shorter to type? I noticed you only do this for variables that are being repeated in one formula. if it optimizes code then all these years i have doing it the wrong way
These optimizing tips should be in the help file.
btw h is in km. it's height above sealevel. the solar radiation increases for every km above sea level. Which in tern makes everything all crazy. cause now the sunrise and sunsets are all off. Elevation angles are all off as well you can see the sun even at negative elevations. Sadly the PSA algorithm doesn't take into account the height of the location.
The key is to set everything up so that you only call the component based function once. This shows how to do that. I only changed the sheet up to the first graph, but it should be clear what you need to do for the rest.
did you recreate your own date formulas or are they hidden away somewhere.
did you recreate your own date formulas or are they hidden away somewhere.
Yes, they are redefined. They all rely on a call to the single scripted component function that executes VBscript code. There are a couple of downsides to doing it that way:
1) You need to know VBscript (something of a moot point in this case I guess, since Alvaro has defined the necessary Date functions)!
2) The functions handle a vectors of values by calling the component multiple times. As already discussed, that is very slow.
Actually, there is a small bug too. The first time the component is called you get back "VBS: Something is wrong". Either the script needs to be modified with "Dim ans" at the top, or the component needs to be called once as VBS("Dim ans") to initialize it.
you should include Alvaroz date functions in your date function file that you have uploaded.
you should include Alvaroz date functions in your date function file that you have uploaded.
They don't do anything the existing date functions don't already do. In fact, they do rather less since they don't handle vectors of dates. I'm not sure why he redefined them that way.
Richard Jackson wrote:
you should include Alvaroz date functions in your date function file that you have uploaded.
They don't do anything the existing date functions don't already do. In fact, they do rather less since they don't handle vectors of dates. I'm not sure why he redefined them that way.
I just playing with the avaibility of enable only one vbscript component to call any vbscript code. I have exported VBS function as component -but with my own name, hard to discover-, and have it enable for calling vbscript code at any time.
It's right, not only have less functionality, also handle with some others restrictions original functions, which are more robusts and complete. This is the why I redefine this functions -also have another version with components that shows the code to be executed.
The "Dim ans" at the top was deleted in the component, it must to have it.
The actual "optimization" was done storing all results in the DATE array, for a year from the date in Num, and redefining Date function as an element of DATE. In this way script was called only 366 times for the calculus of alpha. It can be made with the originals date functions.
I don't study the Richard's optimized file post -have not mcad rigth now.
Assignations like HRA <- HRA(d,hrs) in the functions are doing in the assumption that any program is faster doing assignations than function evaluations. This is an accepted axiom for every programming language.
Hope above explains some other several posts.
Best regards. Alvaro.
Mathcad 14 only. it contains scripts that mathcad 11 doesn't like.
It's not the scripts, it's just the DMS function. If you define a DMS function it works fine. In fact, it doesn't have the speed problems that it has in version 14!
the FillVec to create the hrs variable instead of a range variable should be part of the optimizing tips section somewhere.
There are many versions of that function kickng around, both with that name and with different names. In my opinion it should be a built in Mathcad function.
just curious.
Now i have to run the hrs variable for every single day of the year. Thats going to be lots and lots of iterations.
So the FillVec function for hrs will greatly speed up the computations right?
So the FillVec function for hrs will greatly speed up the computations right?
The FillVec function is just an easy way to fill a vector with values. What matters is that if you want to use the date functions for multiple values you put the values in a vector, and pass the vector to the functions. How you create the vector makes no difference to the speed.
Take an example function:
f(x):=3*x^2+12*x+1/x
If you use a range variable it is not a set of values. It is an iterator, defined by a start, an increment, and an end.
n:=10
i:=0,1...10
Answer[i:=f(i)
So the function f is called n+1 times, and each time it is called it is passed a scalar value, which is the current value of i.
If you use a vector that is a set of values
V:=FillVec(0,1...10)
Answer:=f(V)
so f is called once, and is passed all the values at one time. It then returns a vector of answers.
In most cases the overhead in calling a function is very low, so it makes little difference to the calculation speed which way you do it. But the overhead in calling a function based on a component is very high (in versions 12 or later; in versions 11 and earlier this was not a major problem) so you need to pass it a vector.
Richard,
Fantastic explanation - as in the other thread statements like these should also be included in the "wiki document". How many times just this get queried?
Mike
The interesting thing about range variables vs vectors is that nobody ever asks. Misunderstandings about the difference (or even that there is a difference) leads to an almost continuous stream of problems though!
They are easily confused at first though, because Mathcad doesn't have functions to create range vectors and therefore the only way to learn is through forums.
Mike
or Mathcad internally can treat range variables as vectors and then we never have to worry about them at all.
or Mathcad internally can treat range variables as vectors and then we never have to worry about them at all.
There was a discussion about that some time ago. We came to the conclusion that there were certain case where that was not desirable and/or would break existing worksheets. Off the top of my head, I don't recall what those cases were though.
Any idea if Mathcad prime will improve up this