Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optims to detect when SoA matrices can be used #955

Merged
merged 96 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
47a5c3d
start adding optimize_soa
SteveBronder Aug 17, 2021
be78db7
adds read and declaring var_matrix types
SteveBronder Aug 24, 2021
d3f80af
Adds catches for explicit template return type in needed functions
SteveBronder Aug 24, 2021
f08b861
turn of kill function for soa so results propogate deeper
SteveBronder Aug 25, 2021
bb98e1d
update test
SteveBronder Aug 26, 2021
86c5bb8
use math library checkers for non parameter constraints
SteveBronder Aug 26, 2021
7b29323
update assignment to do filling dummy variables on one line
SteveBronder Aug 27, 2021
98784bc
format
SteveBronder Aug 27, 2021
ce2791a
fix data in reading
SteveBronder Aug 27, 2021
6fef45a
update data decls
SteveBronder Aug 27, 2021
584f018
fix bad rhs of decl for arrays
SteveBronder Aug 27, 2021
1bf7167
fix checks
SteveBronder Aug 27, 2021
b29a497
force remove of .hpp.gch file
SteveBronder Aug 27, 2021
31d2ab3
format
SteveBronder Aug 27, 2021
c1dca2b
update formatting for printing reads
SteveBronder Aug 27, 2021
25ad68d
trying to fix precompiled header
SteveBronder Aug 28, 2021
a191503
update Jenkins
SteveBronder Aug 28, 2021
4b23b45
trying to turn off precompiled header
SteveBronder Aug 28, 2021
d998ad7
change DEPFLAGS_OS flag to include system headers
SteveBronder Aug 28, 2021
32fa689
revert changes to jenkinsfile
SteveBronder Aug 30, 2021
a00d718
update to only use value_of() for autodiffable types in constraints
SteveBronder Aug 30, 2021
52a0a07
update stan math signatures
SteveBronder Aug 30, 2021
eb36ee3
have the performance tests execute in different folders
SteveBronder Aug 30, 2021
cbe8498
cleanup sh command in jenkins for both
SteveBronder Aug 30, 2021
efe43cb
Update readlink for being in lower folder
SteveBronder Aug 30, 2021
a712982
Update readlink for being in lower folder
SteveBronder Aug 30, 2021
33d1912
Update test folder location for being in lower folder
SteveBronder Aug 30, 2021
4d84486
Update test folder location for being in lower folder
SteveBronder Aug 30, 2021
745463c
force demotion of functions when we have entered a non-supported func…
SteveBronder Aug 30, 2021
3d71d17
remove bad post instruction in jenkins
SteveBronder Aug 31, 2021
778debe
Make the end to end tests their own block
SteveBronder Aug 31, 2021
537394b
update to remove value_of() from checks
SteveBronder Sep 1, 2021
720eea2
update to master and test PR from math
SteveBronder Sep 1, 2021
903fa61
swap order of jenkins nodes
SteveBronder Sep 1, 2021
eafaf87
Merge remote-tracking branch 'upstream/master' into feature/soa-optim
SteveBronder Sep 2, 2021
ee91ba1
update to master
SteveBronder Sep 2, 2021
046145d
Merge remote-tracking branch 'upstream/master' into feature/soa-optim
SteveBronder Sep 8, 2021
3118484
update to master
SteveBronder Sep 8, 2021
ac1964d
update stan math
SteveBronder Sep 8, 2021
29a1cd2
remove query_bad_assign_fun2
SteveBronder Sep 8, 2021
9a5178f
Cleanup function names and docs
SteveBronder Sep 8, 2021
28fc44b
start breaking up tests into smaller examples
SteveBronder Sep 9, 2021
20d8bd0
fix assignment logic for mixes of data and var scalars
SteveBronder Sep 9, 2021
8abd15c
fix assignment logic for mixes of data and var scalars
SteveBronder Sep 9, 2021
2a9a2c1
remove use of special math branch (need to wait for cmdstan to update…
SteveBronder Sep 9, 2021
87b0162
update to master
SteveBronder Sep 14, 2021
7198670
update supported funcs
SteveBronder Sep 15, 2021
9d2b42a
update to_matrix logic
SteveBronder Sep 15, 2021
6bae5f4
remove rep_matrix from available functions
SteveBronder Sep 16, 2021
6493c22
Merge remote-tracking branch 'upstream/master' into feature/soa-optim
SteveBronder Sep 21, 2021
f33599e
fix signature file
SteveBronder Sep 21, 2021
b1eb081
update to master
SteveBronder Sep 21, 2021
3bc1db0
update to master
SteveBronder Sep 27, 2021
be5cabb
update csr_matrix to be varmat compatible
SteveBronder Sep 27, 2021
cc600ac
Merge remote-tracking branch 'upstream/master' into feature/soa-optim
SteveBronder Sep 29, 2021
d3b1581
update docs
SteveBronder Sep 30, 2021
d5e1197
Merge remote-tracking branch 'upstream/master' into feature/soa-optim
SteveBronder Sep 30, 2021
26c08f6
update to master
SteveBronder Oct 1, 2021
3e32a62
update to master
SteveBronder Oct 15, 2021
7cf959c
trying to update logic for handling expressions which do not return S…
SteveBronder Oct 18, 2021
077a005
update to master
SteveBronder Oct 18, 2021
289809a
cleanup logic for checking bad assign exprs
SteveBronder Oct 19, 2021
9e79386
cleanup logic for understanding if a tp can be reused
SteveBronder Oct 19, 2021
58cb966
Remove ternary operator logic for SoA and always go to AoS
SteveBronder Oct 19, 2021
5d086d4
kickoff jenkins
SteveBronder Oct 19, 2021
8f3cd4d
switch back Jenkinsfile to master version
SteveBronder Oct 19, 2021
24c6448
fixup docs
SteveBronder Oct 27, 2021
1cb5be3
update to master
SteveBronder Nov 8, 2021
4395761
update logic for demotion when looking at assignments
SteveBronder Nov 9, 2021
0444cfa
adds an option to turn off SoA optims
SteveBronder Nov 9, 2021
656d3c5
update to new ocaml
SteveBronder Nov 16, 2021
d5833b6
update to master
SteveBronder Nov 19, 2021
db1d461
update with deep_dependence test
SteveBronder Nov 19, 2021
45b744a
update
SteveBronder Nov 19, 2021
335e7a9
update to master
SteveBronder Dec 21, 2021
a3455c9
make format
SteveBronder Dec 21, 2021
b9c7c70
only use forward pass for check
SteveBronder Dec 21, 2021
9db14ae
remove print statements from mother.stan model
SteveBronder Dec 21, 2021
5f774cb
have circular_flowgraph use rev_flowgraph to find the final nodes
SteveBronder Dec 22, 2021
3e92d2b
format
SteveBronder Dec 22, 2021
1a4ee86
Merge branch 'master' into feature/soa-optim
rok-cesnovar Dec 22, 2021
5962159
dune promote
rok-cesnovar Dec 22, 2021
150f500
turn of new matrix type for lkj
SteveBronder Dec 22, 2021
96d05ec
Merge branch 'feature/soa-optim' of github.com:SteveBronder/stanc3 in…
SteveBronder Dec 22, 2021
5cd98be
turn off NaN optim
SteveBronder Dec 22, 2021
aaea223
update to master
SteveBronder Jan 2, 2022
21540c6
update to master and move mem_patterns tests to the compiler optims file
SteveBronder Jan 6, 2022
98c62e4
update test file
SteveBronder Jan 6, 2022
f50fb68
print optimized mir for soa integration test
SteveBronder Jan 7, 2022
0d21330
Make initial check a fold statement so we can check previously demote…
SteveBronder Jan 7, 2022
f1dd90e
use recursive fold when searching for initial demotables
SteveBronder Jan 7, 2022
e241be9
fix eigen name lookup in func demotion
SteveBronder Jan 7, 2022
5d4fbae
fix empty udf funcs
SteveBronder Jan 11, 2022
138d740
update to master
SteveBronder Jan 11, 2022
ec1ea37
move optimize_soa to only happen at O1
SteveBronder Jan 12, 2022
8d068b4
Merge branch 'feature/soa-optim' of github.com:SteveBronder/stanc3 in…
SteveBronder Jan 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
636 changes: 636 additions & 0 deletions src/analysis_and_optimization/Mem_pattern.ml

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion src/analysis_and_optimization/Mir_utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,15 @@ let fwd_traverse_statement stmt ~init ~f =
| For vars ->
let s', c = f init vars.body in
(s', For {vars with body= c})
| Profile (_, stmts) | Block stmts ->
| Profile (name, stmts) ->
let s', ls =
List.fold_left stmts
~f:(fun (s, l) stmt ->
let s', c = f s stmt in
(s', List.cons c l) )
~init:(init, []) in
(s', Profile (name, List.rev ls))
| Block stmts ->
let s', ls =
List.fold_left stmts
~f:(fun (s, l) stmt ->
Expand Down
1 change: 1 addition & 0 deletions src/analysis_and_optimization/Monotone_framework.ml
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ let minimal_variables_fwd_transfer
let gen = gen_variable flowgraph_to_mir l p in
let kill =
match mir_node with
(* This probably isn't necessary because Stan doesn't allow shadowing, right? *)
| Decl {decl_id; decl_adtype= DataOnly; _} -> Set.Poly.singleton decl_id
| _ -> Set.Poly.empty in
transfer_gen_kill p gen kill end : TRANSFER_FUNCTION
Expand Down
86 changes: 77 additions & 9 deletions src/analysis_and_optimization/Optimize.ml
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,10 @@ let rec inline_function_statement propto adt fim Stmt.Fixed.{pattern; meta} =
( [inline_function_statement propto adt fim body]
@ map_no_loc s_upper )
; meta= Location_span.empty } ) } )
| Profile (_, l) | Block l ->
| Profile (name, l) ->
Profile
(name, List.map l ~f:(inline_function_statement propto adt fim))
| Block l ->
Block (List.map l ~f:(inline_function_statement propto adt fim))
| SList l ->
SList (List.map l ~f:(inline_function_statement propto adt fim))
Expand Down Expand Up @@ -535,7 +538,7 @@ let unroll_loop_one_step_statement _ =
( Expr.Fixed.
{ lower with
pattern=
FunApp (StanLib ("Geq__", FnPlain, SoA), [upper; lower]) }
FunApp (StanLib ("Geq__", FnPlain, AoS), [upper; lower]) }
, { pattern=
(let body_unrolled =
subst_args_stmt [loopvar] [lower]
Expand All @@ -550,7 +553,7 @@ let unroll_loop_one_step_statement _ =
{ lower with
pattern=
FunApp
( StanLib ("Plus__", FnPlain, SoA)
( StanLib ("Plus__", FnPlain, AoS)
, [lower; Expr.Helpers.loop_bottom] ) } }
; meta= Location_span.empty } in
match body_unrolled.pattern with
Expand Down Expand Up @@ -722,7 +725,10 @@ let dead_code_elimination (mir : Program.Typed.t) =
&& is_skip_break_continue body.pattern
then Skip
else For {loopvar; lower; upper; body}
| Profile (_, l) | Block l ->
| Profile (name, l) ->
let l' = List.filter ~f:(fun x -> x.pattern <> Skip) l in
if List.length l' = 0 then Skip else Profile (name, l')
| Block l ->
let l' = List.filter ~f:(fun x -> x.pattern <> Skip) l in
if List.length l' = 0 then Skip else Block l'
| SList l ->
Expand Down Expand Up @@ -1118,6 +1124,64 @@ let optimize_ad_levels (mir : Program.Typed.t) =
stmt in
transform_program_blockwise mir transform

(**
* Deduces whether types can be Structures of Arrays (SoA/fast) or
* Arrays of Structs (AoS/slow). See the docs in
* Mem_pattern.query_demote_stmt/exprs* functions for
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see those docs in Mem_pattern, maybe this pointer could be clearer

* details on the rules surrounding when demotion from
* SoA -> AoS needs to happen.
*
* This first does a simple iter over
* the log_prob portion of the MIR, finding the names of all matrices
* (and arrays of matrices) where either the Stan math function
* does not support SoA or the object is single cell accesed within a
* For or While loop. These are the initial variables
* given to the monotone framework. Then log_prob has all matrix like objects
* and the functions that use them to SoA. After that the
* Monotone framework is used to deduce assignment paths of AoS <-> SoA
* and vice versa which need to be demoted to AoS as well as updating
* functions and objects after these assignment passes that then
* also need to be AoS.
*
* @param mir: The program's whole MIR.
*)
let optimize_soa (mir : Program.Typed.t) =
let gen_aos_variables
(flowgraph_to_mir : (int, Stmt.Located.Non_recursive.t) Map.Poly.t)
(l : int) (aos_variables : string Set.Poly.t) =
let mir_node mir_idx = Map.find_exn flowgraph_to_mir mir_idx in
match (mir_node l).pattern with
| stmt -> Mem_pattern.query_demotable_stmt aos_variables stmt in
let initial_variables =
List.fold ~init:Set.Poly.empty
~f:(Mem_pattern.query_initial_demotable_stmt false)
mir.log_prob in
(*
let print_set s =
Set.Poly.iter ~f:print_endline s in
let () = print_set initial_variables in
*)
let mod_exprs aos_exits mod_expr =
Mir_utils.map_rec_expr (Mem_pattern.modify_expr_pattern aos_exits) mod_expr
in
let modify_stmt_patt stmt_pattern variable_set =
Mem_pattern.modify_stmt_pattern stmt_pattern variable_set in
let transform stmt =
optimize_minimal_variables ~gen_variables:gen_aos_variables
~update_expr:mod_exprs ~update_stmt:modify_stmt_patt ~initial_variables
stmt ~extra_variables:(fun _ -> initial_variables) in
let transform' s =
match transform {pattern= SList s; meta= Location_span.empty} with
| { pattern=
SList (l : (Expr.Typed.Meta.t, Stmt.Located.Meta.t) Stmt.Fixed.t list)
; _ } ->
l
| _ ->
raise
(Failure "Something went wrong with program transformation packing!")
in
{mir with log_prob= transform' mir.log_prob}

(* Apparently you need to completely copy/paste type definitions between
ml and mli files?*)
type optimization_settings =
Expand All @@ -1134,7 +1198,8 @@ type optimization_settings =
; partial_evaluation: bool
; lazy_code_motion: bool
; optimize_ad_levels: bool
; preserve_stability: bool }
; preserve_stability: bool
; optimize_soa: bool }

let settings_const b =
{ function_inlining= b
Expand All @@ -1150,7 +1215,8 @@ let settings_const b =
; partial_evaluation= b
; lazy_code_motion= b
; optimize_ad_levels= b
; preserve_stability= not b }
; preserve_stability= not b
; optimize_soa= b }

