11use std:: collections:: { HashMap , HashSet } ;
22use std:: sync:: { Arc , Mutex } ;
33
4- use faer:: sparse:: SparseColMat ;
4+ use faer:: sparse:: { SparseColMat , SymbolicSparseColMat , ValuesOrder } ;
55use faer_ext:: IntoFaer ;
66use nalgebra as na;
77use rayon:: prelude:: * ;
@@ -24,8 +24,12 @@ impl Default for Problem {
2424 }
2525}
2626
27- /// (col idx in matrix, row idx in matrix, value)
28- type JacobianValue = ( usize , usize , f64 ) ;
27+ pub struct SymbolicStructure {
28+ pattern : SymbolicSparseColMat < usize > ,
29+ order : ValuesOrder < usize > ,
30+ }
31+
32+ type JacobianValue = f64 ;
2933
3034impl Problem {
3135 pub fn new ( ) -> Problem {
@@ -39,6 +43,51 @@ impl Problem {
3943 }
4044 }
4145
46+ pub fn build_symbolic_structure (
47+ & self ,
48+ parameter_blocks : & HashMap < String , ParameterBlock > ,
49+ total_variable_dimension : usize ,
50+ variable_name_to_col_idx_dict : & HashMap < String , usize > ,
51+ ) -> SymbolicStructure {
52+ let mut indices = Vec :: < ( usize , usize ) > :: new ( ) ;
53+
54+ self . residual_blocks . iter ( ) . for_each ( |( _, residual_block) | {
55+ let mut variable_local_idx_size_list = Vec :: < ( usize , usize ) > :: new ( ) ;
56+ let mut count_variable_local_idx: usize = 0 ;
57+ for var_key in & residual_block. variable_key_list {
58+ if let Some ( param) = parameter_blocks. get ( var_key) {
59+ variable_local_idx_size_list
60+ . push ( ( count_variable_local_idx, param. tangent_size ( ) ) ) ;
61+ count_variable_local_idx += param. tangent_size ( ) ;
62+ } ;
63+ }
64+ for ( i, var_key) in residual_block. variable_key_list . iter ( ) . enumerate ( ) {
65+ if let Some ( variable_global_idx) = variable_name_to_col_idx_dict. get ( var_key) {
66+ let ( _, var_size) = variable_local_idx_size_list[ i] ;
67+ for row_idx in 0 ..residual_block. dim_residual {
68+ for col_idx in 0 ..var_size {
69+ let global_row_idx = residual_block. residual_row_start_idx + row_idx;
70+ let global_col_idx = variable_global_idx + col_idx;
71+ indices. push ( ( global_row_idx, global_col_idx) ) ;
72+ }
73+ }
74+ }
75+ }
76+ } ) ;
77+ let start = std:: time:: Instant :: now ( ) ;
78+ let ( s, o) = SymbolicSparseColMat :: try_new_from_indices (
79+ self . total_residual_dimension ,
80+ total_variable_dimension,
81+ & indices,
82+ )
83+ . unwrap ( ) ;
84+ log:: trace!( "Built symbolic matrix: {:?}" , start. elapsed( ) ) ;
85+ SymbolicStructure {
86+ pattern : s,
87+ order : o,
88+ }
89+ }
90+
4291 pub fn get_variable_name_to_col_idx_dict (
4392 & self ,
4493 parameter_blocks : & HashMap < String , ParameterBlock > ,
@@ -147,16 +196,14 @@ impl Problem {
147196 let total_residual = Arc :: new ( Mutex :: new ( na:: DVector :: < f64 > :: zeros (
148197 self . total_residual_dimension ,
149198 ) ) ) ;
150- self . residual_blocks
151- . par_iter ( )
152- . for_each ( |( _, residual_block) | {
153- self . compute_residual_impl (
154- residual_block,
155- parameter_blocks,
156- & total_residual,
157- with_loss_fn,
158- )
159- } ) ;
199+ self . residual_blocks . iter ( ) . for_each ( |( _, residual_block) | {
200+ self . compute_residual_impl (
201+ residual_block,
202+ parameter_blocks,
203+ & total_residual,
204+ with_loss_fn,
205+ )
206+ } ) ;
160207 let total_residual = Arc :: try_unwrap ( total_residual)
161208 . unwrap ( )
162209 . into_inner ( )
@@ -170,42 +217,46 @@ impl Problem {
170217 parameter_blocks : & HashMap < String , ParameterBlock > ,
171218 variable_name_to_col_idx_dict : & HashMap < String , usize > ,
172219 total_variable_dimension : usize ,
220+ symbolic_structure : & SymbolicStructure ,
173221 ) -> ( faer:: Mat < f64 > , SparseColMat < usize , f64 > ) {
174222 // multi
175223 let total_residual = Arc :: new ( Mutex :: new ( na:: DVector :: < f64 > :: zeros (
176224 self . total_residual_dimension ,
177225 ) ) ) ;
178- let jacobian_list = Arc :: new ( Mutex :: new ( Vec :: < JacobianValue > :: new ( ) ) ) ;
179226
180- self . residual_blocks
227+ let mut start = std:: time:: Instant :: now ( ) ;
228+ let jacobian_lists: Vec < JacobianValue > = self
229+ . residual_blocks
181230 . par_iter ( )
182- . for_each ( |( _, residual_block) | {
231+ . map ( |( _, residual_block) | {
183232 self . compute_residual_and_jacobian_impl (
184233 residual_block,
185234 parameter_blocks,
186235 variable_name_to_col_idx_dict,
187236 & total_residual,
188- & jacobian_list,
189237 )
190- } ) ;
238+ } )
239+ . flatten ( )
240+ . collect ( ) ;
191241
242+ log:: debug!( "compute_residual_and_jacobian_impl: {:?}, total_variable_dim: {:?}, total_residual: {:?}" , start. elapsed( ) , total_variable_dimension, self . total_residual_dimension) ;
243+ start = std:: time:: Instant :: now ( ) ;
192244 let total_residual = Arc :: try_unwrap ( total_residual)
193245 . unwrap ( )
194246 . into_inner ( )
195247 . unwrap ( ) ;
196- let jacobian_list = Arc :: try_unwrap ( jacobian_list)
197- . unwrap ( )
198- . into_inner ( )
199- . unwrap ( ) ;
200- // end
201248
202249 let residual_faer = total_residual. view_range ( .., ..) . into_faer ( ) . to_owned ( ) ;
203- let jacobian_faer = SparseColMat :: try_new_from_triplets (
204- self . total_residual_dimension ,
205- total_variable_dimension,
206- & jacobian_list,
250+ log:: debug!( "residual_faer: {:?}" , start. elapsed( ) ) ;
251+ start = std:: time:: Instant :: now ( ) ;
252+ let jacobian_faer = SparseColMat :: new_from_order_and_values (
253+ symbolic_structure. pattern . clone ( ) ,
254+ & symbolic_structure. order ,
255+ jacobian_lists. as_slice ( ) ,
207256 )
208257 . unwrap ( ) ;
258+ log:: debug!( "jacobian_faer: {:?}" , start. elapsed( ) ) ;
259+ //log::debug!("rest of the function: {:?}", start.elapsed());
209260 ( residual_faer, jacobian_faer)
210261 }
211262
@@ -241,8 +292,7 @@ impl Problem {
241292 parameter_blocks : & HashMap < String , ParameterBlock > ,
242293 variable_name_to_col_idx_dict : & HashMap < String , usize > ,
243294 total_residual : & Arc < Mutex < na:: DVector < f64 > > > ,
244- jacobian_list : & Arc < Mutex < Vec < JacobianValue > > > ,
245- ) {
295+ ) -> Vec < JacobianValue > {
246296 let mut params = Vec :: new ( ) ;
247297 let mut variable_local_idx_size_list = Vec :: < ( usize , usize ) > :: new ( ) ;
248298 let mut count_variable_local_idx: usize = 0 ;
@@ -264,22 +314,25 @@ impl Problem {
264314 . copy_from ( & res) ;
265315 }
266316
317+ let mut local_jacobian_list = Vec :: new ( ) ;
318+
267319 for ( i, var_key) in residual_block. variable_key_list . iter ( ) . enumerate ( ) {
268- if let Some ( variable_global_idx ) = variable_name_to_col_idx_dict. get ( var_key) {
320+ if variable_name_to_col_idx_dict. contains_key ( var_key) {
269321 let ( variable_local_idx, var_size) = variable_local_idx_size_list[ i] ;
270322 let variable_jac = jac. view ( ( 0 , variable_local_idx) , ( jac. shape ( ) . 0 , var_size) ) ;
271- let mut local_jacobian_list = Vec :: new ( ) ;
272323 for row_idx in 0 ..jac. shape ( ) . 0 {
273324 for col_idx in 0 ..var_size {
274- let global_row_idx = residual_block. residual_row_start_idx + row_idx;
275- let global_col_idx = variable_global_idx + col_idx;
276- let value = variable_jac[ ( row_idx, col_idx) ] ;
277- local_jacobian_list. push ( ( global_row_idx, global_col_idx, value) ) ;
325+ local_jacobian_list. push ( variable_jac[ ( row_idx, col_idx) ] ) ;
278326 }
279327 }
280- let mut jacobian_list = jacobian_list. lock ( ) . unwrap ( ) ;
281- jacobian_list. extend ( local_jacobian_list) ;
328+ } else {
329+ panic ! (
330+ "Missing key {} in variable-to-column-index mapping" ,
331+ var_key
332+ ) ;
282333 }
283334 }
335+
336+ local_jacobian_list
284337 }
285338}
0 commit comments