summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/numeric/ublas/benchmarks
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/Jamfile23
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/add.cpp63
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/add.hpp36
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/benchmark.hpp52
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/init.hpp37
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/inner_prod.cpp89
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/mm_prod.cpp62
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/mv_prod.cpp64
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/Jamfile27
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/add.cpp93
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/benchmark.hpp214
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/init.hpp40
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/inner_prod.cpp94
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/mm_prod.cpp94
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/mv_prod.cpp95
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/opencl/outer_prod.cpp95
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/outer_prod.cpp90
-rwxr-xr-xsrc/boost/libs/numeric/ublas/benchmarks/plot.py60
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/prod.hpp36
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/reference/add.cpp88
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/reference/inner_prod.cpp91
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/reference/mm_prod.cpp93
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/reference/mv_prod.cpp92
-rw-r--r--src/boost/libs/numeric/ublas/benchmarks/reference/outer_prod.cpp92
24 files changed, 1820 insertions, 0 deletions
diff --git a/src/boost/libs/numeric/ublas/benchmarks/Jamfile b/src/boost/libs/numeric/ublas/benchmarks/Jamfile
new file mode 100644
index 00000000..ab2f77e8
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/Jamfile
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2018 Stefan Seefeld
+# Use, modification and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+project boost/ublas/benchmarks
+ : requirements <library>/boost/program_options//boost_program_options
+ ;
+
+exe add : add.cpp ;
+exe mm_prod : mm_prod.cpp ;
+exe mv_prod : mv_prod.cpp ;
+exe inner_prod : inner_prod.cpp ;
+exe outer_prod : outer_prod.cpp ;
+
+exe reference/add : reference/add.cpp ;
+exe reference/mm_prod : reference/mm_prod.cpp ;
+exe reference/mv_prod : reference/mv_prod.cpp ;
+exe reference/inner_prod : reference/inner_prod.cpp ;
+exe reference/outer_prod : reference/outer_prod.cpp ;
+
+build-project opencl ;
diff --git a/src/boost/libs/numeric/ublas/benchmarks/add.cpp b/src/boost/libs/numeric/ublas/benchmarks/add.cpp
new file mode 100644
index 00000000..0bab90bc
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/add.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/program_options.hpp>
+#include "add.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using vector = ublas::vector<T>;
+ bm::add<vector(vector, vector)> a("add(vector<" + type + ">, vector<" + type + ">)");
+ a.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Vector-vector addition\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/add.hpp b/src/boost/libs/numeric/ublas/benchmarks/add.hpp
new file mode 100644
index 00000000..d5d03d09
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/add.hpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include "init.hpp"
+#include "benchmark.hpp"
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class add;
+
+template <typename R, typename O1, typename O2>
+class add<R(O1, O2)> : public benchmark
+{
+public:
+ add(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ c = a + b;
+ }
+private:
+ O1 a;
+ O2 b;
+ R c;
+};
+
+}}}}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/benchmark.hpp b/src/boost/libs/numeric/ublas/benchmarks/benchmark.hpp
new file mode 100644
index 00000000..b06cbe55
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/benchmark.hpp
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#include <iostream>
+#include <chrono>
+#include <ctime>
+#include <cmath>
+#include <string>
+#include <vector>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+class benchmark
+{
+ using clock = std::chrono::system_clock;
+public:
+ benchmark(std::string const &name) : name_(name) {}
+ void print_header()
+ {
+ std::cout << "# benchmark : " << name_ << '\n'
+ << "# size \ttime (ms)" << std::endl;
+ }
+ virtual void setup(long) {}
+ virtual void operation(long) {}
+ virtual void teardown() {}
+
+ void run(std::vector<long> const &sizes, unsigned times = 10)
+ {
+ print_header();
+ for (auto s : sizes)
+ {
+ setup(s);
+ auto start = clock::now();
+ for (unsigned i = 0; i != times; ++i)
+ operation(s);
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - start);
+ teardown();
+ std::cout << s << '\t' << duration.count()*1./times << std::endl;
+ }
+ }
+private:
+ std::string name_;
+};
+
+}}}}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/init.hpp b/src/boost/libs/numeric/ublas/benchmarks/init.hpp
new file mode 100644
index 00000000..1528389c
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/init.hpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename T>
+void init(vector<T> &v, unsigned long size, int max_value)
+{
+ v = vector<T>(size);
+ for (unsigned long i = 0; i < v.size(); ++i)
+ v(i) = std::rand() % max_value;
+}
+
+template <typename T, typename L>
+void init(matrix<T, L> &m, unsigned long size1, unsigned long size2, int max_value)
+{
+ m = matrix<T, L>(size1, size2);
+ for (unsigned long i = 0; i < m.size1(); ++i)
+ for (unsigned long j = 0; j < m.size2(); ++j)
+ m(i, j) = std::rand() % max_value;
+}
+
+template <typename T, typename L>
+void init(matrix<T, L> &m, unsigned long size, int max_value)
+{
+ return init(m, size, size, max_value);
+}
+
+}}}}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/inner_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/inner_prod.cpp
new file mode 100644
index 00000000..9d95a333
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/inner_prod.cpp
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "init.hpp"
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class inner_prod;
+
+template <typename R, typename V1, typename V2>
+class inner_prod<R(V1, V2)> : public benchmark
+{
+public:
+ inner_prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ c = ublas::inner_prod(a, b);
+ }
+private:
+ V1 a;
+ V2 b;
+ R c;
+};
+
+}}}}
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using vector = ublas::vector<T>;
+ bm::inner_prod<T(vector, vector)> p("inner_prod(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Inner product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/mm_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/mm_prod.cpp
new file mode 100644
index 00000000..f87271c7
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/mm_prod.cpp
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/program_options.hpp>
+#include "prod.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using matrix = ublas::matrix<T, ublas::basic_row_major<>>;
+ bm::prod<matrix(matrix, matrix)> p("prod(matrix<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512}));//, 1024}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/mv_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/mv_prod.cpp
new file mode 100644
index 00000000..bc6da204
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/mv_prod.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/program_options.hpp>
+#include "prod.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using matrix = ublas::matrix<T, ublas::basic_row_major<>>;
+ using vector = ublas::vector<T>;
+ bm::prod<vector(matrix, vector)> p("prod(matrix<" + type + ">, vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix-vector product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/Jamfile b/src/boost/libs/numeric/ublas/benchmarks/opencl/Jamfile
new file mode 100644
index 00000000..670ec66b
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/Jamfile
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2018 Stefan Seefeld
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or
+# copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import ac ;
+
+# work around a bug in Boost.Build
+import ../../opencl ;
+import ../../clblas ;
+using opencl ;
+using clblas ;
+
+project boost/ublas/benchmarks/opencl
+ : requirements
+ <library>/boost/program_options//boost_program_options
+ <toolset>gcc:<cxxflags>-Wno-ignored-attributes
+ [ ac.check-library /clblas//clblas : <library>/clblas//clblas <library>/opencl//opencl : <build>no ]
+ ;
+
+exe add : add.cpp ;
+exe mm_prod : mm_prod.cpp ;
+exe mv_prod : mv_prod.cpp ;
+exe inner_prod : inner_prod.cpp ;
+exe outer_prod : outer_prod.cpp ;
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/add.cpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/add.cpp
new file mode 100644
index 00000000..b998cd2c
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/add.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_UBLAS_ENABLE_OPENCL
+#include <boost/numeric/ublas/opencl.hpp>
+#include <boost/program_options.hpp>
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+namespace opencl = boost::numeric::ublas::opencl;
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl {
+
+template <typename S, bool C> class add;
+
+template <typename V, bool C>
+class add<void(V,V,V), C> : public benchmark<void(V,V,V), C>
+{
+public:
+ add(std::string const &name) : benchmark<void(V,V,V), C>(name) {}
+ virtual void operation(long l)
+ {
+ ublas::opencl::element_add(*this->a, *this->b, *this->c, this->queue);
+ }
+};
+
+}}}}}
+
+template <typename T>
+void benchmark(std::string const &type, bool copy)
+{
+ using vector = ublas::vector<T>;
+ std::string name = "opencl::elementwise_add(vector<" + type + ">)";
+ std::vector<long> sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096});
+ if (copy)
+ {
+ bm::opencl::add<void(vector, vector, vector), true> p(name);
+ p.run(sizes);
+ }
+ else
+ {
+ bm::opencl::add<void(vector, vector, vector), false> p(name);
+ p.run(sizes);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ opencl::library lib;
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix-vector product (OpenCL)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+ desc.add_options()("copy,c", po::value<bool>(), "include host<->device copy in timing");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ bool copy = vm.count("copy") ? vm["copy"].as<bool>() : false;
+ if (type == "float")
+ benchmark<float>("float", copy);
+ else if (type == "double")
+ benchmark<double>("double", copy);
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>", copy);
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>", copy);
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/benchmark.hpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/benchmark.hpp
new file mode 100644
index 00000000..fb607599
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/benchmark.hpp
@@ -0,0 +1,214 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or
+// copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef opencl_benchmark_hpp_
+#define opencl_benchmark_hpp_
+#define BOOST_UBLAS_ENABLE_OPENCL
+
+#include <boost/numeric/ublas/opencl.hpp>
+#include "../benchmark.hpp"
+#include "init.hpp"
+#include <memory>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+namespace opencl {
+
+struct base
+{
+ base(compute::device d = compute::system::default_device())
+ : context(d),
+ queue(context, d)
+ {}
+ compute::context context;
+ compute::command_queue queue;
+};
+
+template <typename T, bool C> struct data_factory;
+template <typename T>
+struct data_factory<T, true>
+{
+ typedef T type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long) { return ptr_type(new T());}
+};
+template <typename T>
+struct data_factory<T, false>
+{
+ typedef T type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long, compute::context) { return ptr_type(new T());}
+};
+template <>
+struct data_factory<void, true>
+{
+ typedef void type;
+ typedef void *ptr_type;
+ static ptr_type create(long) { return 0;}
+};
+template <>
+struct data_factory<void, false>
+{
+ typedef void type;
+ typedef void *ptr_type;
+ static ptr_type create(long, compute::context) { return 0;}
+};
+template <typename T>
+struct data_factory<ublas::vector<T>, true>
+{
+ typedef ublas::vector<T> type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long l) { return ptr_type(new type(l));}
+};
+template <typename T>
+struct data_factory<ublas::vector<T>, false>
+{
+ typedef ublas::vector<T, ublas::opencl::storage> type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long l, compute::context c)
+ { return ptr_type(new type(l, c));}
+};
+template <typename T, typename L>
+struct data_factory<ublas::matrix<T, L>, true>
+{
+ typedef ublas::matrix<T, L> type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long l)
+ { return ptr_type(new type(l, l));}
+};
+template <typename T, typename L>
+struct data_factory<ublas::matrix<T, L>, false>
+{
+ typedef ublas::matrix<T, L, ublas::opencl::storage> type;
+ typedef std::unique_ptr<type> ptr_type;
+ static ptr_type create(long l, compute::context c)
+ { return ptr_type(new type(l, l, c));}
+};
+
+template <typename S, bool> class benchmark;
+
+template <typename R, typename O>
+class benchmark<R(O), true> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name)
+ : base(),
+ ublas::benchmark::benchmark(name + " with copy")
+ {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, true>::create(l);
+ a = data_factory<O, true>::create(l);
+ init(*a, l, 200);
+ }
+ typename data_factory<R, true>::ptr_type r;
+ typename data_factory<O, true>::ptr_type a;
+};
+
+template <typename R, typename O1, typename O2>
+class benchmark<R(O1, O2), true> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name)
+ : base(),
+ ublas::benchmark::benchmark(name + " with copy")
+ {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, true>::create(l);
+ a = data_factory<O1, true>::create(l);
+ init(*a, l, 200);
+ b = data_factory<O2, true>::create(l);
+ init(*b, l, 200);
+ }
+ typename data_factory<R, true>::ptr_type r;
+ typename data_factory<O1, true>::ptr_type a;
+ typename data_factory<O2, true>::ptr_type b;
+};
+
+template <typename R, typename O1, typename O2, typename O3>
+class benchmark<R(O1, O2, O3), true> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name)
+ : base(),
+ ublas::benchmark::benchmark(name + " with copy")
+ {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, true>::create(l);
+ a = data_factory<O1, true>::create(l);
+ init(*a, l, 200);
+ b = data_factory<O2, true>::create(l);
+ init(*b, l, 200);
+ c = data_factory<O3, true>::create(l);
+ init(*c, l, 200);
+ }
+ typename data_factory<R, true>::ptr_type r;
+ typename data_factory<O1, true>::ptr_type a;
+ typename data_factory<O2, true>::ptr_type b;
+ typename data_factory<O3, true>::ptr_type c;
+};
+
+template <typename R, typename O>
+class benchmark<R(O), false> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name)
+ : base(),
+ ublas::benchmark::benchmark(name + " w/o copy")
+ {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, false>::create(l, context);
+ a = data_factory<O, false>::create(l, context);
+ init(*a, l, 200);
+ }
+ typename data_factory<R, false>::ptr_type r;
+ typename data_factory<O, false>::ptr_type a;
+};
+
+template <typename R, typename O1, typename O2>
+class benchmark<R(O1, O2), false> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name) : base(), ublas::benchmark::benchmark(name + " w/o copy") {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, false>::create(l, context);
+ a = data_factory<O1, false>::create(l, context);
+ init(*a, l, 200);
+ b = data_factory<O2, false>::create(l, context);
+ init(*b, l, 200);
+ }
+ typename data_factory<R, false>::ptr_type r;
+ typename data_factory<O1, false>::ptr_type a;
+ typename data_factory<O2, false>::ptr_type b;
+};
+
+template <typename R, typename O1, typename O2, typename O3>
+class benchmark<R(O1, O2, O3), false> : public base, public ublas::benchmark::benchmark
+{
+public:
+ benchmark(std::string const &name) : base(), ublas::benchmark::benchmark(name + " w/o copy") {}
+ virtual void setup(long l)
+ {
+ r = data_factory<R, false>::create(l, context);
+ a = data_factory<O1, false>::create(l, context);
+ init(*a, l, 200);
+ b = data_factory<O2, false>::create(l, context);
+ init(*b, l, 200);
+ c = data_factory<O3, false>::create(l, context);
+ init(*c, l, 200);
+ }
+ typename data_factory<R, false>::ptr_type r;
+ typename data_factory<O1, false>::ptr_type a;
+ typename data_factory<O2, false>::ptr_type b;
+ typename data_factory<O3, false>::ptr_type c;
+};
+}}}}}
+
+#endif
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/init.hpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/init.hpp
new file mode 100644
index 00000000..a1141028
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/init.hpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#include <boost/numeric/ublas/opencl.hpp>
+#include "../init.hpp"
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename T>
+void init(T &v, unsigned long size, int max_value)
+{
+ // TBD
+}
+
+template <typename T>
+void init(vector<T, opencl::storage> &v, unsigned long size, int max_value)
+{
+ // TBD
+}
+
+template <typename T>
+void init(matrix<T, opencl::storage> &m, unsigned long size1, unsigned long size2, int max_value)
+{
+ // TBD
+}
+
+template <typename T>
+void init(matrix<T, opencl::storage> &m, unsigned long size, int max_value)
+{
+ init(m, size, size, max_value);
+}
+
+}}}}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/inner_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/inner_prod.cpp
new file mode 100644
index 00000000..a25664cb
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/inner_prod.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_UBLAS_ENABLE_OPENCL
+#include <boost/numeric/ublas/opencl.hpp>
+#include <boost/program_options.hpp>
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+namespace opencl = boost::numeric::ublas::opencl;
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl {
+
+template <typename S, bool C> class inner_prod;
+
+template <typename R, typename V, bool C>
+class inner_prod<R(V,V), C> : public benchmark<R(V,V), C>
+{
+public:
+ inner_prod(std::string const &name) : benchmark<R(V,V), C>(name) {}
+ virtual void operation(long l)
+ {
+ ublas::opencl::inner_prod(*this->a, *this->b, this->queue);
+ }
+};
+
+}}}}}
+
+template <typename T>
+void benchmark(std::string const &type, bool copy)
+{
+ using vector = ublas::vector<T>;
+ std::string name = "opencl::inner_prod(vector<" + type + ">)";
+ std::vector<long> sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536});
+ if (copy)
+ {
+ bm::opencl::inner_prod<T(vector,vector), true> p(name);
+ p.run(sizes);
+ }
+ else
+ {
+ bm::opencl::inner_prod<T(vector,vector), false> p(name);
+ p.run(sizes);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ opencl::library lib;
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Inner product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+ desc.add_options()("copy,c", po::value<bool>(), "include host<->device copy in timing");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ bool copy = vm.count("copy") ? vm["copy"].as<bool>() : false;
+ if (type == "float")
+ benchmark<float>("float", copy);
+ else if (type == "double")
+ benchmark<double>("double", copy);
+ // else if (type == "fcomplex")
+ // benchmark<std::complex<float>>("std::complex<float>", copy);
+ // else if (type == "dcomplex")
+ // benchmark<std::complex<double>>("std::complex<double>", copy);
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/mm_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/mm_prod.cpp
new file mode 100644
index 00000000..e306031f
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/mm_prod.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_UBLAS_ENABLE_OPENCL
+#include <boost/numeric/ublas/opencl.hpp>
+#include <boost/program_options.hpp>
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+namespace opencl = boost::numeric::ublas::opencl;
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl {
+
+template <typename S, bool C> class prod;
+
+template <typename M, bool C>
+class prod<void(M,M,M), C> : public benchmark<void(M,M,M), C>
+{
+public:
+ prod(std::string const &name) : benchmark<void(M,M,M), C>(name) {}
+ virtual void operation(long l)
+ {
+ ublas::opencl::prod(*this->a, *this->b, *this->c, this->queue);
+ }
+};
+
+}}}}}
+
+template <typename T>
+void benchmark(std::string const &type, bool copy)
+{
+ using matrix = ublas::matrix<T>;
+ std::string name = "opencl::prod(matrix<" + type + ">)";
+ std::vector<long> sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096});
+ if (copy)
+ {
+ bm::opencl::prod<void(matrix, matrix, matrix), true> p(name);
+ p.run(sizes);
+ }
+ else
+ {
+ bm::opencl::prod<void(matrix, matrix, matrix), false> p(name);
+ p.run(sizes);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ opencl::library lib;
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix product (OpenCL)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+ desc.add_options()("copy,c", po::value<bool>(), "include host<->device copy in timing");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ bool copy = vm.count("copy") ? vm["copy"].as<bool>() : false;
+ if (type == "float")
+ benchmark<float>("float", copy);
+ else if (type == "double")
+ benchmark<double>("double", copy);
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>", copy);
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>", copy);
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/mv_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/mv_prod.cpp
new file mode 100644
index 00000000..70344a4b
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/mv_prod.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_UBLAS_ENABLE_OPENCL
+#include <boost/numeric/ublas/opencl.hpp>
+#include <boost/program_options.hpp>
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+namespace opencl = boost::numeric::ublas::opencl;
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl {
+
+template <typename S, bool C> class prod;
+
+template <typename M, typename V, bool C>
+class prod<void(M,V,V), C> : public benchmark<void(M,V,V), C>
+{
+public:
+ prod(std::string const &name) : benchmark<void(M,V,V), C>(name) {}
+ virtual void operation(long l)
+ {
+ ublas::opencl::prod(*this->a, *this->b, *this->c, this->queue);
+ }
+};
+
+}}}}}
+
+template <typename T>
+void benchmark(std::string const &type, bool copy)
+{
+ using vector = ublas::vector<T>;
+ using matrix = ublas::matrix<T>;
+ std::string name = "opencl::prod(matrix<" + type + ", vector<" + type + ">)";
+ std::vector<long> sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096});
+ if (copy)
+ {
+ bm::opencl::prod<void(matrix, vector, vector), true> p(name);
+ p.run(sizes);
+ }
+ else
+ {
+ bm::opencl::prod<void(matrix, vector, vector), false> p(name);
+ p.run(sizes);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ opencl::library lib;
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix-vector product (OpenCL)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+ desc.add_options()("copy,c", po::value<bool>(), "include host<->device copy in timing");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ bool copy = vm.count("copy") ? vm["copy"].as<bool>() : false;
+ if (type == "float")
+ benchmark<float>("float", copy);
+ else if (type == "double")
+ benchmark<double>("double", copy);
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>", copy);
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>", copy);
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/opencl/outer_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/opencl/outer_prod.cpp
new file mode 100644
index 00000000..b00bb840
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/opencl/outer_prod.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_UBLAS_ENABLE_OPENCL
+#include <boost/numeric/ublas/opencl.hpp>
+#include <boost/program_options.hpp>
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+namespace opencl = boost::numeric::ublas::opencl;
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl {
+
+template <typename S, bool C> class outer_prod;
+
+template <typename V, typename M, bool C>
+class outer_prod<void(V,V,M), C> : public benchmark<void(V,V,M), C>
+{
+public:
+ outer_prod(std::string const &name) : benchmark<void(V,V,M), C>(name) {}
+ virtual void operation(long l)
+ {
+ ublas::opencl::outer_prod(*this->a, *this->b, *this->c, this->queue);
+ }
+};
+
+}}}}}
+
+template <typename T>
+void benchmark(std::string const &type, bool copy)
+{
+ using vector = ublas::vector<T>;
+ using matrix = ublas::matrix<T>;
+ std::string name = "opencl::outer_prod(vector<" + type + ">)";
+ std::vector<long> sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096});
+ if (copy)
+ {
+ bm::opencl::outer_prod<void(vector, vector, matrix), true> p(name);
+ p.run(sizes);
+ }
+ else
+ {
+ bm::opencl::outer_prod<void(vector, vector, matrix), false> p(name);
+ p.run(sizes);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ opencl::library lib;
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Outer product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+ desc.add_options()("copy,c", po::value<bool>(), "include host<->device copy in timing");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ bool copy = vm.count("copy") ? vm["copy"].as<bool>() : false;
+ if (type == "float")
+ benchmark<float>("float", copy);
+ else if (type == "double")
+ benchmark<double>("double", copy);
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>", copy);
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>", copy);
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/outer_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/outer_prod.cpp
new file mode 100644
index 00000000..b907c360
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/outer_prod.cpp
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "init.hpp"
+#include "benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class outer_prod;
+
+template <typename R, typename V1, typename V2>
+class outer_prod<R(V1, V2)> : public benchmark
+{
+public:
+ outer_prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ c = ublas::outer_prod(a, b);
+ }
+private:
+ V1 a;
+ V2 b;
+ R c;
+};
+
+}}}}
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using vector = ublas::vector<T>;
+ using matrix = ublas::matrix<T>;
+ bm::outer_prod<matrix(vector, vector)> p("outer_prod(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Outer product\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/plot.py b/src/boost/libs/numeric/ublas/benchmarks/plot.py
new file mode 100755
index 00000000..1ca5e5a7
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/plot.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 Stefan Seefeld
+# All rights reserved.
+#
+# This file is part of Boost.uBLAS. It is made available under the
+# Boost Software License, Version 1.0.
+# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+import argparse
+import matplotlib.pyplot as plt
+import numpy as np
+
+
+class plot(object):
+
+ def __init__(self, label, data):
+ self.label = label
+ self.data = data
+
+
+def load_file(filename):
+
+ lines = open(filename, 'r').readlines()
+ label = lines[0][1:-1].strip()
+ lines = [l.strip() for l in lines]
+ lines = [l.split('#', 1)[0] for l in lines]
+ lines = [l for l in lines if l]
+ data = [l.split() for l in lines]
+ return plot(label, list(zip(*data)))
+
+
+def main(argv):
+
+ parser = argparse.ArgumentParser(prog=argv[0], description='benchmark plotter')
+ parser.add_argument('data', nargs='+', help='benchmark data to plot')
+ parser.add_argument('--log', choices=['no', 'all', 'x', 'y'], help='use a logarithmic scale')
+ args = parser.parse_args(argv[1:])
+ runs = [load_file(d) for d in args.data]
+ plt.title('Benchmark plot')
+ plt.xlabel('size')
+ plt.ylabel('time (s)')
+ if args.log == 'all':
+ plot = plt.loglog
+ elif args.log == 'x':
+ plot = plt.semilogx
+ elif args.log == 'y':
+ plot = plt.semilogy
+ else:
+ plot = plt.plot
+ plots = [plot(r.data[0], r.data[1], label=r.label) for r in runs]
+ plt.legend()
+ plt.show()
+ return True
+
+
+if __name__ == '__main__':
+
+ import sys
+ sys.exit(0 if main(sys.argv) else 1)
diff --git a/src/boost/libs/numeric/ublas/benchmarks/prod.hpp b/src/boost/libs/numeric/ublas/benchmarks/prod.hpp
new file mode 100644
index 00000000..243bafcb
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/prod.hpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include "init.hpp"
+#include "benchmark.hpp"
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class prod;
+
+template <typename R, typename O1, typename O2>
+class prod<R(O1, O2)> : public benchmark
+{
+public:
+ prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ c = ublas::prod(a, b);
+ }
+private:
+ O1 a;
+ O2 b;
+ R c;
+};
+
+}}}}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/reference/add.cpp b/src/boost/libs/numeric/ublas/benchmarks/reference/add.cpp
new file mode 100644
index 00000000..d5b98870
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/reference/add.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "../init.hpp"
+#include "../benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename T>
+class add : public benchmark
+{
+public:
+ add(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ for (int i = 0; i < l; ++i)
+ c(i) = a(i) + b(i);
+ }
+private:
+ ublas::vector<T> a;
+ ublas::vector<T> b;
+ ublas::vector<T> c;
+};
+
+}}}}
+
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ bm::add<T> p("ref::add(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Vector-vector addition (reference implementation)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/reference/inner_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/reference/inner_prod.cpp
new file mode 100644
index 00000000..dc175257
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/reference/inner_prod.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "../init.hpp"
+#include "../benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class inner_prod;
+
+template <typename R, typename V1, typename V2>
+class inner_prod<R(V1, V2)> : public benchmark
+{
+public:
+ inner_prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ c = R(0);
+ for (int i = 0; i < l; ++i)
+ c += a(i) * b(i);
+ }
+private:
+ V1 a;
+ V2 b;
+ R c;
+};
+
+}}}}
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using vector = ublas::vector<T>;
+ bm::inner_prod<T(vector, vector)> p("ref::inner_prod(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Inner product (reference implementation)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/reference/mm_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/reference/mm_prod.cpp
new file mode 100644
index 00000000..4b436316
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/reference/mm_prod.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/program_options.hpp>
+#include "../init.hpp"
+#include "../benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename T>
+class prod : public benchmark
+{
+public:
+ prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ for (int i = 0; i < l; ++i)
+ for (int j = 0; j < l; ++j)
+ {
+ c(i,j) = 0;
+ for (int k = 0; k < l; ++k)
+ c(i,j) += a(i,k) * b(k,j);
+ }
+ }
+private:
+ ublas::matrix<T> a;
+ ublas::matrix<T> b;
+ ublas::matrix<T> c;
+};
+
+}}}}
+
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ // using matrix = ublas::matrix<T, ublas::basic_row_major<>>;
+ bm::prod<T> p("ref::prod(matrix<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512}));//, 1024}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix product (reference implementation)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/reference/mv_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/reference/mv_prod.cpp
new file mode 100644
index 00000000..e3a15745
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/reference/mv_prod.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/matrix.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "../init.hpp"
+#include "../benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename T>
+class prod : public benchmark
+{
+public:
+ prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ for (int i = 0; i < l; ++i)
+ {
+ c(i) = 0;
+ for (int j = 0; j < l; ++j)
+ c(i) += a(i,j) * b(j);
+ }
+ }
+private:
+ ublas::matrix<T> a;
+ ublas::vector<T> b;
+ ublas::vector<T> c;
+};
+
+}}}}
+
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ bm::prod<T> p("ref::prod(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Matrix-vector product (reference implementation)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}
diff --git a/src/boost/libs/numeric/ublas/benchmarks/reference/outer_prod.cpp b/src/boost/libs/numeric/ublas/benchmarks/reference/outer_prod.cpp
new file mode 100644
index 00000000..a300066c
--- /dev/null
+++ b/src/boost/libs/numeric/ublas/benchmarks/reference/outer_prod.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2018 Stefan Seefeld
+// All rights reserved.
+//
+// This file is part of Boost.uBLAS. It is made available under the
+// Boost Software License, Version 1.0.
+// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/program_options.hpp>
+#include "../init.hpp"
+#include "../benchmark.hpp"
+#include <complex>
+#include <string>
+
+namespace boost { namespace numeric { namespace ublas { namespace benchmark {
+
+template <typename S> class outer_prod;
+
+template <typename R, typename V1, typename V2>
+class outer_prod<R(V1, V2)> : public benchmark
+{
+public:
+ outer_prod(std::string const &name) : benchmark(name) {}
+ virtual void setup(long l)
+ {
+ init(a, l, 200);
+ init(b, l, 200);
+ }
+ virtual void operation(long l)
+ {
+ for (int i = 0; i < l; ++i)
+ for (int j = 0; j < l; ++j)
+ c(i,j) = - a(i) * b(j);
+ }
+private:
+ V1 a;
+ V2 b;
+ R c;
+};
+
+}}}}
+
+namespace po = boost::program_options;
+namespace ublas = boost::numeric::ublas;
+namespace bm = boost::numeric::ublas::benchmark;
+
+template <typename T>
+void benchmark(std::string const &type)
+{
+ using vector = ublas::vector<T>;
+ using matrix = ublas::matrix<T>;
+ bm::outer_prod<matrix(vector, vector)> p("ref::outer_prod(vector<" + type + ">)");
+ p.run(std::vector<long>({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}));
+}
+
+int main(int argc, char **argv)
+{
+ po::variables_map vm;
+ try
+ {
+ po::options_description desc("Outer product (reference implementation)\n"
+ "Allowed options");
+ desc.add_options()("help,h", "produce help message");
+ desc.add_options()("type,t", po::value<std::string>(), "select value-type (float, double, fcomplex, dcomplex)");
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ }
+ catch(std::exception &e)
+ {
+ std::cerr << "error: " << e.what() << std::endl;
+ return 1;
+ }
+ std::string type = vm.count("type") ? vm["type"].as<std::string>() : "float";
+ if (type == "float")
+ benchmark<float>("float");
+ else if (type == "double")
+ benchmark<double>("double");
+ else if (type == "fcomplex")
+ benchmark<std::complex<float>>("std::complex<float>");
+ else if (type == "dcomplex")
+ benchmark<std::complex<double>>("std::complex<double>");
+ else
+ std::cerr << "unsupported value-type \"" << vm["type"].as<std::string>() << '\"' << std::endl;
+}