Python Unit Expressions - Benchmarks
The package unitexpr provides classes and meta-classes that
make it trivial to define custom unit systems and numpy arrays
with unit support.
A search on pypi shows that there are a few packages available
for doing unit analysis. The most notable I found is scimath,
which supports unit conversion and working with united numpy arrays.
The section below contains benchmarks comparing the performance of
unitexpr units with those provided by the
package scimath.
Note: To run the benchmarks one must install the packages:
pytest-benchmark and pytest.
Unit Expressions
To run the benchmarks clone the repository available at
unitexpr, navigate to the package root directory
and use the command:
$ pytest benchmarks/unit_benchmark.py
An excerpt of a sample output (produced on a PC with 32GB RAM memory and an Intel Core i5-6260U CPU running at 1.80GHz) is displayed below:
-------------------------------- benchmark: 6 tests -----------------------------------
Name (time in ns) Mean StdDev Rounds Iterations
---------------------------------------------------------------------------------------
test_compare_scimath_units 384.6454 (1.0) 49.9329 (1.0) 4 20000
test_compare_unitexpr_units 455.8162 (1.19) 62.7644 (1.26) 4 20000
test_add_scimath_units 3,698.7334 (9.62) 199.3424 (3.99) 4 20000
test_add_unitexpr_units 5,527.3140 (14.37) 666.3501 (13.34) 4 20000
test_mult_scimath_units 4,363.7948 (11.34) 204.8872 (4.10) 4 20000
test_mult_unitexpr_units 5,780.7208 (15.03) 205.6521 (4.12) 4 20000
---------------------------------------------------------------------------------------
As the test runs above show scimath unit comparisons and unit
operations are calculated slightly faster compared to unitexpr units.
This result is expected due to the additional computational effort
involved with keeping track of unitexpr terms as
well as type checking required
during comparison and arithmetic operations.
For the purpose of optimization scimath computes and stores unit
expressions in terms of base units. The package
unitexpr stores unit expressions in terms of
base units and derived units.
United Numpy Arrays
To support scientific calculation
the package also includes a united array.
The class qarray
extends numpy's ndarray adding the additional
instance attribute unit (with default value 1.0).
The section below contains benchmarks comparing the performance of
unitexpr united numpy arrays with united arrays
provided by the package scimath.
To run the benchmarks from the root directory of the
package unitexpr use the command:
$ pytest benchmarks/qarray_benchmark.py
A sample output (not all columns are shown) produced on a PC with 32GB RAM memory and an Intel Core i5-6260U CPU running at 1.80GHz is displayed below:
---------------------------- benchmar: 4 tests -------------------------
Name (time in us) Mean StdDev Rounds Iterations
-------------------------------------------------------------------------
test_add_qarray 68.1265 (1.05) 21.3399 (4.15) 4 700
test_add_unit_array 81.0177 (1.25) 6.1296 (1.19) 4 700
test_mult_qarray 65.4302 (1.01) 5.1430 (1.0) 4 700
test_mult_unit_array 64.8208 (1.0) 7.3627 (1.43) 4 700
-------------------------------------------------------------------------
To produce the benchmarks the following arrays were constructed:
from numpy import ndarray, array_equal
from unitexpr.si_units import m, s, SiUnit
from unitexpr.qarray import qarray
from scimath.units.length import meter, centimeter
from scimath.units.time import second
from scimath.units.mass import kilogram
from scimath.units.unit_array import UnitArray as UnitArraySci
cm = SiUnit("cm", "centimeter", "length", 1.0e-2 * m)
nx = 200
ny = 200
A = ndarray(shape=(nx, ny))
A.fill(10.0)
M = qarray.from_input(A, unit=m ** 2)
C = qarray(shape=(nx, ny), unit=cm ** 2)
C.fill(1.0e4)
S = qarray.from_input(A, unit=s)
R = qarray(shape=(nx, ny), unit=m ** 2)
R.fill(11)
A1 = UnitArraySci(A)
M1 = UnitArraySci(A, units=meter * meter)
C1 = UnitArraySci(C, units=centimeter * centimeter)
S1 = UnitArraySci(A, units=second)
R1 = UnitArraySci(R, units=meter * meter)
The first set of benchmarks was produced by repeatedly calculating the
expressions: M + C and M1 + C1.
The second set of benchmarks was produced by calculating
M/(S**2) and M1/(S1**2).
The results displayed above show that the performance of
unitexpr and scimath united arrays is similar.
As a rough estimate calculations involving units are of the order of microseconds to tens of microseconds (depending on the complexitiy of the unit expression).
The fraction of computational time spent on unit operations becomes negligable when performing calculations on large arrays with more than 50000 elements.
Features and bugs
Please file feature requests and bugs at the issue tracker. Contributions are welcome.