Skip to content

Commit 811248f

Browse files
Make ThreadedSparseMatrixCSC subtype of AbstractSparseMatrixCSC (#5)
* Make ThreadedSparseMatrixCSC subtype of AbstractSparseMatrixCSC * Remove ThreadedColumnizedSparseMatrix * Add GitHub CI
1 parent d4204ea commit 811248f

File tree

3 files changed

+60
-63
lines changed

3 files changed

+60
-63
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: CI
2+
on:
3+
pull_request:
4+
branches:
5+
- master
6+
push:
7+
branches:
8+
- master
9+
tags: '*'
10+
jobs:
11+
test:
12+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
version:
18+
- '1.4' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
19+
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
20+
- 'nightly'
21+
os:
22+
- ubuntu-latest
23+
- macOS-latest
24+
- windows-latest
25+
arch:
26+
- x64
27+
steps:
28+
- uses: actions/checkout@v2
29+
- uses: julia-actions/setup-julia@v1
30+
with:
31+
version: ${{ matrix.version }}
32+
arch: ${{ matrix.arch }}
33+
- uses: actions/cache@v1
34+
env:
35+
cache-name: cache-artifacts
36+
with:
37+
path: ~/.julia/artifacts
38+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
39+
restore-keys: |
40+
${{ runner.os }}-test-${{ env.cache-name }}-
41+
${{ runner.os }}-test-
42+
${{ runner.os }}-
43+
- uses: julia-actions/julia-buildpkg@v1
44+
- uses: julia-actions/julia-runtest@v1
45+
- uses: julia-actions/julia-processcoverage@v1
46+
- uses: codecov/codecov-action@v1
47+
with:
48+
file: lcov.info

src/ThreadedSparseArrays.jl

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
module ThreadedSparseArrays
22

3+
4+
export ThreadedSparseMatrixCSC
5+
6+
37
using LinearAlgebra
48
import LinearAlgebra: mul!
59
using SparseArrays
6-
import SparseArrays: getcolptr
10+
import SparseArrays: getcolptr, AbstractSparseMatrixCSC
711
const AdjOrTransDenseMatrix = if VERSION < v"1.6.0-rc2"
812
SparseArrays.AdjOrTransStridedOrTriangularMatrix
913
else
@@ -36,31 +40,18 @@ Base.iterate(it::RangeIterator, i::Int=1) = i>it.k ? nothing : (endpos(it,i-1)+1
3640
Thin container around `A::SparseMatrixCSC` that will enable certain
3741
threaded multiplications of `A` with dense matrices.
3842
"""
39-
struct ThreadedSparseMatrixCSC{Tv,Ti,At} <: AbstractSparseMatrix{Tv,Ti}
43+
struct ThreadedSparseMatrixCSC{Tv,Ti,At} <: AbstractSparseMatrixCSC{Tv,Ti}
4044
A::At
41-
ThreadedSparseMatrixCSC(A::At) where {Tv,Ti,At<:AbstractSparseMatrix{Tv,Ti}} =
45+
ThreadedSparseMatrixCSC(A::At) where {Tv,Ti,At<:AbstractSparseMatrixCSC{Tv,Ti}} =
4246
new{Tv,Ti,At}(A)
4347
end
4448

4549
Base.size(A::ThreadedSparseMatrixCSC, args...) = size(A.A, args...)
46-
Base.eltype(A::ThreadedSparseMatrixCSC) = eltype(A.A)
47-
Base.getindex(A::ThreadedSparseMatrixCSC, args...) = getindex(A.A, args...)
48-
49-
# Need to override printing
50-
# Need to forward findnz, etc
5150

5251
for f in [:rowvals, :nonzeros, :getcolptr]
5352
@eval SparseArrays.$(f)(A::ThreadedSparseMatrixCSC) = SparseArrays.$(f)(A.A)
5453
end
5554

56-
# For non-threaded implementations, fallback to sparse methods and not generic matmul.
57-
mul!(C::AbstractVector, A::ThreadedSparseMatrixCSC, B::AbstractVector, α::Number, β::Number) = mul!(C, A.A, B, α, β)
58-
mul!(C::AbstractMatrix, A::ThreadedSparseMatrixCSC, B::AbstractMatrix, α::Number, β::Number) = mul!(C, A.A, B, α, β)
59-
mul!(C::AbstractVector, A::Adjoint{<:Any,<:ThreadedSparseMatrixCSC}, B::AbstractVector, α::Number, β::Number) = mul!(C, adjoint(A.parent.A), B, α, β)
60-
mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:ThreadedSparseMatrixCSC}, B::AbstractMatrix, α::Number, β::Number) = mul!(C, adjoint(A.parent.A), B, α, β)
61-
mul!(C::AbstractVector, A::Transpose{<:Any,<:ThreadedSparseMatrixCSC}, B::AbstractVector, α::Number, β::Number) = mul!(C, transpose(A.parent.A), B, α, β)
62-
mul!(C::AbstractMatrix, A::Transpose{<:Any,<:ThreadedSparseMatrixCSC}, B::AbstractMatrix, α::Number, β::Number) = mul!(C, transpose(A.parent.A), B, α, β)
63-
6455
function mul!(C::StridedVecOrMat, A::ThreadedSparseMatrixCSC, B::Union{StridedVector,AdjOrTransDenseMatrix}, α::Number, β::Number)
6556
size(A, 2) == size(B, 1) || throw(DimensionMismatch())
6657
size(A, 1) == size(C, 1) || throw(DimensionMismatch())
@@ -201,42 +192,4 @@ function mul!(C::StridedVecOrMat, X::AdjOrTransDenseMatrix, A::ThreadedSparseMat
201192
C
202193
end
203194

204-
# * ThreadedColumnizedSparseMatrix
205-
206-
"""
207-
ThreadedColumnizedSparseMatrix(columns, m, n)
208-
209-
Sparse matrix of size `m×n` where the `columns` are stored separately,
210-
enabling threaded multiplication. Seems faster than
211-
[`ThreadedSparseMatrixCSC`](@ref) for some use cases.
212-
"""
213-
struct ThreadedColumnizedSparseMatrix{Tv,Ti,Columns} <: AbstractSparseMatrix{Tv,Ti}
214-
columns::Columns
215-
m::Int
216-
n::Int
217-
ThreadedColumnizedSparseMatrix(::Type{Tv}, ::Type{Ti}, columns::Columns, m, n) where {Tv,Ti,Columns} =
218-
new{Tv,Ti,Columns}(columns, m, n)
219-
end
220-
221-
function ThreadedColumnizedSparseMatrix(A::AbstractSparseMatrix{Tv,Ti}) where {Tv,Ti}
222-
m,n = size(A)
223-
Column = typeof(A[:,1])
224-
columns = Column[A[:,j] for j = 1:n]
225-
ThreadedColumnizedSparseMatrix(Tv, Ti, columns, m, n)
226-
end
227-
228-
Base.size(A::ThreadedColumnizedSparseMatrix) = (A.m,A.n)
229-
Base.size(A::ThreadedColumnizedSparseMatrix,i) = size(A)[i]
230-
Base.getindex(A::ThreadedColumnizedSparseMatrix, i, j) = A.columns[j][i]
231-
232-
function LinearAlgebra.mul!(A::AbstractMatrix, B::AbstractMatrix, C::ThreadedColumnizedSparseMatrix,
233-
α::Number=true, β::Number=false)
234-
Threads.@threads for j = 1:C.n
235-
LinearAlgebra.mul!(view(A, :, j), B, C.columns[j], α, β)
236-
end
237-
A
238-
end
239-
240-
export ThreadedSparseMatrixCSC, ThreadedColumnizedSparseMatrix
241-
242195
end # module

test/runtests.jl

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ using Test
99
T = ComplexF64
1010

1111
C = sprand(T, N, n, 0.05)
12-
@testset "$(Mat)_R" for Mat in [ThreadedSparseMatrixCSC, ThreadedColumnizedSparseMatrix]
12+
@testset "$(Mat)_R" for Mat in [ThreadedSparseMatrixCSC]
1313
Ct = Mat(C)
1414

1515
eye = Matrix(one(T)*I, N, N)
@@ -56,8 +56,7 @@ using Test
5656
@testset "$(Mat)_L_sparsevec" for Mat in [ThreadedSparseMatrixCSC]
5757
Ct = Mat(C)
5858

59-
out = similar(sx, T, N)
60-
LinearAlgebra.mul!(out, Ct, sx)
59+
out = Ct*sx
6160
ref = C*sx
6261
@test norm(ref-out) == 0
6362
@test typeof(ref)==typeof(out)
@@ -67,8 +66,7 @@ using Test
6766
@testset "$(Mat)_L_$(op)_sparsevec" for op in [adjoint,transpose], Mat in [ThreadedSparseMatrixCSC]
6867
Ct = Mat(C)
6968

70-
out = similar(sx, T, n)
71-
LinearAlgebra.mul!(out, op(Ct), sx)
69+
out = op(Ct)*sx
7270
ref = op(C)*sx
7371
@test norm(ref-out) == 0
7472
@test typeof(ref)==typeof(out)
@@ -78,8 +76,7 @@ using Test
7876
@testset "$(Mat)_L_sparse" for Mat in [ThreadedSparseMatrixCSC]
7977
Ct = Mat(C)
8078

81-
out = similar(sx, T, N, 10)
82-
LinearAlgebra.mul!(out, Ct, sx)
79+
out = Ct*sx
8380
ref = C*sx
8481
@test norm(ref-out) == 0
8582
@test typeof(ref)==typeof(out)
@@ -89,8 +86,7 @@ using Test
8986
@testset "$(Mat)_L_$(op)_sparse" for op in [adjoint,transpose], Mat in [ThreadedSparseMatrixCSC]
9087
Ct = Mat(C)
9188

92-
out = similar(sx, T, n, 10)
93-
LinearAlgebra.mul!(out, op(Ct), sx)
89+
out = op(Ct)*sx
9490
ref = op(C)*sx
9591
@test norm(ref-out) == 0
9692
@test typeof(ref)==typeof(out)

0 commit comments

Comments
 (0)