let all_optimizations : optimization_settings = settings_const true
let no_optimizations : optimization_settings = settings_const false
Expand All @@ -1159,7 +1225,7 @@ type optimization_level = O0 | O1 | Oexperimental

let level_optimizations (lvl : optimization_level) : optimization_settings =
match lvl with
| O0 -> {no_optimizations with allow_uninitialized_decls= false}
| O0 -> no_optimizations
| O1 ->
{ function_inlining= false
; static_loop_unrolling= false
Expand All @@ -1174,7 +1240,8 @@ let level_optimizations (lvl : optimization_level) : optimization_settings =
; lazy_code_motion= false
; allow_uninitialized_decls= false
; optimize_ad_levels= true
; preserve_stability= false }
; preserve_stability= false
; optimize_soa= true }
| Oexperimental -> all_optimizations

let optimization_suite ?(settings = all_optimizations) mir =
Expand Down Expand Up @@ -1220,7 +1287,8 @@ let optimization_suite ?(settings = all_optimizations) mir =
; (optimize_ad_levels, settings.optimize_ad_levels)
(* Book: Machine idioms and instruction combining *)
(* Matthijs: Everything < block_fixing *)
; (block_fixing, settings.block_fixing) ] in
; (block_fixing, settings.block_fixing)
; (optimize_soa, settings.optimize_soa) ] in
let optimizations =
List.filter_map maybe_optimizations ~f:(fun (fn, flag) ->
if flag then Some fn else None ) in
Expand Down
3 changes: 2 additions & 1 deletion src/analysis_and_optimization/Optimize.mli
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ type optimization_settings =
; partial_evaluation: bool
; lazy_code_motion: bool
; optimize_ad_levels: bool
; preserve_stability: bool }
; preserve_stability: bool
; optimize_soa: bool }

