Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8475266
Add autotune preference integration to default solver selection
ChrisRackauckas Aug 14, 2025
a28f52a
Optimize autotune preference integration with compile-time constants
ChrisRackauckas Aug 14, 2025
fea6b0c
Complete optimization with all requested improvements
ChrisRackauckas Aug 14, 2025
56a417d
Add algorithm availability checking and fallback system
ChrisRackauckas Aug 14, 2025
59ce71f
Add comprehensive tests for dual preference system integration in def…
ChrisRackauckas Aug 15, 2025
7f9bd67
Add explicit algorithm choice verification tests for dual preference …
ChrisRackauckas Aug 15, 2025
9484b72
Clean up algorithm choice tests and ensure proper preference reset
ChrisRackauckas Aug 15, 2025
5eda050
Add separate Preferences test group with FastLapack algorithm verific…
ChrisRackauckas Aug 15, 2025
5a3f480
Fix preference tests: only print on failure, correct extension-depend…
ChrisRackauckas Aug 15, 2025
913cded
Fix size category boundaries to match LinearSolveAutotune and add com…
ChrisRackauckas Aug 15, 2025
374aba5
Remove unnecessary success prints from FastLapack and RecursiveFactor…
ChrisRackauckas Aug 15, 2025
822ff6a
Add explicit algorithm choice verification for FastLapack and RFLU
ChrisRackauckas Aug 15, 2025
ee4f0b0
Add explicit algorithm choice tests: verify FastLU and RFLU selection…
ChrisRackauckas Aug 15, 2025
6af69d8
Apply suggestions from code review
ChrisRackauckas Aug 15, 2025
89bcb9e
Add comprehensive size category algorithm verification with different…
ChrisRackauckas Aug 15, 2025
6847dc5
Fix algorithm choice test to use AppleAccelerateLUFactorization from …
ChrisRackauckas Aug 15, 2025
19beb8d
Add comprehensive algorithm choice analysis function for testing and …
ChrisRackauckas Aug 15, 2025
a372fdb
Make preference tests strict: require exact algorithm match
ChrisRackauckas Aug 15, 2025
3240462
Remove boundary testing section as requested
ChrisRackauckas Aug 15, 2025
66faf95
Revert "Remove boundary testing section as requested"
ChrisRackauckas Aug 15, 2025
4958c38
Remove non-LU algorithms from _string_to_algorithm_choice
ChrisRackauckas Aug 15, 2025
beeec34
Move show_algorithm_choices to main package and simplify
ChrisRackauckas Aug 15, 2025
c55e420
Update documentation for dual preference system and show_algorithm_ch…
ChrisRackauckas Aug 15, 2025
3dc46f1
Update test/preferences.jl
ChrisRackauckas Aug 15, 2025
7ee156c
Fix FastLapack test to use GenericLUFactorization as always_loaded
ChrisRackauckas Aug 15, 2025
5161904
Add reset_defaults! function for testing preference system integration
ChrisRackauckas Aug 16, 2025
6150d55
Clean up preference system and enhance show_algorithm_choices display
ChrisRackauckas Aug 16, 2025
a86bd4c
Streamline preference tests with single reset_defaults! call
ChrisRackauckas Aug 16, 2025
a52b267
Move preference handling to dedicated src/preferences.jl file
ChrisRackauckas Aug 16, 2025
fbd7155
Fix preference tests: correct FastLU mapping and add preference isola…
ChrisRackauckas Aug 16, 2025
da8f72d
Replace algorithm test with robust RFLU vs GenericLU verification
ChrisRackauckas Aug 16, 2025
0e69356
Update test/preferences.jl
ChrisRackauckas Aug 16, 2025
9881aeb
Clean up preference system: remove analysis.jl, use eval-based testin…
ChrisRackauckas Aug 16, 2025
bb9c717
Rename reset_defaults! to make_preferences_dynamic!
ChrisRackauckas Aug 16, 2025
1be6f5b
Update documentation for final preference system implementation
ChrisRackauckas Aug 16, 2025
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
1 change: 1 addition & 0 deletions .github/workflows/Tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
- "LinearSolvePardiso"
- "NoPre"
- "LinearSolveAutotune"
- "Preferences"
os:
- ubuntu-latest
- macos-latest
Expand Down
69 changes: 69 additions & 0 deletions docs/src/advanced/internal_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,77 @@ The automatic algorithm selection is one of LinearSolve.jl's key features:

```@docs
LinearSolve.defaultalg
LinearSolve.get_tuned_algorithm
LinearSolve.is_algorithm_available
LinearSolve.show_algorithm_choices
LinearSolve.make_preferences_dynamic!
```

### Preference System Architecture

The dual preference system provides intelligent algorithm selection with comprehensive fallbacks:

#### **Core Functions**
- **`get_tuned_algorithm`**: Retrieves tuned algorithm preferences based on matrix size and element type
- **`is_algorithm_available`**: Checks if a specific algorithm is currently available (extensions loaded)
- **`show_algorithm_choices`**: Analysis function displaying algorithm choices for all element types
- **`make_preferences_dynamic!`**: Testing function that enables runtime preference checking

