ViennaCL - The Vienna Computing Library
1.5.2
|
00001 #ifndef VIENNACL_DEVICE_SPECIFIC_TEMPLATES_REDUCTION_UTILS_HPP 00002 #define VIENNACL_DEVICE_SPECIFIC_TEMPLATES_REDUCTION_UTILS_HPP 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, 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 00021 00027 #include <vector> 00028 00029 #include "viennacl/scheduler/forwards.h" 00030 00031 #include "viennacl/device_specific/tree_parsing/evaluate_expression.hpp" 00032 #include "viennacl/device_specific/utils.hpp" 00033 00034 00035 namespace viennacl{ 00036 00037 namespace device_specific{ 00038 00039 static void compute_reduction(utils::kernel_generation_stream & os, std::string accidx, std::string curidx, std::string const & acc, std::string const & cur, scheduler::op_element const & op){ 00040 if(utils::is_index_reduction(op)) 00041 { 00042 os << accidx << "= select(" << accidx << "," << curidx << "," << cur << ">" << acc << ");" << std::endl; 00043 os << acc << "="; 00044 if(op.type==scheduler::OPERATION_BINARY_ELEMENT_ARGFMAX_TYPE) os << "fmax"; 00045 if(op.type==scheduler::OPERATION_BINARY_ELEMENT_ARGMAX_TYPE) os << "max"; 00046 if(op.type==scheduler::OPERATION_BINARY_ELEMENT_ARGFMIN_TYPE) os << "fmin"; 00047 if(op.type==scheduler::OPERATION_BINARY_ELEMENT_ARGMIN_TYPE) os << "min"; 00048 os << "(" << acc << "," << cur << ");"<< std::endl; 00049 } 00050 else{ 00051 os << acc << "="; 00052 if(utils::elementwise_function(op)) 00053 os << tree_parsing::evaluate(op.type) << "(" << acc << "," << cur << ")"; 00054 else 00055 os << "(" << acc << ")" << tree_parsing::evaluate(op.type) << "(" << cur << ")"; 00056 os << ";" << std::endl; 00057 } 00058 } 00059 00060 00061 inline void reduce_1d_local_memory(utils::kernel_generation_stream & stream, unsigned int size, std::vector<std::string> const & bufs, std::vector<scheduler::op_element> const & rops) 00062 { 00063 //Reduce local memory 00064 stream << "#pragma unroll" << std::endl; 00065 stream << "for(unsigned int stride = " << size/2 << "; stride >0 ; stride /=2){" << std::endl; 00066 stream.inc_tab(); 00067 stream << "barrier(CLK_LOCAL_MEM_FENCE); " << std::endl; 00068 stream << "if(lid < stride){" << std::endl; 00069 stream.inc_tab(); 00070 for(unsigned int k = 0 ; k < bufs.size() ; ++k){ 00071 std::string acc = bufs[k] + "[lid]"; 00072 std::string accidx = (bufs[k] + "idx") + "[lid]"; 00073 std::string cur = bufs[k] + "[lid + stride]"; 00074 std::string curidx = (bufs[k] + "idx") + "[lid + stride]"; 00075 compute_reduction(stream,accidx,curidx,acc,cur,rops[k]); 00076 } 00077 stream.dec_tab(); 00078 stream << "}" << std::endl; 00079 stream.dec_tab(); 00080 stream << "}" << std::endl; 00081 } 00082 00083 inline std::string neutral_element(scheduler::op_element const & op){ 00084 switch(op.type){ 00085 case scheduler::OPERATION_BINARY_ADD_TYPE : return "0"; 00086 case scheduler::OPERATION_BINARY_MULT_TYPE : return "1"; 00087 case scheduler::OPERATION_BINARY_DIV_TYPE : return "1"; 00088 case scheduler::OPERATION_BINARY_ELEMENT_FMAX_TYPE : return "-INFINITY"; 00089 case scheduler::OPERATION_BINARY_ELEMENT_ARGFMAX_TYPE : return "-INFINITY"; 00090 case scheduler::OPERATION_BINARY_ELEMENT_MAX_TYPE : return "-INFINITY"; 00091 case scheduler::OPERATION_BINARY_ELEMENT_ARGMAX_TYPE : return "-INFINITY"; 00092 case scheduler::OPERATION_BINARY_ELEMENT_FMIN_TYPE : return "INFINITY"; 00093 case scheduler::OPERATION_BINARY_ELEMENT_ARGFMIN_TYPE : return "INFINITY"; 00094 case scheduler::OPERATION_BINARY_ELEMENT_MIN_TYPE : return "INFINITY"; 00095 case scheduler::OPERATION_BINARY_ELEMENT_ARGMIN_TYPE : return "INFINITY"; 00096 00097 default: throw generator_not_supported_exception("Unsupported reduction operator : no neutral element known"); 00098 } 00099 } 00100 00101 } 00102 } 00103 00104 #endif