ViennaCL - The Vienna Computing Library  1.5.2
viennacl/device_specific/templates/reduction_utils.hpp
Go to the documentation of this file.
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