val all_optimizations : optimization_settings
val no_optimizations : optimization_settings
Expand Down
21 changes: 2 additions & 19 deletions src/frontend/Ast_to_Mir.ml
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,6 @@ type transform_action = Check | Constrain | Unconstrain | IgnoreTransform
type decl_context =
{transform_action: transform_action; dadlevel: UnsizedType.autodifftype}

let constraint_forl = function
| Transformation.Identity | Offset _ | Multiplier _ | OffsetMultiplier _
|Lower _ | Upper _ | LowerUpper _ ->
Stmt.Helpers.for_scalar
| Ordered | PositiveOrdered | Simplex | UnitVector | CholeskyCorr
|CholeskyCov | Correlation | Covariance ->
Stmt.Helpers.for_eigen

let same_shape decl_id decl_var id var meta =
if UnsizedType.is_scalar_type (Expr.Typed.type_of var) then []
else
Expand Down Expand Up @@ -291,16 +283,7 @@ let param_size transform sizedtype =
(fun k -> Expr.Helpers.(binop k Plus (k_choose_2 k)))
sizedtype

let remove_possibly_exn pst action loc =
match pst with
| Type.Sized st -> st
| Unsized _ ->
Common.FatalError.fatal_error_msg
[%message
"Error extracting sizedtype" ~action ~loc:(loc : Location_span.t)]

