Closed ChristopherRabotin closed 6 years ago
Wow, this proposed enhancement drastically speeds up the computation of the gradient!
I compared the code above by enabling either the vector computation or the matrix computation by moving the diff
or diff_mat
code into a #[no_mangle] pub fn
, and called that function one billion times. The result from std::time::Instant
shows that the matrix computation takes strictly zero seconds to execute all billion calls (albeit there may be drastic optimizations by the compiler here since I'm running with the --release
flag). That same piece of code with the Vector6 call took several minutes (I Ctrl-C'd it).
FWTW, I'm working on getting non-square partials working using the hyperdual space. Something is wrong somewhere, and I haven't figure it out yet.
Proposal
Currently,
nabla
will call the functionf
N times, where N is the size of the input vector to the functionf
. Although this computes the gradient properly, it would probably be advantageous in terms of calling stack to only call the function once. This can be achieved by generating a hyperdual space and calling the provided function with the base-defining matrix. In terms of precise computations, this will should not have any impact: performing math on a matrix instead of doing the same on N vector will indeed require the same number of computations.Impact
This will require changing the signature of the
f
function parameter tonabla
fromFn(T, &VectorN<Dual<T>, N>) -> VectorN<Dual<T>, N>
toFn(T, &MatrixMN<Dual<T>, N, N>) -> MatrixMN<Dual<T>, N, N>
. This is a breaking change.Proof of concept
It is important to note the difference between functions
eom
andeom_mat
:eom_mat
is noticeably more complicated as it requires extracting different parts of the provided state. Further enhancements may hopefully limit such changes (possibly by definingDual<T>
as ana::Scalar
(which might not be possible since Dual is itself represented as aVector2
, although mathematically, I think that a Dual is a scalar number)).