summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/graph/mutators/InPlaceOperationMutator.cpp10
-rw-r--r--utils/GraphUtils.cpp14
-rw-r--r--utils/GraphUtils.h46
3 files changed, 65 insertions, 5 deletions
diff --git a/src/graph/mutators/InPlaceOperationMutator.cpp b/src/graph/mutators/InPlaceOperationMutator.cpp
index 1c2985dce..07e3ecf2c 100644
--- a/src/graph/mutators/InPlaceOperationMutator.cpp
+++ b/src/graph/mutators/InPlaceOperationMutator.cpp
@@ -57,7 +57,11 @@ void InPlaceOperationMutator::mutate(Graph &g)
ARM_COMPUTE_ERROR_ON(current_output_tensor == nullptr || new_output_tensor == nullptr);
// Prevent in-place operation if there is an accessor bound to the in-place tensor or quantization info are different
- if(new_output_tensor->accessor() == nullptr || current_output_tensor->desc().quant_info == new_output_tensor->desc().quant_info)
+ if(new_output_tensor->accessor() != nullptr || current_output_tensor->desc().quant_info != new_output_tensor->desc().quant_info)
+ {
+ ARM_COMPUTE_LOG_GRAPH_VERBOSE("Prevented in-place operation as there is an accessor bound to the input tensor or the quantization info are different.\n");
+ }
+ else
{
ARM_COMPUTE_LOG_GRAPH_VERBOSE("Switching to in-place computation for the node with ID : "
<< node->id() << " and name : " << node->name() << std::endl);
@@ -66,10 +70,6 @@ void InPlaceOperationMutator::mutate(Graph &g)
// Update output
node->set_output_tensor(new_output_tensor->id(), 0);
}
- else
- {
- ARM_COMPUTE_LOG_GRAPH_VERBOSE("Prevented in-place operation as there is an accessor bound to the input tensor\n");
- }
}
}
}
diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp
index 6be289a7e..dad9aed6a 100644
--- a/utils/GraphUtils.cpp
+++ b/utils/GraphUtils.cpp
@@ -184,6 +184,20 @@ bool NumPyAccessor::access_tensor(ITensor &tensor)
return false;
}
+SaveNumPyAccessor::SaveNumPyAccessor(std::string npy_name, const bool is_fortran)
+ : _npy_name(std::move(npy_name)), _is_fortran(is_fortran)
+{
+}
+
+bool SaveNumPyAccessor::access_tensor(ITensor &tensor)
+{
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&tensor, 1, DataType::F32);
+
+ utils::save_to_npy(tensor, _npy_name, _is_fortran);
+
+ return false;
+}
+
ImageAccessor::ImageAccessor(std::string filename, bool bgr, std::unique_ptr<IPreprocessor> preprocessor)
: _already_loaded(false), _filename(std::move(filename)), _bgr(bgr), _preprocessor(std::move(preprocessor))
{
diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h
index 88221c7dc..fe19eb319 100644
--- a/utils/GraphUtils.h
+++ b/utils/GraphUtils.h
@@ -167,6 +167,31 @@ private:
std::ostream &_output_stream;
};
+/** SaveNumPy accessor class */
+class SaveNumPyAccessor final : public graph::ITensorAccessor
+{
+public:
+ /** Constructor
+ *
+ * @param[in] npy_name Npy file name.
+ * @param[in] is_fortran (Optional) If true, save tensor in fortran order.
+ */
+ SaveNumPyAccessor(const std::string npy_name, const bool is_fortran = false);
+ /** Allow instances of this class to be move constructed */
+ SaveNumPyAccessor(SaveNumPyAccessor &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ SaveNumPyAccessor(const SaveNumPyAccessor &) = delete;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ SaveNumPyAccessor &operator=(const SaveNumPyAccessor &) = delete;
+
+ // Inherited methods overriden:
+ bool access_tensor(ITensor &tensor) override;
+
+private:
+ const std::string _npy_name;
+ const bool _is_fortran;
+};
+
/** Image accessor class */
class ImageAccessor final : public graph::ITensorAccessor
{
@@ -558,6 +583,27 @@ inline std::unique_ptr<graph::ITensorAccessor> get_npy_output_accessor(const std
}
}
+/** Generates appropriate npy output accessor according to the specified npy_path
+ *
+ * @note If npy_path is empty will generate a DummyAccessor else will generate a SaveNpyAccessor
+ *
+ * @param[in] npy_name Npy filename.
+ * @param[in] is_fortran (Optional) If true, save tensor in fortran order.
+ *
+ * @return An appropriate tensor accessor
+ */
+inline std::unique_ptr<graph::ITensorAccessor> get_save_npy_output_accessor(const std::string &npy_name, const bool is_fortran = false)
+{
+ if(npy_name.empty())
+ {
+ return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
+ }
+ else
+ {
+ return arm_compute::support::cpp14::make_unique<SaveNumPyAccessor>(npy_name, is_fortran);
+ }
+}
+
/** Permutes a given tensor shape given the input and output data layout
*
* @param[in] tensor_shape Tensor shape to permute