#### **Size Categorization**
The system categorizes matrix sizes to match LinearSolveAutotune benchmarking:
- **tiny**: ≀20 elements (matrices ≀10 always override to GenericLU)
- **small**: 21-100 elements
- **medium**: 101-300 elements
- **large**: 301-1000 elements
- **big**: >1000 elements

#### **Dual Preference Structure**
For each category and element type (Float32, Float64, ComplexF32, ComplexF64):
- `best_algorithm_{type}_{size}`: Overall fastest algorithm from autotune
- `best_always_loaded_{type}_{size}`: Fastest always-available algorithm (fallback)

#### **Preference File Organization**
All preference-related functionality is consolidated in `src/preferences.jl`:

**Compile-Time Constants**:
- `AUTOTUNE_PREFS`: Preference structure loaded at package import
- `AUTOTUNE_PREFS_SET`: Fast path check for whether any preferences are set
- `_string_to_algorithm_choice`: Mapping from preference strings to algorithm enums

**Runtime Functions**:
- `_get_tuned_algorithm_runtime`: Dynamic preference checking for testing
- `_choose_available_algorithm`: Algorithm availability and fallback logic
- `show_algorithm_choices`: Comprehensive analysis and display function

**Testing Infrastructure**:
- `make_preferences_dynamic!`: Eval-based function redefinition for testing
- Enables runtime preference verification without affecting production performance

#### **Testing Mode Operation**
The testing system uses an elegant eval-based approach:
```julia
# Production: Uses compile-time constants (maximum performance)
get_tuned_algorithm(Float64, Float64, 200) # β†’ Uses AUTOTUNE_PREFS constants

# Testing: Redefines function to use runtime checking
make_preferences_dynamic!()
get_tuned_algorithm(Float64, Float64, 200) # β†’ Uses runtime preference loading
```

This approach maintains type stability and inference while enabling comprehensive testing.

#### **Algorithm Support Scope**
The preference system focuses exclusively on LU algorithms for dense matrices:

**Supported LU Algorithms**:
- `LUFactorization`, `GenericLUFactorization`, `RFLUFactorization`
- `MKLLUFactorization`, `AppleAccelerateLUFactorization`
- `SimpleLUFactorization`, `FastLUFactorization` (both map to LU)
- GPU LU variants (CUDA, Metal, AMDGPU - all map to LU)

**Non-LU algorithms** (QR, Cholesky, SVD, etc.) are not included in the preference system
as they serve different use cases and are not typically the focus of dense matrix autotune optimization.

## Trait Functions

These trait functions help determine algorithm capabilities and requirements:
Expand Down
55 changes: 54 additions & 1 deletion docs/src/basics/algorithm_selection.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,57 @@ end
sol = solve(prob, LinearSolveFunction(my_custom_solver))
```

See the [Custom Linear Solvers](@ref custom) section for more details.
See the [Custom Linear Solvers](@ref custom) section for more details.

## Tuned Algorithm Selection

LinearSolve.jl includes a sophisticated preference system that can be tuned using LinearSolveAutotune for optimal performance on your specific hardware:

```julia
using LinearSolve
using LinearSolveAutotune

# Run autotune to benchmark algorithms and set preferences
results = autotune_setup(set_preferences = true)

# View what algorithms are now being chosen
show_algorithm_choices()
```

The system automatically sets preferences for:
- **Different matrix sizes**: tiny (≀20), small (21-100), medium (101-300), large (301-1000), big (>1000)
- **Different element types**: Float32, Float64, ComplexF32, ComplexF64
- **Dual preferences**: Best overall algorithm + best always-available fallback

### Viewing Algorithm Choices

Use `show_algorithm_choices()` to see what algorithms are currently being selected:

```julia
using LinearSolve
show_algorithm_choices()
```

This shows a comprehensive analysis:
- Current autotune preferences for all element types (if set)
- Algorithm choices for all element types across all size categories
- Side-by-side comparison showing Float32, Float64, ComplexF32, ComplexF64 behavior
- System information (available extensions: MKL, Apple Accelerate, RecursiveFactorization)

Example output:
```
πŸ“Š Default Algorithm Choices:
Size Category Float32 Float64 ComplexF32 ComplexF64
8Γ—8 tiny GenericLUFactorization GenericLUFactorization GenericLUFactorization GenericLUFactorization
50Γ—50 small MKLLUFactorization MKLLUFactorization MKLLUFactorization MKLLUFactorization
200Γ—200 medium MKLLUFactorization GenericLUFactorization MKLLUFactorization MKLLUFactorization
```

When preferences are set, you can see exactly how they affect algorithm choice across different element types.

### Preference System Benefits

- **Automatic optimization**: Uses the fastest algorithms found by benchmarking
- **Intelligent fallbacks**: Falls back to always-available algorithms when extensions aren't loaded
- **Size-specific tuning**: Different algorithms optimized for different matrix sizes
- **Type-specific tuning**: Optimized algorithm selection for different numeric types
54 changes: 37 additions & 17 deletions docs/src/tutorials/autotune.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

LinearSolve.jl includes an automatic tuning system that benchmarks all available linear algebra algorithms on your specific hardware and automatically selects optimal algorithms for different problem sizes and data types. This tutorial will show you how to use the `LinearSolveAutotune` sublibrary to optimize your linear solve performance.

!!! warn
The autotuning system is under active development. While benchmarking and result sharing are fully functional, automatic preference setting for algorithm selection is still being refined.
The autotuning system provides comprehensive benchmarking and automatic algorithm selection optimization for your specific hardware.

## Quick Start

Expand Down Expand Up @@ -418,33 +417,54 @@ for config in configs
end
```

