aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichalis Spyrou <michalis.spyrou@arm.com>2018-01-10 14:08:50 +0000
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:43:10 +0000
commit2b5f0f2574551f59970bb9d710bafad2bc4bbd4a (patch)
treefd586f56b1285f0d6c52ecefc174eba0a9c8f157
parent571b18a1fca4a5ed4dd24a38cb619f4de43ba3ed (diff)
downloadComputeLibrary-2b5f0f2574551f59970bb9d710bafad2bc4bbd4a.tar.gz
COMPMID-782 Port examples to the new format
Change-Id: Ib178a97c080ff650094d02ee49e2a0aa22376dd0 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/115717 Reviewed-by: Anthony Barbier <anthony.barbier@arm.com> Tested-by: Jenkins <bsgcomp@arm.com>
-rw-r--r--examples/cl_events.cpp132
-rw-r--r--examples/cl_sgemm.cpp272
-rw-r--r--examples/gc_absdiff.cpp122
-rw-r--r--examples/gc_dc.cpp141
-rw-r--r--examples/graph_alexnet.cpp226
-rw-r--r--examples/graph_googlenet.cpp292
-rw-r--r--examples/graph_lenet.cpp151
-rw-r--r--examples/graph_mobilenet.cpp244
-rw-r--r--examples/graph_squeezenet.cpp294
-rw-r--r--examples/graph_vgg16.cpp340
-rw-r--r--examples/graph_vgg19.cpp358
-rw-r--r--examples/neon_cartoon_effect.cpp109
-rw-r--r--examples/neon_cnn.cpp415
-rw-r--r--examples/neon_convolution.cpp102
-rw-r--r--examples/neon_copy_objects.cpp208
-rw-r--r--examples/neon_scale.cpp91
-rw-r--r--examples/neoncl_scale_median_gaussian.cpp145
-rw-r--r--utils/Utils.cpp35
-rw-r--r--utils/Utils.h17
19 files changed, 1886 insertions, 1808 deletions
diff --git a/examples/cl_events.cpp b/examples/cl_events.cpp
index c9c3e5d039..ec02fc30f9 100644
--- a/examples/cl_events.cpp
+++ b/examples/cl_events.cpp
@@ -33,78 +33,88 @@
using namespace arm_compute;
using namespace utils;
-void main_cl_events(int argc, char **argv)
+class CLEventsExample : public Example
{
- /** [OpenCL events] **/
- PPMLoader ppm;
- CLImage src, tmp_scale_median, tmp_median_gauss, dst;
- constexpr int scale_factor = 2;
-
- CLScheduler::get().default_init();
-
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: ./build/cl_events [input_image.ppm]\n\n";
- std::cout << "No input_image provided, creating a dummy 640x480 image\n";
- // Create an empty grayscale 640x480 image
- src.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else
+public:
+ void do_setup(int argc, char **argv) override
{
- ppm.open(argv[1]);
- ppm.init_image(src, Format::U8);
- }
+ /** [OpenCL events] **/
+ PPMLoader ppm;
+ constexpr int scale_factor = 2;
- // Declare and configure the functions to create the following pipeline: scale -> median -> gauss
- CLScale scale;
- CLMedian3x3 median;
- CLGaussian5x5 gauss;
+ CLScheduler::get().default_init();
- TensorInfo dst_info(src.info()->dimension(0) / scale_factor, src.info()->dimension(1) / scale_factor, Format::U8);
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: ./build/cl_events [input_image.ppm]\n\n";
+ std::cout << "No input_image provided, creating a dummy 640x480 image\n";
+ // Create an empty grayscale 640x480 image
+ src.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm.open(argv[1]);
+ ppm.init_image(src, Format::U8);
+ }
- // Configure the temporary and destination images
- dst.allocator()->init(dst_info);
- tmp_scale_median.allocator()->init(dst_info);
- tmp_median_gauss.allocator()->init(dst_info);
+ TensorInfo dst_info(src.info()->dimension(0) / scale_factor, src.info()->dimension(1) / scale_factor, Format::U8);
- //Configure the functions:
- scale.configure(&src, &tmp_scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
- median.configure(&tmp_scale_median, &tmp_median_gauss, BorderMode::REPLICATE);
- gauss.configure(&tmp_median_gauss, &dst, BorderMode::REPLICATE);
+ // Configure the temporary and destination images
+ dst.allocator()->init(dst_info);
+ tmp_scale_median.allocator()->init(dst_info);
+ tmp_median_gauss.allocator()->init(dst_info);
- // Allocate all the images
- src.allocator()->allocate();
- dst.allocator()->allocate();
- tmp_scale_median.allocator()->allocate();
- tmp_median_gauss.allocator()->allocate();
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm.is_open())
- {
- ppm.fill_image(src);
- }
+ //Configure the functions:
+ scale.configure(&src, &tmp_scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
+ median.configure(&tmp_scale_median, &tmp_median_gauss, BorderMode::REPLICATE);
+ gauss.configure(&tmp_median_gauss, &dst, BorderMode::REPLICATE);
- // Enqueue and flush the scale OpenCL kernel:
- scale.run();
- // Create a synchronisation event between scale and median:
- cl::Event scale_event = CLScheduler::get().enqueue_sync_event();
- // Enqueue and flush the median OpenCL kernel:
- median.run();
- // Enqueue and flush the Gaussian OpenCL kernel:
- gauss.run();
+ // Allocate all the images
+ src.allocator()->allocate();
+ dst.allocator()->allocate();
+ tmp_scale_median.allocator()->allocate();
+ tmp_median_gauss.allocator()->allocate();
- //Make sure all the OpenCL jobs are done executing:
- scale_event.wait(); // Block until Scale is done executing (Median3x3 and Gaussian5x5 might still be running)
- CLScheduler::get().sync(); // Block until Gaussian5x5 is done executing
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm.is_open())
+ {
+ ppm.fill_image(src);
+ output_filename = std::string(argv[1]) + "_out.ppm";
+ }
+ /** [OpenCL events] **/
+ }
+ void do_run() override
+ {
+ // Enqueue and flush the scale OpenCL kernel:
+ scale.run();
+ // Create a synchronisation event between scale and median:
+ cl::Event scale_event = CLScheduler::get().enqueue_sync_event();
+ // Enqueue and flush the median OpenCL kernel:
+ median.run();
+ // Enqueue and flush the Gaussian OpenCL kernel:
+ gauss.run();
- // Save the result to file:
- if(ppm.is_open())
+ //Make sure all the OpenCL jobs are done executing:
+ scale_event.wait(); // Block until Scale is done executing (Median3x3 and Gaussian5x5 might still be running)
+ CLScheduler::get().sync(); // Block until Gaussian5x5 is done executing
+ }
+ void do_teardown() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ }
}
- /** [OpenCL events] **/
-}
+
+private:
+ CLImage src{}, tmp_scale_median{}, tmp_median_gauss{}, dst{};
+ CLScale scale{};
+ CLMedian3x3 median{};
+ CLGaussian5x5 gauss{};
+ std::string output_filename{};
+};
/** Main program for convolution test
*
@@ -113,5 +123,5 @@ void main_cl_events(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_cl_events);
+ return utils::run_example<CLEventsExample>(argc, argv);
}
diff --git a/examples/cl_sgemm.cpp b/examples/cl_sgemm.cpp
index 939870fabf..f2c63985f6 100644
--- a/examples/cl_sgemm.cpp
+++ b/examples/cl_sgemm.cpp
@@ -36,174 +36,184 @@
using namespace arm_compute;
using namespace utils;
-void main_cl_sgemm(int argc, char **argv)
+class CLSGEMMExample : public Example
{
- NPYLoader npy0, npy1, npy2;
- CLTensor src0, src1, src2, dst;
- float alpha = 1.0f, beta = 0.0f;
-
- CLTuner tuner;
- CLScheduler::get().default_init(&tuner);
-
- std::ifstream stream;
- if(argc > 1)
+public:
+ void do_setup(int argc, char **argv) override
{
- stream.open(argv[1], std::fstream::in);
- }
+ NPYLoader npy0, npy1, npy2;
+ alpha = 1.0f;
+ beta = 0.0f;
- if(argc < 3 || (argc < 4 && stream.bad()))
- {
- // Print help
- std::cout << "Usage: 1) ./build/cl_sgemm input_matrix_1.npy input_matrix_2.npy [input_matrix_3.npy] [alpha = 1] [beta = 0]\n";
- std::cout << " 2) ./build/cl_sgemm M N K [alpha = 1.0f] [beta = 0.0f]\n\n";
- std::cout << "Too few or no input_matrices provided. Using M=7, N=3, K=5, alpha=1.0f and beta=0.0f\n\n";
-
- src0.allocator()->init(TensorInfo(TensorShape(5U, 7U), 1, DataType::F32));
- src1.allocator()->init(TensorInfo(TensorShape(3U, 5U), 1, DataType::F32));
- src2.allocator()->init(TensorInfo(TensorShape(3U, 7U), 1, DataType::F32));
- }
- else
- {
- if(stream.good()) /* case file1.npy file2.npy [file3.npy] [alpha = 1.0f] [beta = 0.0f] */
+ CLScheduler::get().default_init(&tuner);
+
+ std::ifstream stream;
+ if(argc > 1)
{
- npy0.open(argv[1]);
- npy0.init_tensor(src0, DataType::F32);
- npy1.open(argv[2]);
- npy1.init_tensor(src1, DataType::F32);
+ stream.open(argv[1], std::fstream::in);
+ }
- if(argc > 3)
+ if(argc < 3 || (argc < 4 && stream.bad()))
+ {
+ // Print help
+ std::cout << "Usage: 1) ./build/cl_sgemm input_matrix_1.npy input_matrix_2.npy [input_matrix_3.npy] [alpha = 1] [beta = 0]\n";
+ std::cout << " 2) ./build/cl_sgemm M N K [alpha = 1.0f] [beta = 0.0f]\n\n";
+ std::cout << "Too few or no input_matrices provided. Using M=7, N=3, K=5, alpha=1.0f and beta=0.0f\n\n";
+
+ src0.allocator()->init(TensorInfo(TensorShape(5U, 7U), 1, DataType::F32));
+ src1.allocator()->init(TensorInfo(TensorShape(3U, 5U), 1, DataType::F32));
+ src2.allocator()->init(TensorInfo(TensorShape(3U, 7U), 1, DataType::F32));
+ }
+ else
+ {
+ if(stream.good()) /* case file1.npy file2.npy [file3.npy] [alpha = 1.0f] [beta = 0.0f] */
{
- stream.close();
- stream.clear();
- stream.open(argv[3], std::fstream::in);
- if(stream.good()) /* case with third file */
- {
- npy2.open(argv[3]);
- npy2.init_tensor(src2, DataType::F32);
+ npy0.open(argv[1]);
+ npy0.init_tensor(src0, DataType::F32);
+ npy1.open(argv[2]);
+ npy1.init_tensor(src1, DataType::F32);
- if(argc > 4)
+ if(argc > 3)
+ {
+ stream.close();
+ stream.clear();
+ stream.open(argv[3], std::fstream::in);
+ if(stream.good()) /* case with third file */
{
- // Convert string to float
- alpha = strtof(argv[4], nullptr);
+ npy2.open(argv[3]);
+ npy2.init_tensor(src2, DataType::F32);
- if(argc > 5)
+ if(argc > 4)
{
// Convert string to float
- beta = strtof(argv[5], nullptr);
+ alpha = strtof(argv[4], nullptr);
+
+ if(argc > 5)
+ {
+ // Convert string to float
+ beta = strtof(argv[5], nullptr);
+ }
}
}
- }
- else /* case without third file */
- {
- alpha = strtof(argv[3], nullptr);
-
- if(argc > 4)
+ else /* case without third file */
{
- beta = strtof(argv[4], nullptr);
+ alpha = strtof(argv[3], nullptr);
+
+ if(argc > 4)
+ {
+ beta = strtof(argv[4], nullptr);
+ }
}
}
}
- }
- else /* case M N K [alpha = 1.0f] [beta = 0.0f] */
- {
- size_t M = strtol(argv[1], nullptr, 10);
- size_t N = strtol(argv[2], nullptr, 10);
- size_t K = strtol(argv[3], nullptr, 10);
-
- src0.allocator()->init(TensorInfo(TensorShape(K, M), 1, DataType::F32));
- src1.allocator()->init(TensorInfo(TensorShape(N, K), 1, DataType::F32));
- src2.allocator()->init(TensorInfo(TensorShape(N, M), 1, DataType::F32));
-
- if(argc > 4)
+ else /* case M N K [alpha = 1.0f] [beta = 0.0f] */
{
- alpha = strtof(argv[4], nullptr);
+ size_t M = strtol(argv[1], nullptr, 10);
+ size_t N = strtol(argv[2], nullptr, 10);
+ size_t K = strtol(argv[3], nullptr, 10);
+
+ src0.allocator()->init(TensorInfo(TensorShape(K, M), 1, DataType::F32));
+ src1.allocator()->init(TensorInfo(TensorShape(N, K), 1, DataType::F32));
+ src2.allocator()->init(TensorInfo(TensorShape(N, M), 1, DataType::F32));
- if(argc > 5)
+ if(argc > 4)
{
- beta = strtof(argv[5], nullptr);
+ alpha = strtof(argv[4], nullptr);
+
+ if(argc > 5)
+ {
+ beta = strtof(argv[5], nullptr);
+ }
}
}
}
- }
- init_sgemm_output(dst, src0, src1, DataType::F32);
+ init_sgemm_output(dst, src0, src1, DataType::F32);
- // Configure function
- CLGEMM sgemm;
- sgemm.configure(&src0, &src1, (src2.info()->total_size() > 0) ? &src2 : nullptr, &dst, alpha, beta);
+ // Configure function
+ sgemm.configure(&src0, &src1, (src2.info()->total_size() > 0) ? &src2 : nullptr, &dst, alpha, beta);
- // Allocate all the images
- src0.allocator()->allocate();
- src1.allocator()->allocate();
- dst.allocator()->allocate();
+ // Allocate all the images
+ src0.allocator()->allocate();
+ src1.allocator()->allocate();
+ dst.allocator()->allocate();
- // Fill the input images with either the data provided or random data
- if(npy0.is_open())
- {
- npy0.fill_tensor(src0);
- npy1.fill_tensor(src1);
+ // Fill the input images with either the data provided or random data
+ if(npy0.is_open())
+ {
+ npy0.fill_tensor(src0);
+ npy1.fill_tensor(src1);
+
+ output_filename = "sgemm_out.npy";
+ is_fortran = npy0.is_fortran();
- if(npy2.is_open())
+ if(npy2.is_open())
+ {
+ src2.allocator()->allocate();
+ npy2.fill_tensor(src2);
+ }
+ }
+ else
{
src2.allocator()->allocate();
- npy2.fill_tensor(src2);
+
+ fill_random_tensor(src0, -1.f, 1.f);
+ fill_random_tensor(src1, -1.f, 1.f);
+ fill_random_tensor(src2, -1.f, 1.f);
}
- }
- else
- {
- src2.allocator()->allocate();
- fill_random_tensor(src0, -1.f, 1.f);
- fill_random_tensor(src1, -1.f, 1.f);
- fill_random_tensor(src2, -1.f, 1.f);
+ // Dummy run for CLTuner
+ sgemm.run();
}
-
- // Dummy run for CLTuner
- sgemm.run();
-
- auto start = std::chrono::high_resolution_clock::now();
-
- // Execute the function
- sgemm.run();
-
- // Make sure all the OpenCL jobs are done executing:
- CLScheduler::get().sync();
-
- auto stop = std::chrono::high_resolution_clock::now();
-
- if(!npy0.is_open()) /* If the inputs were not files, print the results */
+ void do_run() override
{
- std::cout << "\nMatrix 1:" << std::endl;
- src0.map(true);
- src0.print(std::cout, IOFormatInfo());
- src0.unmap();
-
- std::cout << "Matrix 2:" << std::endl;
- src1.map(true);
- src1.print(std::cout, IOFormatInfo());
- src1.unmap();
-
- std::cout << "Matrix 3:" << std::endl;
- src2.map(true);
- src2.print(std::cout, IOFormatInfo());
- src2.unmap();
-
- std::cout << "Alpha:" << alpha << "\n\n";
- std::cout << "Beta:" << beta << "\n\n";
-
- std::cout << "Output Matrix:" << std::endl;
- dst.map(true);
- dst.print(std::cout, IOFormatInfo());
- dst.unmap();
+ // Execute the function
+ sgemm.run();
+
+ // Make sure all the OpenCL jobs are done executing:
+ CLScheduler::get().sync();
}
- else /* Save to .npy file */
+ void do_teardown() override
{
- save_to_npy(dst, "sgemm_out.npy", npy0.is_fortran());
+ if(output_filename.empty()) /* If the inputs were not files, print the results */
+ {
+ std::cout << "\nMatrix 1:" << std::endl;
+ src0.map(true);
+ src0.print(std::cout, IOFormatInfo());
+ src0.unmap();
+
+ std::cout << "Matrix 2:" << std::endl;
+ src1.map(true);
+ src1.print(std::cout, IOFormatInfo());
+ src1.unmap();
+
+ std::cout << "Matrix 3:" << std::endl;
+ src2.map(true);
+ src2.print(std::cout, IOFormatInfo());
+ src2.unmap();
+
+ std::cout << "Alpha:" << alpha << "\n\n";
+ std::cout << "Beta:" << beta << "\n\n";
+
+ std::cout << "Output Matrix:" << std::endl;
+ dst.map(true);
+ dst.print(std::cout, IOFormatInfo());
+ dst.unmap();
+ }
+ else /* Save to .npy file */
+ {
+ save_to_npy(dst, output_filename, is_fortran);
+ }
}
- auto delta = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
- std::cout << "Time elapsed: " << delta.count() << "us." << std::endl;
-}
+private:
+ CLTensor src0{}, src1{}, src2{}, dst{};
+ CLGEMM sgemm{};
+ CLTuner tuner{};
+ float alpha{}, beta{};
+ bool is_fortran{};
+ std::string output_filename{};
+};
/** Main program for sgemm test
*
@@ -212,5 +222,5 @@ void main_cl_sgemm(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_cl_sgemm);
+ return utils::run_example<CLSGEMMExample>(argc, argv);
}
diff --git a/examples/gc_absdiff.cpp b/examples/gc_absdiff.cpp
index 997feed8e8..32f946d421 100644
--- a/examples/gc_absdiff.cpp
+++ b/examples/gc_absdiff.cpp
@@ -34,71 +34,83 @@
using namespace arm_compute;
using namespace utils;
-void main_gc_absdiff(int argc, char **argv)
+class GCAbsDiffExample : public Example
{
- PPMLoader ppm1, ppm2;
- GCImage src1, src2, dst;
- GCScheduler::get().default_init();
- if(argc < 2)
+public:
+ void do_setup(int argc, char **argv) override
{
- // Print help
- std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
- std::cout << "No input_image provided, creating two dummy 640x480 images\n";
- // Create two empty grayscale 640x480 images
- src1.allocator()->init(TensorInfo(640, 480, Format::U8));
- src2.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else if(argc < 3)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
- std::cout << "Only one input_image provided, creating a dummy 640x480 image\n";
- ppm1.open(argv[1]);
- ppm1.init_image(src1, Format::U8);
- // Create an empty grayscale 640x480 image
- src2.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else
- {
- ppm1.open(argv[1]);
- ppm1.init_image(src1, Format::U8);
- ppm2.open(argv[2]);
- ppm2.init_image(src2, Format::U8);
- }
+ PPMLoader ppm1, ppm2;
- // Configure the temporary and destination images
- dst.allocator()->init(*src1.info());
+ GCScheduler::get().default_init();
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
+ std::cout << "No input_image provided, creating two dummy 640x480 images\n";
+ // Create two empty grayscale 640x480 images
+ src1.allocator()->init(TensorInfo(640, 480, Format::U8));
+ src2.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else if(argc < 3)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
+ std::cout << "Only one input_image provided, creating a dummy 640x480 image\n";
+ ppm1.open(argv[1]);
+ ppm1.init_image(src1, Format::U8);
+ // Create an empty grayscale 640x480 image
+ src2.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm1.open(argv[1]);
+ ppm1.init_image(src1, Format::U8);
+ ppm2.open(argv[2]);
+ ppm2.init_image(src2, Format::U8);
+ }
- GCAbsoluteDifference absdiff;
- absdiff.configure(&src1, &src2, &dst);
+ // Configure the temporary and destination images
+ dst.allocator()->init(*src1.info());
- // Allocate all the images
- src1.allocator()->allocate();
- src2.allocator()->allocate();
- dst.allocator()->allocate();
+ absdiff.configure(&src1, &src2, &dst);
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm1.is_open())
- {
- ppm1.fill_image(src1);
+ // Allocate all the images
+ src1.allocator()->allocate();
+ src2.allocator()->allocate();
+ dst.allocator()->allocate();
+
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm1.is_open())
+ {
+ ppm1.fill_image(src1);
+ output_filename = std::string(argv[1]) + "_out.ppm";
+ }
+ if(ppm2.is_open())
+ {
+ ppm2.fill_image(src2);
+ }
}
- if(ppm2.is_open())
+ void do_run() override
{
- ppm2.fill_image(src2);
+ // Execute the functions:
+ absdiff.run();
}
-
- // Execute the functions:
- absdiff.run();
-
- // Save the result to file:
- if(ppm1.is_open())
+ void do_teardown() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- // save_to_ppm maps and unmaps the image to store as PPM
- // The GCTensor::map call inside the save_to_ppm will block until all pending operations on that image have completed
- save_to_ppm(dst, output_filename);
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ // save_to_ppm maps and unmaps the image to store as PPM
+ // The GCTensor::map call inside the save_to_ppm will block until all pending operations on that image have completed
+ save_to_ppm(dst, output_filename);
+ }
}
-}
+
+private:
+ GCImage src1{}, src2{}, dst{};
+ GCAbsoluteDifference absdiff{};
+ std::string output_filename{};
+};
/** Main program for absdiff test
*
@@ -107,5 +119,5 @@ void main_gc_absdiff(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_gc_absdiff);
+ return utils::run_example<GCAbsDiffExample>(argc, argv);
}
diff --git a/examples/gc_dc.cpp b/examples/gc_dc.cpp
index 174c88458d..8b6f4414e0 100644
--- a/examples/gc_dc.cpp
+++ b/examples/gc_dc.cpp
@@ -33,84 +33,91 @@
using namespace arm_compute;
using namespace utils;
-namespace
+class GCDCExample : public Example
{
-TensorShape get_output_shape(TensorShape in_shape, TensorShape kernel_shape, const PadStrideInfo &info)
-{
- TensorShape out_shape(in_shape);
- const std::pair<unsigned int, unsigned int> scaled_dims = scaled_dimensions(in_shape.x(),
- in_shape.y(),
- kernel_shape.x(),
- kernel_shape.y(),
- info);
- out_shape.set(0, scaled_dims.first);
- out_shape.set(1, scaled_dims.second);
- out_shape.set(2, kernel_shape[3]);
- return out_shape;
-}
-} // namespace
-
-void main_gc_dc(int argc, char **argv)
-{
- ARM_COMPUTE_UNUSED(argc);
- ARM_COMPUTE_UNUSED(argv);
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ ARM_COMPUTE_UNUSED(argc);
+ ARM_COMPUTE_UNUSED(argv);
- // init instance
- GCScheduler::get().default_init();
+ // init instance
+ GCScheduler::get().default_init();
- const TensorShape src_shape = TensorShape{ 11U /* W */, 13U /* H */, 4U /* C */, 3U /* N */ };
- const unsigned int kernel_size = 3;
- const int stride_x = 1;
- const int stride_y = 1;
- const int pad_x = 0;
- const int pad_y = 0;
- const unsigned int num_kernels = 256;
- const DataType data_type = DataType::F16;
+ const TensorShape src_shape = TensorShape{ 11U /* W */, 13U /* H */, 4U /* C */, 3U /* N */ };
+ const unsigned int kernel_size = 3;
+ const int stride_x = 1;
+ const int stride_y = 1;
+ const int pad_x = 0;
+ const int pad_y = 0;
+ const unsigned int num_kernels = 256;
+ const DataType data_type = DataType::F16;
- // generate shape
- const TensorShape weights_shape(kernel_size, kernel_size, src_shape.z(), num_kernels);
- const TensorShape bias_shape(num_kernels);
- const PadStrideInfo pad_info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);
+ // generate shape
+ const TensorShape weights_shape(kernel_size, kernel_size, src_shape.z(), num_kernels);
+ const TensorShape bias_shape(num_kernels);
+ const PadStrideInfo pad_info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);
- // output shape should be 9*11*256*3 (W*H*C*N)
- const TensorShape dst_shape = get_output_shape(src_shape, weights_shape, pad_info);
+ // output shape should be 9*11*256*3 (W*H*C*N)
+ const TensorShape dst_shape = get_output_shape(src_shape, weights_shape, pad_info);
- // create tensors
- GCTensor src, weights, bias, dst;
- src.allocator()->init(TensorInfo(src_shape, 1, data_type));
- weights.allocator()->init(TensorInfo(weights_shape, 1, data_type));
- bias.allocator()->init(TensorInfo(bias_shape, 1, data_type));
- dst.allocator()->init(TensorInfo(dst_shape, 1, data_type));
+ // create tensors
+ src.allocator()->init(TensorInfo(src_shape, 1, data_type));
+ weights.allocator()->init(TensorInfo(weights_shape, 1, data_type));
+ bias.allocator()->init(TensorInfo(bias_shape, 1, data_type));
+ dst.allocator()->init(TensorInfo(dst_shape, 1, data_type));
- // configure layer
- GCDirectConvolutionLayer conv;
- conv.configure(&src, &weights, &bias, &dst, pad_info);
+ // configure layer
+ conv.configure(&src, &weights, &bias, &dst, pad_info);
- // allocate tensors
- src.allocator()->allocate();
- weights.allocator()->allocate();
- bias.allocator()->allocate();
- dst.allocator()->allocate();
+ // allocate tensors
+ src.allocator()->allocate();
+ weights.allocator()->allocate();
+ bias.allocator()->allocate();
+ dst.allocator()->allocate();
- // To demonstrate how to fill tensor with some values...
- src.map();
- Window window;
- window.use_tensor_dimensions(src_shape);
- Iterator it(&src, window);
- execute_window_loop(window, [&](const Coordinates & id)
+ // To demonstrate how to fill tensor with some values...
+ src.map();
+ Window window;
+ window.use_tensor_dimensions(src_shape);
+ Iterator it(&src, window);
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ *reinterpret_cast<half_float::half *>(it.ptr()) = half_float::half(1.f);
+ });
+ src.unmap();
+ }
+ void do_run() override
+ {
+ // run the layer
+ conv.run();
+ }
+ void do_teardown() override
{
- *reinterpret_cast<half_float::half *>(it.ptr()) = half_float::half(1.f);
- });
- src.unmap();
+ // check result
+ dst.map();
+ // do something
+ dst.unmap();
+ }
- // run the layer
- conv.run();
+private:
+ GCTensor src{}, weights{}, bias{}, dst{};
+ GCDirectConvolutionLayer conv{};
- // check result
- dst.map();
- // do something
- dst.unmap();
-}
+ TensorShape get_output_shape(TensorShape in_shape, TensorShape kernel_shape, const PadStrideInfo &info)
+ {
+ TensorShape out_shape(in_shape);
+ const std::pair<unsigned int, unsigned int> scaled_dims = scaled_dimensions(in_shape.x(),
+ in_shape.y(),
+ kernel_shape.x(),
+ kernel_shape.y(),
+ info);
+ out_shape.set(0, scaled_dims.first);
+ out_shape.set(1, scaled_dims.second);
+ out_shape.set(2, kernel_shape[3]);
+ return out_shape;
+ }
+};
/** Main program for directconvolution test
*
@@ -119,5 +126,5 @@ void main_gc_dc(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_gc_dc);
+ return utils::run_example<GCDCExample>(argc, argv);
}
diff --git a/examples/graph_alexnet.cpp b/examples/graph_alexnet.cpp
index 6423fe48d3..8705c8ed1e 100644
--- a/examples/graph_alexnet.cpp
+++ b/examples/graph_alexnet.cpp
@@ -31,6 +31,7 @@
#include <iostream>
#include <memory>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
@@ -39,122 +40,129 @@ using namespace arm_compute::graph_utils;
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_alexnet(int argc, char **argv)
+class GraphAlexnetExample : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
- }
- else if(argc == 4)
- {
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << Tensor(TensorInfo(TensorShape(227U, 227U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ // Layer 1
+ << ConvolutionLayer(
+ 11U, 11U, 96U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_b.npy"),
+ PadStrideInfo(4, 4, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 2
+ << convolution_hint
+ << ConvolutionLayer(
+ 5U, 5U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_b.npy"),
+ PadStrideInfo(1, 1, 2, 2), 2)
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 3
+ << ConvolutionLayer(
+ 3U, 3U, 384U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 4
+ << ConvolutionLayer(
+ 3U, 3U, 384U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_b.npy"),
+ PadStrideInfo(1, 1, 1, 1), 2)
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 5
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_b.npy"),
+ PadStrideInfo(1, 1, 1, 1), 2)
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 6
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 7
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 8
+ << FullyConnectedLayer(
+ 1000U,
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_b.npy"))
+ // Softmax
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
+ // Run graph
+ graph.run();
}
- Graph graph;
-
- graph << target_hint
- << Tensor(TensorInfo(TensorShape(227U, 227U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- // Layer 1
- << ConvolutionLayer(
- 11U, 11U, 96U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_b.npy"),
- PadStrideInfo(4, 4, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
- // Layer 2
- << convolution_hint
- << ConvolutionLayer(
- 5U, 5U, 256U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_b.npy"),
- PadStrideInfo(1, 1, 2, 2), 2)
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
- // Layer 3
- << ConvolutionLayer(
- 3U, 3U, 384U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 4
- << ConvolutionLayer(
- 3U, 3U, 384U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_b.npy"),
- PadStrideInfo(1, 1, 1, 1), 2)
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 5
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_b.npy"),
- PadStrideInfo(1, 1, 1, 1), 2)
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
- // Layer 6
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 7
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 8
- << FullyConnectedLayer(
- 1000U,
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_b.npy"))
- // Softmax
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
-
- // Run graph
- graph.run();
-}
+private:
+ Graph graph{};
+};
/** Main program for AlexNet
*
@@ -163,5 +171,5 @@ void main_graph_alexnet(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_alexnet);
+ return arm_compute::utils::run_example<GraphAlexnetExample>(argc, argv);
}
diff --git a/examples/graph_googlenet.cpp b/examples/graph_googlenet.cpp
index 746d558389..1e9601b492 100644
--- a/examples/graph_googlenet.cpp
+++ b/examples/graph_googlenet.cpp
@@ -31,167 +31,173 @@
#include <cstdlib>
#include <tuple>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
-namespace
-{
-BranchLayer get_inception_node(const std::string &data_path, std::string &&param_path,
- unsigned int a_filt,
- std::tuple<unsigned int, unsigned int> b_filters,
- std::tuple<unsigned int, unsigned int> c_filters,
- unsigned int d_filt)
-{
- std::string total_path = "/cnn_data/googlenet_model/" + param_path + "/" + param_path + "_";
- SubGraph i_a;
- i_a << ConvolutionLayer(
- 1U, 1U, a_filt,
- get_weights_accessor(data_path, total_path + "1x1_w.npy"),
- get_weights_accessor(data_path, total_path + "1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- SubGraph i_b;
- i_b << ConvolutionLayer(
- 1U, 1U, std::get<0>(b_filters),
- get_weights_accessor(data_path, total_path + "3x3_reduce_w.npy"),
- get_weights_accessor(data_path, total_path + "3x3_reduce_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, std::get<1>(b_filters),
- get_weights_accessor(data_path, total_path + "3x3_w.npy"),
- get_weights_accessor(data_path, total_path + "3x3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- SubGraph i_c;
- i_c << ConvolutionLayer(
- 1U, 1U, std::get<0>(c_filters),
- get_weights_accessor(data_path, total_path + "5x5_reduce_w.npy"),
- get_weights_accessor(data_path, total_path + "5x5_reduce_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 5U, 5U, std::get<1>(c_filters),
- get_weights_accessor(data_path, total_path + "5x5_w.npy"),
- get_weights_accessor(data_path, total_path + "5x5_b.npy"),
- PadStrideInfo(1, 1, 2, 2))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- SubGraph i_d;
- i_d << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(1, 1, 1, 1, DimensionRoundingType::CEIL)))
- << ConvolutionLayer(
- 1U, 1U, d_filt,
- get_weights_accessor(data_path, total_path + "pool_proj_w.npy"),
- get_weights_accessor(data_path, total_path + "pool_proj_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b), std::move(i_c), std::move(i_d));
-}
-} // namespace
-
/** Example demonstrating how to implement Googlenet's network using the Compute Library's graph API
*
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_googlenet(int argc, char **argv)
+class GraphGooglenetExample : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ << ConvolutionLayer(
+ 7U, 7U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_b.npy"),
+ PadStrideInfo(2, 2, 3, 3))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+ << convolution_hint
+ << ConvolutionLayer(
+ 1U, 1U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 192U,
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << get_inception_node(data_path, "inception_3a", 64, std::make_tuple(96U, 128U), std::make_tuple(16U, 32U), 32U)
+ << get_inception_node(data_path, "inception_3b", 128, std::make_tuple(128U, 192U), std::make_tuple(32U, 96U), 64U)
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << get_inception_node(data_path, "inception_4a", 192, std::make_tuple(96U, 208U), std::make_tuple(16U, 48U), 64U)
+ << get_inception_node(data_path, "inception_4b", 160, std::make_tuple(112U, 224U), std::make_tuple(24U, 64U), 64U)
+ << get_inception_node(data_path, "inception_4c", 128, std::make_tuple(128U, 256U), std::make_tuple(24U, 64U), 64U)
+ << get_inception_node(data_path, "inception_4d", 112, std::make_tuple(144U, 288U), std::make_tuple(32U, 64U), 64U)
+ << get_inception_node(data_path, "inception_4e", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << get_inception_node(data_path, "inception_5a", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
+ << get_inception_node(data_path, "inception_5b", 384, std::make_tuple(192U, 384U), std::make_tuple(48U, 128U), 128U)
+ << PoolingLayer(PoolingLayerInfo(PoolingType::AVG, 7, PadStrideInfo(1, 1, 0, 0, DimensionRoundingType::CEIL)))
+ << FullyConnectedLayer(
+ 1000U,
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_b.npy"))
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else if(argc == 4)
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Run graph
+ graph.run();
}
- else
+
+private:
+ Graph graph{};
+
+ BranchLayer get_inception_node(const std::string &data_path, std::string &&param_path,
+ unsigned int a_filt,
+ std::tuple<unsigned int, unsigned int> b_filters,
+ std::tuple<unsigned int, unsigned int> c_filters,
+ unsigned int d_filt)
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
- }
+ std::string total_path = "/cnn_data/googlenet_model/" + param_path + "/" + param_path + "_";
+ SubGraph i_a;
+ i_a << ConvolutionLayer(
+ 1U, 1U, a_filt,
+ get_weights_accessor(data_path, total_path + "1x1_w.npy"),
+ get_weights_accessor(data_path, total_path + "1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- Graph graph;
+ SubGraph i_b;
+ i_b << ConvolutionLayer(
+ 1U, 1U, std::get<0>(b_filters),
+ get_weights_accessor(data_path, total_path + "3x3_reduce_w.npy"),
+ get_weights_accessor(data_path, total_path + "3x3_reduce_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, std::get<1>(b_filters),
+ get_weights_accessor(data_path, total_path + "3x3_w.npy"),
+ get_weights_accessor(data_path, total_path + "3x3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- graph << target_hint
- << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- << ConvolutionLayer(
- 7U, 7U, 64U,
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_b.npy"),
- PadStrideInfo(2, 2, 3, 3))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
- << convolution_hint
- << ConvolutionLayer(
- 1U, 1U, 64U,
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 192U,
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << get_inception_node(data_path, "inception_3a", 64, std::make_tuple(96U, 128U), std::make_tuple(16U, 32U), 32U)
- << get_inception_node(data_path, "inception_3b", 128, std::make_tuple(128U, 192U), std::make_tuple(32U, 96U), 64U)
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << get_inception_node(data_path, "inception_4a", 192, std::make_tuple(96U, 208U), std::make_tuple(16U, 48U), 64U)
- << get_inception_node(data_path, "inception_4b", 160, std::make_tuple(112U, 224U), std::make_tuple(24U, 64U), 64U)
- << get_inception_node(data_path, "inception_4c", 128, std::make_tuple(128U, 256U), std::make_tuple(24U, 64U), 64U)
- << get_inception_node(data_path, "inception_4d", 112, std::make_tuple(144U, 288U), std::make_tuple(32U, 64U), 64U)
- << get_inception_node(data_path, "inception_4e", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << get_inception_node(data_path, "inception_5a", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
- << get_inception_node(data_path, "inception_5b", 384, std::make_tuple(192U, 384U), std::make_tuple(48U, 128U), 128U)
- << PoolingLayer(PoolingLayerInfo(PoolingType::AVG, 7, PadStrideInfo(1, 1, 0, 0, DimensionRoundingType::CEIL)))
- << FullyConnectedLayer(
- 1000U,
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_b.npy"))
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
+ SubGraph i_c;
+ i_c << ConvolutionLayer(
+ 1U, 1U, std::get<0>(c_filters),
+ get_weights_accessor(data_path, total_path + "5x5_reduce_w.npy"),
+ get_weights_accessor(data_path, total_path + "5x5_reduce_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 5U, 5U, std::get<1>(c_filters),
+ get_weights_accessor(data_path, total_path + "5x5_w.npy"),
+ get_weights_accessor(data_path, total_path + "5x5_b.npy"),
+ PadStrideInfo(1, 1, 2, 2))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- graph.run();
-}
+ SubGraph i_d;
+ i_d << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(1, 1, 1, 1, DimensionRoundingType::CEIL)))
+ << ConvolutionLayer(
+ 1U, 1U, d_filt,
+ get_weights_accessor(data_path, total_path + "pool_proj_w.npy"),
+ get_weights_accessor(data_path, total_path + "pool_proj_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+ return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b), std::move(i_c), std::move(i_d));
+ }
+};
/** Main program for Googlenet
*
@@ -200,5 +206,5 @@ void main_graph_googlenet(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_googlenet);
+ return arm_compute::utils::run_example<GraphGooglenetExample>(argc, argv);
}
diff --git a/examples/graph_lenet.cpp b/examples/graph_lenet.cpp
index 3e4727f189..2442cffe08 100644
--- a/examples/graph_lenet.cpp
+++ b/examples/graph_lenet.cpp
@@ -29,103 +29,88 @@
#include <cstdlib>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
-namespace
-{
-/** Generates appropriate accessor according to the specified path
- *
- * @note If path is empty will generate a DummyAccessor else will generate a NumPyBinLoader
- *
- * @param path Path to the data files
- * @param data_file Relative path to the data files from path
- *
- * @return An appropriate tensor accessor
- */
-std::unique_ptr<ITensorAccessor> get_accessor(const std::string &path, const std::string &data_file)
-{
- if(path.empty())
- {
- return arm_compute::support::cpp14::make_unique<DummyAccessor>();
- }
- else
- {
- return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(path + data_file);
- }
-}
-} // namespace
-
/** Example demonstrating how to implement LeNet's network using the Compute Library's graph API
*
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] batches )
*/
-void main_graph_lenet(int argc, char **argv)
+class GraphLenetExample : public Example
{
- std::string data_path; /** Path to the trainable data */
- unsigned int batches = 4; /** Number of batches */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /** Path to the trainable data */
+ unsigned int batches = 4; /** Number of batches */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [batches]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [batches]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- //Do something with argv[1]
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " [path_to_data] [batches]\n\n";
- std::cout << "No number of batches where specified, thus will use the default : " << batches << "\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [batches]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [batches]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ //Do something with argv[1]
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " [path_to_data] [batches]\n\n";
+ std::cout << "No number of batches where specified, thus will use the default : " << batches << "\n\n";
+ }
+ else
+ {
+ //Do something with argv[1] and argv[2]
+ data_path = argv[2];
+ batches = std::strtol(argv[3], nullptr, 0);
+ }
+
+ //conv1 << pool1 << conv2 << pool2 << fc1 << act1 << fc2 << smx
+ graph << target_hint
+ << Tensor(TensorInfo(TensorShape(28U, 28U, 1U, batches), 1, DataType::F32), DummyAccessor())
+ << ConvolutionLayer(
+ 5U, 5U, 20U,
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/conv1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/conv1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ << ConvolutionLayer(
+ 5U, 5U, 50U,
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/conv2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/conv2_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ << FullyConnectedLayer(
+ 500U,
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/ip1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/ip1_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << FullyConnectedLayer(
+ 10U,
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/ip2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/lenet_model/ip2_b.npy"))
+ << SoftmaxLayer()
+ << Tensor(DummyAccessor());
}
- else
+ void do_run() override
{
- //Do something with argv[1] and argv[2]
- data_path = argv[2];
- batches = std::strtol(argv[3], nullptr, 0);
+ // Run graph
+ graph.run();
}
- Graph graph;
-
- //conv1 << pool1 << conv2 << pool2 << fc1 << act1 << fc2 << smx
- graph << target_hint
- << Tensor(TensorInfo(TensorShape(28U, 28U, 1U, batches), 1, DataType::F32), DummyAccessor())
- << ConvolutionLayer(
- 5U, 5U, 20U,
- get_accessor(data_path, "/cnn_data/lenet_model/conv1_w.npy"),
- get_accessor(data_path, "/cnn_data/lenet_model/conv1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- << ConvolutionLayer(
- 5U, 5U, 50U,
- get_accessor(data_path, "/cnn_data/lenet_model/conv2_w.npy"),
- get_accessor(data_path, "/cnn_data/lenet_model/conv2_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- << FullyConnectedLayer(
- 500U,
- get_accessor(data_path, "/cnn_data/lenet_model/ip1_w.npy"),
- get_accessor(data_path, "/cnn_data/lenet_model/ip1_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << FullyConnectedLayer(
- 10U,
- get_accessor(data_path, "/cnn_data/lenet_model/ip2_w.npy"),
- get_accessor(data_path, "/cnn_data/lenet_model/ip2_b.npy"))
- << SoftmaxLayer()
- << Tensor(DummyAccessor());
-
- graph.run();
-}
+private:
+ Graph graph{};
+};
/** Main program for LeNet
*
@@ -134,5 +119,5 @@ void main_graph_lenet(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_lenet);
+ return arm_compute::utils::run_example<GraphLenetExample>(argc, argv);
}
diff --git a/examples/graph_mobilenet.cpp b/examples/graph_mobilenet.cpp
index c468093e56..193e5c336e 100644
--- a/examples/graph_mobilenet.cpp
+++ b/examples/graph_mobilenet.cpp
@@ -29,142 +29,148 @@
#include <cstdlib>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
-namespace
-{
-BranchLayer get_dwsc_node(const std::string &data_path, std::string &&param_path,
- unsigned int conv_filt,
- PadStrideInfo dwc_pad_stride_info, PadStrideInfo conv_pad_stride_info)
-{
- std::string total_path = "/cnn_data/mobilenet_v1_model/" + param_path + "_";
- SubGraph sg;
- sg << DepthwiseConvolutionLayer(
- 3U, 3U,
- get_weights_accessor(data_path, total_path + "depthwise_depthwise_weights.npy"),
- std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
- dwc_pad_stride_info,
- true)
- << BatchNormalizationLayer(
- get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_mean.npy"),
- get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_variance.npy"),
- get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_beta.npy"),
- get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_gamma.npy"),
- 0.001f)
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
- << ConvolutionLayer(
- 1U, 1U, conv_filt,
- get_weights_accessor(data_path, total_path + "pointwise_weights.npy"),
- std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
- conv_pad_stride_info)
- << BatchNormalizationLayer(
- get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_mean.npy"),
- get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_variance.npy"),
- get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_beta.npy"),
- get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_gamma.npy"),
- 0.001f)
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f));
-
- return BranchLayer(std::move(sg));
-}
-} // namespace
-
/** Example demonstrating how to implement MobileNet's network using the Compute Library's graph API
*
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_mobilenet(int argc, char **argv)
+class GraphMobilenetExample : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
- }
- else if(argc == 4)
- {
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ << convolution_hint
+ << ConvolutionLayer(
+ 3U, 3U, 32U,
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_weights.npy"),
+ std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+ PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))
+ << BatchNormalizationLayer(
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_mean.npy"),
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_variance.npy"),
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_beta.npy"),
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_gamma.npy"),
+ 0.001f)
+
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
+ << get_dwsc_node(data_path, "Conv2d_1", 64, PadStrideInfo(1, 1, 1, 1), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_2", 128, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_3", 128, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_4", 256, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_5", 256, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_6", 512, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_7", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_8", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_9", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_10", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_11", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_12", 1024, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << get_dwsc_node(data_path, "Conv2d_13", 1024, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
+ << ConvolutionLayer(
+ 1U, 1U, 1001U,
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_weights.npy"),
+ get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_biases.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ReshapeLayer(TensorShape(1001U))
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
+ // Run graph
+ graph.run();
}
- Graph graph;
+private:
+ Graph graph{};
- graph << target_hint
- << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- << convolution_hint
- << ConvolutionLayer(
- 3U, 3U, 32U,
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_weights.npy"),
- std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
- PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))
- << BatchNormalizationLayer(
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_mean.npy"),
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_variance.npy"),
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_beta.npy"),
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_gamma.npy"),
- 0.001f)
-
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
- << get_dwsc_node(data_path, "Conv2d_1", 64, PadStrideInfo(1, 1, 1, 1), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_2", 128, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_3", 128, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_4", 256, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_5", 256, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_6", 512, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_7", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_8", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_9", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_10", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_11", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_12", 1024, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << get_dwsc_node(data_path, "Conv2d_13", 1024, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
- << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
- << ConvolutionLayer(
- 1U, 1U, 1001U,
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_weights.npy"),
- get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_biases.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ReshapeLayer(TensorShape(1001U))
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
+ BranchLayer get_dwsc_node(const std::string &data_path, std::string &&param_path,
+ unsigned int conv_filt,
+ PadStrideInfo dwc_pad_stride_info, PadStrideInfo conv_pad_stride_info)
+ {
+ std::string total_path = "/cnn_data/mobilenet_v1_model/" + param_path + "_";
+ SubGraph sg;
+ sg << DepthwiseConvolutionLayer(
+ 3U, 3U,
+ get_weights_accessor(data_path, total_path + "depthwise_depthwise_weights.npy"),
+ std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+ dwc_pad_stride_info,
+ true)
+ << BatchNormalizationLayer(
+ get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_mean.npy"),
+ get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_variance.npy"),
+ get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_beta.npy"),
+ get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_gamma.npy"),
+ 0.001f)
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
+ << ConvolutionLayer(
+ 1U, 1U, conv_filt,
+ get_weights_accessor(data_path, total_path + "pointwise_weights.npy"),
+ std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+ conv_pad_stride_info)
+ << BatchNormalizationLayer(
+ get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_mean.npy"),
+ get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_variance.npy"),
+ get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_beta.npy"),
+ get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_gamma.npy"),
+ 0.001f)
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f));
- graph.run();
-}
+ return BranchLayer(std::move(sg));
+ }
+};
/** Main program for MobileNetV1
*
@@ -173,5 +179,5 @@ void main_graph_mobilenet(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_mobilenet);
+ return arm_compute::utils::run_example<GraphMobilenetExample>(argc, argv);
}
diff --git a/examples/graph_squeezenet.cpp b/examples/graph_squeezenet.cpp
index 11a80a7bd8..b21f2fe5c4 100644
--- a/examples/graph_squeezenet.cpp
+++ b/examples/graph_squeezenet.cpp
@@ -31,33 +31,13 @@
#include <cstdlib>
#include <tuple>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
using namespace arm_compute::logging;
namespace
{
-BranchLayer get_expand_fire_node(const std::string &data_path, std::string &&param_path, unsigned int expand1_filt, unsigned int expand3_filt)
-{
- std::string total_path = "/cnn_data/squeezenet_v1.0_model/" + param_path + "_";
- SubGraph i_a;
- i_a << ConvolutionLayer(
- 1U, 1U, expand1_filt,
- get_weights_accessor(data_path, total_path + "expand1x1_w.npy"),
- get_weights_accessor(data_path, total_path + "expand1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- SubGraph i_b;
- i_b << ConvolutionLayer(
- 3U, 3U, expand3_filt,
- get_weights_accessor(data_path, total_path + "expand3x3_w.npy"),
- get_weights_accessor(data_path, total_path + "expand3x3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
-
- return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b));
-}
} // namespace
/** Example demonstrating how to implement Squeezenet's network using the Compute Library's graph API
@@ -65,136 +45,166 @@ BranchLayer get_expand_fire_node(const std::string &data_path, std::string &&par
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_squeezenet(int argc, char **argv)
+class GraphSqueezenetExample : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
- }
- else if(argc == 4)
- {
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ << ConvolutionLayer(
+ 7U, 7U, 96U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_b.npy"),
+ PadStrideInfo(2, 2, 0, 0))
+ << convolution_hint
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << ConvolutionLayer(
+ 1U, 1U, 16U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire2", 64U, 64U)
+ << ConvolutionLayer(
+ 1U, 1U, 16U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire3", 64U, 64U)
+ << ConvolutionLayer(
+ 1U, 1U, 32U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire4", 128U, 128U)
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << ConvolutionLayer(
+ 1U, 1U, 32U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire5", 128U, 128U)
+ << ConvolutionLayer(
+ 1U, 1U, 48U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire6", 192U, 192U)
+ << ConvolutionLayer(
+ 1U, 1U, 48U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire7", 192U, 192U)
+ << ConvolutionLayer(
+ 1U, 1U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire8", 256U, 256U)
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+ << ConvolutionLayer(
+ 1U, 1U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << get_expand_fire_node(data_path, "fire9", 256U, 256U)
+ << ConvolutionLayer(
+ 1U, 1U, 1000U,
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
+ << FlattenLayer()
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
+ // Run graph
+ graph.run();
}
- Graph graph;
+private:
+ Graph graph{};
- graph << target_hint
- << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- << ConvolutionLayer(
- 7U, 7U, 96U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_b.npy"),
- PadStrideInfo(2, 2, 0, 0))
- << convolution_hint
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << ConvolutionLayer(
- 1U, 1U, 16U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire2", 64U, 64U)
- << ConvolutionLayer(
- 1U, 1U, 16U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire3", 64U, 64U)
- << ConvolutionLayer(
- 1U, 1U, 32U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire4", 128U, 128U)
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << ConvolutionLayer(
- 1U, 1U, 32U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire5", 128U, 128U)
- << ConvolutionLayer(
- 1U, 1U, 48U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire6", 192U, 192U)
- << ConvolutionLayer(
- 1U, 1U, 48U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire7", 192U, 192U)
- << ConvolutionLayer(
- 1U, 1U, 64U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire8", 256U, 256U)
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
- << ConvolutionLayer(
- 1U, 1U, 64U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << get_expand_fire_node(data_path, "fire9", 256U, 256U)
- << ConvolutionLayer(
- 1U, 1U, 1000U,
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_b.npy"),
- PadStrideInfo(1, 1, 0, 0))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
- << FlattenLayer()
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
+ BranchLayer get_expand_fire_node(const std::string &data_path, std::string &&param_path, unsigned int expand1_filt, unsigned int expand3_filt)
+ {
+ std::string total_path = "/cnn_data/squeezenet_v1.0_model/" + param_path + "_";
+ SubGraph i_a;
+ i_a << ConvolutionLayer(
+ 1U, 1U, expand1_filt,
+ get_weights_accessor(data_path, total_path + "expand1x1_w.npy"),
+ get_weights_accessor(data_path, total_path + "expand1x1_b.npy"),
+ PadStrideInfo(1, 1, 0, 0))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- graph.run();
-}
+ SubGraph i_b;
+ i_b << ConvolutionLayer(
+ 3U, 3U, expand3_filt,
+ get_weights_accessor(data_path, total_path + "expand3x3_w.npy"),
+ get_weights_accessor(data_path, total_path + "expand3x3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+ return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b));
+ }
+};
/** Main program for Squeezenet v1.0
*
@@ -203,5 +213,5 @@ void main_graph_squeezenet(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_squeezenet);
+ return arm_compute::utils::run_example<GraphSqueezenetExample>(argc, argv);
}
diff --git a/examples/graph_vgg16.cpp b/examples/graph_vgg16.cpp
index fcaa6182cb..1a804a4882 100644
--- a/examples/graph_vgg16.cpp
+++ b/examples/graph_vgg16.cpp
@@ -29,6 +29,7 @@
#include <cstdlib>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
@@ -37,179 +38,186 @@ using namespace arm_compute::graph_utils;
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_vgg16(int argc, char **argv)
+class GraphVGG16Example : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 123.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 123.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
- }
- else if(argc == 4)
- {
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << convolution_hint
+ << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ << ConvolutionMethodHint::DIRECT
+ // Layer 1
+ << ConvolutionLayer(
+ 3U, 3U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 2
+ << ConvolutionLayer(
+ 3U, 3U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 3
+ << ConvolutionLayer(
+ 3U, 3U, 128U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 4
+ << ConvolutionLayer(
+ 3U, 3U, 128U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 5
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 6
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 7
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 8
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 9
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 10
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 11
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 12
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 13
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 14
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 15
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 16
+ << FullyConnectedLayer(
+ 1000U,
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_b.npy"))
+ // Softmax
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
+ // Run graph
+ graph.run();
}
- Graph graph;
-
- graph << target_hint
- << convolution_hint
- << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- << ConvolutionMethodHint::DIRECT
- // Layer 1
- << ConvolutionLayer(
- 3U, 3U, 64U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 2
- << ConvolutionLayer(
- 3U, 3U, 64U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 3
- << ConvolutionLayer(
- 3U, 3U, 128U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 4
- << ConvolutionLayer(
- 3U, 3U, 128U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 5
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 6
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 7
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 8
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 9
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 10
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 11
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 12
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 13
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 14
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 15
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 16
- << FullyConnectedLayer(
- 1000U,
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_b.npy"))
- // Softmax
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
-
- // Run graph
- graph.run();
-}
+private:
+ Graph graph{};
+};
/** Main program for VGG16
*
@@ -218,5 +226,5 @@ void main_graph_vgg16(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_vgg16);
+ return arm_compute::utils::run_example<GraphVGG16Example>(argc, argv);
}
diff --git a/examples/graph_vgg19.cpp b/examples/graph_vgg19.cpp
index 1f6cba4441..5214438d7f 100644
--- a/examples/graph_vgg19.cpp
+++ b/examples/graph_vgg19.cpp
@@ -29,6 +29,7 @@
#include <cstdlib>
+using namespace arm_compute::utils;
using namespace arm_compute::graph;
using namespace arm_compute::graph_utils;
@@ -37,188 +38,195 @@ using namespace arm_compute::graph_utils;
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
*/
-void main_graph_vgg19(int argc, char **argv)
+class GraphVGG19Example : public Example
{
- std::string data_path; /* Path to the trainable data */
- std::string image; /* Image data */
- std::string label; /* Label data */
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ std::string data_path; /* Path to the trainable data */
+ std::string image; /* Image data */
+ std::string label; /* Label data */
- constexpr float mean_r = 123.68f; /* Mean value to subtract from red channel */
- constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
- constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
+ constexpr float mean_r = 123.68f; /* Mean value to subtract from red channel */
+ constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
+ constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
- // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
- TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
- ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
+ // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+ TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+ ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
- // Parse arguments
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 2)
- {
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
- std::cout << "No data folder provided: using random values\n\n";
- }
- else if(argc == 3)
- {
- data_path = argv[2];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
- std::cout << "No image provided: using random values\n\n";
- }
- else if(argc == 4)
- {
- data_path = argv[2];
- image = argv[3];
- std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
- std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ // Parse arguments
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 2)
+ {
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+ std::cout << "No data folder provided: using random values\n\n";
+ }
+ else if(argc == 3)
+ {
+ data_path = argv[2];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+ std::cout << "No image provided: using random values\n\n";
+ }
+ else if(argc == 4)
+ {
+ data_path = argv[2];
+ image = argv[3];
+ std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+ std::cout << "No text file with labels provided: skipping output accessor\n\n";
+ }
+ else
+ {
+ data_path = argv[2];
+ image = argv[3];
+ label = argv[4];
+ }
+
+ graph << target_hint
+ << convolution_hint
+ << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+ get_input_accessor(image, mean_r, mean_g, mean_b))
+ // Layer 1
+ << ConvolutionLayer(
+ 3U, 3U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 64U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 2
+ << ConvolutionLayer(
+ 3U, 3U, 128U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 128U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 3
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 256U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 4
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 5
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << ConvolutionLayer(
+ 3U, 3U, 512U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_b.npy"),
+ PadStrideInfo(1, 1, 1, 1))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+ // Layer 6
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 7
+ << FullyConnectedLayer(
+ 4096U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_b.npy"))
+ << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+ // Layer 8
+ << FullyConnectedLayer(
+ 1000U,
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_w.npy"),
+ get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_b.npy"))
+ // Softmax
+ << SoftmaxLayer()
+ << Tensor(get_output_accessor(label, 5));
}
- else
+ void do_run() override
{
- data_path = argv[2];
- image = argv[3];
- label = argv[4];
+ // Run graph
+ graph.run();
}
- Graph graph;
-
- graph << target_hint
- << convolution_hint
- << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
- get_input_accessor(image, mean_r, mean_g, mean_b))
- // Layer 1
- << ConvolutionLayer(
- 3U, 3U, 64U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 64U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 2
- << ConvolutionLayer(
- 3U, 3U, 128U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 128U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 3
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 256U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 4
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 5
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << ConvolutionLayer(
- 3U, 3U, 512U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_b.npy"),
- PadStrideInfo(1, 1, 1, 1))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
- // Layer 6
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 7
- << FullyConnectedLayer(
- 4096U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_b.npy"))
- << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
- // Layer 8
- << FullyConnectedLayer(
- 1000U,
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_w.npy"),
- get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_b.npy"))
- // Softmax
- << SoftmaxLayer()
- << Tensor(get_output_accessor(label, 5));
-
- // Run graph
- graph.run();
-}
+private:
+ Graph graph{};
+};
/** Main program for VGG19
*
@@ -227,5 +235,5 @@ void main_graph_vgg19(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return arm_compute::utils::run_example(argc, argv, main_graph_vgg19);
+ return arm_compute::utils::run_example<GraphVGG19Example>(argc, argv);
}
diff --git a/examples/neon_cartoon_effect.cpp b/examples/neon_cartoon_effect.cpp
index 0ecd9410a1..da8ce3f84f 100644
--- a/examples/neon_cartoon_effect.cpp
+++ b/examples/neon_cartoon_effect.cpp
@@ -30,67 +30,76 @@
using namespace arm_compute;
using namespace utils;
-void main_neon_cartoon_effect(int argc, char **argv)
+class NEONCartoonEffectExample : public Example
{
- // Open PPM file
- PPMLoader ppm;
- Image src_img;
- Image dst_img;
- Image gaus5x5_img;
- Image canny_edge_img;
-
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: ./build/neon_cartoon_effect [input_image.ppm]\n\n";
- std::cout << "No input_image provided, creating a dummy 640x480 image\n";
- // Create an empty grayscale 640x480 image
- src_img.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else
+public:
+ void do_setup(int argc, char **argv) override
{
- ppm.open(argv[1]);
- ppm.init_image(src_img, Format::U8);
- }
+ // Open PPM file
+ PPMLoader ppm;
- // Initialize just the dimensions and format of the images:
- gaus5x5_img.allocator()->init(*src_img.info());
- canny_edge_img.allocator()->init(*src_img.info());
- dst_img.allocator()->init(*src_img.info());
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: ./build/neon_cartoon_effect [input_image.ppm]\n\n";
+ std::cout << "No input_image provided, creating a dummy 640x480 image\n";
+ // Create an empty grayscale 640x480 image
+ src_img.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm.open(argv[1]);
+ ppm.init_image(src_img, Format::U8);
+ }
- NEGaussian5x5 gaus5x5;
- NECannyEdge canny_edge;
- NEArithmeticSubtraction sub;
+ // Initialize just the dimensions and format of the images:
+ gaus5x5_img.allocator()->init(*src_img.info());
+ canny_edge_img.allocator()->init(*src_img.info());
+ dst_img.allocator()->init(*src_img.info());
- // Configure the functions to call
- gaus5x5.configure(&src_img, &gaus5x5_img, BorderMode::REPLICATE);
- canny_edge.configure(&src_img, &canny_edge_img, 100, 80, 3, 1, BorderMode::REPLICATE);
- sub.configure(&gaus5x5_img, &canny_edge_img, &dst_img, ConvertPolicy::SATURATE);
+ // Configure the functions to call
+ gaus5x5.configure(&src_img, &gaus5x5_img, BorderMode::REPLICATE);
+ canny_edge.configure(&src_img, &canny_edge_img, 100, 80, 3, 1, BorderMode::REPLICATE);
+ sub.configure(&gaus5x5_img, &canny_edge_img, &dst_img, ConvertPolicy::SATURATE);
- // Now that the padding requirements are known we can allocate the images:
- src_img.allocator()->allocate();
- dst_img.allocator()->allocate();
- gaus5x5_img.allocator()->allocate();
- canny_edge_img.allocator()->allocate();
+ // Now that the padding requirements are known we can allocate the images:
+ src_img.allocator()->allocate();
+ dst_img.allocator()->allocate();
+ gaus5x5_img.allocator()->allocate();
+ canny_edge_img.allocator()->allocate();
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm.is_open())
- {
- ppm.fill_image(src_img);
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm.is_open())
+ {
+ ppm.fill_image(src_img);
+ output_filename = std::string(argv[1]) + "_out.ppm";
+ }
}
- // Execute the functions:
- gaus5x5.run();
- canny_edge.run();
- sub.run();
+ void do_run() override
+ {
+ // Execute the functions:
+ gaus5x5.run();
+ canny_edge.run();
+ sub.run();
+ }
- // Save the result to file:
- if(ppm.is_open())
+ void do_teardown() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- save_to_ppm(dst_img, output_filename);
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ save_to_ppm(dst_img, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ }
}
-}
+
+private:
+ Image src_img{}, dst_img{}, gaus5x5_img{}, canny_edge_img{};
+ NEGaussian5x5 gaus5x5{};
+ NECannyEdge canny_edge{};
+ NEArithmeticSubtraction sub{};
+ std::string output_filename{};
+};
/** Main program for cartoon effect test
*
@@ -99,5 +108,5 @@ void main_neon_cartoon_effect(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_neon_cartoon_effect);
+ return utils::run_example<NEONCartoonEffectExample>(argc, argv);
}
diff --git a/examples/neon_cnn.cpp b/examples/neon_cnn.cpp
index 2be5acfbaf..05b6c832bc 100644
--- a/examples/neon_cnn.cpp
+++ b/examples/neon_cnn.cpp
@@ -33,254 +33,261 @@
using namespace arm_compute;
using namespace utils;
-void main_cnn(int argc, char **argv)
+class NEONCNNExample : public Example
{
- ARM_COMPUTE_UNUSED(argc);
- ARM_COMPUTE_UNUSED(argv);
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ ARM_COMPUTE_UNUSED(argc);
+ ARM_COMPUTE_UNUSED(argv);
- // Create NEON allocator
- Allocator allocator;
+ // Create memory manager components
+ // We need 2 memory managers: 1 for handling the tensors within the functions (mm_layers) and 1 for handling the input and output tensors of the functions (mm_transitions))
+ auto lifetime_mgr0 = std::make_shared<BlobLifetimeManager>(); // Create lifetime manager
+ auto lifetime_mgr1 = std::make_shared<BlobLifetimeManager>(); // Create lifetime manager
+ auto pool_mgr0 = std::make_shared<PoolManager>(); // Create pool manager
+ auto pool_mgr1 = std::make_shared<PoolManager>(); // Create pool manager
+ auto mm_layers = std::make_shared<MemoryManagerOnDemand>(lifetime_mgr0, pool_mgr0); // Create the memory manager
+ auto mm_transitions = std::make_shared<MemoryManagerOnDemand>(lifetime_mgr1, pool_mgr1); // Create the memory manager
- // Create memory manager components
- // We need 2 memory managers: 1 for handling the tensors within the functions (mm_layers) and 1 for handling the input and output tensors of the functions (mm_transitions))
- auto lifetime_mgr0 = std::make_shared<BlobLifetimeManager>(); // Create lifetime manager
- auto lifetime_mgr1 = std::make_shared<BlobLifetimeManager>(); // Create lifetime manager
- auto pool_mgr0 = std::make_shared<PoolManager>(); // Create pool manager
- auto pool_mgr1 = std::make_shared<PoolManager>(); // Create pool manager
- auto mm_layers = std::make_shared<MemoryManagerOnDemand>(lifetime_mgr0, pool_mgr0); // Create the memory manager
- auto mm_transitions = std::make_shared<MemoryManagerOnDemand>(lifetime_mgr1, pool_mgr1); // Create the memory manager
+ // The weights and biases tensors should be initialized with the values inferred with the training
- // The src tensor should contain the input image
- Tensor src;
-
- // The weights and biases tensors should be initialized with the values inferred with the training
- Tensor weights0;
- Tensor weights1;
- Tensor weights2;
- Tensor biases0;
- Tensor biases1;
- Tensor biases2;
-
- Tensor out_conv0;
- Tensor out_conv1;
- Tensor out_act0;
- Tensor out_act1;
- Tensor out_act2;
- Tensor out_pool0;
- Tensor out_pool1;
- Tensor out_fc0;
- Tensor out_softmax;
-
- // Create layers and set memory manager where allowed to manage internal memory requirements
- NEConvolutionLayer conv0(mm_layers);
- NEConvolutionLayer conv1(mm_layers);
- NEPoolingLayer pool0;
- NEPoolingLayer pool1;
- NEFullyConnectedLayer fc0(mm_layers);
- NEActivationLayer act0;
- NEActivationLayer act1;
- NEActivationLayer act2;
- NESoftmaxLayer softmax(mm_layers);
+ // Set memory manager where allowed to manage internal memory requirements
+ conv0 = arm_compute::support::cpp14::make_unique<NEConvolutionLayer>(mm_layers);
+ conv1 = arm_compute::support::cpp14::make_unique<NEConvolutionLayer>(mm_layers);
+ fc0 = arm_compute::support::cpp14::make_unique<NEFullyConnectedLayer>(mm_layers);
+ softmax = arm_compute::support::cpp14::make_unique<NESoftmaxLayer>(mm_layers);
- /* [Initialize tensors] */
+ /* [Initialize tensors] */
- // Initialize src tensor
- constexpr unsigned int width_src_image = 32;
- constexpr unsigned int height_src_image = 32;
- constexpr unsigned int ifm_src_img = 1;
+ // Initialize src tensor
+ constexpr unsigned int width_src_image = 32;
+ constexpr unsigned int height_src_image = 32;
+ constexpr unsigned int ifm_src_img = 1;
- const TensorShape src_shape(width_src_image, height_src_image, ifm_src_img);
- src.allocator()->init(TensorInfo(src_shape, 1, DataType::F32));
+ const TensorShape src_shape(width_src_image, height_src_image, ifm_src_img);
+ src.allocator()->init(TensorInfo(src_shape, 1, DataType::F32));
- // Initialize tensors of conv0
- constexpr unsigned int kernel_x_conv0 = 5;
- constexpr unsigned int kernel_y_conv0 = 5;
- constexpr unsigned int ofm_conv0 = 8;
+ // Initialize tensors of conv0
+ constexpr unsigned int kernel_x_conv0 = 5;
+ constexpr unsigned int kernel_y_conv0 = 5;
+ constexpr unsigned int ofm_conv0 = 8;
- const TensorShape weights_shape_conv0(kernel_x_conv0, kernel_y_conv0, src_shape.z(), ofm_conv0);
- const TensorShape biases_shape_conv0(weights_shape_conv0[3]);
- const TensorShape out_shape_conv0(src_shape.x(), src_shape.y(), weights_shape_conv0[3]);
+ const TensorShape weights_shape_conv0(kernel_x_conv0, kernel_y_conv0, src_shape.z(), ofm_conv0);
+ const TensorShape biases_shape_conv0(weights_shape_conv0[3]);
+ const TensorShape out_shape_conv0(src_shape.x(), src_shape.y(), weights_shape_conv0[3]);
- weights0.allocator()->init(TensorInfo(weights_shape_conv0, 1, DataType::F32));
- biases0.allocator()->init(TensorInfo(biases_shape_conv0, 1, DataType::F32));
- out_conv0.allocator()->init(TensorInfo(out_shape_conv0, 1, DataType::F32));
-
- // Initialize tensor of act0
- out_act0.allocator()->init(TensorInfo(out_shape_conv0, 1, DataType::F32));
-
- // Initialize tensor of pool0
- TensorShape out_shape_pool0 = out_shape_conv0;
- out_shape_pool0.set(0, out_shape_pool0.x() / 2);
- out_shape_pool0.set(1, out_shape_pool0.y() / 2);
- out_pool0.allocator()->init(TensorInfo(out_shape_pool0, 1, DataType::F32));
-
- // Initialize tensors of conv1
- constexpr unsigned int kernel_x_conv1 = 3;
- constexpr unsigned int kernel_y_conv1 = 3;
- constexpr unsigned int ofm_conv1 = 16;
-
- const TensorShape weights_shape_conv1(kernel_x_conv1, kernel_y_conv1, out_shape_pool0.z(), ofm_conv1);
-
- const TensorShape biases_shape_conv1(weights_shape_conv1[3]);
- const TensorShape out_shape_conv1(out_shape_pool0.x(), out_shape_pool0.y(), weights_shape_conv1[3]);
-
- weights1.allocator()->init(TensorInfo(weights_shape_conv1, 1, DataType::F32));
- biases1.allocator()->init(TensorInfo(biases_shape_conv1, 1, DataType::F32));
- out_conv1.allocator()->init(TensorInfo(out_shape_conv1, 1, DataType::F32));
-
- // Initialize tensor of act1
- out_act1.allocator()->init(TensorInfo(out_shape_conv1, 1, DataType::F32));
-
- // Initialize tensor of pool1
- TensorShape out_shape_pool1 = out_shape_conv1;
- out_shape_pool1.set(0, out_shape_pool1.x() / 2);
- out_shape_pool1.set(1, out_shape_pool1.y() / 2);
- out_pool1.allocator()->init(TensorInfo(out_shape_pool1, 1, DataType::F32));
-
- // Initialize tensor of fc0
- constexpr unsigned int num_labels = 128;
-
- const TensorShape weights_shape_fc0(out_shape_pool1.x() * out_shape_pool1.y() * out_shape_pool1.z(), num_labels);
- const TensorShape biases_shape_fc0(num_labels);
- const TensorShape out_shape_fc0(num_labels);
-
- weights2.allocator()->init(TensorInfo(weights_shape_fc0, 1, DataType::F32));
- biases2.allocator()->init(TensorInfo(biases_shape_fc0, 1, DataType::F32));
- out_fc0.allocator()->init(TensorInfo(out_shape_fc0, 1, DataType::F32));
-
- // Initialize tensor of act2
- out_act2.allocator()->init(TensorInfo(out_shape_fc0, 1, DataType::F32));
-
- // Initialize tensor of softmax
- const TensorShape out_shape_softmax(out_shape_fc0.x());
- out_softmax.allocator()->init(TensorInfo(out_shape_softmax, 1, DataType::F32));
+ weights0.allocator()->init(TensorInfo(weights_shape_conv0, 1, DataType::F32));
+ biases0.allocator()->init(TensorInfo(biases_shape_conv0, 1, DataType::F32));
+ out_conv0.allocator()->init(TensorInfo(out_shape_conv0, 1, DataType::F32));
- /* -----------------------End: [Initialize tensors] */
+ // Initialize tensor of act0
+ out_act0.allocator()->init(TensorInfo(out_shape_conv0, 1, DataType::F32));
- /* [Configure functions] */
+ // Initialize tensor of pool0
+ TensorShape out_shape_pool0 = out_shape_conv0;
+ out_shape_pool0.set(0, out_shape_pool0.x() / 2);
+ out_shape_pool0.set(1, out_shape_pool0.y() / 2);
+ out_pool0.allocator()->init(TensorInfo(out_shape_pool0, 1, DataType::F32));
- // in:32x32x1: 5x5 convolution, 8 output features maps (OFM)
- conv0.configure(&src, &weights0, &biases0, &out_conv0, PadStrideInfo(1 /* stride_x */, 1 /* stride_y */, 2 /* pad_x */, 2 /* pad_y */));
+ // Initialize tensors of conv1
+ constexpr unsigned int kernel_x_conv1 = 3;
+ constexpr unsigned int kernel_y_conv1 = 3;
+ constexpr unsigned int ofm_conv1 = 16;
- // in:32x32x8, out:32x32x8, Activation function: relu
- act0.configure(&out_conv0, &out_act0, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+ const TensorShape weights_shape_conv1(kernel_x_conv1, kernel_y_conv1, out_shape_pool0.z(), ofm_conv1);
- // in:32x32x8, out:16x16x8 (2x2 pooling), Pool type function: Max
- pool0.configure(&out_act0, &out_pool0, PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2 /* stride_x */, 2 /* stride_y */)));
+ const TensorShape biases_shape_conv1(weights_shape_conv1[3]);
+ const TensorShape out_shape_conv1(out_shape_pool0.x(), out_shape_pool0.y(), weights_shape_conv1[3]);
+
+ weights1.allocator()->init(TensorInfo(weights_shape_conv1, 1, DataType::F32));
+ biases1.allocator()->init(TensorInfo(biases_shape_conv1, 1, DataType::F32));
+ out_conv1.allocator()->init(TensorInfo(out_shape_conv1, 1, DataType::F32));
+
+ // Initialize tensor of act1
+ out_act1.allocator()->init(TensorInfo(out_shape_conv1, 1, DataType::F32));
- // in:16x16x8: 3x3 convolution, 16 output features maps (OFM)
- conv1.configure(&out_pool0, &weights1, &biases1, &out_conv1, PadStrideInfo(1 /* stride_x */, 1 /* stride_y */, 1 /* pad_x */, 1 /* pad_y */));
+ // Initialize tensor of pool1
+ TensorShape out_shape_pool1 = out_shape_conv1;
+ out_shape_pool1.set(0, out_shape_pool1.x() / 2);
+ out_shape_pool1.set(1, out_shape_pool1.y() / 2);
+ out_pool1.allocator()->init(TensorInfo(out_shape_pool1, 1, DataType::F32));
- // in:16x16x16, out:16x16x16, Activation function: relu
- act1.configure(&out_conv1, &out_act1, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+ // Initialize tensor of fc0
+ constexpr unsigned int num_labels = 128;
- // in:16x16x16, out:8x8x16 (2x2 pooling), Pool type function: Average
- pool1.configure(&out_act1, &out_pool1, PoolingLayerInfo(PoolingType::AVG, 2, PadStrideInfo(2 /* stride_x */, 2 /* stride_y */)));
+ const TensorShape weights_shape_fc0(out_shape_pool1.x() * out_shape_pool1.y() * out_shape_pool1.z(), num_labels);
+ const TensorShape biases_shape_fc0(num_labels);
+ const TensorShape out_shape_fc0(num_labels);
- // in:8x8x16, out:128
- fc0.configure(&out_pool1, &weights2, &biases2, &out_fc0);
+ weights2.allocator()->init(TensorInfo(weights_shape_fc0, 1, DataType::F32));
+ biases2.allocator()->init(TensorInfo(biases_shape_fc0, 1, DataType::F32));
+ out_fc0.allocator()->init(TensorInfo(out_shape_fc0, 1, DataType::F32));
- // in:128, out:128, Activation function: relu
- act2.configure(&out_fc0, &out_act2, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+ // Initialize tensor of act2
+ out_act2.allocator()->init(TensorInfo(out_shape_fc0, 1, DataType::F32));
- // in:128, out:128
- softmax.configure(&out_act2, &out_softmax);
+ // Initialize tensor of softmax
+ const TensorShape out_shape_softmax(out_shape_fc0.x());
+ out_softmax.allocator()->init(TensorInfo(out_shape_softmax, 1, DataType::F32));
- /* -----------------------End: [Configure functions] */
+ /* -----------------------End: [Initialize tensors] */
- /*[ Add tensors to memory manager ]*/
+ /* [Configure functions] */
- // We need 2 memory groups for handling the input and output
- // We call explicitly allocate after manage() in order to avoid overlapping lifetimes
- MemoryGroup memory_group0(mm_transitions);
- MemoryGroup memory_group1(mm_transitions);
+ // in:32x32x1: 5x5 convolution, 8 output features maps (OFM)
+ conv0->configure(&src, &weights0, &biases0, &out_conv0, PadStrideInfo(1 /* stride_x */, 1 /* stride_y */, 2 /* pad_x */, 2 /* pad_y */));
- memory_group0.manage(&out_conv0);
- out_conv0.allocator()->allocate();
- memory_group1.manage(&out_act0);
- out_act0.allocator()->allocate();
- memory_group0.manage(&out_pool0);
- out_pool0.allocator()->allocate();
- memory_group1.manage(&out_conv1);
- out_conv1.allocator()->allocate();
- memory_group0.manage(&out_act1);
- out_act1.allocator()->allocate();
- memory_group1.manage(&out_pool1);
- out_pool1.allocator()->allocate();
- memory_group0.manage(&out_fc0);
- out_fc0.allocator()->allocate();
- memory_group1.manage(&out_act2);
- out_act2.allocator()->allocate();
- memory_group0.manage(&out_softmax);
- out_softmax.allocator()->allocate();
+ // in:32x32x8, out:32x32x8, Activation function: relu
+ act0.configure(&out_conv0, &out_act0, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- /* -----------------------End: [ Add tensors to memory manager ] */
+ // in:32x32x8, out:16x16x8 (2x2 pooling), Pool type function: Max
+ pool0.configure(&out_act0, &out_pool0, PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2 /* stride_x */, 2 /* stride_y */)));
- /* [Allocate tensors] */
+ // in:16x16x8: 3x3 convolution, 16 output features maps (OFM)
+ conv1->configure(&out_pool0, &weights1, &biases1, &out_conv1, PadStrideInfo(1 /* stride_x */, 1 /* stride_y */, 1 /* pad_x */, 1 /* pad_y */));
- // Now that the padding requirements are known we can allocate all tensors
- src.allocator()->allocate();
- weights0.allocator()->allocate();
- weights1.allocator()->allocate();
- weights2.allocator()->allocate();
- biases0.allocator()->allocate();
- biases1.allocator()->allocate();
- biases2.allocator()->allocate();
+ // in:16x16x16, out:16x16x16, Activation function: relu
+ act1.configure(&out_conv1, &out_act1, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- /* -----------------------End: [Allocate tensors] */
+ // in:16x16x16, out:8x8x16 (2x2 pooling), Pool type function: Average
+ pool1.configure(&out_act1, &out_pool1, PoolingLayerInfo(PoolingType::AVG, 2, PadStrideInfo(2 /* stride_x */, 2 /* stride_y */)));
- // Finalize layers memory manager
+ // in:8x8x16, out:128
+ fc0->configure(&out_pool1, &weights2, &biases2, &out_fc0);
- // Set allocator that the memory manager will use
- mm_layers->set_allocator(&allocator);
+ // in:128, out:128, Activation function: relu
+ act2.configure(&out_fc0, &out_act2, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
- // Number of pools that the manager will create. This specifies how many layers you want to run in parallel
- mm_layers->set_num_pools(1);
+ // in:128, out:128
+ softmax->configure(&out_act2, &out_softmax);
- // Finalize the manager. (Validity checks, memory allocations etc)
- mm_layers->finalize();
+ /* -----------------------End: [Configure functions] */
- // Finalize transitions memory manager
+ /*[ Add tensors to memory manager ]*/
- // Set allocator that the memory manager will use
- mm_transitions->set_allocator(&allocator);
+ // We need 2 memory groups for handling the input and output
+ // We call explicitly allocate after manage() in order to avoid overlapping lifetimes
+ memory_group0 = arm_compute::support::cpp14::make_unique<MemoryGroup>(mm_transitions);
+ memory_group1 = arm_compute::support::cpp14::make_unique<MemoryGroup>(mm_transitions);
- // Number of pools that the manager will create. This specifies how many models we can run in parallel.
- // Setting to 2 as we need one for the input and one for the output at any given time
- mm_transitions->set_num_pools(2);
+ memory_group0->manage(&out_conv0);
+ out_conv0.allocator()->allocate();
+ memory_group1->manage(&out_act0);
+ out_act0.allocator()->allocate();
+ memory_group0->manage(&out_pool0);
+ out_pool0.allocator()->allocate();
+ memory_group1->manage(&out_conv1);
+ out_conv1.allocator()->allocate();
+ memory_group0->manage(&out_act1);
+ out_act1.allocator()->allocate();
+ memory_group1->manage(&out_pool1);
+ out_pool1.allocator()->allocate();
+ memory_group0->manage(&out_fc0);
+ out_fc0.allocator()->allocate();
+ memory_group1->manage(&out_act2);
+ out_act2.allocator()->allocate();
+ memory_group0->manage(&out_softmax);
+ out_softmax.allocator()->allocate();
- // Finalize the manager. (Validity checks, memory allocations etc)
- mm_transitions->finalize();
+ /* -----------------------End: [ Add tensors to memory manager ] */
- /* [Initialize weights and biases tensors] */
+ /* [Allocate tensors] */
- // Once the tensors have been allocated, the src, weights and biases tensors can be initialized
- // ...
+ // Now that the padding requirements are known we can allocate all tensors
+ src.allocator()->allocate();
+ weights0.allocator()->allocate();
+ weights1.allocator()->allocate();
+ weights2.allocator()->allocate();
+ biases0.allocator()->allocate();
+ biases1.allocator()->allocate();
+ biases2.allocator()->allocate();
- /* -----------------------[Initialize weights and biases tensors] */
+ /* -----------------------End: [Allocate tensors] */
- /* [Execute the functions] */
+ // Finalize layers memory manager
- // Acquire memory for the memory groups
- memory_group0.acquire();
- memory_group1.acquire();
+ // Set allocator that the memory manager will use
+ mm_layers->set_allocator(&allocator);
- conv0.run();
- act0.run();
- pool0.run();
- conv1.run();
- act1.run();
- pool1.run();
- fc0.run();
- act2.run();
- softmax.run();
+ // Number of pools that the manager will create. This specifies how many layers you want to run in parallel
+ mm_layers->set_num_pools(1);
- // Release memory
- memory_group0.release();
- memory_group1.release();
+ // Finalize the manager. (Validity checks, memory allocations etc)
+ mm_layers->finalize();
- /* -----------------------End: [Execute the functions] */
-}
+ // Finalize transitions memory manager
+
+ // Set allocator that the memory manager will use
+ mm_transitions->set_allocator(&allocator);
+
+ // Number of pools that the manager will create. This specifies how many models we can run in parallel.
+ // Setting to 2 as we need one for the input and one for the output at any given time
+ mm_transitions->set_num_pools(2);
+
+ // Finalize the manager. (Validity checks, memory allocations etc)
+ mm_transitions->finalize();
+ }
+ void do_run() override
+ {
+ // Acquire memory for the memory groups
+ memory_group0->acquire();
+ memory_group1->acquire();
+
+ conv0->run();
+ act0.run();
+ pool0.run();
+ conv1->run();
+ act1.run();
+ pool1.run();
+ fc0->run();
+ act2.run();
+ softmax->run();
+
+ // Release memory
+ memory_group0->release();
+ memory_group1->release();
+ }
+
+private:
+ // The src tensor should contain the input image
+ Tensor src{};
+
+ // Intermediate tensors used
+ Tensor weights0{};
+ Tensor weights1{};
+ Tensor weights2{};
+ Tensor biases0{};
+ Tensor biases1{};
+ Tensor biases2{};
+ Tensor out_conv0{};
+ Tensor out_conv1{};
+ Tensor out_act0{};
+ Tensor out_act1{};
+ Tensor out_act2{};
+ Tensor out_pool0{};
+ Tensor out_pool1{};
+ Tensor out_fc0{};
+ Tensor out_softmax{};
+
+ // NEON allocator
+ Allocator allocator{};
+
+ // Memory groups
+ std::unique_ptr<MemoryGroup> memory_group0{};
+ std::unique_ptr<MemoryGroup> memory_group1{};
+
+ // Layers
+ std::unique_ptr<NEConvolutionLayer> conv0{};
+ std::unique_ptr<NEConvolutionLayer> conv1{};
+ std::unique_ptr<NEFullyConnectedLayer> fc0{};
+ std::unique_ptr<NESoftmaxLayer> softmax{};
+ NEPoolingLayer pool0{};
+ NEPoolingLayer pool1{};
+ NEActivationLayer act0{};
+ NEActivationLayer act1{};
+ NEActivationLayer act2{};
+};
/** Main program for cnn test
*
@@ -293,5 +300,5 @@ void main_cnn(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_cnn);
+ return utils::run_example<NEONCNNExample>(argc, argv);
}
diff --git a/examples/neon_convolution.cpp b/examples/neon_convolution.cpp
index 79800ae897..d51d2013f6 100644
--- a/examples/neon_convolution.cpp
+++ b/examples/neon_convolution.cpp
@@ -49,62 +49,72 @@ const int16_t gaussian5x5[] =
1, 4, 6, 4, 1
};
-void main_neon_convolution(int argc, char **argv)
+class NEONConvolutionExample : public Example
{
- /** [Accurate padding] **/
- PPMLoader ppm;
- Image src, tmp, dst;
-
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: ./build/neon_convolution [input_image.ppm]\n\n";
- std::cout << "No input_image provided, creating a dummy 640x480 image\n";
- // Initialize just the dimensions and format of your buffers:
- src.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else
+public:
+ void do_setup(int argc, char **argv) override
{
- ppm.open(argv[1]);
- // Initialize just the dimensions and format of your buffers:
- ppm.init_image(src, Format::U8);
- }
+ /** [Accurate padding] **/
+ PPMLoader ppm;
- // Initialize just the dimensions and format of the temporary and destination images:
- tmp.allocator()->init(*src.info());
- dst.allocator()->init(*src.info());
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: ./build/neon_convolution [input_image.ppm]\n\n";
+ std::cout << "No input_image provided, creating a dummy 640x480 image\n";
+ // Initialize just the dimensions and format of your buffers:
+ src.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm.open(argv[1]);
+ // Initialize just the dimensions and format of your buffers:
+ ppm.init_image(src, Format::U8);
+ }
- NEConvolution3x3 conv3x3;
- NEConvolution5x5 conv5x5;
+ // Initialize just the dimensions and format of the temporary and destination images:
+ tmp.allocator()->init(*src.info());
+ dst.allocator()->init(*src.info());
- // Apply a Gaussian 3x3 filter to the source image followed by a Gaussian 5x5:
- // The function will automatically update the padding information inside input and output to match its requirements
- conv3x3.configure(&src, &tmp, gaussian3x3, 0 /* Let arm_compute calculate the scale */, BorderMode::UNDEFINED);
- conv5x5.configure(&tmp, &dst, gaussian5x5, 0 /* Let arm_compute calculate the scale */, BorderMode::UNDEFINED);
+ // Apply a Gaussian 3x3 filter to the source image followed by a Gaussian 5x5:
+ // The function will automatically update the padding information inside input and output to match its requirements
+ conv3x3.configure(&src, &tmp, gaussian3x3, 0 /* Let arm_compute calculate the scale */, BorderMode::UNDEFINED);
+ conv5x5.configure(&tmp, &dst, gaussian5x5, 0 /* Let arm_compute calculate the scale */, BorderMode::UNDEFINED);
- // Now that the padding requirements are known we can allocate the images:
- src.allocator()->allocate();
- tmp.allocator()->allocate();
- dst.allocator()->allocate();
+ // Now that the padding requirements are known we can allocate the images:
+ src.allocator()->allocate();
+ tmp.allocator()->allocate();
+ dst.allocator()->allocate();
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm.is_open())
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm.is_open())
+ {
+ ppm.fill_image(src);
+ output_filename = std::string(argv[1]) + "_out.ppm";
+ }
+ /** [Accurate padding] **/
+ }
+ void do_run() override
{
- ppm.fill_image(src);
+ //Execute the functions:
+ conv3x3.run();
+ conv5x5.run();
}
-
- //Execute the functions:
- conv3x3.run();
- conv5x5.run();
-
- // Save the result to file:
- if(ppm.is_open())
+ void do_teardown() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- save_to_ppm(dst, output_filename);
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ }
}
- /** [Accurate padding] **/
-}
+
+private:
+ Image src{}, tmp{}, dst{};
+ NEConvolution3x3 conv3x3{};
+ NEConvolution5x5 conv5x5{};
+ std::string output_filename{};
+};
/** Main program for convolution test
*
@@ -113,5 +123,5 @@ void main_neon_convolution(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_neon_convolution);
+ return utils::run_example<NEONConvolutionExample>(argc, argv);
}
diff --git a/examples/neon_copy_objects.cpp b/examples/neon_copy_objects.cpp
index 55d03dd8bf..9409cf366c 100644
--- a/examples/neon_copy_objects.cpp
+++ b/examples/neon_copy_objects.cpp
@@ -31,116 +31,128 @@
#include <iostream>
using namespace arm_compute;
+using namespace utils;
-void main_neon_copy_objects(int argc, char **argv)
+class NEONCopyObjectsExample : public Example
{
- ARM_COMPUTE_UNUSED(argc);
- ARM_COMPUTE_UNUSED(argv);
+public:
+ void do_setup(int argc, char **argv) override
+ {
+ ARM_COMPUTE_UNUSED(argc);
+ ARM_COMPUTE_UNUSED(argv);
- /** [Copy objects example] */
- constexpr unsigned int width = 4;
- constexpr unsigned int height = 3;
- constexpr unsigned int batch = 2;
+ /** [Copy objects example] */
+ constexpr unsigned int width = 4;
+ constexpr unsigned int height = 3;
+ constexpr unsigned int batch = 2;
- auto *src_data = new float[width * height * batch];
- auto *dst_data = new float[width * height * batch];
+ src_data = new float[width * height * batch];
+ dst_data = new float[width * height * batch];
- // Fill src_data with dummy values:
- for(unsigned int b = 0; b < batch; b++)
- {
- for(unsigned int h = 0; h < height; h++)
+ // Fill src_data with dummy values:
+ for(unsigned int b = 0; b < batch; b++)
{
- for(unsigned int w = 0; w < width; w++)
+ for(unsigned int h = 0; h < height; h++)
{
- src_data[b * (width * height) + h * width + w] = static_cast<float>(100 * b + 10 * h + w);
+ for(unsigned int w = 0; w < width; w++)
+ {
+ src_data[b * (width * height) + h * width + w] = static_cast<float>(100 * b + 10 * h + w);
+ }
}
}
- }
- Tensor input, output;
- NESoftmaxLayer softmax;
-
- // Initialize the tensors dimensions and type:
- const TensorShape shape(width, height, batch);
- input.allocator()->init(TensorInfo(shape, 1, DataType::F32));
- output.allocator()->init(TensorInfo(shape, 1, DataType::F32));
-
- // Configure softmax:
- softmax.configure(&input, &output);
-
- // Allocate the input / output tensors:
- input.allocator()->allocate();
- output.allocator()->allocate();
-
- // Fill the input tensor:
- // Simplest way: create an iterator to iterate through each element of the input tensor:
- Window input_window;
- input_window.use_tensor_dimensions(input.info()->tensor_shape());
- std::cout << " Dimensions of the input's iterator:\n";
- std::cout << " X = [start=" << input_window.x().start() << ", end=" << input_window.x().end() << ", step=" << input_window.x().step() << "]\n";
- std::cout << " Y = [start=" << input_window.y().start() << ", end=" << input_window.y().end() << ", step=" << input_window.y().step() << "]\n";
- std::cout << " Z = [start=" << input_window.z().start() << ", end=" << input_window.z().end() << ", step=" << input_window.z().step() << "]\n";
-
- // Create an iterator:
- Iterator input_it(&input, input_window);
-
- // Iterate through the elements of src_data and copy them one by one to the input tensor:
- // This is equivalent to:
- // for( unsigned int z = 0; z < batch; ++z)
- // {
- // for( unsigned int y = 0; y < height; ++y)
- // {
- // for( unsigned int x = 0; x < width; ++x)
- // {
- // *reinterpret_cast<float*>( input.buffer() + input.info()->offset_element_in_bytes(Coordinates(x,y,z))) = src_data[ z * (width*height) + y * width + x];
- // }
- // }
- // }
- // Except it works for an arbitrary number of dimensions
- execute_window_loop(input_window, [&](const Coordinates & id)
+ // Initialize the tensors dimensions and type:
+ const TensorShape shape(width, height, batch);
+ input.allocator()->init(TensorInfo(shape, 1, DataType::F32));
+ output.allocator()->init(TensorInfo(shape, 1, DataType::F32));
+
+ // Configure softmax:
+ softmax.configure(&input, &output);
+
+ // Allocate the input / output tensors:
+ input.allocator()->allocate();
+ output.allocator()->allocate();
+
+ // Fill the input tensor:
+ // Simplest way: create an iterator to iterate through each element of the input tensor:
+ Window input_window;
+ input_window.use_tensor_dimensions(input.info()->tensor_shape());
+ std::cout << " Dimensions of the input's iterator:\n";
+ std::cout << " X = [start=" << input_window.x().start() << ", end=" << input_window.x().end() << ", step=" << input_window.x().step() << "]\n";
+ std::cout << " Y = [start=" << input_window.y().start() << ", end=" << input_window.y().end() << ", step=" << input_window.y().step() << "]\n";
+ std::cout << " Z = [start=" << input_window.z().start() << ", end=" << input_window.z().end() << ", step=" << input_window.z().step() << "]\n";
+
+ // Create an iterator:
+ Iterator input_it(&input, input_window);
+
+ // Iterate through the elements of src_data and copy them one by one to the input tensor:
+ // This is equivalent to:
+ // for( unsigned int z = 0; z < batch; ++z)
+ // {
+ // for( unsigned int y = 0; y < height; ++y)
+ // {
+ // for( unsigned int x = 0; x < width; ++x)
+ // {
+ // *reinterpret_cast<float*>( input.buffer() + input.info()->offset_element_in_bytes(Coordinates(x,y,z))) = src_data[ z * (width*height) + y * width + x];
+ // }
+ // }
+ // }
+ // Except it works for an arbitrary number of dimensions
+ execute_window_loop(input_window, [&](const Coordinates & id)
+ {
+ std::cout << "Setting item [" << id.x() << "," << id.y() << "," << id.z() << "]\n";
+ *reinterpret_cast<float *>(input_it.ptr()) = src_data[id.z() * (width * height) + id.y() * width + id.x()];
+ },
+ input_it);
+
+ // More efficient way: create an iterator to iterate through each row (instead of each element) of the output tensor:
+ Window output_window;
+ output_window.use_tensor_dimensions(output.info()->tensor_shape(), /* first_dimension =*/Window::DimY); // Iterate through the rows (not each element)
+ std::cout << " Dimensions of the output's iterator:\n";
+ std::cout << " X = [start=" << output_window.x().start() << ", end=" << output_window.x().end() << ", step=" << output_window.x().step() << "]\n";
+ std::cout << " Y = [start=" << output_window.y().start() << ", end=" << output_window.y().end() << ", step=" << output_window.y().step() << "]\n";
+ std::cout << " Z = [start=" << output_window.z().start() << ", end=" << output_window.z().end() << ", step=" << output_window.z().step() << "]\n";
+
+ // Create an iterator:
+ Iterator output_it(&output, output_window);
+
+ // Iterate through the rows of the output tensor and copy them to dst_data:
+ // This is equivalent to:
+ // for( unsigned int z = 0; z < batch; ++z)
+ // {
+ // for( unsigned int y = 0; y < height; ++y)
+ // {
+ // memcpy( dst_data + z * (width*height) + y * width, input.buffer() + input.info()->offset_element_in_bytes(Coordinates(0,y,z)), width * sizeof(float));
+ // }
+ // }
+ // Except it works for an arbitrary number of dimensions
+ execute_window_loop(output_window, [&](const Coordinates & id)
+ {
+ std::cout << "Copying one row starting from [" << id.x() << "," << id.y() << "," << id.z() << "]\n";
+ // Copy one whole row:
+ memcpy(dst_data + id.z() * (width * height) + id.y() * width, output_it.ptr(), width * sizeof(float));
+ },
+ output_it);
+
+ /** [Copy objects example] */
+ }
+ void do_run() override
{
- std::cout << "Setting item [" << id.x() << "," << id.y() << "," << id.z() << "]\n";
- *reinterpret_cast<float *>(input_it.ptr()) = src_data[id.z() * (width * height) + id.y() * width + id.x()];
- },
- input_it);
-
- // Run NEON softmax:
- softmax.run();
-
- // More efficient way: create an iterator to iterate through each row (instead of each element) of the output tensor:
- Window output_window;
- output_window.use_tensor_dimensions(output.info()->tensor_shape(), /* first_dimension =*/Window::DimY); // Iterate through the rows (not each element)
- std::cout << " Dimensions of the output's iterator:\n";
- std::cout << " X = [start=" << output_window.x().start() << ", end=" << output_window.x().end() << ", step=" << output_window.x().step() << "]\n";
- std::cout << " Y = [start=" << output_window.y().start() << ", end=" << output_window.y().end() << ", step=" << output_window.y().step() << "]\n";
- std::cout << " Z = [start=" << output_window.z().start() << ", end=" << output_window.z().end() << ", step=" << output_window.z().step() << "]\n";
-
- // Create an iterator:
- Iterator output_it(&output, output_window);
-
- // Iterate through the rows of the output tensor and copy them to dst_data:
- // This is equivalent to:
- // for( unsigned int z = 0; z < batch; ++z)
- // {
- // for( unsigned int y = 0; y < height; ++y)
- // {
- // memcpy( dst_data + z * (width*height) + y * width, input.buffer() + input.info()->offset_element_in_bytes(Coordinates(0,y,z)), width * sizeof(float));
- // }
- // }
- // Except it works for an arbitrary number of dimensions
- execute_window_loop(output_window, [&](const Coordinates & id)
+ // Run NEON softmax:
+ softmax.run();
+ }
+ void do_teardown() override
{
- std::cout << "Copying one row starting from [" << id.x() << "," << id.y() << "," << id.z() << "]\n";
- // Copy one whole row:
- memcpy(dst_data + id.z() * (width * height) + id.y() * width, output_it.ptr(), width * sizeof(float));
- },
- output_it);
-
- delete[] src_data;
- delete[] dst_data;
- /** [Copy objects example] */
-}
+ delete[] src_data;
+ delete[] dst_data;
+ }
+private:
+ Tensor input{}, output{};
+ float *src_data{};
+ float *dst_data{};
+ NESoftmaxLayer softmax{};
+};
/** Main program for the copy objects test
*
* @param[in] argc Number of arguments
@@ -148,5 +160,5 @@ void main_neon_copy_objects(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_neon_copy_objects);
+ return utils::run_example<NEONCopyObjectsExample>(argc, argv);
}
diff --git a/examples/neon_scale.cpp b/examples/neon_scale.cpp
index 3911f5b3ef..bec277da43 100644
--- a/examples/neon_scale.cpp
+++ b/examples/neon_scale.cpp
@@ -29,55 +29,68 @@
using namespace arm_compute;
using namespace utils;
-void main_neon_scale(int argc, char **argv)
+class NEONScaleExample : public Example
{
- PPMLoader ppm;
- Image src, dst;
-
- if(argc < 2)
- {
- // Print help
- std::cout << "Usage: ./build/neon_scale[input_image.ppm]\n\n";
- std::cout << "No input_image provided, creating a dummy 640x480 image\n";
- // Create an empty grayscale 640x480 image
- src.allocator()->init(TensorInfo(640, 480, Format::U8));
- }
- else
+public:
+ void do_setup(int argc, char **argv) override
{
- ppm.open(argv[1]);
- ppm.init_image(src, Format::U8);
- }
+ PPMLoader ppm;
- constexpr int scale_factor = 2;
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: ./build/neon_scale[input_image.ppm]\n\n";
+ std::cout << "No input_image provided, creating a dummy 640x480 image\n";
+ // Create an empty grayscale 640x480 image
+ src.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm.open(argv[1]);
+ ppm.init_image(src, Format::U8);
+ }
- TensorInfo dst_tensor_info(src.info()->dimension(0) / scale_factor, src.info()->dimension(1) / scale_factor, Format::U8);
+ constexpr int scale_factor = 2;
- // Configure the destination image
- dst.allocator()->init(dst_tensor_info);
+ TensorInfo dst_tensor_info(src.info()->dimension(0) / scale_factor, src.info()->dimension(1) / scale_factor,
+ Format::U8);
- // Create and initialize a Scale function object:
- NEScale scale;
- scale.configure(&src, &dst, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::UNDEFINED);
+ // Configure the destination image
+ dst.allocator()->init(dst_tensor_info);
- // Allocate all the images
- src.allocator()->allocate();
- dst.allocator()->allocate();
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm.is_open())
- {
- ppm.fill_image(src);
- }
+ // Configure Scale function object:
+ scale.configure(&src, &dst, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::UNDEFINED);
- // Run the scale operation:
- scale.run();
+ // Allocate all the images
+ src.allocator()->allocate();
+ dst.allocator()->allocate();
- // Save the result to file:
- if(ppm.is_open())
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm.is_open())
+ {
+ ppm.fill_image(src);
+ output_filename = std::string(argv[1]) + "_out.ppm";
+ }
+ }
+ void do_run() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- save_to_ppm(dst, output_filename);
+ // Run the scale operation:
+ scale.run();
}
-}
+ void do_teardown() override
+ {
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ }
+ }
+
+private:
+ Image src{}, dst{};
+ NEScale scale{};
+ std::string output_filename{};
+};
/** Main program for convolution test
*
@@ -86,5 +99,5 @@ void main_neon_scale(int argc, char **argv)
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_neon_scale);
+ return utils::run_example<NEONScaleExample>(argc, argv);
}
diff --git a/examples/neoncl_scale_median_gaussian.cpp b/examples/neoncl_scale_median_gaussian.cpp
index 0b72314f7b..084005fd1b 100644
--- a/examples/neoncl_scale_median_gaussian.cpp
+++ b/examples/neoncl_scale_median_gaussian.cpp
@@ -39,91 +39,100 @@ using namespace utils;
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Path to PPM image to process )
*/
-void main_neoncl_scale_median_gaussian(int argc, char **argv)
+class NEONCLScaleMedianGaussianExample : public Example
{
- /** [NEON / OpenCL Interop] */
- PPMLoader ppm;
- CLImage src, scale_median, median_gauss, dst;
-
- CLScheduler::get().default_init();
-
- if(argc < 2)
+public:
+ void do_setup(int argc, char **argv) override
{
- // Print help
- std::cout << "Usage: ./build/cl_convolution [input_image.ppm]\n\n";
- std::cout << "No input_image provided, creating a dummy 640x480 image\n";
- // Create an empty grayscale 640x480 image
- src.allocator()->init(TensorInfo(640, 480, Format::U8));
+ /** [NEON / OpenCL Interop] */
+ PPMLoader ppm;
+
+ CLScheduler::get().default_init();
+
+ if(argc < 2)
+ {
+ // Print help
+ std::cout << "Usage: ./build/cl_convolution [input_image.ppm]\n\n";
+ std::cout << "No input_image provided, creating a dummy 640x480 image\n";
+ // Create an empty grayscale 640x480 image
+ src.allocator()->init(TensorInfo(640, 480, Format::U8));
+ }
+ else
+ {
+ ppm.open(argv[1]);
+ ppm.init_image(src, Format::U8);
+ }
+
+ TensorInfo scale_median_info(TensorInfo(src.info()->dimension(0) / 2, src.info()->dimension(1) / 2, Format::U8));
+
+ // Configure the temporary and destination images
+ scale_median.allocator()->init(scale_median_info);
+ median_gauss.allocator()->init(scale_median_info);
+ dst.allocator()->init(scale_median_info);
+
+ scale.configure(&src, &scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
+ median.configure(&scale_median, &median_gauss, BorderMode::REPLICATE);
+ gauss.configure(&median_gauss, &dst, BorderMode::REPLICATE);
+
+ // Allocate all the images
+ src.allocator()->allocate();
+ scale_median.allocator()->allocate();
+ median_gauss.allocator()->allocate();
+ dst.allocator()->allocate();
+
+ // Fill the input image with the content of the PPM image if a filename was provided:
+ if(ppm.is_open())
+ {
+ ppm.fill_image(src);
+ const std::string output_filename = std::string(argv[1]) + "_out.ppm";
+ }
+ /** [NEON / OpenCL Interop] */
}
- else
+ void do_run() override
{
- ppm.open(argv[1]);
- ppm.init_image(src, Format::U8);
- }
-
- TensorInfo scale_median_info(TensorInfo(src.info()->dimension(0) / 2, src.info()->dimension(1) / 2, Format::U8));
+ // Enqueue and flush the OpenCL kernel:
+ scale.run();
- // Configure the temporary and destination images
- scale_median.allocator()->init(scale_median_info);
- median_gauss.allocator()->init(scale_median_info);
- dst.allocator()->init(scale_median_info);
+ // Do a blocking map of the input and output buffers of the NEON function:
+ scale_median.map();
+ median_gauss.map();
- // Declare and configure the functions to create the following pipeline: scale -> median -> gauss
- CLScale scale;
- NEMedian3x3 median;
- CLGaussian5x5 gauss;
+ // Run the NEON function:
+ median.run();
- scale.configure(&src, &scale_median, InterpolationPolicy::NEAREST_NEIGHBOR, BorderMode::REPLICATE);
- median.configure(&scale_median, &median_gauss, BorderMode::REPLICATE);
- gauss.configure(&median_gauss, &dst, BorderMode::REPLICATE);
+ // Unmap the output buffer before it's used again by OpenCL:
+ scale_median.unmap();
+ median_gauss.unmap();
- // Allocate all the images
- src.allocator()->allocate();
- scale_median.allocator()->allocate();
- median_gauss.allocator()->allocate();
- dst.allocator()->allocate();
+ // Run the final OpenCL function:
+ gauss.run();
- // Fill the input image with the content of the PPM image if a filename was provided:
- if(ppm.is_open())
- {
- ppm.fill_image(src);
+ // Make sure all the OpenCL jobs are done executing:
+ CLScheduler::get().sync();
}
-
- // Enqueue and flush the OpenCL kernel:
- scale.run();
-
- // Do a blocking map of the input and output buffers of the NEON function:
- scale_median.map();
- median_gauss.map();
-
- // Run the NEON function:
- median.run();
-
- // Unmap the output buffer before it's used again by OpenCL:
- scale_median.unmap();
- median_gauss.unmap();
-
- // Run the final OpenCL function:
- gauss.run();
-
- // Make sure all the OpenCL jobs are done executing:
- CLScheduler::get().sync();
-
- // Save the result to file:
- if(ppm.is_open())
+ void do_teardown() override
{
- const std::string output_filename = std::string(argv[1]) + "_out.ppm";
- save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ // Save the result to file:
+ if(!output_filename.empty())
+ {
+ save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+ }
}
- /** [NEON / OpenCL Interop] */
-}
-/** Main program for convolution test
+private:
+ CLImage src{}, scale_median{}, median_gauss{}, dst{};
+ CLScale scale{};
+ NEMedian3x3 median{};
+ CLGaussian5x5 gauss{};
+ std::string output_filename{};
+};
+
+/** Main program for neon/cl scale median gaussian test
*
* @param[in] argc Number of arguments
* @param[in] argv Arguments ( [optional] Path to PPM image to process )
*/
int main(int argc, char **argv)
{
- return utils::run_example(argc, argv, main_neoncl_scale_median_gaussian);
+ return utils::run_example<NEONCLScaleMedianGaussianExample>(argc, argv);
}
diff --git a/utils/Utils.cpp b/utils/Utils.cpp
index c2f5449a28..32d5e3a6c0 100644
--- a/utils/Utils.cpp
+++ b/utils/Utils.cpp
@@ -66,41 +66,6 @@ void discard_comments_and_spaces(std::ifstream &fs)
}
} // namespace
-//FIXME: Delete once tests have been ported (COMPMID-782)
-int run_example(int argc, char **argv, example &func)
-{
- std::cout << "\n"
- << argv[0] << "\n\n";
-
- try
- {
- func(argc, argv);
-
- std::cout << "\nTest passed\n";
- return 0;
- }
-#ifdef ARM_COMPUTE_CL
- catch(cl::Error &err)
- {
- std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cerr << std::endl
- << "ERROR " << err.what() << "(" << err.err() << ")" << std::endl;
- std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- }
-#endif /* ARM_COMPUTE_CL */
- catch(std::runtime_error &err)
- {
- std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- std::cerr << std::endl
- << "ERROR " << err.what() << " " << (errno ? strerror(errno) : "") << std::endl;
- std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
- }
-
- std::cout << "\nTest FAILED\n";
-
- return -1;
-}
-
#ifndef BENCHMARK_EXAMPLES
int run_example(int argc, char **argv, Example &example)
{
diff --git a/utils/Utils.h b/utils/Utils.h
index 9b5d0c4aa9..01e5137669 100644
--- a/utils/Utils.h
+++ b/utils/Utils.h
@@ -55,23 +55,6 @@ namespace arm_compute
{
namespace utils
{
-//FIXME: Delete once tests have been ported (COMPMID-782)
-/** Signature of an example to run
- *
- * @param[in] argc Number of command line arguments
- * @param[in] argv Command line arguments
- */
-using example = void(int argc, char **argv);
-
-//FIXME: Delete once tests have been ported (COMPMID-782)
-/** Run an example and handle the potential exceptions it throws
- *
- * @param[in] argc Number of command line arguments
- * @param[in] argv Command line arguments
- * @param[in] func Pointer to the function containing the code to run
- */
-int run_example(int argc, char **argv, example &func);
-
/** Abstract Example class.
*
* All examples have to inherit from this class.