ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/opencl/kernels/matrix_element.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_OPENCL_KERNELS_MATRIX_ELEMENT_HPP
00002 #define VIENNACL_LINALG_OPENCL_KERNELS_MATRIX_ELEMENT_HPP
00003 
00004 #include "viennacl/tools/tools.hpp"
00005 #include "viennacl/ocl/kernel.hpp"
00006 #include "viennacl/ocl/platform.hpp"
00007 #include "viennacl/ocl/utils.hpp"
00008 #include "viennacl/linalg/opencl/kernels/matrix.hpp"
00009 
00012 namespace viennacl
00013 {
00014   namespace linalg
00015   {
00016     namespace opencl
00017     {
00018       namespace kernels
00019       {
00020 
00022 
00023 
00024         //generate code for C = op1(A) * op2(B), where A, B, C can have different storage layouts and opX(D) = D or trans(D)
00025         template <typename StringType>
00026         void generate_matrix_unary_element_ops(StringType & source, std::string const & numeric_string,
00027                                                std::string const & funcname, std::string const & op, std::string const & op_name, bool is_row_major)
00028         {
00029           source.append("__kernel void "); source.append(funcname); source.append("_"); source.append(op_name); source.append("(\n");
00030           source.append("          __global "); source.append(numeric_string); source.append(" * A, \n");
00031           source.append("          unsigned int A_start1, unsigned int A_start2, \n");
00032           source.append("          unsigned int A_inc1,   unsigned int A_inc2, \n");
00033           source.append("          unsigned int A_size1,  unsigned int A_size2, \n");
00034           source.append("          unsigned int A_internal_size1,  unsigned int A_internal_size2, \n");
00035 
00036           source.append("          __global const "); source.append(numeric_string); source.append(" * B, \n");
00037           source.append("          unsigned int B_start1, unsigned int B_start2, \n");
00038           source.append("          unsigned int B_inc1,   unsigned int B_inc2, \n");
00039           source.append("          unsigned int B_internal_size1,  unsigned int B_internal_size2) { \n");
00040 
00041           if (is_row_major)
00042           {
00043             source.append("  unsigned int row_gid = get_global_id(0) / get_local_size(0); \n");
00044             source.append("  unsigned int col_gid = get_global_id(0) % get_local_size(0); \n");
00045 
00046             source.append("  for (unsigned int row = row_gid; row < A_size1; row += get_num_groups(0)) \n");
00047             source.append("    for (unsigned int col = col_gid; col < A_size2; col += get_local_size(0)) \n");
00048             source.append("      A[(row * A_inc1 + A_start1) * A_internal_size2 + col * A_inc2 + A_start2] \n");
00049             source.append("        "); source.append(op); source.append(" "); source.append(funcname); source.append("(B[(row * B_inc1 + B_start1) * B_internal_size2 + col * B_inc2 + B_start2]); \n");
00050           }
00051           else
00052           {
00053             source.append("  unsigned int row_gid = get_global_id(0) % get_local_size(0); \n");
00054             source.append("  unsigned int col_gid = get_global_id(0) / get_local_size(0); \n");
00055 
00056             source.append("  for (unsigned int col = col_gid; col < A_size2; col += get_num_groups(0)) \n");
00057             source.append("    for (unsigned int row = row_gid; row < A_size1; row += get_local_size(0)) \n");
00058             source.append("      A[(row * A_inc1 + A_start1) + (col * A_inc2 + A_start2) * A_internal_size1] \n");
00059             source.append("        "); source.append(op); source.append(" "); source.append(funcname); source.append("(B[(row * B_inc1 + B_start1) + (col * B_inc2 + B_start2) * B_internal_size1]); \n");
00060           }
00061           source.append("} \n");
00062         }
00063 
00064         template <typename StringType>
00065         void generate_matrix_unary_element_ops(StringType & source, std::string const & numeric_string, std::string const & funcname, bool is_row_major)
00066         {
00067           generate_matrix_unary_element_ops(source, numeric_string, funcname, "=", "assign", is_row_major);
00068           //generate_matrix_unary_element_ops(source, numeric_string, funcname, "+=", "plus", is_row_major);
00069           //generate_matrix_unary_element_ops(source, numeric_string, funcname, "-=", "minus", is_row_major);
00070         }
00071 
00073 
00074         // main kernel class
00076         template <typename NumericT, typename F>
00077         struct matrix_element
00078         {
00079           static std::string program_name()
00080           {
00081             return viennacl::ocl::type_to_string<NumericT>::apply() + "_matrix_element_" + detail::type_to_string(F());
00082           }
00083 
00084           static void init(viennacl::ocl::context & ctx)
00085           {
00086             viennacl::ocl::DOUBLE_PRECISION_CHECKER<NumericT>::apply(ctx);
00087             std::string numeric_string = viennacl::ocl::type_to_string<NumericT>::apply();
00088 
00089             static std::map<cl_context, bool> init_done;
00090             if (!init_done[ctx.handle().get()])
00091             {
00092               std::string source;
00093               source.reserve(8192);
00094               bool is_row_major = viennacl::is_row_major<F>::value;
00095 
00096               viennacl::ocl::append_double_precision_pragma<NumericT>(ctx, source);
00097 
00098               // unary operations
00099               if (numeric_string == "float" || numeric_string == "double")
00100               {
00101                 generate_matrix_unary_element_ops(source, numeric_string, "acos",  is_row_major);
00102                 generate_matrix_unary_element_ops(source, numeric_string, "asin",  is_row_major);
00103                 generate_matrix_unary_element_ops(source, numeric_string, "atan",  is_row_major);
00104                 generate_matrix_unary_element_ops(source, numeric_string, "ceil",  is_row_major);
00105                 generate_matrix_unary_element_ops(source, numeric_string, "cos",   is_row_major);
00106                 generate_matrix_unary_element_ops(source, numeric_string, "cosh",  is_row_major);
00107                 generate_matrix_unary_element_ops(source, numeric_string, "exp",   is_row_major);
00108                 generate_matrix_unary_element_ops(source, numeric_string, "fabs",  is_row_major);
00109                 generate_matrix_unary_element_ops(source, numeric_string, "floor", is_row_major);
00110                 generate_matrix_unary_element_ops(source, numeric_string, "log",   is_row_major);
00111                 generate_matrix_unary_element_ops(source, numeric_string, "log10", is_row_major);
00112                 generate_matrix_unary_element_ops(source, numeric_string, "sin",   is_row_major);
00113                 generate_matrix_unary_element_ops(source, numeric_string, "sinh",  is_row_major);
00114                 generate_matrix_unary_element_ops(source, numeric_string, "sqrt",  is_row_major);
00115                 generate_matrix_unary_element_ops(source, numeric_string, "tan",   is_row_major);
00116                 generate_matrix_unary_element_ops(source, numeric_string, "tanh",  is_row_major);
00117               }
00118               else
00119               {
00120                 generate_matrix_unary_element_ops(source, numeric_string, "abs", is_row_major);
00121               }
00122 
00123               std::string prog_name = program_name();
00124               #ifdef VIENNACL_BUILD_INFO
00125               std::cout << "Creating program " << prog_name << std::endl;
00126               #endif
00127               ctx.add_program(source, prog_name);
00128               init_done[ctx.handle().get()] = true;
00129             } //if
00130           } //init
00131         };
00132 
00133       }  // namespace kernels
00134     }  // namespace opencl
00135   }  // namespace linalg
00136 }  // namespace viennacl
00137 #endif
00138