ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/opencl/scalar_operations.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_OPENCL_SCALAR_OPERATIONS_HPP_
00002 #define VIENNACL_LINALG_OPENCL_SCALAR_OPERATIONS_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include "viennacl/forwards.h"
00026 #include "viennacl/ocl/device.hpp"
00027 #include "viennacl/ocl/handle.hpp"
00028 #include "viennacl/ocl/kernel.hpp"
00029 #include "viennacl/tools/tools.hpp"
00030 #include "viennacl/linalg/opencl/kernels/scalar.hpp"
00031 #include "viennacl/linalg/opencl/common.hpp"
00032 #include "viennacl/meta/predicate.hpp"
00033 #include "viennacl/meta/result_of.hpp"
00034 #include "viennacl/meta/enable_if.hpp"
00035 #include "viennacl/traits/size.hpp"
00036 #include "viennacl/traits/start.hpp"
00037 #include "viennacl/traits/handle.hpp"
00038 #include "viennacl/traits/stride.hpp"
00039 
00040 namespace viennacl
00041 {
00042   namespace linalg
00043   {
00044     namespace opencl
00045     {
00046       template <typename S1,
00047                 typename S2, typename ScalarType1>
00048       typename viennacl::enable_if< viennacl::is_scalar<S1>::value
00049                                     && viennacl::is_scalar<S2>::value
00050                                     && viennacl::is_any_scalar<ScalarType1>::value
00051                                   >::type
00052       as(S1 & s1,
00053          S2 const & s2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha)
00054       {
00055         assert( &viennacl::traits::opencl_handle(s1).context() == &viennacl::traits::opencl_handle(s2).context() && bool("Operands not in the same OpenCL context!"));
00056 
00057         typedef typename viennacl::result_of::cpu_value_type<S1>::type        value_type;
00058         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(s1).context());
00059         viennacl::linalg::opencl::kernels::scalar<value_type>::init(ctx);
00060 
00061         cl_uint options_alpha = detail::make_options(len_alpha, reciprocal_alpha, flip_sign_alpha);
00062 
00063         viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::scalar<value_type>::program_name(),
00064                                                    (viennacl::is_cpu_scalar<ScalarType1>::value ? "as_cpu" : "as_gpu"));
00065         k.local_work_size(0, 1);
00066         k.global_work_size(0, 1);
00067         viennacl::ocl::enqueue(k(viennacl::traits::opencl_handle(s1),
00068                                  viennacl::traits::opencl_handle(viennacl::tools::promote_if_host_scalar<value_type>(alpha)),
00069                                  options_alpha,
00070                                  viennacl::traits::opencl_handle(s2) )
00071                               );
00072       }
00073 
00074 
00075       template <typename S1,
00076                 typename S2, typename ScalarType1,
00077                 typename S3, typename ScalarType2>
00078       typename viennacl::enable_if< viennacl::is_scalar<S1>::value
00079                                     && viennacl::is_scalar<S2>::value
00080                                     && viennacl::is_scalar<S3>::value
00081                                     && viennacl::is_any_scalar<ScalarType1>::value
00082                                     && viennacl::is_any_scalar<ScalarType2>::value
00083                                   >::type
00084       asbs(S1 & s1,
00085            S2 const & s2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00086            S3 const & s3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00087       {
00088         assert( &viennacl::traits::opencl_handle(s1).context() == &viennacl::traits::opencl_handle(s2).context() && bool("Operands not in the same OpenCL context!"));
00089         assert( &viennacl::traits::opencl_handle(s2).context() == &viennacl::traits::opencl_handle(s3).context() && bool("Operands not in the same OpenCL context!"));
00090 
00091         typedef typename viennacl::result_of::cpu_value_type<S1>::type        value_type;
00092         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(s1).context());
00093         viennacl::linalg::opencl::kernels::scalar<value_type>::init(ctx);
00094 
00095         std::string kernel_name;
00096         if (viennacl::is_cpu_scalar<ScalarType1>::value && viennacl::is_cpu_scalar<ScalarType2>::value)
00097           kernel_name = "asbs_cpu_cpu";
00098         else if (viennacl::is_cpu_scalar<ScalarType1>::value && !viennacl::is_cpu_scalar<ScalarType2>::value)
00099           kernel_name = "asbs_cpu_gpu";
00100         else if (!viennacl::is_cpu_scalar<ScalarType1>::value && viennacl::is_cpu_scalar<ScalarType2>::value)
00101           kernel_name = "asbs_gpu_cpu";
00102         else
00103           kernel_name = "asbs_gpu_gpu";
00104 
00105         cl_uint options_alpha = detail::make_options(len_alpha, reciprocal_alpha, flip_sign_alpha);
00106         cl_uint options_beta  = detail::make_options(len_beta,  reciprocal_beta,  flip_sign_beta);
00107 
00108         viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::scalar<value_type>::program_name(), kernel_name);
00109         k.local_work_size(0, 1);
00110         k.global_work_size(0, 1);
00111         viennacl::ocl::enqueue(k(viennacl::traits::opencl_handle(s1),
00112                                  viennacl::traits::opencl_handle(viennacl::tools::promote_if_host_scalar<value_type>(alpha)),
00113                                  options_alpha,
00114                                  viennacl::traits::opencl_handle(s2),
00115                                  viennacl::traits::opencl_handle(viennacl::tools::promote_if_host_scalar<value_type>(beta)),
00116                                  options_beta,
00117                                  viennacl::traits::opencl_handle(s3) )
00118                               );
00119       }
00120 
00121 
00122       template <typename S1,
00123                 typename S2, typename ScalarType1,
00124                 typename S3, typename ScalarType2>
00125       typename viennacl::enable_if< viennacl::is_scalar<S1>::value
00126                                     && viennacl::is_scalar<S2>::value
00127                                     && viennacl::is_scalar<S3>::value
00128                                     && viennacl::is_any_scalar<ScalarType1>::value
00129                                     && viennacl::is_any_scalar<ScalarType2>::value
00130                                   >::type
00131       asbs_s(S1 & s1,
00132              S2 const & s2, ScalarType1 const & alpha, vcl_size_t len_alpha, bool reciprocal_alpha, bool flip_sign_alpha,
00133              S3 const & s3, ScalarType2 const & beta,  vcl_size_t len_beta,  bool reciprocal_beta,  bool flip_sign_beta)
00134       {
00135         assert( &viennacl::traits::opencl_handle(s1).context() == &viennacl::traits::opencl_handle(s2).context() && bool("Operands not in the same OpenCL context!"));
00136         assert( &viennacl::traits::opencl_handle(s2).context() == &viennacl::traits::opencl_handle(s3).context() && bool("Operands not in the same OpenCL context!"));
00137 
00138         typedef typename viennacl::result_of::cpu_value_type<S1>::type        value_type;
00139         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(s1).context());
00140         viennacl::linalg::opencl::kernels::scalar<value_type>::init(ctx);
00141 
00142         std::string kernel_name;
00143         if (viennacl::is_cpu_scalar<ScalarType1>::value && viennacl::is_cpu_scalar<ScalarType2>::value)
00144           kernel_name = "asbs_s_cpu_cpu";
00145         else if (viennacl::is_cpu_scalar<ScalarType1>::value && !viennacl::is_cpu_scalar<ScalarType2>::value)
00146           kernel_name = "asbs_s_cpu_gpu";
00147         else if (!viennacl::is_cpu_scalar<ScalarType1>::value && viennacl::is_cpu_scalar<ScalarType2>::value)
00148           kernel_name = "asbs_s_gpu_cpu";
00149         else
00150           kernel_name = "asbs_s_gpu_gpu";
00151 
00152         cl_uint options_alpha = detail::make_options(len_alpha, reciprocal_alpha, flip_sign_alpha);
00153         cl_uint options_beta  = detail::make_options(len_beta,  reciprocal_beta,  flip_sign_beta);
00154 
00155         viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::scalar<value_type>::program_name(), kernel_name);
00156         k.local_work_size(0, 1);
00157         k.global_work_size(0, 1);
00158         viennacl::ocl::enqueue(k(viennacl::traits::opencl_handle(s1),
00159                                  viennacl::traits::opencl_handle(viennacl::tools::promote_if_host_scalar<value_type>(alpha)),
00160                                  options_alpha,
00161                                  viennacl::traits::opencl_handle(s2),
00162                                  viennacl::traits::opencl_handle(viennacl::tools::promote_if_host_scalar<value_type>(beta)),
00163                                  options_beta,
00164                                  viennacl::traits::opencl_handle(s3) )
00165                               );
00166       }
00167 
00168 
00174       template <typename S1, typename S2>
00175       typename viennacl::enable_if<    viennacl::is_scalar<S1>::value
00176                                     && viennacl::is_scalar<S2>::value
00177                                   >::type
00178       swap(S1 & s1, S2 & s2)
00179       {
00180         assert( &viennacl::traits::opencl_handle(s1).context() == &viennacl::traits::opencl_handle(s2).context() && bool("Operands not in the same OpenCL context!"));
00181 
00182         typedef typename viennacl::result_of::cpu_value_type<S1>::type        value_type;
00183         viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(s1).context());
00184         viennacl::linalg::opencl::kernels::scalar<value_type>::init(ctx);
00185 
00186         viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::scalar<value_type>::program_name(), "swap");
00187         k.local_work_size(0, 1);
00188         k.global_work_size(0, 1);
00189         viennacl::ocl::enqueue(k(viennacl::traits::opencl_handle(s1),
00190                                  viennacl::traits::opencl_handle(s2))
00191                               );
00192       }
00193 
00194 
00195 
00196     } //namespace opencl
00197   } //namespace linalg
00198 } //namespace viennacl
00199 
00200 
00201 #endif