lsrock1 / maskrcnn_benchmark.cpp

Implementation maskrcnn-benchmark, pytorch c++ frontend
MIT License
81 stars 23 forks source link

make error with libtorch 1.1.0 cuda_10,(Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0 #3

Closed newforrestgump001 closed 5 years ago

newforrestgump001 commented 5 years ago

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

lsrock1 commented 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?

newforrestgump001 commented 5 years ago

It has should_compute_output method, but it seems that it is not in Function struct. Please check the attached function.h Thanks! Jack

pragma once

include <torch/csrc/autograd/edge.h>

include <torch/csrc/autograd/grad_mode.h>

include <torch/csrc/autograd/anomaly_mode.h>

include <torch/csrc/autograd/profiler.h>

include <torch/csrc/autograd/saved_variable.h>

include <torch/csrc/autograd/input_metadata.h>

include <torch/csrc/autograd/variable.h>

include <torch/csrc/utils/python_stub.h>

include <torch/csrc/utils/variadic.h>

include <ATen/ATen.h>

include <c10/util/Exception.h>

include

include

include

include

include

include

include

namespace torch { namespace autograd {

struct Edge; struct FunctionPostHook; struct FunctionPreHook;

using tensor_list = std::vector; using variable_list = std::vector; using edge_list = std::vector; using saved_variable_list = std::vector; using IndexRange = std::pair<size_t, size_t>;

// 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 Variables and producing zero or more output Variables. 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, Nodes are the vertices or /// nodes, connected to each other via (directed) Edges, which themselves are /// represented via (Node, input_nr) pairs. Variables are the outputs to /// and inputs of Nodes, and travel between these edges during execution /// of the graph. When two or more Edges (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 Nodes 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(). /// Nodes 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 Nodes /// 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_this { public: /// Construct a new Node 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(inputs.begin(), inputs.end()));

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 idxs) const { return std::any_of(idxs.begin(), idxs.end(), [this](IndexRange range) { for (auto i = range.first; i < range.second; i++) { if (should_compute_output(i)) return true; } return false; }); }

/// 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&& post_hook) { posthooks.push_back(std::move(post_hook)); // Use the raw pointer as the unique key to identify this hook. This key // can then be used in del_post_hook(key) to remove this hook. return reinterpret_cast(posthooks.back().get()); }

const std::vector<std::unique_ptr>& post_hooks() const noexcept { return posthooks; }

// 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(it->get())) { posthooks.erase(it); return true; } } return false; }

std::vector<std::unique_ptr>& post_hooks() noexcept { return posthooks; }

void add_pre_hook(std::unique_ptr&& pre_hook) { prehooks.push_back(std::move(pre_hook)); }

const std::vector<std::unique_ptr>& pre_hooks() const noexcept { return prehooks; }

std::vector<std::unique_ptr>& pre_hooks() noexcept { return prehooks; }

// 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 Nodes 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 anomalymetadata = nullptr; std::vector<std::unique_ptr> prehooks; std::vector<std::unique_ptr> posthooks; at::SmallVector<InputMetadata, 2> inputmetadata; };

/// 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 { edge_list next_edges; using IterArgs::operator(); void operator()(const Variable& variable) { if (variable.defined()) { next_edges.push_back(variable.gradient_edge()); } else { next_edges.emplace_back(); } } }; } // namespace detail

/// 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 function) { // Copy before move. const auto input_nr = function->add_input_metadata(variable); variable.set_gradient_edge({std::move(function), input_nr}); }

/// 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 edge_list collect_next_edges(Variables&&... variables) { if (!GradMode::is_enabled()) return {}; detail::MakeNextFunctionList make; make.apply(std::forward(variables)...); return std::move(make.next_edges); } }} // namespace torch::autograd

lsrock1 commented 5 years ago

I tried, but i couldn't reproduce your error sorry.

newforrestgump001 commented 5 years ago

Could you tell me the exact version of gcc ,cuda, ubuntu, and libtorch? I want to follow your system configuration. Thanks a lot!

lsrock1 commented 5 years ago

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

newforrestgump001 commented 5 years ago

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.

newforrestgump001 commented 5 years ago

It is ok with libtorch 1.1 stable, but failed to make with libtorch nightly build. Thanks a lot! @lsrock1

lsrock1 commented 5 years ago

@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

newforrestgump001 commented 5 years ago

@lsrock1 what is the schedule for training, do you have any plan, thank you a lot!

lsrock1 commented 5 years ago

@newforrestgump001 I will optimize the cpp code and test training. I have a problem in gpu and time resource so, i takes time.

newforrestgump001 commented 5 years ago

@lsrock1 I got it, thank you for quick response!