You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doxygen/contributor_help_pages/common_pitfalls.md
+12-9Lines changed: 12 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -177,7 +177,7 @@ We can see in the above that the standard style of a move (the constructor takin
177
177
But in Stan, particularly for reverse mode, we need to keep memory around even if it's only temporary for when we call the gradient calculations in the reverse pass.
178
178
And since memory for reverse mode is stored in our arena allocator no copying happens in the first place.
179
179
180
-
Functions for Stan math's reverse mode autodiff should use [_perfect forwarding_](https://drewcampbell92.medium.com/understanding-move-semantics-and-perfect-forwarding-part-3-65575d523ff8) arguments. This arguments are a template parameter with `&&` next to them.
180
+
Functions for Stan Math's reverse mode autodiff should use [_perfect forwarding_](https://drewcampbell92.medium.com/understanding-move-semantics-and-perfect-forwarding-part-3-65575d523ff8) arguments. Perfect forwarding arguments use a template parameter wit no attributes such as `const` and `volatile` and have a double ampersand `&&` next to them.
181
181
182
182
```c++
183
183
template <typename T>
@@ -186,7 +186,8 @@ Functions for Stan math's reverse mode autodiff should use [_perfect forwarding_
186
186
}
187
187
```
188
188
189
-
A perfect forwarding argument of a function accepts any reference type as it's input argument.
189
+
The `std::forward<T>` in the in the code above tells the compiler that if `T` is deduced to be an rvalue reference (such as `Eigen::MatrixXd&&`), then it should be moved to `my_other_function`, where there it can possibly use another objects move constructor to reuse memory.
190
+
A perfect forwarding argument of a function accepts any reference type as its input argument.
190
191
The above signature is equivalent to writing out several functions with different reference types
191
192
192
193
```c++
@@ -202,10 +203,12 @@ The above signature is equivalent to writing out several functions with differen
202
203
auto my_function(Eigen::MatrixXd&& x) {
203
204
return my_other_function(std::move(x));
204
205
}
206
+
// Accepts a const rvalue reference
207
+
auto my_function(const Eigen::MatrixXd&& x) {
208
+
return my_other_function(std::move(x));
209
+
}
205
210
```
206
211
207
-
The `std::forward<T>` in the in the code above tells the compiler that if `T` is deduced to be an rvalue reference (such as `Eigen::MatrixXd&&`), then it should be moved to `my_other_function`, where there it can possibly use another objects move constructor to reuse memory.
208
-
209
212
In Stan, perfect forwarding is used in reverse mode functions which can accept an Eigen matrix type.
210
213
211
214
```c++
@@ -257,7 +260,7 @@ That expression will be evaluated into new memory allocated in the arena allocat
257
260
return ret;
258
261
```
259
262
260
-
The rest of this code follows the standard format for the rest of Stan math's reverse mode that accepts Eigen types as input.
263
+
The rest of this code follows the standard format for the rest of Stan Math's reverse mode that accepts Eigen types as input.
261
264
The `reverse_pass_callback` function accepts a lambda as input and places the lambda in Stan's callback stack to be called later when `grad()` is called by the user.
262
265
Since `arena_matrix` types only store a pointer to memory allocated elsewhere they are copied into the lambda.
263
266
The body of the lambda holds the gradient calculation needed for the reverse mode pass.
@@ -279,9 +282,9 @@ The general rules to follow for passing values to a function are:
279
282
280
283
The use of auto with the Stan Math library should be used with care, like in [Eigen](https://eigen.tuxfamily.org/dox/TopicPitfalls.html).
281
284
Along with the cautions mentioned in the Eigen docs, there are also memory considerations when using reverse mode automatic differentiation.
282
-
When returning from a function in the Stan math library with an Eigen matrix output with a scalar `var` type, the actual returned type will often be an `arena_matrix<Eigen::Matrix<...>>`.
285
+
When returning from a function in the Stan Math library with an Eigen matrix output with a scalar `var` type, the actual returned type will often be an `arena_matrix<Eigen::Matrix<...>>`.
283
286
The `arena_matrix` class is an Eigen matrix where the underlying array of memory is located in Stan's memory arena.
284
-
The `arena_matrix` that is returned by Stan functions is normally the same one resting in the callback used to calculate gradients in the reverse pass.
287
+
The `arena_matrix` that is returned by Math functions is normally the same one resting in the callback used to calculate gradients in the reverse pass.
285
288
Directly changing the elements of this matrix would also change the memory the reverse pass callback sees which would result in incorrect calculations.
286
289
287
290
The simple solution to this is that when you use a math library function that returns a matrix and then want to assign to any of the individual elements of the matrix, assign to an actual Eigen matrix type instead of using auto.
@@ -367,8 +370,8 @@ grad();
367
370
368
371
Now `res` is `innocent_return` and we've changed one of the elements of `innocent_return`, but that is also going to change the element of `res` which is being used in our reverse pass callback!
369
372
370
-
Care must be taken by end users of Stan math by using `auto` with caution.
371
-
When a user wishes to manipulate the coefficients of a matrix that is a return from a function in Stan math, they should assign the matrix to a plain Eigen type.
373
+
Care must be taken by end users of Stan Math by using `auto` with caution.
374
+
When a user wishes to manipulate the coefficients of a matrix that is a return from a function in Stan Math, they should assign the matrix to a plain Eigen type.
372
375
373
376
```c++
374
377
Eigen::Matrix<var, -1, 1> x = Eigen::Matrix<double, -1, 1>::Random(5);
0 commit comments