ivl 679
|
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