let rec check_decl var decl_type' decl_id decl_trans smeta adlevel =
let decl_type = remove_possibly_exn decl_type' "check" smeta in
match decl_trans with
| Transformation.LowerUpper (lb, ub) ->
check_decl var decl_type' decl_id (Lower lb) smeta adlevel
Expand All @@ -312,7 +295,7 @@ let rec check_decl var decl_type' decl_id decl_trans smeta adlevel =
Stmt.Helpers.internal_nrfunapp
(FnCheck {trans= decl_trans; var_name; var= id})
args smeta in
[(constraint_forl decl_trans) decl_type check_id var smeta]
[check_id var]
| _ -> []

let check_sizedtype name =
Expand Down Expand Up @@ -687,7 +670,7 @@ let trans_block ud_dists declc block prog =
check_transform_shape decl_id decl_var smeta.loc transform
| Check ->
check_transform_shape decl_id decl_var smeta.loc transform
@ check_decl decl_var (Sized type_) decl_id transform
@ check_decl decl_var (Type.Sized type_) decl_id transform
smeta.loc declc.dadlevel
| IgnoreTransform -> [] in
(decl :: rhs_assignment) @ constrain_checks
Expand Down
1 change: 1 addition & 0 deletions src/middle/Expr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ module Typed = struct
let type_of Fixed.{meta= Meta.{type_; _}; _} = type_
let loc_of Fixed.{meta= Meta.{loc; _}; _} = loc
let adlevel_of Fixed.{meta= Meta.{adlevel; _}; _} = adlevel
let fun_arg Fixed.{meta= Meta.{type_; adlevel; _}; _} = (adlevel, type_)
end

