ViennaCL - The Vienna Computing Library
1.5.2
|
00001 00002 #ifndef VIENNACL_LINALG_DETAIL_ILU0_HPP_ 00003 #define VIENNACL_LINALG_DETAIL_ILU0_HPP_ 00004 00005 /* ========================================================================= 00006 Copyright (c) 2010-2014, Institute for Microelectronics, 00007 Institute for Analysis and Scientific Computing, 00008 TU Wien. 00009 Portions of this software are copyright by UChicago Argonne, LLC. 00010 00011 ----------------- 00012 ViennaCL - The Vienna Computing Library 00013 ----------------- 00014 00015 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00016 00017 (A list of authors and contributors can be found in the PDF manual) 00018 00019 License: MIT (X11), see file LICENSE in the base directory 00020 ============================================================================= */ 00021 00039 #include <vector> 00040 #include <cmath> 00041 #include <iostream> 00042 #include "viennacl/forwards.h" 00043 #include "viennacl/tools/tools.hpp" 00044 #include "viennacl/linalg/detail/ilu/common.hpp" 00045 #include "viennacl/compressed_matrix.hpp" 00046 #include "viennacl/backend/memory.hpp" 00047 00048 #include "viennacl/linalg/host_based/common.hpp" 00049 00050 #include <map> 00051 00052 namespace viennacl 00053 { 00054 namespace linalg 00055 { 00056 00059 class ilu0_tag 00060 { 00061 public: 00062 ilu0_tag(bool with_level_scheduling = false) : use_level_scheduling_(with_level_scheduling) {} 00063 00064 bool use_level_scheduling() const { return use_level_scheduling_; } 00065 void use_level_scheduling(bool b) { use_level_scheduling_ = b; } 00066 00067 private: 00068 bool use_level_scheduling_; 00069 }; 00070 00071 00078 template<typename ScalarType> 00079 void precondition(viennacl::compressed_matrix<ScalarType> & A, ilu0_tag const & /* tag */) 00080 { 00081 assert( (A.handle1().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") ); 00082 assert( (A.handle2().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") ); 00083 assert( (A.handle().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") ); 00084 00085 ScalarType * elements = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(A.handle()); 00086 unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle1()); 00087 unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle2()); 00088 00089 // Note: Line numbers in the following refer to the algorithm in Saad's book 00090 00091 for (vcl_size_t i=1; i<A.size1(); ++i) // Line 1 00092 { 00093 unsigned int row_i_begin = row_buffer[i]; 00094 unsigned int row_i_end = row_buffer[i+1]; 00095 for (unsigned int buf_index_k = row_i_begin; buf_index_k < row_i_end; ++buf_index_k) //Note: We do not assume that the column indices within a row are sorted 00096 { 00097 unsigned int k = col_buffer[buf_index_k]; 00098 if (k >= i) 00099 continue; //Note: We do not assume that the column indices within a row are sorted 00100 00101 unsigned int row_k_begin = row_buffer[k]; 00102 unsigned int row_k_end = row_buffer[k+1]; 00103 00104 // get a_kk: 00105 ScalarType a_kk = 0; 00106 for (unsigned int buf_index_akk = row_k_begin; buf_index_akk < row_k_end; ++buf_index_akk) 00107 { 00108 if (col_buffer[buf_index_akk] == k) 00109 { 00110 a_kk = elements[buf_index_akk]; 00111 break; 00112 } 00113 } 00114 00115 ScalarType & a_ik = elements[buf_index_k]; 00116 a_ik /= a_kk; //Line 3 00117 00118 for (unsigned int buf_index_j = row_i_begin; buf_index_j < row_i_end; ++buf_index_j) //Note: We do not assume that the column indices within a row are sorted 00119 { 00120 unsigned int j = col_buffer[buf_index_j]; 00121 if (j <= k) 00122 continue; 00123 00124 // determine a_kj: 00125 ScalarType a_kj = 0; 00126 for (unsigned int buf_index_akj = row_k_begin; buf_index_akj < row_k_end; ++buf_index_akj) 00127 { 00128 if (col_buffer[buf_index_akj] == j) 00129 { 00130 a_kk = elements[buf_index_akj]; 00131 break; 00132 } 00133 } 00134 00135 //a_ij -= a_ik * a_kj 00136 elements[buf_index_j] -= a_ik * a_kj; //Line 5 00137 } 00138 } 00139 } 00140 00141 } 00142 00143 00146 template <typename MatrixType> 00147 class ilu0_precond 00148 { 00149 typedef typename MatrixType::value_type ScalarType; 00150 00151 public: 00152 ilu0_precond(MatrixType const & mat, ilu0_tag const & tag) : tag_(tag), LU() 00153 { 00154 //initialize preconditioner: 00155 //std::cout << "Start CPU precond" << std::endl; 00156 init(mat); 00157 //std::cout << "End CPU precond" << std::endl; 00158 } 00159 00160 template <typename VectorType> 00161 void apply(VectorType & vec) const 00162 { 00163 unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle1()); 00164 unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle2()); 00165 ScalarType const * elements = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(LU.handle()); 00166 00167 viennacl::linalg::host_based::detail::csr_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LU.size2(), unit_lower_tag()); 00168 viennacl::linalg::host_based::detail::csr_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LU.size2(), upper_tag()); 00169 } 00170 00171 private: 00172 void init(MatrixType const & mat) 00173 { 00174 viennacl::context host_context(viennacl::MAIN_MEMORY); 00175 viennacl::switch_memory_context(LU, host_context); 00176 00177 viennacl::copy(mat, LU); 00178 viennacl::linalg::precondition(LU, tag_); 00179 } 00180 00181 ilu0_tag const & tag_; 00182 00183 viennacl::compressed_matrix<ScalarType> LU; 00184 }; 00185 00186 00191 template <typename ScalarType, unsigned int MAT_ALIGNMENT> 00192 class ilu0_precond< compressed_matrix<ScalarType, MAT_ALIGNMENT> > 00193 { 00194 typedef compressed_matrix<ScalarType, MAT_ALIGNMENT> MatrixType; 00195 00196 public: 00197 ilu0_precond(MatrixType const & mat, ilu0_tag const & tag) : tag_(tag), LU(mat.size1(), mat.size2()) 00198 { 00199 //initialize preconditioner: 00200 //std::cout << "Start GPU precond" << std::endl; 00201 init(mat); 00202 //std::cout << "End GPU precond" << std::endl; 00203 } 00204 00205 void apply(vector<ScalarType> & vec) const 00206 { 00207 viennacl::context host_context(viennacl::MAIN_MEMORY); 00208 if (vec.handle().get_active_handle_id() != viennacl::MAIN_MEMORY) 00209 { 00210 if (tag_.use_level_scheduling()) 00211 { 00212 //std::cout << "Using multifrontal on GPU..." << std::endl; 00213 detail::level_scheduling_substitute(vec, 00214 multifrontal_L_row_index_arrays_, 00215 multifrontal_L_row_buffers_, 00216 multifrontal_L_col_buffers_, 00217 multifrontal_L_element_buffers_, 00218 multifrontal_L_row_elimination_num_list_); 00219 00220 vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_); 00221 00222 detail::level_scheduling_substitute(vec, 00223 multifrontal_U_row_index_arrays_, 00224 multifrontal_U_row_buffers_, 00225 multifrontal_U_col_buffers_, 00226 multifrontal_U_element_buffers_, 00227 multifrontal_U_row_elimination_num_list_); 00228 } 00229 else 00230 { 00231 viennacl::context old_context = viennacl::traits::context(vec); 00232 viennacl::switch_memory_context(vec, host_context); 00233 viennacl::linalg::inplace_solve(LU, vec, unit_lower_tag()); 00234 viennacl::linalg::inplace_solve(LU, vec, upper_tag()); 00235 viennacl::switch_memory_context(vec, old_context); 00236 } 00237 } 00238 else //apply ILU0 directly on CPU 00239 { 00240 if (tag_.use_level_scheduling()) 00241 { 00242 //std::cout << "Using multifrontal..." << std::endl; 00243 detail::level_scheduling_substitute(vec, 00244 multifrontal_L_row_index_arrays_, 00245 multifrontal_L_row_buffers_, 00246 multifrontal_L_col_buffers_, 00247 multifrontal_L_element_buffers_, 00248 multifrontal_L_row_elimination_num_list_); 00249 00250 vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_); 00251 00252 detail::level_scheduling_substitute(vec, 00253 multifrontal_U_row_index_arrays_, 00254 multifrontal_U_row_buffers_, 00255 multifrontal_U_col_buffers_, 00256 multifrontal_U_element_buffers_, 00257 multifrontal_U_row_elimination_num_list_); 00258 } 00259 else 00260 { 00261 viennacl::linalg::inplace_solve(LU, vec, unit_lower_tag()); 00262 viennacl::linalg::inplace_solve(LU, vec, upper_tag()); 00263 } 00264 } 00265 } 00266 00267 vcl_size_t levels() const { return multifrontal_L_row_index_arrays_.size(); } 00268 00269 private: 00270 void init(MatrixType const & mat) 00271 { 00272 viennacl::context host_context(viennacl::MAIN_MEMORY); 00273 viennacl::switch_memory_context(LU, host_context); 00274 LU = mat; 00275 viennacl::linalg::precondition(LU, tag_); 00276 00277 if (!tag_.use_level_scheduling()) 00278 return; 00279 00280 // multifrontal part: 00281 viennacl::switch_memory_context(multifrontal_U_diagonal_, host_context); 00282 multifrontal_U_diagonal_.resize(LU.size1(), false); 00283 host_based::detail::row_info(LU, multifrontal_U_diagonal_, viennacl::linalg::detail::SPARSE_ROW_DIAGONAL); 00284 00285 detail::level_scheduling_setup_L(LU, 00286 multifrontal_U_diagonal_, //dummy 00287 multifrontal_L_row_index_arrays_, 00288 multifrontal_L_row_buffers_, 00289 multifrontal_L_col_buffers_, 00290 multifrontal_L_element_buffers_, 00291 multifrontal_L_row_elimination_num_list_); 00292 00293 00294 detail::level_scheduling_setup_U(LU, 00295 multifrontal_U_diagonal_, 00296 multifrontal_U_row_index_arrays_, 00297 multifrontal_U_row_buffers_, 00298 multifrontal_U_col_buffers_, 00299 multifrontal_U_element_buffers_, 00300 multifrontal_U_row_elimination_num_list_); 00301 00302 // 00303 // Bring to device if necessary: 00304 // 00305 00306 // L: 00307 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_row_index_arrays_.begin(); 00308 it != multifrontal_L_row_index_arrays_.end(); 00309 ++it) 00310 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00311 00312 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_row_buffers_.begin(); 00313 it != multifrontal_L_row_buffers_.end(); 00314 ++it) 00315 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00316 00317 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_col_buffers_.begin(); 00318 it != multifrontal_L_col_buffers_.end(); 00319 ++it) 00320 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00321 00322 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_element_buffers_.begin(); 00323 it != multifrontal_L_element_buffers_.end(); 00324 ++it) 00325 viennacl::backend::switch_memory_context<ScalarType>(*it, viennacl::traits::context(mat)); 00326 00327 00328 // U: 00329 00330 viennacl::switch_memory_context(multifrontal_U_diagonal_, viennacl::traits::context(mat)); 00331 00332 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_row_index_arrays_.begin(); 00333 it != multifrontal_U_row_index_arrays_.end(); 00334 ++it) 00335 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00336 00337 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_row_buffers_.begin(); 00338 it != multifrontal_U_row_buffers_.end(); 00339 ++it) 00340 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00341 00342 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_col_buffers_.begin(); 00343 it != multifrontal_U_col_buffers_.end(); 00344 ++it) 00345 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat)); 00346 00347 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_element_buffers_.begin(); 00348 it != multifrontal_U_element_buffers_.end(); 00349 ++it) 00350 viennacl::backend::switch_memory_context<ScalarType>(*it, viennacl::traits::context(mat)); 00351 00352 } 00353 00354 ilu0_tag const & tag_; 00355 viennacl::compressed_matrix<ScalarType> LU; 00356 00357 std::list< viennacl::backend::mem_handle > multifrontal_L_row_index_arrays_; 00358 std::list< viennacl::backend::mem_handle > multifrontal_L_row_buffers_; 00359 std::list< viennacl::backend::mem_handle > multifrontal_L_col_buffers_; 00360 std::list< viennacl::backend::mem_handle > multifrontal_L_element_buffers_; 00361 std::list< vcl_size_t > multifrontal_L_row_elimination_num_list_; 00362 00363 viennacl::vector<ScalarType> multifrontal_U_diagonal_; 00364 std::list< viennacl::backend::mem_handle > multifrontal_U_row_index_arrays_; 00365 std::list< viennacl::backend::mem_handle > multifrontal_U_row_buffers_; 00366 std::list< viennacl::backend::mem_handle > multifrontal_U_col_buffers_; 00367 std::list< viennacl::backend::mem_handle > multifrontal_U_element_buffers_; 00368 std::list< vcl_size_t > multifrontal_U_row_elimination_num_list_; 00369 00370 }; 00371 00372 } 00373 } 00374 00375 00376 00377 00378 #endif 00379 00380 00381