-
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
Layer modules #5294
Layer modules #5294
Conversation
b05c46a
to
3fb47a8
Compare
3d9e309
to
02f6ef3
Compare
Rebased and skipped testing of ModuleLayer. The tests will have to be a separate unit test anyway because it requires specific parameters. I prefer to do this after some feedback on the PR so far. |
c2c2bcb
to
f68bfd0
Compare
f68bfd0
to
3c1c4f3
Compare
3c1c4f3
to
7a06906
Compare
@shelhamer , could you give feedback on this PR? |
Thanks for looking into this! I hope to catch up on PRs after the ICCV deadline 03/17 |
This would be a great feature. The lack of being able to extend Caffe without forking the code (and not resorting to PythonLayer) is, in my opinion, the largest pitfall of Caffe. This comment applies to PythonLayer too and you shouldn't implement it in this PR. Would it be possible to add general variable types, like this: param_int { name: "custom_var1" value: 10 } I find param_str a bit less user friendly. |
That shouldn't be too difficult. In that case it would make sense to add a few utility functions in caffe to read typed parameters by name in an easy manner. Perhaps something along the lines of One downside is that such a scheme doesn't easily allow for more complicated structures in the parameters. While really complex structs might not be a common need for layers, lists may be. There are a couple of ways to go about lists. Anyway, I like the idea, and absolute worst case a Should we discuss this further in a separate issue? |
I agree @williford , the |
@hgaiser or @de-vri-es, would it be possible to provide a barebone example external layer? Just some notes (to those looking at the PR / myself): For people interested in evaluating the PR, but don't know how, you can do the following:
|
The last commit in the PR adds an example layer module: 7a06906 |
I'm not familiar with Halide, but all this PR does is support loading C++ layers from separately compiled modules. I don't see how that relates to Halide, or where the overlap would come from. Could you elaborate on that? |
As I understand #5370 a typical prototxt would look something like:
And in these libraries there have to be two functions defined, What I am thinking is that this PR could be used by your PR to handle the loading and creating of external layers from modules. It appears to me that this PR offers more configurability because it allows multiple layers to be defined in one library, allows parameter passing and extends the way libraries are searched. Whether this conflicts with anything related to Halide I cannot say as I have no experience with Halide. What I don't really understand is why #5370 has the functionality of loading libraries dynamically. Why is that necessary for your Halide implementation, could you elaborate on that? |
Parameter passing was not addressed. Adding a generic parameter string to layer was considered. I would consider single layer per library a feature more than a bug. I don't know to what extent layer search should be in c++, I was considering only cases where nets are freshly baked in python and I would prefer for the problem to be solved there. This approach is compatible with halide libraries. External layers where chosen to factor the build process. Also halide needs to be recompiled for different back ends. |
Hmm to be honest I quite like the option of having more than one layer in a module. That opens the door to modules such as |
Fair point, multi-layer modules is also what TF has chosen. Is there anything preventing a TF->caffe module-layer wrapping from within a layer module i.e. writing a caffe module layer that can in turn call a TF op? |
It sounds like you are proposing for a program written in C++ to invoke python code to find the location of a shared library containing more C++ code. That seems rather more complicated than required to me. Especially considering this PR already has functionality for searching for modules in different locations using the well-known Unix convention of having colon separated paths in a environment variable.
This PR simply allows C++ layers to be compiled in separate libraries and then loaded at runtime. If a C++ layer wants to invoke code written in another programming language, that doesn't matter for this PR. I think it makes sense to treat the problem of splitting layers into shared libraries separate from adding integration with different compiled languages. With this approach, users of the layers don't even need to know in which language they were written. They could use the same layer type for external C++ layers or external Halide layers. I think that's a big plus point.
I'm not sure if that is easily possible, but this PR doesn't change the interface of layers at all, except for the parameter loading (which @williford pointed out, can be improved, but should probably be done for both python and external C++ layers together). It would definitely be interesting to see if layers written for other frameworks can be used in Caffe with a little glue, but I would keep that in a separate PR that can build on top of this one. |
Rebased again against latest master. |
Any update from the caffe maintainers? |
@shelhamer have you had a chance to look at this PR ? |
Sorry, I was pulled away from this by the NIPS deadline and some travel but I do still intend to have a close look and shepherd this for merging as I believe in this direction for extensibility. |
Just a note that this merge does require cmake to be upgraded and will make installing Ubuntu 14.04 much harder (== will require additional step that might break or be difficult for novices). Perhaps this should correspond to a new version (1.1? or 3 :-P). Update: It looks like it might be possible to still support Ubuntu 14.04 with something like this (https://stackoverflow.com/a/31010221/249226):
|
If the bump in cmake version is an issue, I'd prefer to do it the "ugly" way only, instead of both ways. |
The nice thing about using the macro is that |
Ah I just noticed the macro you mentioned uses Given
|
That can also be solved by adding
clang, gcc and the intel C++ compiler use |
@shelhamer could this be picked up again? |
Should this still be updated? Seems like Caffe is dead anyway, judging by the number of unresolved issues and PRs. |
Ping? |
4edf0b2
to
7350fe0
Compare
Rebased again. |
Thanks @hgaiser and @de-vri-es for the effort and patience. This is still in my sights for Caffe 1.1. |
Closing this PR due to inactivity. |
This PR adds support for layer modules in Caffe (as discussed in #5243) and some changes that were required to make that happen. The idea of these layer modules is that developers design their own modules which contain one or more layers which can be used via "Module" layers in their prototxts.
The usage is analogous to that of layers in Caffe with a few exceptions:
REGISTER_LAYER_CLASS
,EXPORT_LAYER_MODULE_CLASS
needs to be called to export layer modules.param_str
, analogous to how params are defined for Python layers. It is up to the developer to determine how this string is to be parsed (YAML parsing for instance).module
param in the prototxt defines the filename, stripped from any prefixes and suffixes. For example, if the module filename islibmodular_layer.so
, themodule
param should be set to"modular_layer"
. This is to ensure OS independent behaviour where the prefix/suffix might be different (.so vs .dylib vs .dll for instance). Expected prefix/suffix can be adjusted through CMake or Makefile.config and defaults to CMakes default for cmake and"lib", ".so"
for Makefile. By default Caffe searches for modules in itsDEFAULT_LAYER_PATH
definition, a colon separated list of directories where modules are expected to be placed. This defaults to$DESTINATION_DIR/lib/caffe/layers
and can be overwritten in CMake or Makefile.config. In addition, if the environment variableCAFFE_LAYER_PATH
is set, it overrides the default search path. If for thecaffe
tool a--layer_path
flag is given it will override the previous search paths. In other words:caffe flags
>cmake
/Makefile.config
>default
.Module
layers,module_param
contains params that describe how to load a layer from the specified module. The most straightforward way is to define thetype
, which would be similar to thetype
used for built-in caffe layers. This definition expects certain symbols in the module to be exposed, as defined through theEXPORT_LAYER_MODULE_CLASS
macro. Creators and deleters can be customized, as can be seen inExampleModularLayer
class in the comments at the end, but normally would not be required.The PR contains an example layer module which shows a minimum example of how it can be used. In addition I made a branch of
py-faster-rcnn
which uses layer modules to execute theROIPooling
andSmoothL1Loss
layers, allowing it to be run on upstream Caffe (including this PR ofcourse) as opposed to their outdatedcaffe-fast-rcnn
fork.The intention is to add unit tests still, but I figured lets ask for some feedback first.