5
5
6
6
Set LinearSolve preferences based on the categorized benchmark results.
7
7
These preferences are stored in the main LinearSolve.jl package.
8
- Handles element type-specific preferences with keys like "Float64_0-128".
8
+
9
+ The function handles type fallbacks:
10
+ - If Float32 wasn't benchmarked, uses Float64 results
11
+ - If ComplexF64 wasn't benchmarked, uses ComplexF32 results (if available) or Float64
12
+ - If ComplexF32 wasn't benchmarked, uses Float64 results
13
+ - For complex types, avoids RFLUFactorization due to known issues
9
14
"""
10
15
function set_algorithm_preferences (categories:: Dict{String, String} )
11
16
@info " Setting LinearSolve preferences based on benchmark results..."
12
-
13
- for (category_key, algorithm) in categories
14
- # Handle element type specific keys like "Float64_0-128"
15
- # Convert to safe preference key format
16
- pref_key = " best_algorithm_$(replace (category_key, " +" => " plus" , " -" => " _" )) "
17
-
18
- # Set preferences in LinearSolve.jl, not LinearSolveAutotune (force=true allows overwriting)
19
- Preferences. set_preferences! (LinearSolve, pref_key => algorithm; force = true )
20
- @info " Set preference $pref_key = $algorithm in LinearSolve.jl"
17
+
18
+ # Define the size category names we use
19
+ size_categories = [" tiny" , " small" , " medium" , " large" , " big" ]
20
+
21
+ # Define the element types we want to set preferences for
22
+ target_eltypes = [" Float32" , " Float64" , " ComplexF32" , " ComplexF64" ]
23
+
24
+ # Extract benchmarked results by element type and size
25
+ benchmarked = Dict {String, Dict{String, String}} ()
26
+ for (key, algorithm) in categories
27
+ if contains (key, " _" )
28
+ eltype, size_range = split (key, " _" , limit= 2 )
29
+ if ! haskey (benchmarked, eltype)
30
+ benchmarked[eltype] = Dict {String, String} ()
31
+ end
32
+ benchmarked[eltype][size_range] = algorithm
33
+ end
21
34
end
22
-
35
+
36
+ # Helper function to get best algorithm for complex types (avoiding RFLU)
37
+ function get_complex_algorithm (results_df, eltype_str, size_range)
38
+ # If we have direct benchmark results, use them
39
+ if haskey (benchmarked, eltype_str) && haskey (benchmarked[eltype_str], size_range)
40
+ alg = benchmarked[eltype_str][size_range]
41
+ # Check if it's RFLU and we should avoid it for complex
42
+ if contains (alg, " RFLU" ) || contains (alg, " RecursiveFactorization" )
43
+ # Find the second best for this case
44
+ # We'd need the full results DataFrame to do this properly
45
+ # For now, we'll just flag it
46
+ @warn " RFLUFactorization selected for $eltype_str at size $size_range , but it has known issues with complex numbers"
47
+ end
48
+ return alg
49
+ end
50
+ return nothing
51
+ end
52
+
53
+ # Process each target element type and size combination
54
+ for eltype in target_eltypes
55
+ for size_cat in size_categories
56
+ # Map size categories to the range strings used in categories
57
+ size_range = if size_cat == " tiny"
58
+ " 0-128" # Maps to tiny range
59
+ elseif size_cat == " small"
60
+ " 0-128" # Small also uses this range
61
+ elseif size_cat == " medium"
62
+ " 128-256" # Medium range
63
+ elseif size_cat == " large"
64
+ " 256-512" # Large range
65
+ elseif size_cat == " big"
66
+ " 512+" # Big range
67
+ else
68
+ continue
69
+ end
70
+
71
+ # Determine the algorithm based on fallback rules
72
+ algorithm = nothing
73
+
74
+ if eltype == " Float64"
75
+ # Float64 should be directly benchmarked
76
+ if haskey (benchmarked, " Float64" ) && haskey (benchmarked[" Float64" ], size_range)
77
+ algorithm = benchmarked[" Float64" ][size_range]
78
+ end
79
+ elseif eltype == " Float32"
80
+ # Float32: use Float32 results if available, else use Float64
81
+ if haskey (benchmarked, " Float32" ) && haskey (benchmarked[" Float32" ], size_range)
82
+ algorithm = benchmarked[" Float32" ][size_range]
83
+ elseif haskey (benchmarked, " Float64" ) && haskey (benchmarked[" Float64" ], size_range)
84
+ algorithm = benchmarked[" Float64" ][size_range]
85
+ end
86
+ elseif eltype == " ComplexF32"
87
+ # ComplexF32: use ComplexF32 if available, else Float64 (avoiding RFLU)
88
+ if haskey (benchmarked, " ComplexF32" ) && haskey (benchmarked[" ComplexF32" ], size_range)
89
+ algorithm = benchmarked[" ComplexF32" ][size_range]
90
+ elseif haskey (benchmarked, " Float64" ) && haskey (benchmarked[" Float64" ], size_range)
91
+ algorithm = benchmarked[" Float64" ][size_range]
92
+ # Check for RFLU and warn
93
+ if contains (algorithm, " RFLU" ) || contains (algorithm, " RecursiveFactorization" )
94
+ @warn " Would use RFLUFactorization for ComplexF32 at $size_cat , but it has issues with complex numbers. Consider benchmarking ComplexF32 directly."
95
+ end
96
+ end
97
+ elseif eltype == " ComplexF64"
98
+ # ComplexF64: use ComplexF64 if available, else ComplexF32, else Float64 (avoiding RFLU)
99
+ if haskey (benchmarked, " ComplexF64" ) && haskey (benchmarked[" ComplexF64" ], size_range)
100
+ algorithm = benchmarked[" ComplexF64" ][size_range]
101
+ elseif haskey (benchmarked, " ComplexF32" ) && haskey (benchmarked[" ComplexF32" ], size_range)
102
+ algorithm = benchmarked[" ComplexF32" ][size_range]
103
+ elseif haskey (benchmarked, " Float64" ) && haskey (benchmarked[" Float64" ], size_range)
104
+ algorithm = benchmarked[" Float64" ][size_range]
105
+ # Check for RFLU and warn
106
+ if contains (algorithm, " RFLU" ) || contains (algorithm, " RecursiveFactorization" )
107
+ @warn " Would use RFLUFactorization for ComplexF64 at $size_cat , but it has issues with complex numbers. Consider benchmarking ComplexF64 directly."
108
+ end
109
+ end
110
+ end
111
+
112
+ # Set the preference if we have an algorithm
113
+ if algorithm != = nothing
114
+ pref_key = " best_algorithm_$(eltype) _$(size_cat) "
115
+ Preferences. set_preferences! (LinearSolve, pref_key => algorithm; force = true )
116
+ @info " Set preference $pref_key = $algorithm in LinearSolve.jl"
117
+ end
118
+ end
119
+ end
120
+
23
121
# Set a timestamp for when these preferences were created
24
122
Preferences. set_preferences! (LinearSolve, " autotune_timestamp" => string (Dates. now ()); force = true )
25
-
123
+
26
124
@info " Preferences updated in LinearSolve.jl. You may need to restart Julia for changes to take effect."
27
125
end
28
126
29
127
"""
30
128
get_algorithm_preferences()
31
129
32
130
Get the current algorithm preferences from LinearSolve.jl.
33
- Handles both legacy and element type-specific preferences .
131
+ Returns preferences organized by element type and size category .
34
132
"""
35
133
function get_algorithm_preferences ()
36
134
prefs = Dict {String, String} ()
37
-
38
- # Get all LinearSolve preferences by checking common preference patterns
39
- # Since there's no direct way to get all preferences, we'll check for known patterns
40
- common_patterns = [
41
- # Element type + size range combinations
42
- " Float64_0_128" , " Float64_128_256" , " Float64_256_512" , " Float64_512plus" ,
43
- " Float32_0_128" , " Float32_128_256" , " Float32_256_512" , " Float32_512plus" ,
44
- " ComplexF64_0_128" , " ComplexF64_128_256" , " ComplexF64_256_512" , " ComplexF64_512plus" ,
45
- " ComplexF32_0_128" , " ComplexF32_128_256" , " ComplexF32_256_512" , " ComplexF32_512plus" ,
46
- " BigFloat_0_128" , " BigFloat_128_256" , " BigFloat_256_512" , " BigFloat_512plus" ,
47
- # Legacy patterns without element type
48
- " 0_128" , " 128_256" , " 256_512" , " 512plus"
49
- ]
50
-
51
- for pattern in common_patterns
52
- pref_key = " best_algorithm_$pattern "
53
- value = Preferences. load_preference (LinearSolve, pref_key, nothing )
54
- if value != = nothing
55
- # Convert back to human-readable key
56
- readable_key = replace (pattern, " _" => " -" , " plus" => " +" )
57
- prefs[readable_key] = value
135
+
136
+ # Define the patterns we look for
137
+ target_eltypes = [" Float32" , " Float64" , " ComplexF32" , " ComplexF64" ]
138
+ size_categories = [" tiny" , " small" , " medium" , " large" , " big" ]
139
+
140
+ for eltype in target_eltypes
141
+ for size_cat in size_categories
142
+ pref_key = " best_algorithm_$(eltype) _$(size_cat) "
143
+ value = Preferences. load_preference (LinearSolve, pref_key, nothing )
144
+ if value != = nothing
145
+ readable_key = " $(eltype) _$(size_cat) "
146
+ prefs[readable_key] = value
147
+ end
58
148
end
59
149
end
60
-
150
+
61
151
return prefs
62
152
end
63
153
64
154
"""
65
155
clear_algorithm_preferences()
66
156
67
157
Clear all autotune-related preferences from LinearSolve.jl.
68
- Handles both legacy and element type-specific preferences.
69
158
"""
70
159
function clear_algorithm_preferences ()
71
160
@info " Clearing LinearSolve autotune preferences..."
72
-
73
- # Clear known preference patterns
74
- common_patterns = [
75
- # Element type + size range combinations
76
- " Float64_0_128" , " Float64_128_256" , " Float64_256_512" , " Float64_512plus" ,
77
- " Float32_0_128" , " Float32_128_256" , " Float32_256_512" , " Float32_512plus" ,
78
- " ComplexF64_0_128" , " ComplexF64_128_256" , " ComplexF64_256_512" , " ComplexF64_512plus" ,
79
- " ComplexF32_0_128" , " ComplexF32_128_256" , " ComplexF32_256_512" , " ComplexF32_512plus" ,
80
- " BigFloat_0_128" , " BigFloat_128_256" , " BigFloat_256_512" , " BigFloat_512plus" ,
81
- # Legacy patterns without element type
82
- " 0_128" , " 128_256" , " 256_512" , " 512plus"
83
- ]
84
-
85
- for pattern in common_patterns
86
- pref_key = " best_algorithm_$pattern "
87
- # Check if preference exists before trying to delete
88
- if Preferences. has_preference (LinearSolve, pref_key)
89
- Preferences. delete_preferences! (LinearSolve, pref_key; force = true )
90
- @info " Cleared preference: $pref_key "
161
+
162
+ # Define the patterns we look for
163
+ target_eltypes = [" Float32" , " Float64" , " ComplexF32" , " ComplexF64" ]
164
+ size_categories = [" tiny" , " small" , " medium" , " large" , " big" ]
165
+
166
+ for eltype in target_eltypes
167
+ for size_cat in size_categories
168
+ pref_key = " best_algorithm_$(eltype) _$(size_cat) "
169
+ if Preferences. has_preference (LinearSolve, pref_key)
170
+ Preferences. delete_preferences! (LinearSolve, pref_key; force = true )
171
+ @info " Cleared preference: $pref_key "
172
+ end
91
173
end
92
174
end
93
-
175
+
94
176
# Clear timestamp
95
177
if Preferences. has_preference (LinearSolve, " autotune_timestamp" )
96
178
Preferences. delete_preferences! (LinearSolve, " autotune_timestamp" ; force = true )
97
179
end
98
-
180
+
99
181
@info " Preferences cleared from LinearSolve.jl."
100
182
end
101
183
@@ -106,19 +188,32 @@ Display the current algorithm preferences from LinearSolve.jl in a readable form
106
188
"""
107
189
function show_current_preferences ()
108
190
prefs = get_algorithm_preferences ()
109
-
191
+
110
192
if isempty (prefs)
111
193
println (" No autotune preferences currently set in LinearSolve.jl." )
112
194
return
113
195
end
114
-
196
+
115
197
println (" Current LinearSolve.jl autotune preferences:" )
116
198
println (" =" ^ 50 )
117
-
118
- for (range, algorithm) in sort (prefs)
119
- println (" Size range $range : $algorithm " )
199
+
200
+ # Group by element type for better display
201
+ by_eltype = Dict {String, Vector{Tuple{String, String}}} ()
202
+ for (key, algorithm) in prefs
203
+ eltype, size_cat = split (key, " _" , limit= 2 )
204
+ if ! haskey (by_eltype, eltype)
205
+ by_eltype[eltype] = Vector {Tuple{String, String}} ()
206
+ end
207
+ push! (by_eltype[eltype], (size_cat, algorithm))
120
208
end
121
-
209
+
210
+ for eltype in sort (collect (keys (by_eltype)))
211
+ println (" \n $eltype :" )
212
+ for (size_cat, algorithm) in sort (by_eltype[eltype])
213
+ println (" $size_cat : $algorithm " )
214
+ end
215
+ end
216
+
122
217
timestamp = Preferences. load_preference (LinearSolve, " autotune_timestamp" , " unknown" )
123
- println (" Last updated: $timestamp " )
124
- end
218
+ println (" \n Last updated: $timestamp " )
219
+ end
0 commit comments