Webel: MMA 13.0 Quantity performance issue (notebook version 2022-04-28 14:30 AEST)
Webel: MMA 13.0 Quantity performance issue (notebook version 2022-04-28 14:30 AEST)
IMPORTANT: This test suite now only uses For loops in timing tests, not Table,
(so any recommendation of QuantityArray for efficiency is not relevant).
(so any recommendation of QuantityArray for efficiency is not relevant).
IMPORTANT: This test deliberately does not use UnitConvert anywhere!
Case: Physics calculation without any use of Quantity
In the following the ‘SI’ everywhere is a hint to users to use values scaled to SI units:
In[]:=
distanceNoUnitsSI[vSI_Real,aSI_Real,tSI_Real]:=vSItSI+1/2aSItSI^2;
In[]:=
distanceNoUnitsSI[1.,2.,3.]
Out[]=
12.
The timing test deliberately using a For (not Table) so it is more like a heat exchanger calculation iteration:
In[]:=
test$distanceNoUnitsSI[n_]:=For[i=1,i<=n,i++,distanceNoUnitsSI[1.i,2.i,3.i]]
In[]:=
test$distanceNoUnitsSI[10000];//Timing
Out[]=
{0.028378,Null}
Case: Physics calculation with internal use of Quantity
Note how this relies on the units-aware system to figure out the correct units (length in m) of the return Quantity,
only the input arguments need to ever invoke the Quantity[val,”unit”] method.
only the input arguments need to ever invoke the Quantity[val,”unit”] method.
In[]:=
distanceWithUnits[v_,a_,t_]:=vt+1/2at^2;
In[]:=
distanceWithUnits[Quantity[1,"Meters"/"Seconds"],Quantity[2,"Meters"/"Seconds"^2],Quantity[3,"Seconds"]]
Out[]=
The timing test uses For so that it’s more like an actual heat exchanger calculation iteration.
Note that this test is inefficiently using the Quantity function as a constructor each time.
Note that this test is inefficiently using the Quantity function as a constructor each time.
In[]:=
test$distanceWithUnits[n_]:=For[i=1,i<=n,i++,distanceWithUnits[Quantity[1.i,"Meters"/"Seconds"],Quantity[2.i,"Meters"/"Seconds"^2],Quantity[3.i,"Seconds"]]];
In[]:=
test$distanceWithUnits[10000];//Timing
Out[]=
{15.0911,Null}
Estimated performance hit factor using Quantity:
In[]:=
14.618174`/0.027599`
Out[]=
529.663
Case: Physics calculation with internal use of Quantity and with
pre-defined arguments and pre-multiplication of each Quantity
pre-defined arguments and pre-multiplication of each Quantity
This test invokes with predefined Quantity items (typically, in the real application,
these would be the return values from other units-aware functions). Note that
this test version accepts pre-defined Quantity args then multiplies each of them by
i in the For loop so that distanceWithUnits is invoked with unique args each time.
these would be the return values from other units-aware functions). Note that
this test version accepts pre-defined Quantity args then multiplies each of them by
i in the For loop so that distanceWithUnits is invoked with unique args each time.
test$distanceWithUnits2[n_,v_,a_,t_]:=For[i=1,i<=n,i++,distanceWithUnits[iv,ia,it]];
In[]:=
v1=Quantity[1.,"Meters"/"Seconds"]
Out[]=
In[]:=
a1=Quantity[2.,"Meters"/"Seconds"^2]
Out[]=
In[]:=
t1=Quantity[3.,"Seconds"]
Out[]=
In[]:=
test$distanceWithUnits2[10000,v1,a1,t1];//Timing
Out[]=
{16.456,Null}
Estimated performance hit factor using Quantity:
In[]:=
16.456011`/0.028378`
Out[]=
579.886
CASE: Use the units-aware physics function in another function
In the real application, the Quantity result of each units-aware function is used by many other units-aware functions
This is contrived, but the distance computed above is then used in another units-aware computation, and then another.
The final fuel consumed will be a volume.
The final fuel consumed will be a volume.
In[]:=
fuelConsumed[v_,a_,t_,nTrips_,fuelPerDistance_]:=distanceWithUnits[v,a,t]fuelPerDistancenTrips;
In[]:=
fuelConsumed[v1,a1,t1,10,Quantity[1.234,"Liters"/"Meters"]]
Out[]=
It is safely units-aware. Except for communication in the user interface, the actual volume units used in the return value are irrelevant:
In[]:=
fuelConsumed[v1,a1,t1,10,Quantity[1234,"Milliliters"/"Meters"]]
Out[]=
In this real application, this is done across of network of hundreds of units-aware functions, with each Quantity return of each function being used in many different contexts, by many other “downstream” units-aware functions.