Opened 6 years ago
Last modified 6 years ago
#4957 new defect
Inefficient code generated for record derivatives
Reported by: | Per Östlund | Owned by: | Lennart Ochel |
---|---|---|---|
Priority: | critical | Milestone: | Future |
Component: | Code Generation | Version: | v1.13.0-dev-nightly |
Keywords: | Cc: | Willi Braun |
Description
The backend generates very inefficent code in some cases involving records, for example in ScalableTestSuite.Thermal.Advection.ScaledExperiments.SteamPipe_N_10
(and presumably any model using the same parts of Modelica.Media). Looking at the omc_$DER$Modelica$PMedia$PWater$PIF97__Utilities$PwaterBaseProp__ph
function in the _functions.c
file for example, there's a line in the Modelica code that looks like:
g := Modelica.Media.Water.IF97_Utilities.BaseIF97.Basic.g1(p, aux.T);
This is translated into the following C-code (line 6213 for me):
tmp1 = omc_Modelica_Media_Water_IF97__Utilities_BaseIF97_Basic_g1(threadData, _p, _aux._T); _g._p = tmp1._p; _g._T = tmp1._T; _g._R = tmp1._R; _g._pi = tmp1._pi; _g._tau = tmp1._tau; _g._g = tmp1._g; _g._gpi = tmp1._gpi; _g._gpipi = tmp1._gpipi; _g._gtau = tmp1._gtau; _g._gtautau = tmp1._gtautau; _g._gtaupi = tmp1._gtaupi;
Assigning each field of _g
separately is a bit weird but might be necessary for all I know, but at least it only calls the functions once. Immediately following this is the following code though (I've shortened the identifiers in the code to make it readable, the actual C-code is much larger):
$funDERg._p = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._p; $funDERg._T = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._T; $funDERg._R = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._R; $funDERg._pi = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._pi; $funDERg._tau = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._tau; $funDERg._g = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._g; $funDERg._gpi = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._gpi; $funDERg._gpipi = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._gpipi; $funDERg._gtau = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._gtau; $funDERg._gtautau = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._gtautau; $funDERg._gtaupi = omc_$DER$g1(threadData, _p, _aux._T, $funDERp, $funDERaux._T)._gtaupi;
It seems like this is calculating some kind of derivative of g
, but it does so by calling the omc_$DER$g1
function once for each record field. This pattern is repeated all over the generated code, causing a huge amount of unnecessary function calls. And at least g1
is quite large and expensive to call, so optimizing this to only call the function once would probably improve the simulation performance quite a bit for models like this.