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
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;
150 std::cout <<
"Checking for zero_vector initializer..." << std::endl;
151 ublas_v1 = ublas::zero_vector<NumericT>(ublas_v1.size());
153 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
156 std::cout <<
"Checking for scalar_vector initializer..." << std::endl;
157 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), cpu_result);
159 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
162 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), gpu_result);
164 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
167 std::cout <<
"Checking for unit_vector initializer..." << std::endl;
168 ublas_v1 = ublas::unit_vector<NumericT>(ublas_v1.size(), 5);
170 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
174 for (std::size_t i=0; i<ublas_v1.size(); ++i)
176 ublas_v1[i] =
NumericT(1.0) + randomNumber();
177 ublas_v2[i] =
NumericT(1.0) + randomNumber();
183 std::cout <<
"Checking for successful copy..." << std::endl;
184 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
186 if (
check(ublas_v2, vcl_v2, epsilon) != EXIT_SUCCESS)
192 std::cout <<
"Testing simple assignments..." << std::endl;
199 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
204 ublas_v1 += ublas_v2;
208 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
213 ublas_v1 -= ublas_v2;
217 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
221 std::cout <<
"Testing composite assignments..." << std::endl;
223 ublas_v1 = ublas_v1 + ublas_v2;
227 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
231 ublas_v1 += alpha * ublas_v1 - beta * ublas_v2 + ublas_v1 / beta - ublas_v2 / alpha;
235 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
240 ublas_v1 = ublas_v1 - ublas_v2;
244 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
248 std::cout <<
"--- Testing reductions ---" << std::endl;
249 std::cout <<
"inner_prod..." << std::endl;
255 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
260 cpu_result =
inner_prod(ublas_v1 + ublas_v2, ublas_v2);
264 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
269 cpu_result =
inner_prod(ublas_v1, ublas_v2 - ublas_v1);
273 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
278 cpu_result =
inner_prod(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
282 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
286 std::cout <<
"norm_1..." << std::endl;
288 cpu_result =
norm_1(ublas_v1);
292 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
297 cpu_result =
norm_1(ublas_v1 + ublas_v2);
301 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
305 std::cout <<
"norm_2..." << std::endl;
307 cpu_result =
norm_2(ublas_v1);
311 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
316 cpu_result =
norm_2(ublas_v1 + ublas_v2);
320 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
324 std::cout <<
"norm_inf..." << std::endl;
330 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
335 cpu_result =
norm_inf(ublas_v1 - ublas_v2);
339 if (
check(cpu_result, gpu_result, epsilon) != EXIT_SUCCESS)
343 std::cout <<
"--- Testing elementwise operations (binary) ---" << std::endl;
344 std::cout <<
"x = element_prod(x, y)... ";
350 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
354 std::cout <<
"x = element_prod(x + y, y)... ";
360 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
364 std::cout <<
"x = element_prod(x, x + y)... ";
370 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
374 std::cout <<
"x = element_prod(x - y, y + x)... ";
376 ublas_v1 =
element_prod(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
380 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
386 std::cout <<
"x = element_div(x, y)... ";
392 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
396 std::cout <<
"x = element_div(x + y, y)... ";
398 ublas_v1 =
element_div(ublas_v1 + ublas_v2, ublas_v2);
402 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
406 std::cout <<
"x = element_div(x, x + y)... ";
408 ublas_v1 =
element_div(ublas_v1, ublas_v1 + ublas_v2);
412 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
416 std::cout <<
"x = element_div(x - y, y + x)... ";
418 ublas_v1 =
element_div(ublas_v1 - ublas_v2, ublas_v2 + ublas_v1);
422 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
427 std::cout <<
"x = element_pow(x, y)... ";
429 for (std::size_t i=0; i<ublas_v1.size(); ++i)
431 ublas_v1[i] =
NumericT(2.0) + randomNumber();
432 ublas_v2[i] =
NumericT(1.0) + randomNumber();
437 for (std::size_t i=0; i<ublas_v1.size(); ++i)
438 ublas_v1[i] = std::pow(ublas_v1[i], ublas_v2[i]);
442 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
446 std::cout <<
"x = element_pow(x + y, y)... ";
448 for (std::size_t i=0; i<ublas_v1.size(); ++i)
450 ublas_v1[i] =
NumericT(2.0) + randomNumber();
451 ublas_v2[i] =
NumericT(1.0) + randomNumber();
456 for (std::size_t i=0; i<ublas_v1.size(); ++i)
457 ublas_v1[i] = std::pow(ublas_v1[i] + ublas_v2[i], ublas_v2[i]);
461 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
465 std::cout <<
"x = element_pow(x, x + y)... ";
467 for (std::size_t i=0; i<ublas_v1.size(); ++i)
469 ublas_v1[i] =
NumericT(2.0) + randomNumber();
470 ublas_v2[i] =
NumericT(1.0) + randomNumber();
475 for (std::size_t i=0; i<ublas_v1.size(); ++i)
476 ublas_v1[i] = std::pow(ublas_v1[i], ublas_v1[i] + ublas_v2[i]);
480 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
484 std::cout <<
"x = element_pow(x - y, y + x)... ";
486 for (std::size_t i=0; i<ublas_v1.size(); ++i)
488 ublas_v1[i] =
NumericT(2.0) + randomNumber();
489 ublas_v2[i] =
NumericT(1.0) + randomNumber();
494 for (std::size_t i=0; i<ublas_v1.size(); ++i)
495 ublas_v1[i] = std::pow(ublas_v1[i] - ublas_v2[i], ublas_v2[i] + ublas_v1[i]);
499 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
503 std::cout <<
"--- Testing elementwise operations (unary) ---" << std::endl;
504 #define GENERATE_UNARY_OP_TEST(OPNAME) \
505 ublas_v1 = ublas::scalar_vector<NumericT>(ublas_v1.size(), NumericT(0.21)); \
506 ublas_v2 = NumericT(3.1415) * ublas_v1; \
507 viennacl::copy(ublas_v1.begin(), ublas_v1.end(), vcl_v1.begin()); \
508 viennacl::copy(ublas_v2.begin(), ublas_v2.end(), vcl_v2.begin()); \
510 for (std::size_t i=0; i<ublas_v1.size(); ++i) \
511 ublas_v1[i] = std::OPNAME(ublas_v2[i]); \
512 viennacl::scheduler::statement my_statement(vcl_v1, viennacl::op_assign(), viennacl::linalg::element_##OPNAME(vcl_v2)); \
513 viennacl::scheduler::execute(my_statement); \
514 if (check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS) \
515 return EXIT_FAILURE; \
518 for (std::size_t i=0; i<ublas_v1.size(); ++i) \
519 ublas_v1[i] = std::OPNAME(ublas_v2[i] / NumericT(2)); \
520 viennacl::scheduler::statement my_statement(vcl_v1, viennacl::op_assign(), viennacl::linalg::element_##OPNAME(vcl_v2 / NumericT(2))); \
521 viennacl::scheduler::execute(my_statement); \
522 if (check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS) \
523 return EXIT_FAILURE; \
541 #undef GENERATE_UNARY_OP_TEST
543 std::cout <<
"--- Testing complicated composite operations ---" << std::endl;
544 std::cout <<
"x = inner_prod(x, y) * y..." << std::endl;
546 ublas_v1 =
inner_prod(ublas_v1, ublas_v2) * ublas_v2;
550 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
554 std::cout <<
"x = y / norm_1(x)..." << std::endl;
556 ublas_v1 = ublas_v2 /
norm_1(ublas_v1);
560 if (
check(ublas_v1, vcl_v1, epsilon) != EXIT_SUCCESS)
570 template<
typename NumericT,
typename Epsilon >
571 int test(Epsilon
const& epsilon)
573 int retval = EXIT_SUCCESS;
574 std::size_t
size = 24656;
578 std::cout <<
"Running tests for vector of size " << size << std::endl;
583 ublas::vector<NumericT> ublas_full_vec(size);
584 ublas::vector<NumericT> ublas_full_vec2(ublas_full_vec.size());
586 for (std::size_t i=0; i<ublas_full_vec.size(); ++i)
588 ublas_full_vec[i] =
NumericT(1.0) + randomNumber();
589 ublas_full_vec2[i] =
NumericT(1.0) + randomNumber();
592 ublas::range r1( ublas_full_vec.size() / 4, 2 * ublas_full_vec.size() / 4);
593 ublas::range r2(2 * ublas_full_vec2.size() / 4, 3 * ublas_full_vec2.size() / 4);
594 ublas::vector_range< ublas::vector<NumericT> > ublas_range_vec(ublas_full_vec, r1);
595 ublas::vector_range< ublas::vector<NumericT> > ublas_range_vec2(ublas_full_vec2, r2);
597 ublas::slice s1( ublas_full_vec.size() / 4, 3, ublas_full_vec.size() / 4);
598 ublas::slice s2(2 * ublas_full_vec2.size() / 4, 2, ublas_full_vec2.size() / 4);
599 ublas::vector_slice< ublas::vector<NumericT> > ublas_slice_vec(ublas_full_vec,
s1);
600 ublas::vector_slice< ublas::vector<NumericT> > ublas_slice_vec2(ublas_full_vec2,
s2);
609 viennacl::copy(ublas_full_vec2.begin(), ublas_full_vec2.end(), vcl_full_vec2.begin());
611 viennacl::range vcl_r1( vcl_full_vec.size() / 4, 2 * vcl_full_vec.size() / 4);
612 viennacl::range vcl_r2(2 * vcl_full_vec2.size() / 4, 3 * vcl_full_vec2.size() / 4);
620 ublas::vector<NumericT> ublas_short_vec(ublas_range_vec);
621 ublas::vector<NumericT> ublas_short_vec2(ublas_range_vec2);
623 std::cout <<
"Testing creation of vectors from range..." << std::endl;
624 if (
check(ublas_short_vec, vcl_short_vec, epsilon) != EXIT_SUCCESS)
626 if (
check(ublas_short_vec2, vcl_short_vec2, epsilon) != EXIT_SUCCESS)
630 viennacl::slice vcl_s1( vcl_full_vec.size() / 4, 3, vcl_full_vec.size() / 4);
631 viennacl::slice vcl_s2(2 * vcl_full_vec2.size() / 4, 2, vcl_full_vec2.size() / 4);
638 ublas::vector<NumericT> ublas_short_vec(ublas_slice_vec);
639 ublas::vector<NumericT> ublas_short_vec2(ublas_slice_vec2);
641 std::cout <<
"Testing creation of vectors from slice..." << std::endl;
642 if (
check(ublas_short_vec, vcl_short_vec, epsilon) != EXIT_SUCCESS)
644 if (
check(ublas_short_vec2, vcl_short_vec2, epsilon) != EXIT_SUCCESS)
652 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = vector **" << std::endl;
653 retval = test<NumericT>(epsilon,
654 ublas_short_vec, ublas_short_vec2,
655 vcl_short_vec, vcl_short_vec2);
656 if (retval != EXIT_SUCCESS)
659 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = range **" << std::endl;
660 retval = test<NumericT>(epsilon,
661 ublas_short_vec, ublas_short_vec2,
662 vcl_short_vec, vcl_range_vec2);
663 if (retval != EXIT_SUCCESS)
666 std::cout <<
" ** vcl_v1 = vector, vcl_v2 = slice **" << std::endl;
667 retval = test<NumericT>(epsilon,
668 ublas_short_vec, ublas_short_vec2,
669 vcl_short_vec, vcl_slice_vec2);
670 if (retval != EXIT_SUCCESS)
675 std::cout <<
" ** vcl_v1 = range, vcl_v2 = vector **" << std::endl;
676 retval = test<NumericT>(epsilon,
677 ublas_short_vec, ublas_short_vec2,
678 vcl_range_vec, vcl_short_vec2);
679 if (retval != EXIT_SUCCESS)
682 std::cout <<
" ** vcl_v1 = range, vcl_v2 = range **" << std::endl;
683 retval = test<NumericT>(epsilon,
684 ublas_short_vec, ublas_short_vec2,
685 vcl_range_vec, vcl_range_vec2);
686 if (retval != EXIT_SUCCESS)
689 std::cout <<
" ** vcl_v1 = range, vcl_v2 = slice **" << std::endl;
690 retval = test<NumericT>(epsilon,
691 ublas_short_vec, ublas_short_vec2,
692 vcl_range_vec, vcl_slice_vec2);
693 if (retval != EXIT_SUCCESS)
698 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = vector **" << std::endl;
699 retval = test<NumericT>(epsilon,
700 ublas_short_vec, ublas_short_vec2,
701 vcl_slice_vec, vcl_short_vec2);
702 if (retval != EXIT_SUCCESS)
705 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = range **" << std::endl;
706 retval = test<NumericT>(epsilon,
707 ublas_short_vec, ublas_short_vec2,
708 vcl_slice_vec, vcl_range_vec2);
709 if (retval != EXIT_SUCCESS)
712 std::cout <<
" ** vcl_v1 = slice, vcl_v2 = slice **" << std::endl;
713 retval = test<NumericT>(epsilon,
714 ublas_short_vec, ublas_short_vec2,
715 vcl_slice_vec, vcl_slice_vec2);
716 if (retval != EXIT_SUCCESS)
729 std::cout << std::endl;
730 std::cout <<
"----------------------------------------------" << std::endl;
731 std::cout <<
"----------------------------------------------" << std::endl;
732 std::cout <<
"## Test :: Vector" << std::endl;
733 std::cout <<
"----------------------------------------------" << std::endl;
734 std::cout <<
"----------------------------------------------" << std::endl;
735 std::cout << std::endl;
737 int retval = EXIT_SUCCESS;
739 std::cout << std::endl;
740 std::cout <<
"----------------------------------------------" << std::endl;
741 std::cout << std::endl;
744 NumericT epsilon =
static_cast<NumericT
>(1.0E-4);
745 std::cout <<
"# Testing setup:" << std::endl;
746 std::cout <<
" eps: " << epsilon << std::endl;
747 std::cout <<
" numeric: float" << std::endl;
748 retval = test<NumericT>(epsilon);
749 if ( retval == EXIT_SUCCESS )
750 std::cout <<
"# Test passed" << std::endl;
754 std::cout << std::endl;
755 std::cout <<
"----------------------------------------------" << std::endl;
756 std::cout << std::endl;
757 #ifdef VIENNACL_WITH_OPENCL
763 NumericT epsilon = 1.0E-12;
764 std::cout <<
"# Testing setup:" << std::endl;
765 std::cout <<
" eps: " << epsilon << std::endl;
766 std::cout <<
" numeric: double" << std::endl;
767 retval = test<NumericT>(epsilon);
768 if ( retval == EXIT_SUCCESS )
769 std::cout <<
"# Test passed" << std::endl;
773 std::cout << std::endl;
774 std::cout <<
"----------------------------------------------" << std::endl;
775 std::cout << std::endl;
778 std::cout << std::endl;
779 std::cout <<
"------- Test completed --------" << std::endl;
780 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) ...
A small collection of sequential random number generators.
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)