Converting script to function causing significant slowdown?
Mostrar comentarios más antiguos
I have an inherited project (roughly 5k lines) where the previous author has set everything up as several scripts that all execute in the base workspace, example structure:
- Main
- - Script 2
- - Script 3
- -- Script 3b
etc.
The general application flow is to load in parameters from Excel (currently that is used as a 'front end'), run the calculations, then export the data (both to Excel and other formats). The entire processing time varies with the input parameters, but in general takes ~80 seconds to complete on my machine.
This application eventually needs to be compiled. I'm able to run it as a deployed application and the processing time is approximately the same, no issue there.
However, I have a need to call the compiled application directly from Excel, and pass it parameters while doing this. To accomplish this I simply converted the main.m script into a function, eg below
function main(input1, input2)
When I do this however, in every format I run the application now (deployed, called from Excel, native Matlab/ non-deployed) it takes significantly longer to run through. From ~80 seconds to 10+ minutes.
My question is, am I doing anything fundamentally wrong here just converting main.m to a function like I did? If so, is there a better way to pass parameters to a deployed application? (my ultimate goal) Or does anyone know why changing just my main.m into a function from a script would cause a huge slowdown?
Thanks in advance for any insight..
Win 10, Matlab 2013b (currently for compatibility issues with this project)
21 comentarios
Rik
el 9 de Mayo de 2018
That slowdown sounds odd. In my experience small functions sped up the process, compared to a single big script. Although I have to admit the only project I actually timed it on was smaller than 500 lines of actual code (so not counting comments and function help). There we managed to increase the fps from single digits to 15-25.
I don't have any solutions/answers/suggestions, so I would be interested to see if others do.
John D'Errico
el 9 de Mayo de 2018
If you execute the function in MATLAB, not by calling it from excel, does it take the same 80 seconds, or does that also take 10 minutes? I'm trying to resolve whether this is a problem with the interface with Excel, with the compiled code, or with the conversion from a script into a function. In the last case, that seems to make no sense at all, from what little you have described. So I want to pin down exactly where the extra time comes in.
I would suggest to do some monitoring, trying to look to see exactly where the time is spent.
Greg
el 10 de Mayo de 2018
Can you run the profiler with main as both script and function, then share any results that look significant?
profile on
main; % or main(input1,input2) for function mode
profile off
profile viewer
One odd thought I have for you try:
main(input1,input2);
tic
clear % try it a second time with "clear all"
toc
And tell us how long the clear takes.
Nick Heinz
el 10 de Mayo de 2018
Nick Heinz
el 10 de Mayo de 2018
Philip Borghesani
el 10 de Mayo de 2018
A couple of more things to check or pieces of information that might be helpful:
- Can you try it on a recent version of MATLAB? The timing may be significantly different.
- Does main call the other scripts multiple times? In a loop? If so then you may be much better off turning those into functions too or inlining them in main.
Nick Heinz
el 10 de Mayo de 2018
Editada: Nick Heinz
el 10 de Mayo de 2018
Greg
el 10 de Mayo de 2018
This is a fun one; I wish I had the code to explore.
I'm not familiar with calling MATLAB from external sources, but isn't there some mechanism for evaluating the .m file? If so, can't that same mechanism create 2 variables before calling the .m file?
% Instantiate MATLAB from VBA
% Use whatever is the correct syntax from the VBA side...
input1 = 7;
input2 = 8;
% As long as it's a script, it should have access to the
% "input1" and "input2" variables.
myScript;
Nick Heinz
el 10 de Mayo de 2018
Greg
el 11 de Mayo de 2018
So, since we're way deep in the weeds and grasping at straws here, what happens if you use a wrapper? Leave main as a script, then use:
function main_wrapper(input1,input2)
main
Nick Heinz
el 11 de Mayo de 2018
Nick Heinz
el 12 de Mayo de 2018
At the risk of stereotyping, I suspect a developer that produced 5000 lines of code in 3 separate scripts also ignored a bunch of other best practices throughout those 5000 lines. I would bet a full restructuring would result in a lot of improvements, including runtime.
Could you provide the total number of variables in the workspace and rough distribution of bytes (memory per variable) after running the code? I'm tempted to write some bogus code to see if it's purely due to the magnitude of the situation.
Nick Heinz
el 12 de Mayo de 2018
Greg
el 13 de Mayo de 2018
In short, my first lazy attempt didn't produce any meaningful results. No change in execution between script mode and function mode.
In further detail, I wrote some code to write some bad code for me. It's hard to produce 5000 lines of meaningful fake code. I created 45 files with a normal distribution of # of lines of code to sum up to about 5000. Each script created 17 of the 765 double variables found in your allVars.mat to correct size using randi. I skipped all of the other variables for first go around. I then randomly nested calls from one script to the next and wrapped it all in a main. See my attachment if you're curious.
I may try to fill in the 5000 lines with (very slightly) more realistic code, but that will take longer.
Jan
el 13 de Mayo de 2018
@Greg: Wow. Programming from hell. I've opened your code directly after my late and comfortable breakfast. If I have an enemy, I would print out the created code and send it by snail mail. Brrrr.
It's hard to produce 5000 lines of meaningful fake code.
Thanks for solving this job heroically. I cannot vote up your comment.
Greg
el 14 de Mayo de 2018
Haha. It did hurt a little to write that code. Gave me eval flashbacks.
Philip Borghesani
el 14 de Mayo de 2018
Greg, I did not look at your code but think you should concentrate on the number and allocation/creation locations of the different variables.
Nick if you can turn your most heavily used scripts into nested functions in main it may run significantly faster, and not be too difficult given that nested function have full access to enclosing works space variables. Accessing calling work space variables from a script can be quite slow and is linear time with the number of variables in created in the code of the calling function, but i believe not for variables created in called scripts or evals.
Base workplace variables can be found much faster from scripts. The reason for this is all script code is compiled to be run from any function and has no direct access to function work space variables at compile time. We are working on optimizing this and recent MATLAB versions are quite a bit better but without problematic examples we are not sure what to concentrate on...
Greg
el 15 de Mayo de 2018
I tried adding some slightly less trivial filler code, and adding in a couple more of the non-double variables. And I installed R2013b as well. Still no luck reproducing the issue.
Nick: can you provide any more detail on the struct and the large cell array? I'm wondering if they are key components because of the relatively large memory size. Also, in general, would you say there is much cross-script variable access? For example, does script3 use or manipulate anything created in script2?
Nick Heinz
el 21 de Mayo de 2018
Respuestas (0)
Categorías
Más información sobre Programming en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!