ViennaCL - The Vienna Computing Library
1.5.2
|
00001 #ifndef VIENNACL_LINALG_OPENCL_KERNELS_NMF_HPP 00002 #define VIENNACL_LINALG_OPENCL_KERNELS_NMF_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 00011 namespace viennacl 00012 { 00013 namespace linalg 00014 { 00015 namespace opencl 00016 { 00017 namespace kernels 00018 { 00019 00020 template <typename StringType> 00021 void generate_nmf_el_wise_mul_div(StringType & source, std::string const & numeric_string) 00022 { 00023 source.append("__kernel void el_wise_mul_div( \n"); 00024 source.append(" __global "); source.append(numeric_string); source.append(" * matrix1, \n"); 00025 source.append(" __global const "); source.append(numeric_string); source.append(" * matrix2, \n"); 00026 source.append(" __global const "); source.append(numeric_string); source.append(" * matrix3, \n"); 00027 source.append(" unsigned int size) \n"); 00028 source.append("{ \n"); 00029 source.append(" for (unsigned int i = get_global_id(0); i < size; i += get_global_size(0)) \n"); 00030 source.append(" { \n"); 00031 source.append(" "); source.append(numeric_string); source.append(" val = matrix1[i] * matrix2[i]; \n"); 00032 source.append(" "); source.append(numeric_string); source.append(" divisor = matrix3[i]; \n"); 00033 source.append(" matrix1[i] = (divisor > ("); source.append(numeric_string); source.append(")0.00001) ? (val / divisor) : ("); source.append(numeric_string); source.append(")0; \n"); 00034 source.append(" } \n"); 00035 source.append("} \n"); 00036 } 00037 00038 // main kernel class 00040 template <class NumericT> 00041 struct nmf 00042 { 00043 static std::string program_name() 00044 { 00045 return viennacl::ocl::type_to_string<NumericT>::apply() + "_nmf"; 00046 } 00047 00048 static void init(viennacl::ocl::context & ctx) 00049 { 00050 viennacl::ocl::DOUBLE_PRECISION_CHECKER<NumericT>::apply(ctx); 00051 std::string numeric_string = viennacl::ocl::type_to_string<NumericT>::apply(); 00052 00053 static std::map<cl_context, bool> init_done; 00054 if (!init_done[ctx.handle().get()]) 00055 { 00056 std::string source; 00057 source.reserve(8192); 00058 00059 viennacl::ocl::append_double_precision_pragma<NumericT>(ctx, source); 00060 00061 // only generate for floating points (forces error for integers) 00062 if (numeric_string == "float" || numeric_string == "double") 00063 { 00064 generate_nmf_el_wise_mul_div(source, numeric_string); 00065 } 00066 00067 std::string prog_name = program_name(); 00068 #ifdef VIENNACL_BUILD_INFO 00069 std::cout << "Creating program " << prog_name << std::endl; 00070 #endif 00071 ctx.add_program(source, prog_name); 00072 init_done[ctx.handle().get()] = true; 00073 } //if 00074 } //init 00075 }; 00076 00077 } // namespace kernels 00078 } // namespace opencl 00079 } // namespace linalg 00080 } // namespace viennacl 00081 #endif 00082