ivl 679
ivl/details/core/loops/loops.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 #ifndef IVL_CORE_DETAILS_LOOPS_HPP
00025 #define IVL_CORE_DETAILS_LOOPS_HPP
00026 
00027 namespace ivl {
00028 namespace loops {
00029 
00030 static const int cpu_intensive = 1000000000;
00031 static const int intensive = 1000000000;
00032 
00037 template <class F, class T, class S, class J, class D>
00038 void loop(ivl::array<T, S>& out, const ivl::array<J, D>& in)
00039 {
00040         typedef ivl::array<T, S> out_t;
00041         typedef const ivl::array<J, D> in_t;
00042 
00043         //TODO:
00044         //typename data::reduce_access_tag_to_1d<in_t::optimal_access_tag>::type
00045         //for copying array_nd to arrays
00046         loop_base<1, F, out_t, in_t,
00047                 typename out_t::optimal_access_tag,
00048                 typename in_t::optimal_access_tag,
00049                 typename out_t::has_specialized_iter,
00050                 typename in_t::has_specialized_iter>::exec(out, in);
00051 
00052 }
00053 
00054 template <class F, class T, class S, class J, class D>
00055 void loop_ww(ivl::array<T, S>& out, ivl::array<J, D>& in_out)
00056 {
00057         typedef ivl::array<T, S> out_t;
00058         typedef ivl::array<J, D> in_t;
00059 
00060         //TODO:
00061         //typename data::reduce_access_tag_to_1d<in_t::optimal_access_tag>::type
00062         //for copying array_nd to arrays
00063         loop_base<1, F, out_t, in_t,
00064                 typename out_t::optimal_access_tag,
00065                 typename in_t::optimal_access_tag,
00066                 typename out_t::has_specialized_iter,
00067                 typename in_t::has_specialized_iter>::exec(out, in_out);
00068 
00069 }
00070 
00074 
00075 template<class F, class A1, class A2,
00076 class O_ITER_1, class I_ITER_1>
00077 inline
00078 void loop_base<3, F, A1, A2,
00079         ivl::data::seq_optimal_tag, ivl::data::seq_optimal_tag,
00080         types::t_false, types::t_false,
00081         O_ITER_1, I_ITER_1, types::term, types::term>
00082         ::
00083         exec(A1& out, A2& in_out)
00084 {
00085         O_ITER_1 o = out.begin();
00086         I_ITER_1 i = in_out.begin();
00087         I_ITER_1 e = in_out.end();
00088         while(i != e) {
00089                 F::elem_op(*o, *i);
00090                 ++o;
00091                 ++i;
00092         }
00093 }
00094 
00095 
00096 template<class F, class A1, class A2>
00097 struct mt_loop_rnd_op
00098 {
00099         static void* op(void* ptr)
00100         {
00101 #if defined(_MSC_VER) || defined(WIN32)
00102 
00103 #else
00104                 A1* a1;
00105                 A2* a2;
00106                 size_t start;
00107                 size_t end;
00108                 ((internal::tuple<A1*, A2*, size_t, size_t>*)ptr)->
00109                         get(a1, a2, start, end);
00110                 for(; start != end; start++)
00111                         F::elem_op((*a1)[start], (*a2)[start]);
00112                 pthread_exit(0);
00113 #endif
00114         }
00115 };
00116 
00117 template<class F, class A1, class A2,
00118 class O_ITER_1, class I_ITER_1>
00119 inline void mt_loop_rnd(A1& out, A2& in_out)
00120 {
00121 #if defined(_MSC_VER) || defined(WIN32)
00122         size_t len = in_out.length();
00123         for(size_t i = 0; i < len; i++) {
00124                 F::elem_op(out[i], in_out[i]);
00125         }
00126 #else
00127         typedef internal::tuple<A1*, A2*, size_t, size_t> tpl_t;
00128 
00129         size_t n = in_out.length() / 2;
00130         if(n > 10) n = 10;
00131         size_t step = in_out.length() / n;
00132 
00133         size_t start = 0;
00134         size_t end = step;
00135         tpl_t* dt = new tpl_t[n];
00136         pthread_t* th = new pthread_t[n];
00137 
00138         for(size_t i = 0; i < n; i++)
00139         {
00140                 dt[i].v1 = &out;
00141                 dt[i].v2 = &in_out;
00142                 dt[i].v3 = start;
00143                 dt[i].v4 = end;
00144                 pthread_create(&(th[i]), NULL, mt_loop_rnd_op<F, A1, A2>::op, &(dt[i]));
00145 
00146                 start = end;
00147                 end += step;
00148         }
00149         for(size_t i = 0; i < n; i++)
00150                 pthread_join(th[i], NULL);
00151 
00152         delete[] dt;
00153         delete[] th;
00154 #endif
00155 }
00156 
00158 template<class F, class A1, class A2,
00159 class O_ITER_1, class I_ITER_1>
00160 inline
00161 void loop_base<3, F, A1, A2,
00162         ivl::data::random_optimal_tag, ivl::data::random_optimal_tag,
00163         types::t_false, types::t_false,
00164         O_ITER_1, I_ITER_1, types::term, types::term>
00165         ::
00166         exec(A1& out, A2& in_out)
00167 {
00168         #define IVL_MT
00169         #ifdef IVL_MT
00170         if(A1::optimal_access_cost::value + A2::optimal_access_cost::value > 20)
00171         {
00172                 size_t c = A1::optimal_access_cost::value
00173                         + A2::optimal_access_cost::value;
00174                 if(c * in_out.length() > 2000 && in_out.length() > 1) {
00175                         mt_loop_rnd<F, A1, A2, O_ITER_1, I_ITER_1>(out, in_out);
00176                         return;
00177                 }
00178         }
00179         #endif
00180         size_t len = in_out.length();
00181         for(size_t i = 0; i < len; i++) {
00182                 F::elem_op(out[i], in_out[i]);
00183         }
00184 }
00185 
00186 
00187 } /* namespace loops */
00188 
00189 } /* namespace ivl */
00190 
00191 #endif // IVL_CORE_DETAILS_LOOPS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations