ViennaCL - The Vienna Computing Library
1.5.0
|
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