-
Notifications
You must be signed in to change notification settings - Fork 18.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix types of SetUp, Forward, Backward, and gradient checker calls #945
Conversation
How hard is the refactor to insert input blob pointer also to the output vector when we need to write into the input blob? Opencv for example let to use the same Matrix for input and output when you want to do "in-place" operation. |
I'm in favor of this.
I guess Net would have to create two sets of bottom_vecs and top_vecs (an extra set of bottom_vecs with const blob pointers for the forward pass, and an extra set of top_vecs with const blob pointers for the backward pass) for this to work? That wouldn't be too bad (just a few extra lines of basically duplicate code), I'd think. But maybe not worth it anyway. But if we're ever going to consider doing something like that we should probably do it right now with this PR, so I thought it would be good to bring up... |
@bhack, I don't know what you are suggesting that is different from what already exists; in-place operations are supported, in which case you will have @jeffdonahue, nice suggestion, I'll look into it. There are some complications, such as the implementation of compositions (e.g., in LRN layer) which will need the same redundancy as Net (however, compositions are already pretty redundant, and should probably be done with a different mechanism anyway). Also, hinge loss layer begins the backward computation in the forward pass, using bottom diff; that should probably just be fixed to not happen. |
@longjon nevermind, was similar to what @jeffdonahue proposed. The non const pointers in the net passed to forward/back is the "output vector" |
I am in general not a big fan of breaking coding convention (for example, the const may give people an impression that this should not be changed). But in this case there are both pros and cons, and the problem is mainly because of C++'s flaky definition of const decorator, so looks good to me :) |
If the input and the output types must have different forms, the original types can be replaced by explicit aliases |
In the case of inputblob also Blob* need to be const? |
4278286
to
c01f07a
Compare
I looked into @jeffdonahue's suggestion of using Furthermore, the const correctness itself doesn't change the content of the layer code, unlike the agreed upon pointer dereference, so it seems reasonable to me to push the latter through while keeping the former in mind in the future. I'll note that that there are (at least) two other possible ways to inject
An orthogonal issue mentioned above is whether we should use Here is my suggested course of action for this PR:
|
suggested course of action SGTM |
Using the type vector<Blob<Dtype*>* for outputs allows modification of the vector itself, while it is only okay to modify the blobs pointed to by the elements of the vector. Switching the types to const vector<Blob<Dtype>*>& makes them more correct.
Fix types of SetUp, Forward, Backward, and gradient checker calls
For those who want to update their own branches or layers according to the changes made here, this is the complete list of sed commands that were used to update dev.
|
Wow @longjon this just broke my PR #1070 I will rebase it again, but hope it gets reviewed @jeffdonahue soon. |
Fix types of SetUp, Forward, Backward, and gradient checker calls
Fix types of SetUp, Forward, Backward, and gradient checker calls
Currently, vectors of blobs that are output arguments (such as Forward's top and Backward's bottom) have the type
vector<Blob*>*
. This type was chosen following the rule that outputs should be always be pointers. However, the semantics of this type are not correct for its use in Caffe; they allow modification of the vector itself (such as adding blobs, or changing the elements to point to other blobs), which will break Caffe. The real output arguments in these cases are the blobs themselves, which are correctly passed in via pointers. This incongruity also leads to a bunch of line noise, since every reference to an argument of this form must be dereferenced before it can be indexed, which in turn causes confusion.This PR changes all such output arguments to have type
const vector<Blob*>&
, thus cleaning up code and turning dynamic errors into static ones.(One might also observe that input vectors don't have quite the right type -- they are also
const vector<Blob*>&
, which allows modification of the input blobs. Unfortunately this is more difficult to solve, as blob vectors have to be used both as inputs and outputs, and C++ lacks container covariance.)I think there is a general consensus(?) among BVLC folk that this is the right thing to do. Nevertheless, some reasons not to merge this PR are:
top
tobottom
or vice versa)