## Preferences Integration
## Algorithm Selection Analysis

You can analyze what algorithms are currently being chosen for different matrix sizes:

```julia
using LinearSolve

!!! warn
Automatic preference setting is still under development and may not affect algorithm selection in the current version.
# Show current algorithm choices and preferences
show_algorithm_choices()
```

The autotuner can set preferences that LinearSolve.jl will use for automatic algorithm selection:
This displays:
- Current autotune preferences for all element types (if any are set)
- Algorithm choices for all element types across representative sizes in each category
- Comprehensive element type behavior (Float32, Float64, ComplexF32, ComplexF64)
- System information (MKL, Apple Accelerate, RecursiveFactorization status)

The output shows a clear table format:
```
πŸ“Š Default Algorithm Choices:
Size Category Float32 Float64 ComplexF32 ComplexF64
8Γ—8 tiny GenericLUFactorization GenericLUFactorization GenericLUFactorization GenericLUFactorization
200Γ—200 medium MKLLUFactorization MKLLUFactorization MKLLUFactorization MKLLUFactorization
```

## Preferences Integration

The autotuner sets preferences that LinearSolve.jl uses for automatic algorithm selection:

```julia
using LinearSolveAutotune

# View current preferences (if any)
LinearSolveAutotune.show_current_preferences()

# Run autotune and set preferences
results = autotune_setup(set_preferences = true)

# Clear all autotune preferences
LinearSolveAutotune.clear_algorithm_preferences()
# View what algorithms are now being chosen
using LinearSolve
show_algorithm_choices()

# Manually set custom preferences
custom_categories = Dict(
"Float64_0-128" => "RFLUFactorization",
"Float64_128-256" => "LUFactorization"
)
LinearSolveAutotune.set_algorithm_preferences(custom_categories)
# View current preferences
LinearSolveAutotune.show_current_preferences()

# Clear all autotune preferences if needed
LinearSolveAutotune.clear_algorithm_preferences()
```

After running autotune with `set_preferences = true`, LinearSolve.jl will automatically use the fastest algorithms found for each matrix size and element type, with intelligent fallbacks when extensions are not available.

## Troubleshooting

### Common Issues
Expand Down
33 changes: 32 additions & 1 deletion src/LinearSolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ else
const usemkl = false
end


@reexport using SciMLBase

"""
Expand Down Expand Up @@ -276,6 +277,35 @@ EnumX.@enumx DefaultAlgorithmChoice begin
KrylovJL_LSMR
end

# Autotune preference constants - loaded once at package import time

# Algorithm availability checking functions
"""
is_algorithm_available(alg::DefaultAlgorithmChoice.T)

Check if the given algorithm is currently available (extensions loaded, etc.).
"""
function is_algorithm_available(alg::DefaultAlgorithmChoice.T)
if alg === DefaultAlgorithmChoice.LUFactorization
return true # Always available
elseif alg === DefaultAlgorithmChoice.GenericLUFactorization
return true # Always available
elseif alg === DefaultAlgorithmChoice.MKLLUFactorization
return usemkl # Available if MKL is loaded
elseif alg === DefaultAlgorithmChoice.AppleAccelerateLUFactorization
return appleaccelerate_isavailable() # Available on macOS with Accelerate
elseif alg === DefaultAlgorithmChoice.RFLUFactorization
return userecursivefactorization(nothing) # Requires RecursiveFactorization extension
else
# For extension-dependent algorithms not explicitly handled above,
# we cannot easily check availability without trying to use them.
# For now, assume they're not available in the default selection.
# This includes FastLU, BLIS, CUDA, Metal, etc. which would require
# specific extension checks.
return false
end
end

"""
DefaultLinearSolver(;safetyfallback=true)

Expand Down Expand Up @@ -309,6 +339,7 @@ include("simplelu.jl")
include("simplegmres.jl")
include("iterative_wrappers.jl")
include("preconditioners.jl")
include("preferences.jl")
include("solve_function.jl")
include("default.jl")
include("init.jl")
Expand Down Expand Up @@ -390,7 +421,7 @@ export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization,
BunchKaufmanFactorization, CHOLMODFactorization, LDLtFactorization,
CUSOLVERRFFactorization, CliqueTreesFactorization

export LinearSolveFunction, DirectLdiv!
export LinearSolveFunction, DirectLdiv!, show_algorithm_choices

export KrylovJL, KrylovJL_CG, KrylovJL_MINRES, KrylovJL_GMRES,
KrylovJL_BICGSTAB, KrylovJL_LSMR, KrylovJL_CRAIGMR,
Expand Down
Loading
Loading