summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/numeric/ublas/benchmarks/opencl
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/numeric/ublas/benchmarks/opencl')
-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
8 files changed, 752 insertions, 0 deletions
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;
+}