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

Cleanup Wrappers and Tests #37

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
12 changes: 10 additions & 2 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
name: TagBot
on:
schedule:
- cron: 0 0 * * *
issue_comment:
types:
- created
workflow_dispatch:
inputs:
lookback:
default: 3
permissions:
contents: write
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
35 changes: 19 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
name: ci
on:
- push
- pull_request
pull_request:
branches:
- master
push:
branches:
- master
- release-*
- runci/*
tags: ['*']
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.version == 'nightly' }}
strategy:
fail-fast: false
matrix:
Expand All @@ -20,21 +28,16 @@ jobs:
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Cache artifacts
uses: actions/cache@v1
env:
cache-name: cache-artifacts
show-versioninfo: true
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-runtest@latest
file: lcov.info
7 changes: 4 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "MKLSparse"
uuid = "0c723cd3-b8cd-5d40-b370-ba682dde9aae"
version = "1.1.0"
version = "1.2.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand All @@ -9,10 +9,11 @@ MKL_jll = "856f044c-d86e-5d09-b602-aeab76dc8ba7"

[compat]
julia = "1.6"
MKL_jll = "2022.2.0"
MKL_jll = "2022.2.0, 2023.0.0"

[extras]
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Test", "Random"]
12 changes: 9 additions & 3 deletions src/MKLSparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ using LinearAlgebra, SparseArrays
using LinearAlgebra: BlasInt, BlasFloat, checksquare
using MKL_jll: libmkl_rt

# For testing purposes:
global const __counter = Ref(0)
# counts total MKL Sparse API calls (for testing purposes)
global const __mklsparse_calls_count = Ref(0)

# increments to the `__mklsparse_calls_count` variable
function _log_mklsparse_call(fname)
#@debug "$fname called"
__mklsparse_calls_count[] += 1
end

function __init__()
ccall((:MKL_Set_Interface_Layer, libmkl_rt), Cint, (Cint,), Base.USE_BLAS64 ? 1 : 0)
@ccall libmkl_rt.MKL_Set_Interface_Layer((Base.USE_BLAS64 ? 1 : 0)::Cint)::Cint
end

# Wrappers generated by Clang.jl
Expand Down
95 changes: 53 additions & 42 deletions src/generator.jl
Original file line number Diff line number Diff line change
@@ -1,58 +1,73 @@
# The increments to the `__counter` variable is for testing purposes

function _check_transa(t::Char)
if !(t in ('C', 'N', 'T'))
error("transa: is '$t', must be 'N', 'T', or 'C'")
throw(ArgumentError("transa: is '$t', must be 'N', 'T', or 'C'"))
end
end

mkl_size(t::Char, M::AbstractVecOrMat) = t == 'N' ? size(M) : reverse(size(M))

# Checks sizes for the multiplication C <- tA[A] * tB[B]
function _check_mat_mult_matvec(C, A, tA, B, tB)
_size(t::Char, M::AbstractMatrix) = t == 'N' ? size(M) : reverse(size(M))
_size(t::Char, V::AbstractVector) = t == 'N' ? (size(V, 1), 1) : (1, size(V, 1))
_str(M::AbstractMatrix) = string("[", size(M, 1), ", ", size(M, 2), "]")
_str(V::AbstractVector) = string("[", size(V, 1), "]")
_t(t) = t == 'T' ? "ᵀ" : t == 'C' ? "ᴴ" : t == 'N' ? "" : "ERROR"

# Checks sizes for the multiplication C <- A * B
function _check_mat_mult_matvec(C, A, B, tA)
_size(v::AbstractMatrix) = size(v)
_size(v::AbstractVector) = (size(v,1), 1)
_str(v::AbstractMatrix) = string("[", size(v,1), ", ", size(v,2), "]")
_str(v::AbstractVector) = string("[", size(v,1), "]")
mA, nA = mkl_size(tA, A)
mB, nB = _size(B)
mC, nC = _size(C)
mA, nA = _size(tA, A)
mB, nB = _size(tB, B)
mC, nC = _size('N', C)
if nA != mB || mC != mA || nC != nB
t = ""
if tA == 'T'; t = ".\'"; end
if tA == 'C'; t = "\'"; end
str = string("arrays had inconsistent dimensions for C <- A", t, " * B: ", _str(C), " <- ", _str(A), t, " * ", _str(B))
str = string("arrays had inconsistent dimensions for C = A", _t(tA), " * B", _t(tB), ": ",
_str(C), " = ", _str(A), _t(tA), " * ", _str(B), _t(tB))
throw(DimensionMismatch(str))
end
end

# MKL convention by annotating the type of numeric arguments in method names
mkl_typespec(::Type{T}) where T =
T == Float32 ? "s" :
T == Float64 ? "d" :
T == ComplexF32 ? "c" :
T == ComplexF64 ? "z" :
throw(ArgumentError("Unsupported type $(T)"))

# calls MKL function with the name template F (e.g. :mkl_Tcscmm),
# with 'T' char replaced by a type-specifier corresponding to the input type T,
# (e.g. 's' for Float32), so the function called is :mkl_scscmm
@inline @generated function mkl_call(::Val{F}, ::Type{T}, args...) where {F, T}
fname = Symbol(replace(String(F), "T" => mkl_typespec(T)))
quote
_log_mklsparse_call($fname)
$fname(args...)
end
end

# same but doesn't log the call
@inline @generated function mkl_call_nolog(::Val{F}, ::Type{T}, args...) where {F, T}
fname = Symbol(replace(String(F), "T" => mkl_typespec(T)))
:($fname(args...))
end

function cscmv!(transa::Char, α::T, matdescra::String,
A::SparseMatrixCSC{T, BlasInt}, x::StridedVector{T},
β::T, y::StridedVector{T}) where {T <: BlasFloat}
_check_transa(transa)
_check_mat_mult_matvec(y, A, x, transa)
__counter[] += 1
_check_mat_mult_matvec(y, A, transa, x, 'N')

T == Float32 && (mkl_scscmv(transa, A.m, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, β, y))
T == Float64 && (mkl_dcscmv(transa, A.m, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, β, y))
T == ComplexF32 && (mkl_ccscmv(transa, A.m, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, β, y))
T == ComplexF64 && (mkl_zcscmv(transa, A.m, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, β, y))
mkl_call(Val(:mkl_Tcscmv), T, transa, A.m, A.n, α, matdescra,
A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, β, y)
return y
end

function cscmm!(transa::Char, α::T, matdescra::String,
A::SparseMatrixCSC{T, BlasInt}, B::StridedMatrix{T},
β::T, C::StridedMatrix{T}) where {T <: BlasFloat}
_check_transa(transa)
_check_mat_mult_matvec(C, A, B, transa)
_check_mat_mult_matvec(C, A, transa, B, 'N')
mB, nB = size(B)
mC, nC = size(C)
__counter[] += 1
T == Float32 && (mkl_scscmm(transa, A.m, nC, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, β, C, mC))
T == Float64 && (mkl_dcscmm(transa, A.m, nC, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, β, C, mC))
T == ComplexF32 && (mkl_ccscmm(transa, A.m, nC, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, β, C, mC))
T == ComplexF64 && (mkl_zcscmm(transa, A.m, nC, A.n, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, β, C, mC))

mkl_call(Val(:mkl_Tcscmm), T, transa, A.m, nC, A.n, α, matdescra,
A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, β, C, mC)
return C
end

Expand All @@ -61,12 +76,10 @@ function cscsv!(transa::Char, α::T, matdescra::String,
y::StridedVector{T}) where {T <: BlasFloat}
n = checksquare(A)
_check_transa(transa)
_check_mat_mult_matvec(y, A, x, transa)
__counter[] += 1
T == Float32 && (mkl_scscsv(transa, A.m, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, y))
T == Float64 && (mkl_dcscsv(transa, A.m, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, y))
T == ComplexF32 && (mkl_ccscsv(transa, A.m, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, y))
T == ComplexF64 && (mkl_zcscsv(transa, A.m, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, y))
_check_mat_mult_matvec(y, A, transa, x, 'N')

mkl_call(Val(:mkl_Tcscsv), T, transa, A.m, α, matdescra,
A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), x, y)
return y
end

Expand All @@ -77,11 +90,9 @@ function cscsm!(transa::Char, α::T, matdescra::String,
mC, nC = size(C)
n = checksquare(A)
_check_transa(transa)
_check_mat_mult_matvec(C, A, B, transa)
__counter[] += 1
T == Float32 && (mkl_scscsm(transa, A.n, nC, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, C, mC))
T == Float64 && (mkl_dcscsm(transa, A.n, nC, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, C, mC))
T == ComplexF32 && (mkl_ccscsm(transa, A.n, nC, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, C, mC))
T == ComplexF64 && (mkl_zcscsm(transa, A.n, nC, α, matdescra, A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, C, mC))
_check_mat_mult_matvec(C, A, transa, B, 'N')

mkl_call(Val(:mkl_Tcscsm), T, transa, A.n, nC, α, matdescra,
A.nzval, A.rowval, A.colptr, pointer(A.colptr, 2), B, mB, C, mC)
return C
end
4 changes: 3 additions & 1 deletion src/matdescra.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# SparseBLAS description of A structure
# see https://www.intel.com/content/www/us/en/develop/documentation/onemkl-developer-reference-c/top/blas-and-sparse-blas-routines/sparse-blas-level-2-and-level-3-routines/interface-consideration.html#interface-consideration_GUID-0C896CB1-25B6-4B53-A425-C5954B4C22F9
matdescra(A::LowerTriangular) = "TLNF"
matdescra(A::UpperTriangular) = "TUNF"
matdescra(A::Diagonal) = "DUNF"
matdescra(A::UnitLowerTriangular) = "TLUF"
matdescra(A::UnitUpperTriangular) = "TUUF"
matdescra(A::Symmetric) = string('S', A.uplo, 'N', 'F')
matdescra(A::Hermitian) = string('H', A.uplo, 'N', 'F')
matdescra(A::SparseMatrixCSC) = "GUUF"
matdescra(A::SparseMatrixCSC) = "GFNF"
Loading