(** Expressions with associated location, type and label *)
Expand Down
1 change: 1 addition & 0 deletions src/middle/Expr.mli
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module Typed : sig
val type_of : t -> UnsizedType.t
val loc_of : t -> Location_span.t
val adlevel_of : t -> UnsizedType.autodifftype
val fun_arg : t -> UnsizedType.autodifftype * UnsizedType.t
end

module Labelled : sig
Expand Down
10 changes: 9 additions & 1 deletion src/middle/Index.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,18 @@ let bounds = function
@param op a functor to run with inputs of inner exprs
@param ind the Index.t to
*)
let apply ~default ~merge op ind =
let apply ~default ~merge op (ind : 'a t) =
match ind with
| All -> default
| Single ind_expr -> op ind_expr
| Upfrom ind_expr -> op ind_expr
| Between (expr_top, expr_bottom) -> merge (op expr_top) (op expr_bottom)
| MultiIndex exprs -> op exprs

let folder (acc : string Set.Poly.t) op (ind : 'a t) : string Set.Poly.t =
match ind with
| All -> acc
| Single ind_expr | Upfrom ind_expr | MultiIndex ind_expr -> op acc ind_expr
| Between (expr_top, expr_bottom) ->
let top_fold = op acc expr_top in
Set.Poly.union top_fold (op top_fold expr_bottom)
Loading