aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorIsabella Gottardi <isabella.gottardi@arm.com>2018-04-06 12:24:55 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:52:35 +0000
commit88d5b22eb5574d8b564474df2c758d222b3b5547 (patch)
tree92edf8ecc38a9349faf1ef958998abddcf5b9a8c /utils
parentbcedf513938fca9e33331bdef975f0488288bad4 (diff)
downloadComputeLibrary-88d5b22eb5574d8b564474df2c758d222b3b5547.tar.gz
COMPMID-1035 - Add ResneXt50 as a graph example
Change-Id: I42f0e7dab38e45b5eecfe6858eaecee8939c8585 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/129291 Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com> Tested-by: Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'utils')
-rw-r--r--utils/GraphUtils.cpp39
-rw-r--r--utils/GraphUtils.h64
-rw-r--r--utils/Utils.h37
3 files changed, 139 insertions, 1 deletions
diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp
index 145e44950b..0edb6f2a56 100644
--- a/utils/GraphUtils.cpp
+++ b/utils/GraphUtils.cpp
@@ -129,6 +129,45 @@ bool DummyAccessor::access_tensor(ITensor &tensor)
return ret;
}
+NumPyAccessor::NumPyAccessor(std::string npy_path, TensorShape shape, DataType data_type, std::ostream &output_stream)
+ : _npy_tensor(), _filename(std::move(npy_path)), _output_stream(output_stream)
+{
+ NumPyBinLoader loader(_filename);
+
+ TensorInfo info(shape, 1, data_type);
+ _npy_tensor.allocator()->init(info);
+ _npy_tensor.allocator()->allocate();
+
+ loader.access_tensor(_npy_tensor);
+}
+
+template <typename T>
+void NumPyAccessor::access_numpy_tensor(ITensor &tensor)
+{
+ const int num_elements = tensor.info()->total_size();
+ int num_mismatches = utils::compare_tensor<T>(tensor, _npy_tensor);
+ float percentage_mismatches = static_cast<float>(num_mismatches) / num_elements;
+
+ _output_stream << "Results: " << 100.f - (percentage_mismatches * 100) << " % matches with the provided output[" << _filename << "]." << std::endl;
+}
+
+bool NumPyAccessor::access_tensor(ITensor &tensor)
+{
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&tensor, 1, DataType::F32);
+ ARM_COMPUTE_ERROR_ON(_npy_tensor.info()->dimension(0) != tensor.info()->dimension(0));
+
+ switch(tensor.info()->data_type())
+ {
+ case DataType::F32:
+ access_numpy_tensor<float>(tensor);
+ break;
+ default:
+ ARM_COMPUTE_ERROR("NOT SUPPORTED!");
+ }
+
+ return false;
+}
+
PPMAccessor::PPMAccessor(std::string ppm_path, bool bgr, std::unique_ptr<IPreprocessor> preprocessor)
: _ppm_path(std::move(ppm_path)), _bgr(bgr), _preprocessor(std::move(preprocessor))
{
diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h
index a8507b1ac7..597708369d 100644
--- a/utils/GraphUtils.h
+++ b/utils/GraphUtils.h
@@ -25,9 +25,11 @@
#define __ARM_COMPUTE_GRAPH_UTILS_H__
#include "arm_compute/core/PixelValue.h"
+#include "arm_compute/core/utils/misc/Utility.h"
#include "arm_compute/graph/Graph.h"
#include "arm_compute/graph/ITensorAccessor.h"
#include "arm_compute/graph/Types.h"
+#include "arm_compute/runtime/Tensor.h"
#include <array>
#include <random>
@@ -117,6 +119,37 @@ private:
unsigned int _maximum;
};
+/** NumPy accessor class */
+class NumPyAccessor final : public graph::ITensorAccessor
+{
+public:
+ /** Constructor
+ *
+ * @param[in] npy_path Path to npy file.
+ * @param[in] shape Shape of the numpy tensor data.
+ * @param[in] data_type DataType of the numpy tensor data.
+ * @param[out] output_stream (Optional) Output stream
+ */
+ NumPyAccessor(std::string npy_path, TensorShape shape, DataType data_type, std::ostream &output_stream = std::cout);
+ /** Allow instances of this class to be move constructed */
+ NumPyAccessor(NumPyAccessor &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ NumPyAccessor(const NumPyAccessor &) = delete;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ NumPyAccessor &operator=(const NumPyAccessor &) = delete;
+
+ // Inherited methods overriden:
+ bool access_tensor(ITensor &tensor) override;
+
+private:
+ template <typename T>
+ void access_numpy_tensor(ITensor &tensor);
+
+ Tensor _npy_tensor;
+ const std::string _filename;
+ std::ostream &_output_stream;
+};
+
/** PPM accessor class */
class PPMAccessor final : public graph::ITensorAccessor
{
@@ -273,7 +306,14 @@ inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::str
}
else
{
- return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, std::move(preprocessor));
+ if(arm_compute::utility::endswith(ppm_path, ".npy"))
+ {
+ return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(ppm_path);
+ }
+ else
+ {
+ return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, std::move(preprocessor));
+ }
}
}
@@ -298,6 +338,28 @@ inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const std::st
return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
}
}
+/** 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 NpyAccessor
+ *
+ * @param[in] npy_path Path to npy file.
+ * @param[in] shape Shape of the numpy tensor data.
+ * @param[in] data_type DataType of the numpy tensor data.
+ * @param[out] output_stream (Optional) Output stream
+ *
+ * @return An appropriate tensor accessor
+ */
+inline std::unique_ptr<graph::ITensorAccessor> get_npy_output_accessor(const std::string &npy_path, TensorShape shape, DataType data_type, std::ostream &output_stream = std::cout)
+{
+ if(npy_path.empty())
+ {
+ return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
+ }
+ else
+ {
+ return arm_compute::support::cpp14::make_unique<NumPyAccessor>(npy_path, shape, data_type, output_stream);
+ }
+}
/** Utility function to return the TargetHint
*
diff --git a/utils/Utils.h b/utils/Utils.h
index cadba3a088..6cb71fd3ba 100644
--- a/utils/Utils.h
+++ b/utils/Utils.h
@@ -924,6 +924,43 @@ void init_sgemm_output(T &dst, T &src0, T &src1, arm_compute::DataType dt)
* @return The free memory in kB
*/
uint64_t get_mem_free_from_meminfo();
+
+/** Compare to tensor
+ *
+ * @param[in] tensor1 First tensor to be compared.
+ * @param[in] tensor2 Second tensor to be compared.
+ *
+ * @return The number of mismatches
+ */
+template <typename T>
+int compare_tensor(ITensor &tensor1, ITensor &tensor2)
+{
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(&tensor1, &tensor2);
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(&tensor1, &tensor2);
+
+ int num_mismatches = 0;
+ Window window;
+ window.use_tensor_dimensions(tensor1.info()->tensor_shape());
+
+ map(tensor1, true);
+ map(tensor2, true);
+ Iterator itensor1(&tensor1, window);
+ Iterator itensor2(&tensor2, window);
+
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ if(std::abs(*reinterpret_cast<T *>(itensor1.ptr()) - *reinterpret_cast<T *>(itensor2.ptr())) > 0.00001)
+ {
+ ++num_mismatches;
+ }
+ },
+ itensor1, itensor2);
+
+ unmap(itensor1);
+ unmap(itensor2);
+
+ return num_mismatches;
+}
} // namespace utils
} // namespace arm_compute
#endif /* __UTILS_UTILS_H__*/