-
Notifications
You must be signed in to change notification settings - Fork 9
Optimized implementation for structured matrices V2 #319
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| module SparseMatrixColoringsBandedMatricesExt | ||
|
|
||
| using BandedMatrices: BandedMatrix, bandrange, bandwidths, colrange, rowrange | ||
| using SparseMatrixColorings: | ||
| BipartiteGraph, | ||
| ColoringProblem, | ||
| ColumnColoringResult, | ||
| StructuredColoringAlgorithm, | ||
| RowColoringResult, | ||
| column_colors, | ||
| cycle_range, | ||
| row_colors | ||
| import SparseMatrixColorings as SMC | ||
|
|
||
| #= | ||
| This code is partly taken from ArrayInterface.jl and FiniteDiff.jl | ||
| https://github.com/JuliaArrays/ArrayInterface.jl | ||
| https://github.com/JuliaDiff/FiniteDiff.jl | ||
| =# | ||
|
|
||
| function SMC.coloring( | ||
| A::BandedMatrix, | ||
| ::ColoringProblem{:nonsymmetric,:column}, | ||
| ::StructuredColoringAlgorithm; | ||
| kwargs..., | ||
| ) | ||
| width = length(bandrange(A)) | ||
| color = cycle_range(width, size(A, 2)) | ||
| bg = BipartiteGraph(A) | ||
| return ColumnColoringResult(A, bg, color) | ||
| end | ||
|
|
||
| function SMC.coloring( | ||
| A::BandedMatrix, | ||
| ::ColoringProblem{:nonsymmetric,:row}, | ||
| ::StructuredColoringAlgorithm; | ||
| kwargs..., | ||
| ) | ||
| width = length(bandrange(A)) | ||
| color = cycle_range(width, size(A, 1)) | ||
| bg = BipartiteGraph(A) | ||
| return RowColoringResult(A, bg, color) | ||
| end | ||
|
|
||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| module SparseMatrixColoringsBlockBandedMatricesExt | ||
|
|
||
| using BlockArrays: blockaxes, blockfirsts, blocklasts, blocksize, blocklengths | ||
| using BlockBandedMatrices: | ||
| BandedBlockBandedMatrix, | ||
| BlockBandedMatrix, | ||
| blockbandrange, | ||
| blockbandwidths, | ||
| blocklengths, | ||
| blocksize, | ||
| subblockbandwidths | ||
| using SparseMatrixColorings: | ||
| BipartiteGraph, | ||
| ColoringProblem, | ||
| ColumnColoringResult, | ||
| StructuredColoringAlgorithm, | ||
| RowColoringResult, | ||
| column_colors, | ||
| cycle_range, | ||
| row_colors | ||
| import SparseMatrixColorings as SMC | ||
|
|
||
| #= | ||
| This code is partly taken from ArrayInterface.jl and FiniteDiff.jl | ||
| https://github.com/JuliaArrays/ArrayInterface.jl | ||
| https://github.com/JuliaDiff/FiniteDiff.jl | ||
| =# | ||
|
|
||
| function subblockbandrange(A::BandedBlockBandedMatrix) | ||
| u, l = subblockbandwidths(A) | ||
| return (-l):u | ||
| end | ||
|
|
||
| function blockbanded_coloring( | ||
| A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, dim::Integer | ||
| ) | ||
| # consider blocks of columns or rows (let's call them vertices) depending on `dim` | ||
| nb_blocks = blocksize(A, dim) | ||
| nb_in_block = blocklengths(axes(A, dim)) | ||
| first_in_block = blockfirsts(axes(A, dim)) | ||
| last_in_block = blocklasts(axes(A, dim)) | ||
| color = zeros(Int, size(A, dim)) | ||
|
|
||
| # give a macroscopic color to each block, so that 2 blocks with the same macro color are orthogonal | ||
| # same idea as for BandedMatrices | ||
| nb_macrocolors = length(blockbandrange(A)) | ||
| macrocolor = cycle_range(nb_macrocolors, nb_blocks) | ||
|
|
||
| width = if A isa BandedBlockBandedMatrix | ||
| # vertices within a block are colored cleverly using bands | ||
| length(subblockbandrange(A)) | ||
| else | ||
| # vertices within a block are colored naively with distinct micro colors (~ infinite band width) | ||
| typemax(Int) | ||
| end | ||
|
|
||
| # for each macroscopic color, count how many microscopic colors will be needed | ||
| nb_colors_in_macrocolor = zeros(Int, nb_macrocolors) | ||
| for mc in 1:nb_macrocolors | ||
| largest_nb_in_macrocolor = maximum(nb_in_block[mc:nb_macrocolors:nb_blocks]; init=0) | ||
| nb_colors_in_macrocolor[mc] = min(width, largest_nb_in_macrocolor) | ||
| end | ||
| color_shift_in_macrocolor = vcat(0, cumsum(nb_colors_in_macrocolor)[1:(end - 1)]) | ||
|
|
||
| # assign a microscopic color to each column as a function of its macroscopic color and its position within the block | ||
| for b in 1:nb_blocks | ||
| block_color = cycle_range(width, nb_in_block[b]) | ||
| shift = color_shift_in_macrocolor[macrocolor[b]] | ||
| color[first_in_block[b]:last_in_block[b]] .= shift .+ block_color | ||
| end | ||
|
|
||
| return color | ||
| end | ||
|
|
||
| function SMC.coloring( | ||
| A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, | ||
| ::ColoringProblem{:nonsymmetric,:column}, | ||
| ::StructuredColoringAlgorithm; | ||
| kwargs..., | ||
| ) | ||
| color = blockbanded_coloring(A, 2) | ||
| bg = BipartiteGraph(A) | ||
| return ColumnColoringResult(A, bg, color) | ||
| end | ||
|
|
||
| function SMC.coloring( | ||
| A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, | ||
| ::ColoringProblem{:nonsymmetric,:row}, | ||
| ::StructuredColoringAlgorithm; | ||
| kwargs..., | ||
| ) | ||
| color = blockbanded_coloring(A, 1) | ||
| bg = BipartiteGraph(A) | ||
| return RowColoringResult(A, bg, color) | ||
| end | ||
|
|
||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,35 @@ | ||
| module SparseMatrixColoringsCUDAExt | ||
|
|
||
| using LinearAlgebra | ||
| import SparseMatrixColorings as SMC | ||
| using SparseArrays: SparseMatrixCSC, rowvals, nnz, nzrange | ||
| using CUDA: CuVector, CuMatrix | ||
| using CUDA: CuArray, CuVector, CuMatrix | ||
| using cuSPARSE: AbstractCuSparseMatrix, CuSparseMatrixCSC, CuSparseMatrixCSR | ||
|
|
||
| ## Basic support for GPU sparsity pattern stuff | ||
|
|
||
| function SMC.SparsityPatternCSC(A::CuSparseMatrixCSC) | ||
| SMC.SparsityPatternCSC(first(A.dims), last(A.dims), A.colPtr, A.rowVal) | ||
| end | ||
|
|
||
| for R in (:Diagonal, :Bidiagonal, :Tridiagonal) | ||
| @eval function SMC.BipartiteGraph( | ||
| A::$R{T,<:CuArray}; symmetric_pattern::Bool=false | ||
| ) where {T} | ||
| return SMC.BipartiteGraph(CuSparseMatrixCSC(A); symmetric_pattern) | ||
| end | ||
| end | ||
|
|
||
| function SMC.BipartiteGraph(A::CuSparseMatrixCSC; symmetric_pattern::Bool=false) | ||
| S2 = SMC.SparsityPatternCSC(A) | ||
| if symmetric_pattern | ||
| checksquare(A) # proxy for checking full symmetry | ||
| S1 = S2 | ||
| else | ||
| S1 = transpose(S2) # rows to columns | ||
| end | ||
| return SMC.BipartiteGraph(S1, S2) | ||
| end | ||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gdalle For now I just want to make sure the structured coloring algorithms working for Diagonal, Bidiagonal and Tridiagonal matrices, but it turns out we still need to make
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above, I think I need additional context to understand what you did here |
||
| ## CSC Result | ||
|
|
||
| function SMC.ColumnColoringResult( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -271,8 +271,9 @@ function show_colors!( | |
| A_ccolor_indices = mod1.(column_colors(res), length(colorscheme)) | ||
| A_rcolor_indices = mod1.(row_shift .+ row_colors(res), length(colorscheme)) | ||
| B_ccolor_indices = mod1.(1:maximum(column_colors(res)), length(colorscheme)) | ||
| B_rcolor_indices = | ||
| mod1.((row_shift + 1):(row_shift + maximum(row_colors(res))), length(colorscheme)) | ||
| B_rcolor_indices = mod1.( | ||
| (row_shift + 1):(row_shift + maximum(row_colors(res))), length(colorscheme) | ||
| ) | ||
|
Comment on lines
+274
to
+276
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If possible, it's better to avoid formatting changes that only add noise |
||
| A_ccolors = colorscheme[A_ccolor_indices] | ||
| A_rcolors = colorscheme[A_rcolor_indices] | ||
| B_ccolors = colorscheme[B_ccolor_indices] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ function optimal_distance2_coloring( | |
| model = Model(optimizer) | ||
| silent && set_silent(model) | ||
| # one variable per vertex to color, removing some renumbering symmetries | ||
| @variable(model, 1 <= color[i=1:n] <= i, Int) | ||
| @variable(model, 1 <= color[i = 1:n] <= i, Int) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment about formatting noise |
||
| # one variable to count the number of distinct colors | ||
| @variable(model, ncolors, Int) | ||
| @constraint(model, [ncolors; color] in MOI.CountDistinct(n + 1)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,8 +17,8 @@ Copied from `SparseMatrixCSC`: | |
| struct SparsityPatternCSC{Ti<:Integer} <: AbstractMatrix{Bool} | ||
| m::Int | ||
| n::Int | ||
| colptr::Vector{Ti} | ||
| rowval::Vector{Ti} | ||
| colptr::AbstractVector{Ti} | ||
| rowval::AbstractVector{Ti} | ||
|
Comment on lines
+20
to
+21
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a really bad idea because it will introduce type instability throughout the coloring and decompression algorithms. Can you explain why you deem it necessary? |
||
| end | ||
|
|
||
| SparsityPatternCSC(A::SparseMatrixCSC) = SparsityPatternCSC(A.m, A.n, A.colptr, A.rowval) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? The coloring will take place on the CPU anyway so I don't see why we would need a GPU-based graph structure