Optimization Question - structs are slower but more organized, supplementary functions are slower but more organized
24 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Hi Everyone. I'm running simulations with lots of parameters that take a long time. For organized code, I create a (1) value structure that updates throughout the simulation, a (2) a parameter structure that determines how the value structure changes, and (3) supplementary functions that update the value structure with the parameters in the parameter structure. I can't analytically solve the simulation, it needs to update each step.
I've noticed that some bottlenecks result from using supplementary functions to update parameters with struct inputs. This is much "cleaner" but sometimes significantly slower. If you pass a struct into a function because it has a parameter you need to update a value, it takes longer than just updating the value. It also takes longer than not calling the function at all.
I wrote a minimum working example copied below in the code. It has functions in the script so shouldn't need anything else to run. (I know that this example could be completed in one line without for loops, it's just an example).
If anyone has ideas on how to reap the speedups from ditching the wrapper functions and structs but still maintaining organized code, I'd appreciate it!
I'm on Matlab 2020b and when I run this code as is it prints:
Testing versions:
Outer Funx / Struct... 0.59692 second
Inner Funx / Struct... 0.57595 second
None Funx / Struct... 0.19709 second
Outer Funx / Scalar... 0.06846 second
Inner Funx / Scalar... 0.04698 second
None Funx / Scalar... 0.02228 second
fprintf('\nTesting versions: \n');
iterations = 1000000;
% Value and parameter in struct
aStruct.value = 0;
aStruct.nudgeValue = 1;
outsideStruct = tic;
for i = 1:iterations
% OutsideFunction calls insideFunction
% InsideFunction updates a struct.value with struct.parameter
aStruct = outsideFunctionStruct(aStruct);
end
fprintf('Outer Funx / Struct... %.5f second\n',toc(outsideStruct));
insideStruct = tic;
for i = 1:iterations
% InsideFunction updates a struct.value with struct.parameter
aStruct = insideFunctionStruct(aStruct);
end
fprintf('Inner Funx / Struct... %.5f second\n',toc(insideStruct));
noneStruct = tic;
for i = 1:iterations
% Directly update struct.value with struct.parameter
aStruct.value = aStruct.value + aStruct.nudgeValue*randn(1);
end
fprintf('None Funx / Struct... %.5f second\n',toc(noneStruct));
% Without Struct, only scalars
value = 0;
nudge = 1;
outsideScalar = tic;
for i = 1:iterations
% OutsideFunction calls insideFunction
% InsideFunction updates a value with a parameter
value = outsideFunctionScalar(value,nudge);
end
fprintf('Outer Funx / Scalar... %.5f second\n',toc(outsideScalar));
insideScalar = tic;
for i = 1:iterations
% InsideFunction updates value with parameter
value = insideFunctionScalar(value,nudge);
end
fprintf('Inner Funx / Scalar... %.5f second\n',toc(insideScalar));
noneScalar = tic;
for i = 1:iterations
% Directly update value
value = value + nudge*randn(1);
end
fprintf('None Funx / Scalar... %.5f second\n',toc(noneScalar));
% --- Functions Necessary To Run Script ---
function value = outsideFunctionScalar(value,nudge)
value = insideFunctionScalar(value,nudge);
end
function aStruct = outsideFunctionStruct(aStruct)
aStruct = insideFunctionStruct(aStruct);
end
% The following two are the same, but one uses a struct to hold variables
function a_struct = insideFunctionStruct(a_struct)
a_struct.value = a_struct.value + a_struct.nudgeValue * randn(1);
end
function valueOutput = insideFunctionScalar(valueInput,nudgeValue)
valueOutput = valueInput + nudgeValue*randn(1);
end
3 Kommentare
Bruno Luong
am 27 Mär. 2021
You should put the script inside a function, the JIT can make different in both cases.
So calling function is expensive. I always avoid to call functions withon a for-loop with big number of iteration for simple arithmetics operations.
The function should accept a struct and have loop inside it, then broastcast fields parameters to local worrkspace variables; then loop with simple arithmetics.
So I simply tell you what youu have observed and no proper alternative to speed it up.
Antworten (1)
Nipun
am 16 Mai 2024
Hi Andrew,
I understand that you are trying to optimize the performance of your simulations in MATLAB, which involve updating values based on parameters using a structured approach. You have noticed that using supplementary functions and structures to update these values introduces significant overhead compared to directly manipulating scalar values. To maintain organized code while improving performance, consider adopting MATLAB's class system. By defining classes for your simulation entities, you can encapsulate the value and parameter update logic within methods. This approach not only keeps your code organized but also can enhance performance by reducing the overhead associated with frequent structure field access and function calls. Classes allow for efficient data encapsulation and manipulation, potentially offering a good balance between code clarity and execution speed.
For a simulation that heavily relies on updating values based on parameters, you could define a class that encapsulates both the value and parameter update logic. Here's a simplified example:
classdef SimulationEntity
properties
Value = 0;
NudgeValue = 1;
end
methods
function obj = updateValue(obj)
obj.Value = obj.Value + obj.NudgeValue * randn(1);
end
end
end
And in your simulation loop:
simEntity = SimulationEntity();
for i = 1:iterations
simEntity = simEntity.updateValue();
end
This approach keeps your code organized and encapsulated while potentially offering better performance than using structures and separate functions. However, the actual performance gain can vary, so it's essential to profile and compare different approaches in the context of your specific application.
Hope this helps.
Regards,
Nipun
0 Kommentare
Siehe auch
Kategorien
Mehr zu Structures finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!