Closed newforrestgump001 closed 5 years ago
your make cannot find Function struct, should_compute_output method in function struct. Those must be in libtorch/include/torch/csrc/autograd/function.h. Could you check it?
It has should_compute_output method, but it seems that it is not in Function struct. Please check the attached function.h Thanks! Jack
namespace torch { namespace autograd {
struct Edge; struct FunctionPostHook; struct FunctionPreHook;
using tensor_list = std::vector
// Custom deleter to prevent stack overflows. TORCH_API void deleteNode(Node* function);
///~~~~~~~~~~~~~~~~~
/// Node
///~~~~~~~~~~~~~~~~~
/// A Node
is an abstract class that represents an operation taking zero
/// or more input Variable
s and producing zero or more output Variable
s. All
/// functions in PyTorch's autograd machinery derive from this class and
/// override its apply
method. Instances of such subclasses will then be
/// invokeable via the call operator.
///
/// Nodes in the Autograd Graph
///~~~~~~~~~~~~~~~~~
/// When viewing the autograd system as a graph, Node
s are the vertices or
/// nodes, connected to each other via (directed) Edge
s, which themselves are
/// represented via (Node
, input_nr) pairs. Variable
s are the outputs to
/// and inputs of Node
s, and travel between these edges during execution
/// of the graph. When two or more Edge
s (from different sources) point at the
/// same input to a Node
, the values produced along all of these edges are
/// implicitly summed prior to being forwarded to the target Node
.
///
/// Hierarchy
///~~~~~~~~~~~~~~~~~
/// Subclasses usually represent differentiable functions as well as their
/// gradient operators. Note, however, that due to the very general definition
/// of a Node
taking zero or more inputs and producing zero or more
/// outputs, uses of Node
s are flexible and extend beyond purely
/// mathematical operations. For example, the AccumulateGrad
function is a
/// sink: it takes one input, but produces no outputs, instead accumulating
/// the input as a side effect. At the other extreme, the GraphRoot
function
/// receives no inputs from other functions, but produces multiple outputs.
///
/// Interface
///~~~~~~~~~~~~~~~~~
/// The most important method on Node
is the call operator, which takes in
/// a list of variables and produces a list of variables. The precise size of
/// these lists can be determined with num_inputs()
and num_outputs()
.
/// Node
s are stitched together via their next_edge
interface, which let
/// you manipulate the set of outgoing edges of a Node
. You can add an
/// edge with add_next_edge()
, retrieve an edge with next_edge(index)
and
/// iterate over them via the next_edges()
method. Other methods exist for
/// integration with the JIT and other parts of PyTorch. Every Node
has a
/// sequence number that increases monotonically in the order of Node
/// construction. It can be retrieved via the sequence_nr()
method. Note that
/// this sequence number is thread local. This means that when Node
s
/// A
, B
and C
are created consecutively in the same thread, their
/// sequence numbers will be ordered A
< B
< C
. If, however, A
and B
/// are created in one thread and C
is created in a new thread, there are no
/// guarantees w.r.t. the ordering of C
relative to A
or B
.
///~~~~~~~~~~~~~~~~~
struct TORCH_API Node : std::enable_shared_from_thisNode
with the given next_edges
. sequence_nr
is
/// a (currently THE) hint to prioritization in the backward() pass, with
/// higher sequence numbers prioritized before lower sequence numbers.
explicit Node(
uint64_t sequence_nr,
edge_list&& next_edges = edge_list())
: sequencenr(sequence_nr),
nextedges(std::move(next_edges)) {
if (AnomalyMode::is_enabled()) {
metadata()->store_stack();
}
}
explicit Node(edge_list&& next_edges = edge_list()) : Node(get_next_sequence_nr()++, std::move(next_edges)) {}
/// Nodes are neither copyable nor moveable. Node(const Node& other) = delete; Node(Node&& other) = delete; Node& operator=(const Node& other) = delete; Node& operator=(Node&& other) = delete; virtual ~Node() = default;
/// Evaluates the function on the given inputs and returns the result of the
/// function call.
variable_list operator()(variable_list&& inputs) {
RECORD_FUNCTION(
this, std::vector
return apply(std::move(inputs));
}
// Graph Connectivity API
//~~~~~~~~~~~~~~~
// Inputs. NOTE: inputs of the grad_fn correspond to Tensor outputs of the // forward function.
// Marker for expected undefined input struct undefined_input {};
/// Adds the type and shape metadata for a new input. Returns the index of /// of the new input. uint32_t add_input_metadata( const at::DeprecatedTypeProperties& type , at::IntArrayRef shape , at::Device device) noexcept { uint32_t input_nr = inputmetadata.size(); inputmetadata.emplace_back(type, shape, device); return input_nr; }
uint32_t add_input_metadata(const at::Tensor& t) noexcept { uint32_t input_nr = inputmetadata.size(); inputmetadata.emplace_back(t); return input_nr; }
/// Adds a placeholder for an input that will not be used. uint32_t add_input_metadata(undefined_input u) noexcept { uint32_t input_nr = inputmetadata.size(); inputmetadata.emplace_back(); return input_nr; }
uint32_t num_inputs() const noexcept { return inputmetadata.size(); }
const InputMetadata& input_metadata(size_t index) const { return inputmetadata[index]; }
void clear_input_metadata() { inputmetadata.clear(); }
// Outputs ("Next Edges")
const Edge& next_edge(size_t index) const noexcept { return nextedges[index]; }
void set_next_edge(size_t index, Edge edge) { nextedges[index] = std::move(edge); }
void add_next_edge(Edge edge) { nextedges.push_back(std::move(edge)); }
void set_next_edges(edge_list&& next_edges) { nextedges = std::move(next_edges); }
const edge_list& next_edges() const noexcept { return nextedges; }
edge_list& next_edges() noexcept { return nextedges; }
uint32_t num_outputs() const noexcept { return nextedges.size(); }
// Miscellaneous Methods
//~~~~~~~~~~~~~~~
/// The sequence number of this Node
.
uint64_t sequence_nr() const noexcept {
return sequencenr;
}
/// Returns the name of the dynamic type of the function, for debugging. virtual std::string name() const;
/// Returns true if the particular output edge is active, and that particular /// output of this function should be computed. bool should_compute_output(size_t output_edge_index) const { TORCH_CHECK(output_edge_index < num_outputs(), "Index out of range"); return nextedges[output_edge_index].is_valid(); }
/// Returns true if any of the output edges in any of the ranges are active.
bool should_compute_output(std::initializer_list
/// Returns the PyObject
stored for this Node
(for Python
/// interaction).
PyObject* pyobj() const noexcept {
return pyobj_;
}
/// Sets the PyObject
stored for this Node
(for Python interaction).
void setpyobj(PyObject* pyobj) noexcept {
pyobj = pyobj;
}
/// Returns the anomaly metadata stored for this Node
.
/// If none exist, creates a new empty one.
AnomalyMetadata* metadata() noexcept;
// Hook API
//~~~~~~~~~~~~~~~
uintptr_t add_post_hook(std::unique_ptr
const std::vector<std::unique_ptr
// delete a post hook matching the key
bool del_post_hook(const uintptr_t& key) {
for (auto it = posthooks.begin(); it != posthooks.end(); ++it) {
if (key == reinterpret_cast
std::vector<std::unique_ptr
void add_pre_hook(std::unique_ptr
const std::vector<std::unique_ptr
std::vector<std::unique_ptr
// Customization Points for Subclasses
//~~~~~~~~~~~~~~~
/// Releases saved variables if the operation won't be reused. virtual void release_variables() {}
/// Called before an apply if release_variables()
is going to be called.
/// Allows larger ops like InterpreterAutogradFunction
to incrementally
/// release variables as they run.
virtual void will_release_variables() {}
/// Returns true if this function is traceable. An op is traceable if all
/// operations happening within apply()
are performed on autograd
/// Variables
(i.e. apply mostly instantiates and applies other functions).
virtual bool is_traceable() {
return false;
}
/// A Node
is said to pass state transparently to backward, if the
/// state consists only of (Saved)Variables and only non-variable objects
/// that parameterize the operation in some way that defines the graph
/// structure AND the backward function is traceable. In particular,
/// parametrization MUST NOT depend on the data of any Variable
.
/// TODO: it might be possible to handle cases where backward is
/// non-traceable but state passing could be considered transparent. This
/// will probably depend on saved_variable_list being mutable.
/// NOTE: this value matters only if is_traceable() returns false.
virtual bool passes_state_transparently() {
return false;
}
static uint64_t peek_at_next_sequence_nr();
protected: static uint64_t& get_next_sequence_nr();
/// Performs the Node
's actual operation.
virtual variable_list apply(variable_list&& inputs) = 0;
/// Calls apply()
, but instruments it with tracing machinery.
variable_list traced_apply(variable_list inputs);
// Since Node
s are neither copyable nor moveable, we can have const
// fields.
const uint64_t sequencenr;
edge_list nextedges;
PyObject* pyobj_ = nullptr; // weak reference
std::unique_ptr
/// See Node::is_traceable() for definition. struct TraceableFunction : public Node { using Node::Node; bool is_traceable() final { return true; } };
//~~~~~~~~~~~~~~~~~~
// Associated Free Nodes
//~~~~~~~~~~~~~~~~~~
namespace detail {
// Implementation of collect_next_edges
(see below).
struct MakeNextFunctionList : IterArgs
/// Create an Edge
between the given variable
and the function
, which is
/// assumed to be the gradient function of this variable (i.e. the function
/// through which this variable is backpropagated during the backward pass).
/// This sets the grad_fn
property of the variable
. This function assumes
/// that the Variable
is a new input to the gradient function and its
/// input_nr
thus equal to function->num_inputs()
. Additionally, it
/// increments the Node
's number of inputs by one. Approximately
/// equivalent to variable.set_gradient_edge(function, /// function->add_input_metadata(variable.dispatch_type(), variable.sizes()))
.
/// If you don't want the Node
's num_inputs
to be incremented, use
/// set_gradient_edge
directly.
inline void create_gradient_edge(
Variable& variable,
std::shared_ptr
/// Return true if any of the variables in the list require a gradient. inline bool any_variable_requires_grad(const variable_list& variables) { return std::any_of( variables.begin(), variables.end(), [](const Variable& variable) { return variable.defined() && variable.requires_grad(); }); }
/// Return the next edges of all the given variables, or tuples of variables.
template
I tried, but i couldn't reproduce your error sorry.
Could you tell me the exact version of gcc ,cuda, ubuntu, and libtorch? I want to follow your system configuration. Thanks a lot!
perhaps, did you compile opencv and yaml-cpp with -DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0 this options?
i tested cuda 10.0.130 ubuntu 16.04.11 gcc 5.4 libtorch 1.10
Thanks! I did as yours constructions (-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0), since it is important. I will have a try again.
It is ok with libtorch 1.1 stable, but failed to make with libtorch nightly build. Thanks a lot! @lsrock1
@newforrestgump001 Oh, thank you for your helpful information! I have checked it, function was renamed "node" https://github.com/pytorch/pytorch/commit/e7a9b0d62f6ca6f3e9f350e827ff7b58a2cb7bdb#diff-ae9195738a5a095e75cab564ccdb9aba
@lsrock1 what is the schedule for training, do you have any plan, thank you a lot!
@newforrestgump001 I will optimize the cpp code and test training. I have a problem in gpu and time resource so, i takes time.
@lsrock1 I got it, thank you for quick response!
In file included from /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp:2:0: /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/../../../include/rcnn/layers/conv2d.h:12:68: error: expected class-name before ‘{’ token struct _NewEmptyTensorOpBackward : public torch::autograd::Function{ ^ /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/../../../include/rcnn/layers/conv2d.h:14:34: error: ‘torch::autograd::variable_list rcnn::layers::_NewEmptyTensorOpBackward::apply(torch::autograd::variable_list&&)’ marked ‘override’, but does not override torch::autograd::variable_list apply(torch::autograd::variable_list&& grads) override; ^~~~~ /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp: In member function ‘torch::autograd::variable_list rcnn::layers::_NewEmptyTensorOpBackward::apply(torch::autograd::variable_list&&)’: /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp:16:9: error: ‘should_compute_output’ was not declared in this scope if (should_compute_output(0)) { ^
~~~~/home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp: In function ‘at::Tensor rcnn::layers::_NewEmptyTensorOp(at::Tensor, c10::IntArrayRef)’: /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp:55:113: error: ‘deleteFunction’ is not a member of ‘torch::autograd’ auto grad_fn = std::shared_ptr<_NewEmptyTensorOpBackward>(new _NewEmptyTensorOpBackward(), torch::autograd::deleteFunction); ^~~~~~ /home2/maskrcnn_benchmark.cpp/source/rcnn/layers/conv2d.cpp:55:113: note: suggested alternative: ‘TraceableFunction’ auto grad_fn = std::shared_ptr<_NewEmptyTensorOpBackward>(new _NewEmptyTensorOpBackward(), torch::autograd::deleteFunction); ^~~~~~ TraceableFunction source/rcnn/layers/CMakeFiles/layers.dir/build.make:75: recipe for target 'source/rcnn/layers/CMakeFiles/layers.dir/conv2d.cpp.o' failed make[2]: [source/rcnn/layers/CMakeFiles/layers.dir/conv2d.cpp.o] Error 1 CMakeFiles/Makefile2:342: recipe for target 'source/rcnn/layers/CMakeFiles/layers.dir/all' failed make[1]: [source/rcnn/layers/CMakeFiles/layers.dir/all] Error 2 Makefile:129: recipe for target 'all' failed make: *** [all] Error 2