Skip to content

Reverse mode specializaiton for matrix add and subtract - #1812

Closed
dpsimpson wants to merge 3 commits into
stan-dev:developfrom
dpsimpson:feature/issue-1787-matrix-add-subtract-rev
Closed

Reverse mode specializaiton for matrix add and subtract#1812
dpsimpson wants to merge 3 commits into
stan-dev:developfrom
dpsimpson:feature/issue-1787-matrix-add-subtract-rev

Conversation

@dpsimpson

Copy link
Copy Markdown
Contributor

Summary

This is addresses part of #1787 by adding reverse mode specializations for the matrix add and subtract functions. This should reduce the size of the autodiff stack.

The implementation uses a lot of tricks copped from the specialization of multiply.

subtract uses a few constexpr ifs to avoid re-writing code. I'm getting a C++17 warning, and I can change them to ordinary ifs if it's easier. They're there so I didn't have to implement different vari extensions for A - c and c - A (where A is a matrix and c is a scalar). I had honestly hoped I wouldn't need to write almost equivalent code for subtract(Scalar,Matrix) and subtract(Matrix, Scalar) (lines 549-600 of rev/fun/subtract.hpp) but I couldn't work out how to do that.

As always, any suggestions/substitutions/changes greatly appreciated.

Tests

The following tests are implemented for both add and subtract:

  • (double, double), (double, var), (var, double), (var, var) using random matrices.
  • Bound checking tests

I'm happy to add more, but I couldn't think of any.

Side Effects

This should be a plug in replacement.

Release notes

Replace this text with a short note on what will change if this pull request is merged in which case this will be included in the release notes.

Checklist

  • Math issue autodiff for matrix add and subtract #1787 (Partial)

  • Copyright holder: Daniel simpson

    The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
    - Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
    - Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

  • the basic tests are passing

    • unit tests pass (to run, use: ./runTests.py test/unit)
    • header checks pass, (make test-headers)
    • dependencies checks pass, (make test-math-dependencies)
    • docs build, (make doxygen)
    • code passes the built in C++ standards checks (make cpplint)
  • the code is written in idiomatic C++ and changes are documented in the doxygen

  • the new changes are tested

@bob-carpenter

bob-carpenter commented Mar 31, 2020

Copy link
Copy Markdown
Member

Thanks for writing tests, but they're probably largely redundant given the testing framework tests which cover all levels of autodiff against values and finite differences of the double implementation. For these functions, those are in:

test/unit/math/mix/fun/multiply_test.cpp
test/unit/math/mix/fun/add_test.cpp

The one thing that should be done is to add throw tests for mismatched sizes in multiply_test.cpp like the ones for add_test.cpp.

@andrjohns

Copy link
Copy Markdown
Collaborator

I'll take the review for this one (if nobody else had started)

@andrjohns andrjohns left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Some suggestions included. The main issue is the use of if constexpr which is above the C++ standard that Stan currently requires, so that will need to be re-written/replaced

Comment thread stan/math/prim/fun/add.hpp
Comment thread stan/math/rev/fun/add.hpp
@@ -0,0 +1,538 @@
#ifndef STAN_MATH_REV_FUN_MATRIX_ADD_HPP
#define STAN_MATH_REV_FUN_MATRIX_ADD_HPP

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be *_FUN_ADD_HPP (i.e. no 'MATRIX') for consistency with prim?

Comment thread stan/math/rev/fun/add.hpp
#include <stan/math/rev/core.hpp>
#include <stan/math/prim.hpp>
#include <type_traits>
#include <iostream>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These last two headers should be removed

Comment thread stan/math/rev/fun/add.hpp
* vari's constructor.
*
* @param A matrix
* @param B matrix

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param B matrix
* @param B matrix

Comment thread stan/math/rev/fun/add.hpp
* vari's constructor.
*
* @param A matrix
* @param B matrix

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param B matrix
* @param B matrix

* The class stores the structure of each matrix,
* the double values of A and B, and pointers to
* the varis for A and B if A or B is a var. It
* also instatiates and stores pointers to varis

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* also instatiates and stores pointers to varis
* also instantiates and stores pointers to varis

Comment on lines +157 to +159
matrix_d adjAminusB(rows_, cols_);
adjAminusB = Map<matrix_vi>(variRefAminusB_, rows_, cols_).adj();
Map<matrix_vi>(variRefB_, rows_, cols_).adj() -= adjAminusB;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrix_d adjAminusB(rows_, cols_);
adjAminusB = Map<matrix_vi>(variRefAminusB_, rows_, cols_).adj();
Map<matrix_vi>(variRefB_, rows_, cols_).adj() -= adjAminusB;
Map<matrix_vi> AminusB(variRefAminusB_, rows_, cols_);
Map<matrix_vi>(variRefB_, rows_, cols_).adj() -= AminusB.adj();

Map<matrix_d> Ad(Ad_, rows_, cols_);
double cd = c.val();
Ad = A.val();
if constexpr (MatMinusScal) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if constexpr is c++17, and we're only up to c++14

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, see #1300 for more info

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of these days!!!

* @tparam Scal type of the scalar
* @tparam Mat type of the matrix or expression
* @param c Scalar.
* @param m Matrix.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param m Matrix.
* @param A Matrix.

Comment thread stan/math/rev/fun/add.hpp
Comment on lines +474 to +480
double cd = c.val();
Map<matrix_d> Ad(Ad_, rows_, cols_);
Ad = A.val();
Map<matrix_vi>(variRefAplusc_, rows_, cols_)
= (Ad.array() + cd).matrix().unaryExpr([](double x) {
return new vari(x, false);
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same suggested changes as the above

@bbbales2

bbbales2 commented Apr 6, 2020

Copy link
Copy Markdown
Member

@dpsimpson How did this compare in the end to the un-autodiffed version?

@dpsimpson

dpsimpson commented Apr 6, 2020 via email

Copy link
Copy Markdown
Contributor Author

@wds15

wds15 commented Apr 13, 2020

Copy link
Copy Markdown
Contributor

This will be in 2.24? Or can this move in today?

@SteveBronder

Copy link
Copy Markdown
Collaborator

I think this would be a new feature so it will be in the next release

@wds15

wds15 commented Apr 13, 2020

Copy link
Copy Markdown
Contributor

Of course...this is new stuff. The pr comments sounded as if this is about ready. I expect this pr to speed up things quite a bit which is why I was bumping this for some attention.

But let’s wait for the next release.

@dpsimpson

dpsimpson commented Apr 13, 2020 via email

Copy link
Copy Markdown
Contributor Author

@SteveBronder

Copy link
Copy Markdown
Collaborator

Closing this for now but feel free to open when you have time to fixup!

@spinkney

spinkney commented Feb 3, 2023

Copy link
Copy Markdown
Collaborator

@dpsimpson any chance this can get resurrected?

@dpsimpson

dpsimpson commented Feb 3, 2023 via email

Copy link
Copy Markdown
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants