33 #include <boost/numeric/ublas/io.hpp>
34 #include <boost/numeric/ublas/vector.hpp>
35 #include <boost/numeric/ublas/vector_proxy.hpp>
41 #define VIENNACL_WITH_UBLAS 1
55 using namespace boost::numeric;
61 template<
typename ScalarType>
65 if (std::fabs(s1 - s2) > 0)
66 return (s1 - s2) /
std::max(std::fabs(s1), std::fabs(s2));
72 template<
typename ScalarType>
76 if (std::fabs(s1 - s2) > 0)
77 return (s1 - s2) /
std::max(std::fabs(s1), std::fabs(s2));
83 template<
typename ScalarType>
87 if (std::fabs(s1 - s2) > 0)
88 return (s1 - s2) /
std::max(std::fabs(s1), std::fabs(s2));
94 template<
typename ScalarType,
typename ViennaCLVectorType>
95 ScalarType diff(ublas::vector<ScalarType>
const &
v1, ViennaCLVectorType
const & vcl_vec)
97 ublas::vector<ScalarType> v2_cpu(vcl_vec.size());
101 for (
unsigned int i=0;i<v1.size(); ++i)
103 if (
std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) > 0 )
104 v2_cpu[i] = std::fabs(v2_cpu[i] - v1[i]) /
std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) );
113 template<
typename T1,
typename T2>
114 int check(T1
const & t1, T2
const & t2,
double epsilon)
116 int retval = EXIT_SUCCESS;
118 double temp = std::fabs(
diff(t1, t2));
121 std::cout <<
"# Error! Relative difference: " << temp << std::endl;
122 retval = EXIT_FAILURE;
125 std::cout <<
"PASSED!" << std::endl;
133 template<
typename NumericT,
typename Epsilon,
typename UblasVectorType,
typename ViennaCLVectorType1,
typename ViennaCLVectorType2 >
134 int test(Epsilon
const& epsilon,
135 UblasVectorType & ublas_v1, UblasVectorType & ublas_v2,
136 ViennaCLVectorType1 & vcl_v1, ViennaCLVectorType2 & vcl_v2)
138 int retval = EXIT_SUCCESS;
140 NumericT cpu_result = 42.0;
142 NumericT alpha = NumericT(3.1415);
143 NumericT beta = NumericT(2.7172);
148 std::cout <<
"Checking for zero_vector initializer..." << std::endl;
149 ublas_v1 = ublas::zero_vector<NumericT>(ublas_v1.size());
151 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
154 std::cout <<
"Checking for scalar_vector initializer..." << std::endl;
155 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), cpu_result);
157 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
160 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), gpu_result);
162 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
165 std::cout <<
"Checking for unit_vector initializer..." << std::endl;
166 ublas_v1 = ublas::unit_vector<NumericT>(ublas_v1.size(), 5);
168 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
172 for (std::size_t i=0; i<ublas_v1.size(); ++i)
174 ublas_v1[i] = NumericT(1.0) + random<NumericT>();
175 ublas_v2[i] = NumericT(1.0) + random<NumericT>();
181 std::cout <<
"Checking for successful copy..." << std::endl;
182 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
184 if (
check(ublas_v2, vcl_v2, epsilon) != EXIT_SUCCESS)
190 std::cout <<
"Testing simple assignments..." << std::endl;
197 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
202 ublas_v1 += ublas_v2;
206 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
211 ublas_v1 -= ublas_v2;
215 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
219 std::cout <<
"Testing composite assignments..." << std::endl;
221 ublas_v1 = ublas_v1 + ublas_v2;
225 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
229 ublas_v1 += alpha * ublas_v1 - beta * ublas_v2 + ublas_v1 / beta - ublas_v2 / alpha;
233 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
238 ublas_v1 = ublas_v1 - ublas_v2;
242 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
246 std::cout <<
"--- Testing reductions ---" << std::endl;
247 std::cout <<
"inner_prod..." << std::endl;
253 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
258 cpu_result =
inner_prod(ublas_v1 + ublas_v2, ublas_v2);
262 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
267 cpu_result =
inner_prod(ublas_v1, ublas_v2 - ublas_v1);
271 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
276 cpu_result =
inner_prod(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
280 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
284 std::cout <<
"norm_1..." << std::endl;
286 cpu_result =
norm_1(ublas_v1);
290 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
295 cpu_result =
norm_1(ublas_v1 + ublas_v2);
299 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
303 std::cout <<
"norm_2..." << std::endl;
305 cpu_result =
norm_2(ublas_v1);
309 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
314 cpu_result =
norm_2(ublas_v1 + ublas_v2);
318 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
322 std::cout <<
"norm_inf..." << std::endl;
328 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
333 cpu_result =
norm_inf(ublas_v1 - ublas_v2);
337 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
341 std::cout <<
"--- Testing elementwise operations (binary) ---" << std::endl;
342 std::cout <<
"x = element_prod(x, y)... ";
348 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
352 std::cout <<
"x = element_prod(x + y, y)... ";
358 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
362 std::cout <<
"x = element_prod(x, x + y)... ";
368 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
372 std::cout <<
"x = element_prod(x - y, y + x)... ";
374 ublas_v1 =
element_prod(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
378 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
384 std::cout <<
"x = element_div(x, y)... ";
390 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
394 std::cout <<
"x = element_div(x + y, y)... ";
396 ublas_v1 =
element_div(ublas_v1 + ublas_v2, ublas_v2);
400 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
404 std::cout <<
"x = element_div(x, x + y)... ";
406 ublas_v1 =
element_div(ublas_v1, ublas_v1 + ublas_v2);
410 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
414 std::cout <<
"x = element_div(x - y, y + x)... ";
416 ublas_v1 =
element_div(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
420 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
425 std::cout <<
"x = element_pow(x, y)... ";
427 for (std::size_t i=0; i<ublas_v1.size(); ++i)
429 ublas_v1[i] = NumericT(2.0) + random<NumericT>();
430 ublas_v2[i] = NumericT(1.0) + random<NumericT>();
435 for (std::size_t i=0; i<ublas_v1.size(); ++i)
436 ublas_v1[i] = std::pow(ublas_v1[i], ublas_v2[i]);
440 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
444 std::cout <<
"x = element_pow(x + y, y)... ";
446 for (std::size_t i=0; i<ublas_v1.size(); ++i)
448 ublas_v1[i] = NumericT(2.0) + random<NumericT>();
449 ublas_v2[i] = NumericT(1.0) + random<NumericT>();
454 for (std::size_t i=0; i<ublas_v1.size(); ++i)
455 ublas_v1[i] = std::pow(ublas_v1[i] + ublas_v2[i], ublas_v2[i]);
459 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
463 std::cout <<
"x = element_pow(x, x + y)... ";
465 for (std::size_t i=0; i<ublas_v1.size(); ++i)
467 ublas_v1[i] = NumericT(2.0) + random<NumericT>();
468 ublas_v2[i] = NumericT(1.0) + random<NumericT>();
473 for (std::size_t i=0; i<ublas_v1.size(); ++i)
474 ublas_v1[i] = std::pow(ublas_v1[i], ublas_v1[i] + ublas_v2[i]);
478 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
482 std::cout <<
"x = element_pow(x - y, y + x)... ";
484 for (std::size_t i=0; i<ublas_v1.size(); ++i)
486 ublas_v1[i] = NumericT(2.0) + random<NumericT>();
487 ublas_v2[i] = NumericT(1.0) + random<NumericT>();
492 for (std::size_t i=0; i<ublas_v1.size(); ++i)
493 ublas_v1[i] = std::pow(ublas_v1[i] - ublas_v2[i], ublas_v2[i] + ublas_v1[i]);
497 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
501 std::cout <<
"--- Testing elementwise operations (unary) ---" << std::endl;
502 #define GENERATE_UNARY_OP_TEST(OPNAME) \
503 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), NumericT(0.21)); \
504 ublas_v2 = NumericT(3.1415) * ublas_v1; \
505 viennacl::copy(ublas_v1.begin(), ublas_v1.end(), vcl_v1.begin()); \
506 viennacl::copy(ublas_v2.begin(), ublas_v2.end(), vcl_v2.begin()); \
508 for (std::size_t i=0; i<ublas_v1.size(); ++i) \
509 ublas_v1[i] = std::OPNAME(ublas_v2[i]); \
510 viennacl::scheduler::statement my_statement(vcl_v1, viennacl::op_assign(), viennacl::linalg::element_##OPNAME(vcl_v2)); \
511 viennacl::scheduler::execute(my_statement); \
512 if (check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS) \
513 return EXIT_FAILURE; \
516 for (std::size_t i=0; i<ublas_v1.size(); ++i) \
517 ublas_v1[i] = std::OPNAME(ublas_v2[i] / NumericT(2)); \
518 viennacl::scheduler::statement my_statement(vcl_v1, viennacl::op_assign(), viennacl::linalg::element_##OPNAME(vcl_v2 / NumericT(2))); \
519 viennacl::scheduler::execute(my_statement); \
520 if (check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS) \
521 return EXIT_FAILURE; \
539 #undef GENERATE_UNARY_OP_TEST
541 std::cout <<
"--- Testing complicated composite operations ---" << std::endl;
542 std::cout <<
"x = inner_prod(x, y) * y..." << std::endl;
544 ublas_v1 =
inner_prod(ublas_v1, ublas_v2) * ublas_v2;
548 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
552 std::cout <<
"x = y / norm_1(x)..." << std::endl;
554 ublas_v1 = ublas_v2 /
norm_1(ublas_v1);
558 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
568 template<
typename NumericT,
typename Epsilon >
569 int test(Epsilon
const& epsilon)
571 int retval = EXIT_SUCCESS;
572 std::size_t
size = 24656;
574 std::cout <<
"Running tests for vector of size " << size << std::endl;
579 ublas::vector<NumericT> ublas_full_vec(size);
580 ublas::vector<NumericT> ublas_full_vec2(ublas_full_vec.size());
582 for (std::size_t i=0; i<ublas_full_vec.size(); ++i)
584 ublas_full_vec[i] = NumericT(1.0) + random<NumericT>();
585 ublas_full_vec2[i] = NumericT(1.0) + random<NumericT>();
588 ublas::range r1( ublas_full_vec.size() / 4, 2 * ublas_full_vec.size() / 4);
589 ublas::range r2(2 * ublas_full_vec2.size() / 4, 3 * ublas_full_vec2.size() / 4);
590 ublas::vector_range< ublas::vector<NumericT> > ublas_range_vec(ublas_full_vec, r1);
591 ublas::vector_range< ublas::vector<NumericT> > ublas_range_vec2(ublas_full_vec2, r2);
593 ublas::slice s1( ublas_full_vec.size() / 4, 3, ublas_full_vec.size() / 4);
594 ublas::slice s2(2 * ublas_full_vec2.size() / 4, 2, ublas_full_vec2.size() / 4);
595 ublas::vector_slice< ublas::vector<NumericT> > ublas_slice_vec(ublas_full_vec,
s1);
596 ublas::vector_slice< ublas::vector<NumericT> > ublas_slice_vec2(ublas_full_vec2,
s2);
605 viennacl::copy(ublas_full_vec2.begin(), ublas_full_vec2.end(), vcl_full_vec2.begin());
607 viennacl::range vcl_r1( vcl_full_vec.size() / 4, 2 * vcl_full_vec.size() / 4);
608 viennacl::range vcl_r2(2 * vcl_full_vec2.size() / 4, 3 * vcl_full_vec2.size() / 4);
616 ublas::vector<NumericT> ublas_short_vec(ublas_range_vec);
617 ublas::vector<NumericT> ublas_short_vec2(ublas_range_vec2);
619 std::cout <<
"Testing creation of vectors from range..." << std::endl;
620 if (
check(ublas_short_vec, vcl_short_vec, epsilon) != EXIT_SUCCESS)
622 if (
check(ublas_short_vec2, vcl_short_vec2, epsilon) != EXIT_SUCCESS)
626 viennacl::slice vcl_s1( vcl_full_vec.size() / 4, 3, vcl_full_vec.size() / 4);
627 viennacl::slice vcl_s2(2 * vcl_full_vec2.size() / 4, 2, vcl_full_vec2.size() / 4);
634 ublas::vector<NumericT> ublas_short_vec(ublas_slice_vec);
635 ublas::vector<NumericT> ublas_short_vec2(ublas_slice_vec2);
637 std::cout <<
"Testing creation of vectors from slice..." << std::endl;
638 if (
check(ublas_short_vec, vcl_short_vec, epsilon) != EXIT_SUCCESS)
640 if (
check(ublas_short_vec2, vcl_short_vec2, epsilon) != EXIT_SUCCESS)
648 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = vector **" << std::endl;
649 retval = test<NumericT>(epsilon,
650 ublas_short_vec, ublas_short_vec2,
651 vcl_short_vec, vcl_short_vec2);
652 if (retval != EXIT_SUCCESS)
655 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = range **" << std::endl;
656 retval = test<NumericT>(epsilon,
657 ublas_short_vec, ublas_short_vec2,
658 vcl_short_vec, vcl_range_vec2);
659 if (retval != EXIT_SUCCESS)
662 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = slice **" << std::endl;
663 retval = test<NumericT>(epsilon,
664 ublas_short_vec, ublas_short_vec2,
665 vcl_short_vec, vcl_slice_vec2);
666 if (retval != EXIT_SUCCESS)
671 std::cout <<
" ** vcl_v1 = range, vcl_v2 = vector **" << std::endl;
672 retval = test<NumericT>(epsilon,
673 ublas_short_vec, ublas_short_vec2,
674 vcl_range_vec, vcl_short_vec2);
675 if (retval != EXIT_SUCCESS)
678 std::cout <<
" ** vcl_v1 = range, vcl_v2 = range **" << std::endl;
679 retval = test<NumericT>(epsilon,
680 ublas_short_vec, ublas_short_vec2,
681 vcl_range_vec, vcl_range_vec2);
682 if (retval != EXIT_SUCCESS)
685 std::cout <<
" ** vcl_v1 = range, vcl_v2 = slice **" << std::endl;
686 retval = test<NumericT>(epsilon,
687 ublas_short_vec, ublas_short_vec2,
688 vcl_range_vec, vcl_slice_vec2);
689 if (retval != EXIT_SUCCESS)
694 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = vector **" << std::endl;
695 retval = test<NumericT>(epsilon,
696 ublas_short_vec, ublas_short_vec2,
697 vcl_slice_vec, vcl_short_vec2);
698 if (retval != EXIT_SUCCESS)
701 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = range **" << std::endl;
702 retval = test<NumericT>(epsilon,
703 ublas_short_vec, ublas_short_vec2,
704 vcl_slice_vec, vcl_range_vec2);
705 if (retval != EXIT_SUCCESS)
708 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = slice **" << std::endl;
709 retval = test<NumericT>(epsilon,
710 ublas_short_vec, ublas_short_vec2,
711 vcl_slice_vec, vcl_slice_vec2);
712 if (retval != EXIT_SUCCESS)
725 std::cout << std::endl;
726 std::cout <<
"----------------------------------------------" << std::endl;
727 std::cout <<
"----------------------------------------------" << std::endl;
728 std::cout <<
"## Test :: Vector" << std::endl;
729 std::cout <<
"----------------------------------------------" << std::endl;
730 std::cout <<
"----------------------------------------------" << std::endl;
731 std::cout << std::endl;
733 int retval = EXIT_SUCCESS;
735 std::cout << std::endl;
736 std::cout <<
"----------------------------------------------" << std::endl;
737 std::cout << std::endl;
739 typedef float NumericT;
740 NumericT epsilon =
static_cast<NumericT
>(1.0E-4);
741 std::cout <<
"# Testing setup:" << std::endl;
742 std::cout <<
" eps: " << epsilon << std::endl;
743 std::cout <<
" numeric: float" << std::endl;
744 retval = test<NumericT>(epsilon);
745 if ( retval == EXIT_SUCCESS )
746 std::cout <<
"# Test passed" << std::endl;
750 std::cout << std::endl;
751 std::cout <<
"----------------------------------------------" << std::endl;
752 std::cout << std::endl;
753 #ifdef VIENNACL_WITH_OPENCL
758 typedef double NumericT;
759 NumericT epsilon = 1.0E-12;
760 std::cout <<
"# Testing setup:" << std::endl;
761 std::cout <<
" eps: " << epsilon << std::endl;
762 std::cout <<
" numeric: double" << std::endl;
763 retval = test<NumericT>(epsilon);
764 if ( retval == EXIT_SUCCESS )
765 std::cout <<
"# Test passed" << std::endl;
769 std::cout << std::endl;
770 std::cout <<
"----------------------------------------------" << std::endl;
771 std::cout << std::endl;
774 std::cout << std::endl;
775 std::cout <<
"------- Test completed --------" << std::endl;
776 std::cout << std::endl;
viennacl::vector_expression< const vector_base< T >, const vector_base< T >, op_element_binary< op_div > > element_div(vector_base< T > const &v1, vector_base< T > const &v2)
T norm_2(std::vector< T, A > const &v1)
This class represents a single scalar value on the GPU and behaves mostly like a built-in scalar type...
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
int test(Epsilon const &epsilon, UblasVectorType &ublas_v1, UblasVectorType &ublas_v2, ViennaCLVectorType1 &vcl_v1, ViennaCLVectorType2 &vcl_v2)
Implementation of the dense matrix class.
Some helper routines for reading/writing/printing scheduler expressions.
A tag class representing assignment.
void finish()
Synchronizes the execution. finish() will only return after all compute kernels (CUDA, OpenCL) have completed.
int check(T1 const &t1, T2 const &t2, double epsilon)
viennacl::enable_if< viennacl::is_stl< typename viennacl::traits::tag_of< VectorT1 >::type >::value, typename VectorT1::value_type >::type inner_prod(VectorT1 const &v1, VectorT2 const &v2)
void execute(statement const &s)
viennacl::scalar< int > s2
viennacl::scalar< float > s1
T max(const T &lhs, const T &rhs)
Maximum.
viennacl::ocl::device const & current_device()
Convenience function for returning the active device in the current context.
Generic interface for the computation of inner products. See viennacl/linalg/vector_operations.hpp for implementations.
A tag class representing inplace addition.
Generic interface for the l^1-norm. See viennacl/linalg/vector_operations.hpp for implementations...
viennacl::vector< float > v1
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Class for representing non-strided subvectors of a bigger vector x.
Class for representing strided subvectors of a bigger vector x.
bool double_support() const
ViennaCL convenience function: Returns true if the device supports double precision.
#define GENERATE_UNARY_OP_TEST(OPNAME)
Proxy classes for vectors.
A tag class representing inplace subtraction.
Represents a vector consisting of 1 at a given index and zeros otherwise.
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
Represents a vector consisting of scalars 's' only, i.e. v[i] = s for all i. To be used as an initial...
T norm_inf(std::vector< T, A > const &v1)
void copy(std::vector< NumericT > &cpu_vec, circulant_matrix< NumericT, AlignmentV > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
T norm_1(std::vector< T, A > const &v1)
A range class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded.
ScalarType diff(ScalarType const &s1, ScalarType const &s2)
viennacl::vector_expression< const vector_base< T >, const vector_base< T >, op_element_binary< op_prod > > element_prod(vector_base< T > const &v1, vector_base< T > const &v2)
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
A slice class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded.
A proxy class for a single element of a vector or matrix. This proxy should not be noticed by end-use...
Generic interface for the l^infty-norm. See viennacl/linalg/vector_operations.hpp for implementations...
void fast_copy(const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_begin, const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_end, CPU_ITERATOR cpu_begin)