ViennaCL - The Vienna Computing Library
1.5.1
|
00001 #ifndef VIENNACL_LINALG_DETAIL_ILU_COMMON_HPP_ 00002 #define VIENNACL_LINALG_DETAIL_ILU_COMMON_HPP_ 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2014, 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 00025 #include <vector> 00026 #include <cmath> 00027 #include <iostream> 00028 #include <map> 00029 #include <list> 00030 00031 #include "viennacl/forwards.h" 00032 #include "viennacl/tools/tools.hpp" 00033 #include "viennacl/backend/memory.hpp" 00034 00035 #include "viennacl/linalg/host_based/common.hpp" 00036 #include "viennacl/linalg/misc_operations.hpp" 00037 00038 namespace viennacl 00039 { 00040 namespace linalg 00041 { 00042 namespace detail 00043 { 00044 00045 00046 // 00047 // Level Scheduling Setup for ILU: 00048 // 00049 00050 template <typename ScalarType, unsigned int ALIGNMENT> 00051 void level_scheduling_setup_impl(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU, 00052 vector<ScalarType> const & diagonal_LU, 00053 std::list< viennacl::backend::mem_handle > & row_index_arrays, 00054 std::list< viennacl::backend::mem_handle > & row_buffers, 00055 std::list< viennacl::backend::mem_handle > & col_buffers, 00056 std::list< viennacl::backend::mem_handle > & element_buffers, 00057 std::list< vcl_size_t > & row_elimination_num_list, 00058 bool setup_U) 00059 { 00060 ScalarType const * diagonal_buf = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(diagonal_LU.handle()); 00061 ScalarType const * elements = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(LU.handle()); 00062 unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle1()); 00063 unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle2()); 00064 00065 // 00066 // Step 1: Determine row elimination order for each row and build up meta information about the number of entries taking part in each elimination step: 00067 // 00068 std::vector<vcl_size_t> row_elimination(LU.size1()); 00069 std::map<vcl_size_t, std::map<vcl_size_t, vcl_size_t> > row_entries_per_elimination_step; 00070 00071 vcl_size_t max_elimination_runs = 0; 00072 for (vcl_size_t row2 = 0; row2 < LU.size1(); ++row2) 00073 { 00074 vcl_size_t row = setup_U ? (LU.size1() - row2) - 1 : row2; 00075 00076 vcl_size_t row_begin = row_buffer[row]; 00077 vcl_size_t row_end = row_buffer[row+1]; 00078 vcl_size_t elimination_index = 0; //Note: first run corresponds to elimination_index = 1 (otherwise, type issues with int <-> unsigned int would arise 00079 for (vcl_size_t i = row_begin; i < row_end; ++i) 00080 { 00081 unsigned int col = col_buffer[i]; 00082 if ( (!setup_U && col < row) || (setup_U && col > row) ) 00083 { 00084 elimination_index = std::max<vcl_size_t>(elimination_index, row_elimination[col]); 00085 row_entries_per_elimination_step[row_elimination[col]][row] += 1; 00086 } 00087 } 00088 row_elimination[row] = elimination_index + 1; 00089 max_elimination_runs = std::max<vcl_size_t>(max_elimination_runs, elimination_index + 1); 00090 } 00091 00092 //std::cout << "Number of elimination runs: " << max_elimination_runs << std::endl; 00093 00094 // 00095 // Step 2: Build row-major elimination matrix for each elimination step 00096 // 00097 00098 //std::cout << "Elimination order: " << std::endl; 00099 //for (vcl_size_t i=0; i<row_elimination.size(); ++i) 00100 // std::cout << row_elimination[i] << ", "; 00101 //std::cout << std::endl; 00102 00103 //vcl_size_t summed_rows = 0; 00104 for (vcl_size_t elimination_run = 1; elimination_run <= max_elimination_runs; ++elimination_run) 00105 { 00106 std::map<vcl_size_t, vcl_size_t> const & current_elimination_info = row_entries_per_elimination_step[elimination_run]; 00107 00108 // count cols and entries handled in this elimination step 00109 vcl_size_t num_tainted_cols = current_elimination_info.size(); 00110 vcl_size_t num_entries = 0; 00111 00112 for (std::map<vcl_size_t, vcl_size_t>::const_iterator it = current_elimination_info.begin(); 00113 it != current_elimination_info.end(); 00114 ++it) 00115 num_entries += it->second; 00116 00117 //std::cout << "num_entries: " << num_entries << std::endl; 00118 //std::cout << "num_tainted_cols: " << num_tainted_cols << std::endl; 00119 00120 if (num_tainted_cols > 0) 00121 { 00122 row_index_arrays.push_back(viennacl::backend::mem_handle()); 00123 viennacl::backend::switch_memory_context<unsigned int>(row_index_arrays.back(), viennacl::traits::context(LU)); 00124 viennacl::backend::typesafe_host_array<unsigned int> elim_row_index_array(row_index_arrays.back(), num_tainted_cols); 00125 00126 row_buffers.push_back(viennacl::backend::mem_handle()); 00127 viennacl::backend::switch_memory_context<unsigned int>(row_buffers.back(), viennacl::traits::context(LU)); 00128 viennacl::backend::typesafe_host_array<unsigned int> elim_row_buffer(row_buffers.back(), num_tainted_cols + 1); 00129 00130 col_buffers.push_back(viennacl::backend::mem_handle()); 00131 viennacl::backend::switch_memory_context<unsigned int>(col_buffers.back(), viennacl::traits::context(LU)); 00132 viennacl::backend::typesafe_host_array<unsigned int> elim_col_buffer(col_buffers.back(), num_entries); 00133 00134 element_buffers.push_back(viennacl::backend::mem_handle()); 00135 viennacl::backend::switch_memory_context<ScalarType>(element_buffers.back(), viennacl::traits::context(LU)); 00136 std::vector<ScalarType> elim_elements_buffer(num_entries); 00137 00138 row_elimination_num_list.push_back(num_tainted_cols); 00139 00140 vcl_size_t k=0; 00141 vcl_size_t nnz_index = 0; 00142 elim_row_buffer.set(0, 0); 00143 00144 for (std::map<vcl_size_t, vcl_size_t>::const_iterator it = current_elimination_info.begin(); 00145 it != current_elimination_info.end(); 00146 ++it) 00147 { 00148 //vcl_size_t col = setup_U ? (elimination_matrix.size() - it->first) - 1 : col2; 00149 vcl_size_t row = it->first; 00150 elim_row_index_array.set(k, row); 00151 00152 vcl_size_t row_begin = row_buffer[row]; 00153 vcl_size_t row_end = row_buffer[row+1]; 00154 for (vcl_size_t i = row_begin; i < row_end; ++i) 00155 { 00156 unsigned int col = col_buffer[i]; 00157 if ( (!setup_U && col < row) || (setup_U && col > row) ) //entry of L/U 00158 { 00159 if (row_elimination[col] == elimination_run) // this entry is substituted in this run 00160 { 00161 elim_col_buffer.set(nnz_index, col); 00162 elim_elements_buffer[nnz_index] = setup_U ? elements[i] / diagonal_buf[it->first] : elements[i]; 00163 ++nnz_index; 00164 } 00165 } 00166 } 00167 00168 elim_row_buffer.set(++k, nnz_index); 00169 } 00170 00171 // 00172 // Wrap in memory_handles: 00173 // 00174 viennacl::backend::memory_create(row_index_arrays.back(), elim_row_index_array.raw_size(), viennacl::traits::context(row_index_arrays.back()), elim_row_index_array.get()); 00175 viennacl::backend::memory_create(row_buffers.back(), elim_row_buffer.raw_size(), viennacl::traits::context(row_buffers.back()), elim_row_buffer.get()); 00176 viennacl::backend::memory_create(col_buffers.back(), elim_col_buffer.raw_size(), viennacl::traits::context(col_buffers.back()), elim_col_buffer.get()); 00177 viennacl::backend::memory_create(element_buffers.back(), sizeof(ScalarType) * elim_elements_buffer.size(), viennacl::traits::context(element_buffers.back()), &(elim_elements_buffer[0])); 00178 } 00179 00180 // Print some info: 00181 //std::cout << "Eliminated columns in run " << elimination_run << ": " << num_tainted_cols << " (tainted columns: " << num_tainted_cols << ")" << std::endl; 00182 //summed_rows += eliminated_rows_in_run; 00183 //if (eliminated_rows_in_run == 0) 00184 // break; 00185 } 00186 //std::cout << "Eliminated rows: " << summed_rows << " out of " << row_elimination.size() << std::endl; 00187 } 00188 00189 00190 template <typename ScalarType, unsigned int ALIGNMENT> 00191 void level_scheduling_setup_L(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU, 00192 vector<ScalarType> const & diagonal_LU, 00193 std::list< viennacl::backend::mem_handle > & row_index_arrays, 00194 std::list< viennacl::backend::mem_handle > & row_buffers, 00195 std::list< viennacl::backend::mem_handle > & col_buffers, 00196 std::list< viennacl::backend::mem_handle > & element_buffers, 00197 std::list< vcl_size_t > & row_elimination_num_list) 00198 { 00199 level_scheduling_setup_impl(LU, diagonal_LU, row_index_arrays, row_buffers, col_buffers, element_buffers, row_elimination_num_list, false); 00200 } 00201 00202 00203 // 00204 // Multifrontal setup of U: 00205 // 00206 00207 template <typename ScalarType, unsigned int ALIGNMENT> 00208 void level_scheduling_setup_U(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU, 00209 vector<ScalarType> const & diagonal_LU, 00210 std::list< viennacl::backend::mem_handle > & row_index_arrays, 00211 std::list< viennacl::backend::mem_handle > & row_buffers, 00212 std::list< viennacl::backend::mem_handle > & col_buffers, 00213 std::list< viennacl::backend::mem_handle > & element_buffers, 00214 std::list< vcl_size_t > & row_elimination_num_list) 00215 { 00216 level_scheduling_setup_impl(LU, diagonal_LU, row_index_arrays, row_buffers, col_buffers, element_buffers, row_elimination_num_list, true); 00217 } 00218 00219 00220 // 00221 // Multifrontal substitution (both L and U). Will partly be moved to single_threaded/opencl/cuda implementations 00222 // 00223 template <typename ScalarType> 00224 void level_scheduling_substitute(vector<ScalarType> & vec, 00225 std::list< viennacl::backend::mem_handle > const & row_index_arrays, 00226 std::list< viennacl::backend::mem_handle > const & row_buffers, 00227 std::list< viennacl::backend::mem_handle > const & col_buffers, 00228 std::list< viennacl::backend::mem_handle > const & element_buffers, 00229 std::list< vcl_size_t > const & row_elimination_num_list) 00230 { 00231 typedef typename std::list< viennacl::backend::mem_handle >::const_iterator ListIterator; 00232 ListIterator row_index_array_it = row_index_arrays.begin(); 00233 ListIterator row_buffers_it = row_buffers.begin(); 00234 ListIterator col_buffers_it = col_buffers.begin(); 00235 ListIterator element_buffers_it = element_buffers.begin(); 00236 typename std::list< vcl_size_t>::const_iterator row_elimination_num_it = row_elimination_num_list.begin(); 00237 for (vcl_size_t i=0; i<row_index_arrays.size(); ++i) 00238 { 00239 viennacl::linalg::detail::level_scheduling_substitute(vec, *row_index_array_it, *row_buffers_it, *col_buffers_it, *element_buffers_it, *row_elimination_num_it); 00240 00241 ++row_index_array_it; 00242 ++row_buffers_it; 00243 ++col_buffers_it; 00244 ++element_buffers_it; 00245 ++row_elimination_num_it; 00246 } 00247 } 00248 00249 00250 00251 00252 00253 } // namespace detail 00254 } // namespace linalg 00255 } // namespace viennacl 00256 00257 00258 00259 00260 #endif 00261 00262 00263