From 5a156b0ef8983366ba47da255f591a76e67501de Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 20 May 2017 15:20:37 -0700 Subject: [PATCH 1/4] Cleanup code for 0.6 - switch to using testsets fulltime - fix import of cudaStream_t from CUDArt.jl - fix depwarns --- src/CUSPARSE.jl | 3 +- src/libcusparse_types.jl | 57 +++--- src/sparse.jl | 56 +++--- src/util.jl | 28 +-- test/axpyi.jl | 88 ++++----- test/bsric.jl | 70 +++---- test/bsrilu.jl | 75 +++----- test/bsrsm.jl | 90 ++++----- test/bsrsv.jl | 94 +++++----- test/csic.jl | 99 ++++++---- test/csilu.jl | 59 +++--- test/cssm.jl | 42 +++-- test/cssv.jl | 72 ++++--- test/dot.jl | 69 +++---- test/geam.jl | 102 ++++++---- test/gemm.jl | 69 +++---- test/gthr.jl | 128 ++++--------- test/gtsv.jl | 228 ++++++++++------------ test/hybsv.jl | 61 +++--- test/mm.jl | 299 ++++++++++++++++++----------- test/mm.png | Bin 123710 -> 0 bytes test/mv.jl | 396 +++++++++++++++++++++------------------ test/mv.png | Bin 122289 -> 0 bytes test/roti.jl | 82 +++----- test/runtests.jl | 244 +++++++++++------------- test/sctr.jl | 60 +++--- test/sv.png | Bin 112388 -> 0 bytes 27 files changed, 1266 insertions(+), 1305 deletions(-) delete mode 100644 test/mm.png delete mode 100644 test/mv.png delete mode 100644 test/sv.png diff --git a/src/CUSPARSE.jl b/src/CUSPARSE.jl index 2dd8d0f..1d4de0a 100644 --- a/src/CUSPARSE.jl +++ b/src/CUSPARSE.jl @@ -7,8 +7,9 @@ else end using CUDArt +using CUDArt.rt.cudaStream_t -typealias SparseChar Char +const SparseChar = Char import Base.one import Base.zero diff --git a/src/libcusparse_types.jl b/src/libcusparse_types.jl index 493b228..097cbca 100644 --- a/src/libcusparse_types.jl +++ b/src/libcusparse_types.jl @@ -4,7 +4,7 @@ """ Status messages from CUSPARSE's C API. """ -typealias cusparseStatus_t UInt32 +const cusparseStatus_t = UInt32 const CUSPARSE_STATUS_SUCCESS = 0 const CUSPARSE_STATUS_NOT_INITIALIZED = 1 const CUSPARSE_STATUS_ALLOC_FAILED = 2 @@ -21,7 +21,9 @@ Perform operation on indices only (`CUSPARSE_ACTION_SYMBOLIC`) or on both data and indices (`CUSPARSE_ACTION_NUMERIC`). Used in conversion routines. """ -typealias cusparseAction_t UInt32 +# perform operation only indices only or +# on both data and indices +const cusparseAction_t = UInt32 const CUSPARSE_ACTION_SYMBOLIC = 0 const CUSPARSE_ACTION_NUMERIC = 1 @@ -30,7 +32,7 @@ const CUSPARSE_ACTION_NUMERIC = 1 Parse dense matrix by rows (`CUSPARSE_DIRECTION_ROW`) or columns (`CUSPARSE_DIRECTION_COL`) to compute its number of non-zeros. """ -typealias cusparseDirection_t UInt32 +const cusparseDirection_t = UInt32 const CUSPARSE_DIRECTION_ROW = 0 const CUSPARSE_DIRECTION_COL = 1 @@ -42,7 +44,8 @@ There are three choices: * `CUSPARSE_HYB_PARTITION_USER` - set the partition manually in the conversion function. * `CUSPARSE_HYB_PARTITION_MAX` - use the maximum partition, putting the matrix in ELL format. """ -typealias cusparseHybPartition_t UInt32 +# how to partition the HYB matrix +const cusparseHybPartition_t = UInt32 const CUSPARSE_HYB_PARTITION_AUTO = 0 const CUSPARSE_HYB_PARTITION_USER = 1 const CUSPARSE_HYB_PARTITION_MAX = 2 @@ -53,7 +56,8 @@ Determines if a symmetric/Hermitian/triangular matrix has its upper (`CUSPARSE_FILL_MODE_UPPER`) or lower (`CUSPARSE_FILL_MODE_LOWER`) triangle filled. """ -typealias cusparseFillMode_t UInt32 +# filling for HE,TR,SY matrices +const cusparseFillMode_t = UInt32 const CUSPARSE_FILL_MODE_LOWER = 0 const CUSPARSE_FILL_MODE_UPPER = 1 @@ -62,7 +66,8 @@ const CUSPARSE_FILL_MODE_UPPER = 1 Determines if the diagonal of a matrix is all ones (`CUSPARSE_DIAG_TYPE_UNIT`) or not all ones (`CUSPARSE_DIAG_TYPE_NON_UNIT`). """ -typealias cusparseDiagType_t UInt32 +# is the diagonal all ones +const cusparseDiagType_t = UInt32 const CUSPARSE_DIAG_TYPE_NON_UNIT = 0 const CUSPARSE_DIAG_TYPE_UNIT = 1 @@ -71,7 +76,7 @@ const CUSPARSE_DIAG_TYPE_UNIT = 1 Determines if scalar arguments to a function are present on the host CPU (`CUSPARSE_POINTER_MODE_HOST`) or on the GPU (`CUSPARSE_POINTER_MODE_DEVICE`). """ -typealias cusparsePointerMode_t UInt32 +const cusparsePointerMode_t = UInt32 const CUSPARSE_POINTER_MODE_HOST = 0 const CUSPARSE_POINTER_MODE_DEVICE = 1 @@ -82,7 +87,7 @@ or solve, on the matrix as-is (`CUSPARSE_OPERATION_NON_TRANSPOSE`), on the matrix's transpose (`CUSPARSE_OPERATION_TRANSPOSE`), or on its conjugate transpose (`CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE`). """ -typealias cusparseOperation_t UInt32 +const cusparseOperation_t = UInt32 const CUSPARSE_OPERATION_NON_TRANSPOSE = 0 const CUSPARSE_OPERATION_TRANSPOSE = 1 const CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE = 2 @@ -96,7 +101,7 @@ symmetric (`CUSPARSE_MATRIX_TYPE_SYMMETRIC`), Hermitian (those in [`CompressedSparse`](@ref)), this can be inferred for some function calls. """ -typealias cusparseMatrixType_t UInt32 +const cusparseMatrixType_t = UInt32 const CUSPARSE_MATRIX_TYPE_GENERAL = 0 const CUSPARSE_MATRIX_TYPE_SYMMETRIC = 1 const CUSPARSE_MATRIX_TYPE_HERMITIAN = 2 @@ -107,7 +112,7 @@ const CUSPARSE_MATRIX_TYPE_TRIANGULAR = 3 Indicates whether to keep level info in solvers (`CUSPARSE_SOLVE_POLICY_USE_LEVEL`) or whether to not use it (`CUSPARSE_SOLVE_POLICY_NO_LEVEL`). """ -typealias cusparseSolvePolicy_t UInt32 +const cusparseSolvePolicy_t = UInt32 const CUSPARSE_SOLVE_POLICY_NO_LEVEL = 0 const CUSPARSE_SOLVE_POLICY_USE_LEVEL = 1 @@ -118,7 +123,7 @@ or one-indexed (`CUSPARSE_INDEX_BASE_ONE`). CUSPARSE.jl supports both. Julia sparse matrices are one-indexed, but you may wish to pass matrices from other libraries which use zero-indexing (e.g. C language ODE solvers). """ -typealias cusparseIndexBase_t UInt32 +const cusparseIndexBase_t = UInt32 const CUSPARSE_INDEX_BASE_ZERO = 0 const CUSPARSE_INDEX_BASE_ONE = 1 @@ -148,23 +153,23 @@ CUSPARSE will take. Generated by [`sv_analysis`](@ref) or [`sm_analysis`](@ref) and passed to [`sv_solve!`](@ref), [`sm_solve`](@ref), [`ic0!`](@ref), or [`ilu0!`](@ref). """ -typealias cusparseSolveAnalysisInfo_t Ptr{Void} -typealias bsrsm2Info_t Ptr{Void} -typealias bsrsv2Info_t Ptr{Void} -typealias csrsv2Info_t Ptr{Void} -typealias csric02Info_t Ptr{Void} -typealias csrilu02Info_t Ptr{Void} -typealias bsric02Info_t Ptr{Void} -typealias bsrilu02Info_t Ptr{Void} +const cusparseSolveAnalysisInfo_t = Ptr{Void} +const bsrsm2Info_t = Ptr{Void} +const bsrsv2Info_t = Ptr{Void} +const csrsv2Info_t = Ptr{Void} +const csric02Info_t = Ptr{Void} +const csrilu02Info_t = Ptr{Void} +const bsric02Info_t = Ptr{Void} +const bsrilu02Info_t = Ptr{Void} -typealias cusparseContext Void -typealias cusparseHandle_t Ptr{cusparseContext} +const cusparseContext = Void +const cusparseHandle_t = Ptr{cusparseContext} #complex numbers -typealias cuComplex Complex{Float32} -typealias cuDoubleComplex Complex{Float64} +const cuComplex = Complex{Float32} +const cuDoubleComplex = Complex{Float64} -typealias CusparseFloat Union{Float64,Float32,Complex128,Complex64} -typealias CusparseReal Union{Float64,Float32} -typealias CusparseComplex Union{Complex128,Complex64} +const CusparseFloat = Union{Float64,Float32,Complex128,Complex64} +const CusparseReal = Union{Float64,Float32} +const CusparseComplex = Union{Complex128,Complex64} diff --git a/src/sparse.jl b/src/sparse.jl index 6a03d6e..b65144e 100644 --- a/src/sparse.jl +++ b/src/sparse.jl @@ -130,7 +130,7 @@ function getDescr( A::CudaSparseMatrix, index::SparseChar ) if ishermitian(A) typ = CUSPARSE_MATRIX_TYPE_HERMITIAN fill = cusparsefill(A.uplo) - elseif issym(A) + elseif issymmetric(A) typ = CUSPARSE_MATRIX_TYPE_SYMMETRIC fill = cusparsefill(A.uplo) end @@ -206,7 +206,7 @@ for (fname,elty) in ((:cusparseScsr2bsr, :Float32), cuinda = cusparseindex(inda) cuindc = cusparseindex(indc) m,n = csr.dims - nnz = Array(Cint,1) + nnz = Array{Cint}(1) mb = div((m + blockDim - 1),blockDim) nb = div((n + blockDim - 1),blockDim) bsrRowPtr = CudaArray(zeros(Cint,mb + 1)) @@ -338,7 +338,7 @@ for (nname,cname,rname,hname,elty) in ((:cusparseSnnz, :cusparseSdense2csc, :cus lda = max(1,stride(A,2)) cudesc = cusparseMatDescr_t(CUSPARSE_MATRIX_TYPE_GENERAL, CUSPARSE_FILL_MODE_LOWER, CUSPARSE_DIAG_TYPE_NON_UNIT, cuind) nnzRowCol = CudaArray(zeros(Cint, fmt == 'R' ? m : n)) - nnzTotal = Array(Cint,1) + nnzTotal = Array{Cint}(1) statuscheck(ccall(($(string(nname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseDirection_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, @@ -543,7 +543,7 @@ for (jname,fname,elty) in ((:doti, :cusparseSdoti, :Float32), function $jname(X::CudaSparseVector{$elty}, Y::CudaVector{$elty}, index::SparseChar) - dot = Array($elty,1) + dot = Array{$elty}(1) cuind = cusparseindex(index) statuscheck(ccall(($(string(fname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Ptr{$elty}, Ptr{Cint}, @@ -830,7 +830,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrsv2_bufferSize, :cusparseSbsrsv2_ end info = bsrsv2Info_t[0] cusparseCreateBsrsv2Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseDirection_t, cusparseOperation_t, Cint, Cint, @@ -849,7 +849,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrsv2_bufferSize, :cusparseSbsrsv2_ cusparsehandle[1], cudir, cutransa, mb, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, A.blockDim, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXbsrsv2_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, bsrsv2Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -1105,7 +1105,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrsv2_bufferSize, :cusparseScsrsv2_ end info = csrsv2Info_t[0] cusparseCreateCsrsv2Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseOperation_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -1121,7 +1121,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrsv2_bufferSize, :cusparseScsrsv2_ Ptr{Void}), cusparsehandle[1], cutransa, m, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsrsv2_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csrsv2Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -1177,7 +1177,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrsv2_bufferSize, :cusparseScsrsv2_ end info = csrsv2Info_t[0] cusparseCreateCsrsv2Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseOperation_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -1193,7 +1193,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrsv2_bufferSize, :cusparseScsrsv2_ Ptr{Void}), cusparsehandle[1], cutransa, m, A.nnz, &cudesc, A.nzVal, A.colPtr, A.rowVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsrsv2_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csrsv2Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2016,7 +2016,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrsm2_bufferSize, :cusparseSbsrsm2_ ldx = max(1,stride(X,2)) info = bsrsm2Info_t[0] cusparseCreateBsrsm2Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseDirection_t, cusparseOperation_t, cusparseOperation_t, Cint, @@ -2037,7 +2037,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrsm2_bufferSize, :cusparseSbsrsm2_ mb, nX, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, A.blockDim, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXbsrsm2_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, bsrsm2Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2101,7 +2101,7 @@ for (fname,elty) in ((:cusparseScsrgeam, :Float32), if( (mA != mB) || (nA != nB) ) throw(DimensionMismatch("")) end - nnzC = Array(Cint,1) + nnzC = Array{Cint}(1) rowPtrC = CudaArray(zeros(Cint,mA+1)) statuscheck(ccall((:cusparseXcsrgeamNnz,libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, @@ -2144,7 +2144,7 @@ for (fname,elty) in ((:cusparseScsrgeam, :Float32), if( (mA != mB) || (nA != nB) ) throw(DimensionMismatch("A and B must have same dimensions!")) end - nnzC = Array(Cint,1) + nnzC = Array{Cint}(1) rowPtrC = CudaArray(zeros(Cint,mA+1)) statuscheck(ccall((:cusparseXcsrgeamNnz,libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, @@ -2249,7 +2249,7 @@ for (fname,elty) in ((:cusparseScsrgemm, :Float32), if k != kB throw(DimensionMismatch("Interior dimension of A, $k, and B, $kB, must match")) end - nnzC = Array(Cint,1) + nnzC = Array{Cint}(1) rowPtrC = CudaArray(zeros(Cint,m + 1)) statuscheck(ccall((:cusparseXcsrgemmNnz,libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseOperation_t, @@ -2314,7 +2314,7 @@ for (fname,elty) in ((:cusparseScsrgemm, :Float32), if k != kB throw(DimensionMismatch("Interior dimension of A, $k, and B, $kB, must match")) end - nnzC = Array(Cint,1) + nnzC = Array{Cint}(1) colPtrC = CudaArray(zeros(Cint,n + 1)) statuscheck(ccall((:cusparseXcsrgemmNnz,libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseOperation_t, @@ -2428,7 +2428,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsric02_bufferSize, :cusparseScsric0 end info = csric02Info_t[0] cusparseCreateCsric02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -2443,7 +2443,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsric02_bufferSize, :cusparseScsric0 Ptr{Void}), cusparsehandle[1], m, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsric02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csric02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2479,7 +2479,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsric02_bufferSize, :cusparseScsric0 end info = csric02Info_t[0] cusparseCreateCsric02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -2494,7 +2494,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsric02_bufferSize, :cusparseScsric0 Ptr{Void}), cusparsehandle[1], m, A.nnz, &cudesc, A.nzVal, A.colPtr, A.rowVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsric02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csric02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2585,7 +2585,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrilu02_bufferSize, :cusparseScsril end info = csrilu02Info_t[0] cusparseCreateCsrilu02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -2600,7 +2600,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrilu02_bufferSize, :cusparseScsril Ptr{Void}), cusparsehandle[1], m, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsrilu02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csrilu02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2636,7 +2636,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrilu02_bufferSize, :cusparseScsril end info = csrilu02Info_t[0] cusparseCreateCsrilu02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, Ptr{Cint}, @@ -2651,7 +2651,7 @@ for (bname,aname,sname,elty) in ((:cusparseScsrilu02_bufferSize, :cusparseScsril Ptr{Void}), cusparsehandle[1], m, A.nnz, &cudesc, A.nzVal, A.colPtr, A.rowVal, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXcsrilu02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, csrilu02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2689,7 +2689,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsric02_bufferSize, :cusparseSbsric0 mb = div(m,A.blockDim) info = bsric02Info_t[0] cusparseCreateBsric02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseDirection_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, @@ -2706,7 +2706,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsric02_bufferSize, :cusparseSbsric0 cusparsehandle[1], cudir, mb, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, A.blockDim, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXbsric02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, bsric02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) @@ -2745,7 +2745,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrilu02_bufferSize, :cusparseSbsril mb = div(m,A.blockDim) info = bsrilu02Info_t[0] cusparseCreateBsrilu02Info(info) - bufSize = Array(Cint,1) + bufSize = Array{Cint}(1) statuscheck(ccall(($(string(bname)),libcusparse), cusparseStatus_t, (cusparseHandle_t, cusparseDirection_t, Cint, Cint, Ptr{cusparseMatDescr_t}, Ptr{$elty}, @@ -2762,7 +2762,7 @@ for (bname,aname,sname,elty) in ((:cusparseSbsrilu02_bufferSize, :cusparseSbsril cusparsehandle[1], cudir, mb, A.nnz, &cudesc, A.nzVal, A.rowPtr, A.colVal, A.blockDim, info[1], CUSPARSE_SOLVE_POLICY_USE_LEVEL, buffer)) - posit = Array(Cint,1) + posit = Array{Cint}(1) statuscheck(ccall((:cusparseXbsrilu02_zeroPivot, libcusparse), cusparseStatus_t, (cusparseHandle_t, bsrilu02Info_t, Ptr{Cint}), cusparsehandle[1], info[1], posit)) diff --git a/src/util.jl b/src/util.jl index 85e33ed..0849e6d 100644 --- a/src/util.jl +++ b/src/util.jl @@ -2,14 +2,14 @@ #using CSC format for interop with Julia's native sparse functionality import Base: length, size, ndims, eltype, similar, pointer, stride, - copy, convert, reinterpret, show, summary, copy!, get!, fill!, issym, + copy, convert, reinterpret, show, summary, copy!, get!, fill!, issymmetric, ishermitian, isupper, islower import Base.LinAlg: BlasFloat, Hermitian, HermOrSym import CUDArt: device, to_host, free -abstract AbstractCudaSparseArray{Tv,N} <: AbstractSparseArray{Tv,Cint,N} -typealias AbstractCudaSparseVector{Tv} AbstractCudaSparseArray{Tv,1} -typealias AbstractCudaSparseMatrix{Tv} AbstractCudaSparseArray{Tv,2} +abstract type AbstractCudaSparseArray{Tv,N} <: AbstractSparseArray{Tv,Cint,N} end +const AbstractCudaSparseVector{Tv} = AbstractCudaSparseArray{Tv,1} +const AbstractCudaSparseMatrix{Tv} = AbstractCudaSparseArray{Tv,2} """ Container to hold sparse vectors on the GPU, similar to `SparseVector` in base Julia. @@ -20,7 +20,7 @@ type CudaSparseVector{Tv} <: AbstractCudaSparseVector{Tv} dims::NTuple{2,Int} nnz::Cint dev::Int - function CudaSparseVector{Tv}(iPtr::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::Int, nnz::Cint, dev::Int) + function CudaSparseVector{Tv}(iPtr::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::Int, nnz::Cint, dev::Int) where {Tv} new(iPtr,nzVal,(dims,1),nnz,dev) end end @@ -40,7 +40,7 @@ type CudaSparseMatrixCSC{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixCSC{Tv}(colPtr::CudaVector{Cint}, rowVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) + function CudaSparseMatrixCSC{Tv}(colPtr::CudaVector{Cint}, rowVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} new(colPtr,rowVal,nzVal,dims,nnz,dev) end end @@ -60,7 +60,7 @@ type CudaSparseMatrixCSR{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixCSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) + function CudaSparseMatrixCSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} new(rowPtr,colVal,nzVal,dims,nnz,dev) end end @@ -80,24 +80,24 @@ type CudaSparseMatrixBSR{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixBSR(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int},blockDim::Cint, dir::SparseChar, nnz::Cint, dev::Int) + function CudaSparseMatrixBSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int},blockDim::Cint, dir::SparseChar, nnz::Cint, dev::Int) where{Tv} new(rowPtr,colVal,nzVal,dims,blockDim,dir,nnz,dev) end end -typealias cusparseHybMat_t Ptr{Void} """ Container to hold sparse matrices in NVIDIA's hybrid (HYB) format on the GPU. HYB format is an opaque struct, which can be converted to/from using CUSPARSE routines. """ +const cusparseHybMat_t = Ptr{Void} type CudaSparseMatrixHYB{Tv} <: AbstractCudaSparseMatrix{Tv} Mat::cusparseHybMat_t dims::NTuple{2,Int} nnz::Cint dev::Int - function CudaSparseMatrixHYB(Mat::cusparseHybMat_t, dims::NTuple{2,Int}, nnz::Cint, dev::Int) + function CudaSparseMatrixHYB{Tv}(Mat::cusparseHybMat_t, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} new(Mat,dims,nnz,dev) end end @@ -108,13 +108,13 @@ and `Hermitian` and `Symmetric` versions of these two containers. A function acc this type can make use of performance improvements by only indexing one triangle of the matrix if it is guaranteed to be hermitian/symmetric. """ -typealias CompressedSparse{T} Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T},HermOrSym{T,CudaSparseMatrixCSC{T}},HermOrSym{T,CudaSparseMatrixCSR{T}}} +const CompressedSparse{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T},HermOrSym{T,CudaSparseMatrixCSC{T}},HermOrSym{T,CudaSparseMatrixCSR{T}}} """ Utility union type of [`CudaSparseMatrixCSC`](@ref), [`CudaSparseMatrixCSR`](@ref), [`CudaSparseMatrixBSR`](@ref), and [`CudaSparseMatrixHYB`](@ref). """ -typealias CudaSparseMatrix{T} Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}, CudaSparseMatrixBSR{T}, CudaSparseMatrixHYB{T}} +const CudaSparseMatrix{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}, CudaSparseMatrixBSR{T}, CudaSparseMatrixHYB{T}} Hermitian{T}(Mat::CudaSparseMatrix{T}) = Hermitian{T,typeof(Mat)}(Mat,'U') @@ -145,9 +145,9 @@ function size{T}(g::CudaSparseMatrix{T}, d::Integer) end end -issym{T}(M::Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}}) = false +issymmetric{T}(M::Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}}) = false ishermitian{T}(M::Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}}) = false -issym{T}(M::Symmetric{T,CudaSparseMatrixCSC{T}}) = true +issymmetric{T}(M::Symmetric{T,CudaSparseMatrixCSC{T}}) = true ishermitian{T}(M::Hermitian{T,CudaSparseMatrixCSC{T}}) = true for mat_type in [:CudaSparseMatrixCSC, :CudaSparseMatrixCSR, :CudaSparseMatrixBSR, :CudaSparseMatrixHYB] diff --git a/test/axpyi.jl b/test/axpyi.jl index 5b63403..3590810 100644 --- a/test/axpyi.jl +++ b/test/axpyi.jl @@ -6,61 +6,39 @@ m = 25 n = 35 k = 10 blockdim = 5 +@testset "axpyi" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "axpyi!" begin + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = rand(elty,m) + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + alpha = rand(elty) + d_y = CUSPARSE.axpyi!(alpha,d_x,d_y,'O') + #compare + h_y = to_host(d_y) + y[x.nzind] += alpha * x.nzval + @test h_y ≈ y + end -############## -# test_axpyi # -############## -function test_axpyi!(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - alpha = rand(elty) - d_y = CUSPARSE.axpyi!(alpha,d_x,d_y,'O') - #compare - h_y = to_host(d_y) - if VERSION >= v"0.5.0-dev+742" - y[x.nzind] += alpha * x.nzval - else - y[x.rowval] += alpha * x.nzval + @testset "axpyi" begin + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = rand(elty,m) + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + alpha = rand(elty) + d_z = CUSPARSE.axpyi(alpha,d_x,d_y,'O') + #compare + h_z = to_host(d_z) + z = copy(y) + z[x.nzind] += alpha * x.nzval + @test h_z ≈ z + d_z = CUSPARSE.axpyi(d_x,d_y,'O') + #compare + h_z = to_host(d_z) + z = copy(y) + z[x.nzind] += x.nzval + @test h_z ≈ z + end end - @test h_y ≈ y -end - -function test_axpyi(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - alpha = rand(elty) - d_z = CUSPARSE.axpyi(alpha,d_x,d_y,'O') - #compare - h_z = to_host(d_z) - z = copy(y) - if VERSION >= v"0.5.0-dev+742" - z[x.nzind] += alpha * x.nzval - else - z[x.rowval] += alpha * x.nzval - end - @test h_z ≈ z - d_z = CUSPARSE.axpyi(d_x,d_y,'O') - #compare - h_z = to_host(d_z) - z = copy(y) - if VERSION >= v"0.5.0-dev+742" - z[x.nzind] += x.nzval - else - z[x.rowval] += x.nzval - end - @test h_z ≈ z -end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_axpyi!(elty) - println("axpyi! took ", toq(), " for ", elty) - tic() - test_axpyi(elty) - println("axpyi took ", toq(), " for ", elty) end diff --git a/test/bsric.jl b/test/bsric.jl index 1453363..c933120 100644 --- a/test/bsric.jl +++ b/test/bsric.jl @@ -7,47 +7,35 @@ n = 35 k = 10 blockdim = 5 -################ -# test_bsric02 # -################ +@testset "bsric02" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = rand(elty, m, m) + A += ctranspose(A) + A += m * eye(elty, m) -function test_bsric02!(elty) - A = rand(elty, m, m) - A += ctranspose(A) - A += m * eye(elty, m) - d_A = CudaSparseMatrixCSR(sparse(tril(A))) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_A = CUSPARSE.ic02!(d_A,'O') - h_A = to_host(CUSPARSE.switch2csr(d_A)) - Ac = sparse(full(cholfact(Hermitian(A)))) - h_A = transpose(h_A) * h_A - @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) - d_A = CudaSparseMatrixCSR(sparse(tril(rand(elty,m,n)))) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.ic02!(d_A,'O') -end - -function test_bsric02(elty) - A = rand(elty, m, m) - A += ctranspose(A) - A += m * eye(elty, m) - d_A = CudaSparseMatrixCSR(sparse(tril(A))) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_B = CUSPARSE.ic02(d_A,'O') - h_A = to_host(CUSPARSE.switch2csr(d_B)) - Ac = sparse(full(cholfact(Hermitian(A)))) - h_A = transpose(h_A) * h_A - @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) -end + @testset "bsric02!" begin + d_A = CudaSparseMatrixCSR(sparse(tril(A))) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_A = CUSPARSE.ic02!(d_A,'O') + h_A = to_host(CUSPARSE.switch2csr(d_A)) + Ac = sparse(full(cholfact(Hermitian(A)))) + h_A = transpose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + d_A = CudaSparseMatrixCSR(sparse(tril(rand(elty,m,n)))) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.ic02!(d_A,'O') + end -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_bsric02!(elty) - println("bsric02! took ", toq(), " for ", elty) - tic() - test_bsric02(elty) - println("bsric02 took ", toq(), " for ", elty) + @testset "bsric02" begin + d_A = CudaSparseMatrixCSR(sparse(tril(A))) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_B = CUSPARSE.ic02(d_A,'O') + h_A = to_host(CUSPARSE.switch2csr(d_B)) + Ac = sparse(full(cholfact(Hermitian(A)))) + h_A = transpose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + end + end end diff --git a/test/bsrilu.jl b/test/bsrilu.jl index acd0059..4b2b74a 100644 --- a/test/bsrilu.jl +++ b/test/bsrilu.jl @@ -7,49 +7,36 @@ n = 35 k = 10 blockdim = 5 -################# -# test_bsrilu02 # -################# +@testset "bsrilu02" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = rand(elty,m,m) + A += transpose(A) + A += m * eye(elty,m) + @testset "bsrilu02!" begin + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_A = CUSPARSE.ilu02!(d_A,'O') + h_A = to_host(CUSPARSE.switch2csr(d_A)) + Alu = lufact(full(A),Val{false}) + Ac = sparse(Alu[:L]*Alu[:U]) + h_A = ctranspose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + d_A = CudaSparseMatrixCSR(sparse(rand(elty,m,n))) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.ilu02!(d_A,'O') + end -function test_bsrilu02!(elty) - A = rand(elty,m,m) - A += transpose(A) - A += m * eye(elty,m) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_A = CUSPARSE.ilu02!(d_A,'O') - h_A = to_host(CUSPARSE.switch2csr(d_A)) - Alu = lufact(full(A),Val{false}) - Ac = sparse(Alu[:L]*Alu[:U]) - h_A = ctranspose(h_A) * h_A - @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) - d_A = CudaSparseMatrixCSR(sparse(rand(elty,m,n))) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.ilu02!(d_A,'O') -end - -function test_bsrilu02(elty) - A = rand(elty,m,m) - A += transpose(A) - A += m * eye(elty,m) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_B = CUSPARSE.ilu02(d_A,'O') - h_A = to_host(CUSPARSE.switch2csr(d_B)) - Alu = lufact(full(A),Val{false}) - Ac = sparse(Alu[:L]*Alu[:U]) - h_A = ctranspose(h_A) * h_A - @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) -end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_bsrilu02!(elty) - println("bsrilu02! took ", toq(), " for ", elty) - tic() - test_bsrilu02(elty) - println("bsrilu02 took ", toq(), " for ", elty) + @testset "bsrilu02" begin + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_B = CUSPARSE.ilu02(d_A,'O') + h_A = to_host(CUSPARSE.switch2csr(d_B)) + Alu = lufact(full(A),Val{false}) + Ac = sparse(Alu[:L]*Alu[:U]) + h_A = ctranspose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + end + end end diff --git a/test/bsrsm.jl b/test/bsrsm.jl index ad5a77b..154fa7b 100644 --- a/test/bsrsm.jl +++ b/test/bsrsm.jl @@ -7,55 +7,45 @@ n = 35 k = 10 blockdim = 5 -############### -# test_bsrsm2 # -############### +@testset "bsrsm2" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "bsrsm2!" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m,n) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_X = CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') + h_Y = to_host(d_X) + Y = A\(alpha * X) + @test Y ≈ h_Y + d_X = CudaArray(rand(elty,n,n)) + @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') + @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','T',alpha,d_A,d_X,'O') + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') + end -function test_bsrsm2!(elty) - A = rand(elty,m,m) - A = triu(A) - X = rand(elty,m,n) - alpha = rand(elty) - d_X = CudaArray(X) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_X = CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') - h_Y = to_host(d_X) - Y = A\(alpha * X) - @test Y ≈ h_Y - d_X = CudaArray(rand(elty,n,n)) - @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') - @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','T',alpha,d_A,d_X,'O') - A = sparse(rand(elty,m,n)) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.bsrsm2!('N','N',alpha,d_A,d_X,'O') -end - -function test_bsrsm2(elty) - A = rand(elty,m,m) - A = triu(A) - X = rand(elty,m,n) - alpha = rand(elty) - d_X = CudaArray(X) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_Y = CUSPARSE.bsrsm2('N','N',alpha,d_A,d_X,'O') - h_Y = to_host(d_Y) - Y = A\(alpha * X) - @test Y ≈ h_Y - A = sparse(rand(elty,m,n)) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.bsrsm2('N','N',alpha,d_A,d_X,'O') -end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_bsrsm2!(elty) - println("bsrsm2! took ", toq(), " for ", elty) - tic() - test_bsrsm2(elty) - println("bsrsm2 took ", toq(), " for ", elty) + @testset "bsrsm2" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m,n) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_Y = CUSPARSE.bsrsm2('N','N',alpha,d_A,d_X,'O') + h_Y = to_host(d_Y) + Y = A\(alpha * X) + @test Y ≈ h_Y + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.bsrsm2('N','N',alpha,d_A,d_X,'O') + end + end end diff --git a/test/bsrsv.jl b/test/bsrsv.jl index f2af536..21419d7 100644 --- a/test/bsrsv.jl +++ b/test/bsrsv.jl @@ -7,57 +7,47 @@ n = 35 k = 10 blockdim = 5 -############### -# test_bsrsv2 # -############### +@testset "bsrsv2" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "bsrsv2!" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_X = CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') + h_Y = to_host(d_X) + Y = A\(alpha * X) + @test Y ≈ h_Y + d_X = CudaArray(rand(elty,n)) + @test_throws DimensionMismatch CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') + end -function test_bsrsv2!(elty) - A = rand(elty,m,m) - A = triu(A) - X = rand(elty,m) - alpha = rand(elty) - d_X = CudaArray(X) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_X = CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') - h_Y = to_host(d_X) - Y = A\(alpha * X) - @test Y ≈ h_Y - d_X = CudaArray(rand(elty,n)) - @test_throws DimensionMismatch CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') - A = sparse(rand(elty,m,n)) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O') -end - -function test_bsrsv2(elty) - A = rand(elty,m,m) - A = triu(A) - X = rand(elty,m) - alpha = rand(elty) - d_X = CudaArray(X) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - d_Y = CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') - h_Y = to_host(d_Y) - Y = A\(alpha * X) - @test Y ≈ h_Y - d_Y = UpperTriangular(d_A)\d_X - h_Y = to_host(d_Y) - @test h_Y ≈ A\X - A = sparse(rand(elty,m,n)) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) - @test_throws DimensionMismatch CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') -end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_bsrsv2!(elty) - println("bsrsv2! took ", toq(), " for ", elty) - tic() - test_bsrsv2(elty) - println("bsrsv2 took ", toq(), " for ", elty) + @testset "bsrsv2" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + d_Y = CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') + h_Y = to_host(d_Y) + Y = A\(alpha * X) + @test Y ≈ h_Y + d_Y = UpperTriangular(d_A)\d_X + h_Y = to_host(d_Y) + @test h_Y ≈ A\X + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5)) + @test_throws DimensionMismatch CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') + end + end end diff --git a/test/csic.jl b/test/csic.jl index f225026..4a2edd2 100644 --- a/test/csic.jl +++ b/test/csic.jl @@ -6,76 +6,95 @@ m = 25 n = 35 k = 10 blockdim = 5 - -for (funcr,funcc,func2,typ) in ((:test_csric0_real,:test_csric0_complex,:test_csric02,:CudaSparseMatrixCSR), - (:test_cscic0_real,:test_cscic0_complex,:test_cscic02,:CudaSparseMatrixCSC)) - @eval begin - function $funcr(elty) +@testset "ic0" begin + @testset for elty in [Float32,Float64] + @testset "csr" begin A = rand(elty, m ,m) A = A + transpose(A) A += m * eye(elty ,m) - d_A = Symmetric($typ(sparse(triu(A)))) + d_A = Symmetric(CudaSparseMatrixCSR(sparse(triu(A)))) info = CUSPARSE.sv_analysis('N', 'S', 'U', d_A, 'O') d_B = CUSPARSE.ic0('N', 'S', d_A, info, 'O') h_A = to_host(d_B) Ac = sparse(full(cholfact(A))) h_A = transpose(h_A) * h_A @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) + @test reduce(&, isfinite.(h_A.nzval)) end - - function $funcc(elty) + @testset "csc" begin + A = rand(elty, m ,m) + A = A + transpose(A) + A += m * eye(elty ,m) + d_A = Symmetric(CudaSparseMatrixCSC(sparse(triu(A)))) + info = CUSPARSE.sv_analysis('N', 'S', 'U', d_A, 'O') + d_B = CUSPARSE.ic0('N', 'S', d_A, info, 'O') + h_A = to_host(d_B) + Ac = sparse(full(cholfact(A))) + h_A = transpose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + end + end + @testset for elty in [Complex64,Complex128] + @testset "csr" begin A = rand(elty,m,m) A = A + ctranspose(A) A += m * eye(elty,m) - d_A = Hermitian($typ(sparse(triu(A)))) + d_A = Hermitian(CudaSparseMatrixCSR(sparse(triu(A)))) info = CUSPARSE.sv_analysis('N', 'H', 'U', d_A, 'O') d_B = CUSPARSE.ic0('N', 'H', d_A, info, 'O') h_A = to_host(d_B) Ac = sparse(full(cholfact(A))) h_A = ctranspose(h_A) * h_A @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) + @test reduce(&, isfinite.(h_A.nzval)) end - - function $func2(elty) + @testset "csc" begin + A = rand(elty,m,m) + A = A + ctranspose(A) + A += m * eye(elty,m) + d_A = Hermitian(CudaSparseMatrixCSC(sparse(triu(A)))) + info = CUSPARSE.sv_analysis('N', 'H', 'U', d_A, 'O') + d_B = CUSPARSE.ic0('N', 'H', d_A, info, 'O') + h_A = to_host(d_B) + Ac = sparse(full(cholfact(A))) + h_A = ctranspose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + end + end +end +@testset "ic2" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "csr" begin + A = rand(elty, m, m) + A += ctranspose(A) + A += m * eye(elty, m) + d_A = CudaSparseMatrixCSR(sparse(tril(A))) + d_B = CUSPARSE.ic02(d_A, 'O') + h_A = to_host(d_B) + Ac = sparse(full(cholfact(Hermitian(A)))) + h_A = transpose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + A = rand(elty,m,n) + d_A = CudaSparseMatrixCSR(sparse(tril(A))) + @test_throws DimensionMismatch CUSPARSE.ic02(d_A, 'O') + end + @testset "csc" begin A = rand(elty, m, m) A += ctranspose(A) A += m * eye(elty, m) - d_A = $typ(sparse(tril(A))) + d_A = CudaSparseMatrixCSC(sparse(tril(A))) d_B = CUSPARSE.ic02(d_A, 'O') h_A = to_host(d_B) Ac = sparse(full(cholfact(Hermitian(A)))) h_A = transpose(h_A) * h_A @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) + @test reduce(&, isfinite.(h_A.nzval)) A = rand(elty,m,n) - d_A = $typ(sparse(tril(A))) + d_A = CudaSparseMatrixCSC(sparse(tril(A))) @test_throws DimensionMismatch CUSPARSE.ic02(d_A, 'O') end end end - -types = [Float32,Float64] -@testset for elty in types - tic() - test_csric0_real(elty) - test_cscic0_real(elty) - println("ic0 took ", toq(), " for ", elty) - tic() - test_csric02(elty) - test_cscic02(elty) - println("ic02 took ", toq(), " for ", elty) -end - -types = [Complex64,Complex128] -@testset for elty in types - tic() - test_csric0_complex(elty) - test_cscic0_complex(elty) - println("ic0 took ", toq(), " for ", elty) - tic() - test_csric02(elty) - test_cscic02(elty) - println("ic02 took ", toq(), " for ", elty) -end diff --git a/test/csilu.jl b/test/csilu.jl index 16f77ef..0241575 100644 --- a/test/csilu.jl +++ b/test/csilu.jl @@ -7,12 +7,22 @@ n = 35 k = 10 blockdim = 5 -for (func,func2,typ) in ((:test_csrilu0,:test_csrilu02,:CudaSparseMatrixCSR), - (:test_cscilu0,:test_cscilu02,:CudaSparseMatrixCSC)) - @eval begin - function $func(elty) - A = rand(elty,m,m) - d_A = $typ(sparse(A)) +@testset "ilu0" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = rand(elty,m,m) + @testset "csr" begin + d_A = CudaSparseMatrixCSR(sparse(A)) + info = CUSPARSE.sv_analysis('N','G','U',d_A,'O') + d_B = CUSPARSE.ilu0('N',d_A,info,'O') + h_B = to_host(d_B) + Alu = lufact(full(A),Val{false}) + Ac = sparse(Alu[:L]*Alu[:U]) + h_A = ctranspose(h_B) * h_B + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) + end + @testset "csc" begin + d_A = CudaSparseMatrixCSC(sparse(A)) info = CUSPARSE.sv_analysis('N','G','U',d_A,'O') d_B = CUSPARSE.ilu0('N',d_A,info,'O') h_B = to_host(d_B) @@ -20,33 +30,38 @@ for (func,func2,typ) in ((:test_csrilu0,:test_csrilu02,:CudaSparseMatrixCSR), Ac = sparse(Alu[:L]*Alu[:U]) h_A = ctranspose(h_B) * h_B @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) + @test reduce(&, isfinite.(h_A.nzval)) end + end +end - function $func2(elty) +@testset "ilu02" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "csr" begin A = rand(elty,m,m) A += transpose(A) A += m * eye(elty,m) - d_A = $typ(sparse(A)) + d_A = CudaSparseMatrixCSR(sparse(A)) d_B = CUSPARSE.ilu02(d_A,'O') h_A = to_host(d_B) Alu = lufact(full(A),Val{false}) Ac = sparse(Alu[:L]*Alu[:U]) h_A = ctranspose(h_A) * h_A @test h_A.rowval ≈ Ac.rowval - @test reduce(&, isfinite(h_A.nzval)) + @test reduce(&, isfinite.(h_A.nzval)) + end + @testset "csc" begin + A = rand(elty,m,m) + A += transpose(A) + A += m * eye(elty,m) + d_A = CudaSparseMatrixCSC(sparse(A)) + d_B = CUSPARSE.ilu02(d_A,'O') + h_A = to_host(d_B) + Alu = lufact(full(A),Val{false}) + Ac = sparse(Alu[:L]*Alu[:U]) + h_A = ctranspose(h_A) * h_A + @test h_A.rowval ≈ Ac.rowval + @test reduce(&, isfinite.(h_A.nzval)) end end end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_csrilu0(elty) - test_cscilu0(elty) - println("ilu0 took ", toq(), " for ", elty) - tic() - test_csrilu02(elty) - test_cscilu02(elty) - println("ilu02 took ", toq(), " for ", elty) -end diff --git a/test/cssm.jl b/test/cssm.jl index acfe62f..870a336 100644 --- a/test/cssm.jl +++ b/test/cssm.jl @@ -7,16 +7,15 @@ n = 35 k = 10 blockdim = 5 -for (func,typ) in ((:test_csrsm,:CudaSparseMatrixCSR), - (:test_cscsm,:CudaSparseMatrixCSC)) - @eval begin - function $func(elty) +@testset "csrsm" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "csr" begin A = rand(elty,m,m) A = triu(A) X = rand(elty,m,n) alpha = rand(elty) d_X = CudaArray(X) - d_A = $typ(sparse(A)) + d_A = CudaSparseMatrixCSR(sparse(A)) info = CUSPARSE.sm_analysis('N','U',d_A,'O') d_Y = CUSPARSE.sm_solve('N','U',alpha,d_A,d_X,info,'O') h_Y = to_host(d_Y) @@ -29,17 +28,32 @@ for (func,typ) in ((:test_csrsm,:CudaSparseMatrixCSR), d_X = CudaArray(rand(elty,n,n)) @test_throws DimensionMismatch CUSPARSE.sm_solve('N','U',alpha,d_A,d_X,info,'O') A = sparse(rand(elty,m,n)) - d_A = $typ(A) + d_A = CudaSparseMatrixCSR(A) + @test_throws DimensionMismatch CUSPARSE.sm_analysis('T','U',d_A,'O') + CUSPARSE.cusparseDestroySolveAnalysisInfo(info) + end + @testset "csc" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m,n) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSC(sparse(A)) + info = CUSPARSE.sm_analysis('N','U',d_A,'O') + d_Y = CUSPARSE.sm_solve('N','U',alpha,d_A,d_X,info,'O') + h_Y = to_host(d_Y) + Y = A\(alpha * X) + @test Y ≈ h_Y + d_y = UpperTriangular(d_A)\d_X + h_y = to_host(d_y) + y = A\X + @test y ≈ h_y + d_X = CudaArray(rand(elty,n,n)) + @test_throws DimensionMismatch CUSPARSE.sm_solve('N','U',alpha,d_A,d_X,info,'O') + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSC(A) @test_throws DimensionMismatch CUSPARSE.sm_analysis('T','U',d_A,'O') CUSPARSE.cusparseDestroySolveAnalysisInfo(info) end end end - -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_csrsm(elty) - test_cscsm(elty) - println("sm took ", toq(), " for ", elty) -end diff --git a/test/cssv.jl b/test/cssv.jl index 30f584e..6b7dbd0 100644 --- a/test/cssv.jl +++ b/test/cssv.jl @@ -7,20 +7,36 @@ n = 35 k = 10 blockdim = 5 -############## -# test_csrsv # -############## +@testset "cssv" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "csrsv" begin + A = rand(elty,m,m) + A = triu(A) + x = rand(elty,m) + alpha = rand(elty) + d_x = CudaArray(x) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_y = CUSPARSE.sv('N','T','U',alpha,d_A,d_x,'O') + h_y = to_host(d_y) + y = A\(alpha * x) + @test y ≈ h_y + x = rand(elty,n) + d_x = CudaArray(x) + info = CUSPARSE.sv_analysis('N','T','U',d_A,'O') + @test_throws DimensionMismatch CUSPARSE.sv_solve('N','U',alpha,d_A,d_x,info,'O') + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + @test_throws DimensionMismatch CUSPARSE.sv_analysis('T','T','U',d_A,'O') + CUSPARSE.cusparseDestroySolveAnalysisInfo(info) + end -for (func,func2,typ) in ((:test_csrsv,:test_csrsv2,:CudaSparseMatrixCSR), - (:test_cscsv,:test_cscsv2,:CudaSparseMatrixCSC)) - @eval begin - function $func(elty) + @testset "cscsv" begin A = rand(elty,m,m) A = triu(A) x = rand(elty,m) alpha = rand(elty) d_x = CudaArray(x) - d_A = $typ(sparse(A)) + d_A = CudaSparseMatrixCSC(sparse(A)) d_y = CUSPARSE.sv('N','T','U',alpha,d_A,d_x,'O') h_y = to_host(d_y) y = A\(alpha * x) @@ -30,18 +46,18 @@ for (func,func2,typ) in ((:test_csrsv,:test_csrsv2,:CudaSparseMatrixCSR), info = CUSPARSE.sv_analysis('N','T','U',d_A,'O') @test_throws DimensionMismatch CUSPARSE.sv_solve('N','U',alpha,d_A,d_x,info,'O') A = sparse(rand(elty,m,n)) - d_A = $typ(A) + d_A = CudaSparseMatrixCSC(A) @test_throws DimensionMismatch CUSPARSE.sv_analysis('T','T','U',d_A,'O') CUSPARSE.cusparseDestroySolveAnalysisInfo(info) end - function $func2(elty) + @testset "csrsv2" begin A = rand(elty,m,m) A = triu(A) X = rand(elty,m) alpha = rand(elty) d_X = CudaArray(X) - d_A = $typ(sparse(A)) + d_A = CudaSparseMatrixCSR(sparse(A)) d_Y = CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') h_Y = to_host(d_Y) Y = A\(alpha * X) @@ -51,20 +67,28 @@ for (func,func2,typ) in ((:test_csrsv,:test_csrsv2,:CudaSparseMatrixCSR), y = A\X @test y ≈ h_y A = sparse(rand(elty,m,n)) - d_A = $typ(A) + d_A = CudaSparseMatrixCSR(A) @test_throws DimensionMismatch CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') end - end -end -types = [Float32,Float64,Complex64,Complex128] -@testset for elty in types - tic() - test_csrsv(elty) - test_cscsv(elty) - println("cssv took ", toq(), " for ", elty) - tic() - test_csrsv2(elty) - test_cscsv2(elty) - println("cssv2 took ", toq(), " for ", elty) + @testset "cscsv2" begin + A = rand(elty,m,m) + A = triu(A) + X = rand(elty,m) + alpha = rand(elty) + d_X = CudaArray(X) + d_A = CudaSparseMatrixCSC(sparse(A)) + d_Y = CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') + h_Y = to_host(d_Y) + Y = A\(alpha * X) + @test Y ≈ h_Y + d_y = UpperTriangular(d_A)\d_X + h_y = to_host(d_y) + y = A\X + @test y ≈ h_y + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSC(A) + @test_throws DimensionMismatch CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O') + end + end end diff --git a/test/dot.jl b/test/dot.jl index a713154..ba76c68 100644 --- a/test/dot.jl +++ b/test/dot.jl @@ -7,59 +7,34 @@ n = 35 k = 10 blockdim = 5 -############# -# test_doti # -############# - -function test_doti(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - ddot = CUSPARSE.doti(d_x,d_y,'O') - #compare - dot = zero(elty) - for i in 1:length(x.nzval) - if VERSION >= v"0.5.0-dev+742" +@testset "doti" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = rand(elty,m) + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + ddot = CUSPARSE.doti(d_x,d_y,'O') + #compare + dot = zero(elty) + for i in 1:length(x.nzval) dot += x.nzval[i] * y[x.nzind[i]] - else - dot += x.nzval[i] * y[x.rowval[i]] end + @test ddot ≈ dot end - @test ddot ≈ dot end -############## -# test_dotci # -############## - -function test_dotci(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - ddot = CUSPARSE.dotci(d_x,d_y,'O') - #compare - dot = zero(elty) - for i in 1:length(x.nzval) - if VERSION >= v"0.5.0-dev+742" +@testset "dotci" begin + @testset for elty in [Complex64,Complex128] + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = rand(elty,m) + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + ddot = CUSPARSE.dotci(d_x,d_y,'O') + #compare + dot = zero(elty) + for i in 1:length(x.nzval) dot += conj(x.nzval[i]) * y[x.nzind[i]] - else - dot += conj(x.nzval[i]) * y[x.rowval[i]] end + @test ddot ≈ dot end - @test ddot ≈ dot -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_doti(elty) - println("doti took ", toq(), " for ", elty) -end -types = [Complex64,Complex128] -for elty in types - tic() - test_dotci(elty) - println("dotci took ", toq(), " for ", elty) end diff --git a/test/geam.jl b/test/geam.jl index 92a9ad4..13d581a 100644 --- a/test/geam.jl +++ b/test/geam.jl @@ -7,17 +7,16 @@ n = 5 k = 10 blockdim = 5 -for (func,typ) in ((:test_geam_csr,:CudaSparseMatrixCSR), - (:test_geam_csc,:CudaSparseMatrixCSC)) - @eval begin - function $func(elty) - A = sparse(rand(elty,m,n)) - B = sparse(rand(elty,m,n)) - alpha = rand(elty) - beta = rand(elty) +@testset "geam" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,n)) + B = sparse(rand(elty,m,n)) + alpha = rand(elty) + beta = rand(elty) + @testset "csr" begin + d_A = CudaSparseMatrixCSR(A) + d_B = CudaSparseMatrixCSR(B) C = alpha * A + beta * B - d_A = $typ(A) - d_B = $typ(B) d_C = CUSPARSE.geam(alpha,d_A,beta,d_B,'O','O','O') h_C = to_host(d_C) @test C ≈ h_C @@ -40,38 +39,59 @@ for (func,typ) in ((:test_geam_csr,:CudaSparseMatrixCSR), d_C = d_A - d_B h_C = to_host(d_C) C = A - B - @test C ≈ h_C - B = sparse(rand(elty,k,n)) - d_B = $typ(B) + @test C ≈ h_C + B_ = sparse(rand(elty,k,n)) + d_B = CudaSparseMatrixCSR(B_) + @test_throws DimensionMismatch CUSPARSE.geam(d_B,d_A,'O','O','O') + end + @testset "csc" begin + d_A = CudaSparseMatrixCSC(A) + d_B = CudaSparseMatrixCSC(B) + C = alpha * A + beta * B + d_C = CUSPARSE.geam(alpha,d_A,beta,d_B,'O','O','O') + h_C = to_host(d_C) + @test C ≈ h_C + d_C = CUSPARSE.geam(d_A,beta,d_B,'O','O','O') + h_C = to_host(d_C) + C = A + beta * B + @test C ≈ h_C + d_C = CUSPARSE.geam(alpha,d_A,d_B,'O','O','O') + h_C = to_host(d_C) + C = alpha * A + B + @test C ≈ h_C + d_C = CUSPARSE.geam(d_A,d_B,'O','O','O') + h_C = to_host(d_C) + C = A + B + @test C ≈ h_C + d_C = d_A + d_B + h_C = to_host(d_C) + C = A + B + @test C ≈ h_C + d_C = d_A - d_B + h_C = to_host(d_C) + C = A - B + @test C ≈ h_C + B_ = sparse(rand(elty,k,n)) + d_B = CudaSparseMatrixCSC(B_) @test_throws DimensionMismatch CUSPARSE.geam(d_B,d_A,'O','O','O') end + @testset "mixed" begin + A = spdiagm(rand(elty,m)) + B = spdiagm(rand(elty,m)) + sparse(diagm(rand(elty,m-1),1)) + d_A = CudaSparseMatrixCSR(A) + d_B = CudaSparseMatrixCSC(B) + d_C = d_B + d_A + h_C = to_host(d_C) + @test h_C ≈ A + B + d_C = d_A + d_B + h_C = to_host(d_C) + @test h_C ≈ A + B + d_C = d_A - d_B + h_C = to_host(d_C) + @test h_C ≈ A - B + d_C = d_B - d_A + h_C = to_host(d_C) + @test h_C ≈ B - A + end end end - -function test_geam_mix(elty) - A = spdiagm(rand(elty,m)) - B = spdiagm(rand(elty,m)) + sparse(diagm(rand(elty,m-1),1)) - d_A = CudaSparseMatrixCSR(A) - d_B = CudaSparseMatrixCSC(B) - d_C = d_B + d_A - h_C = to_host(d_C) - @test h_C ≈ A + B - d_C = d_A + d_B - h_C = to_host(d_C) - @test h_C ≈ A + B - d_C = d_A - d_B - h_C = to_host(d_C) - @test h_C ≈ A - B - d_C = d_B - d_A - h_C = to_host(d_C) - @test h_C ≈ B - A -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_geam_csr(elty) - test_geam_csc(elty) - test_geam_mix(elty) - println("geam took ", toq(), " for ", elty) -end diff --git a/test/gemm.jl b/test/gemm.jl index 4ca0631..4252306 100644 --- a/test/gemm.jl +++ b/test/gemm.jl @@ -7,43 +7,34 @@ n = 35 k = 10 blockdim = 5 -############# -# test_gemm # -############# - -function test_gemm(elty) - A = sparse(rand(elty,m,k)) - B = sparse(rand(elty,k,n)) - C = A * B - d_A = CudaSparseMatrixCSR(A) - d_B = CudaSparseMatrixCSR(B) - d_C = CUSPARSE.gemm('N','N',d_A,d_B,'O','O','O') - r_r = to_host(d_C.rowPtr) - r_c = to_host(d_C.colVal) - r_v = to_host(d_C.nzVal) - h_C = to_host(d_C) - @test C ≈ h_C - @test_throws DimensionMismatch CUSPARSE.gemm('N','T',d_A,d_B,'O','O','O') - @test_throws DimensionMismatch CUSPARSE.gemm('T','T',d_A,d_B,'O','O','O') - @test_throws DimensionMismatch CUSPARSE.gemm('T','N',d_A,d_B,'O','O','O') - @test_throws DimensionMismatch CUSPARSE.gemm('N','N',d_B,d_A,'O','O','O') - #=A = sparse(rand(elty,m,k)) - B = sparse(rand(elty,k,n)) - d_A = CudaSparseMatrixCSC(A) - d_B = CudaSparseMatrixCSC(B) - C = A * B - d_C = CUSPARSE.gemm('N','N',d_A,d_B,'O','O','O') - h_C = to_host(d_C) - @test_approx_eq(C,h_C) - @test_throws(DimensionMismatch,CUSPARSE.gemm('N','T',d_A,d_B,'O','O','O')) - @test_throws(DimensionMismatch,CUSPARSE.gemm('T','T',d_A,d_B,'O','O','O')) - @test_throws(DimensionMismatch,CUSPARSE.gemm('T','N',d_A,d_B,'O','O','O')) - @test_throws(DimensionMismatch,CUSPARSE.gemm('N','N',d_B,d_A,'O','O','O'))=# -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_gemm(elty) - println("gemm took ", toq(), " for ", elty) +@testset "gemm" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,k)) + B = sparse(rand(elty,k,n)) + C = A * B + d_A = CudaSparseMatrixCSR(A) + d_B = CudaSparseMatrixCSR(B) + d_C = CUSPARSE.gemm('N','N',d_A,d_B,'O','O','O') + r_r = to_host(d_C.rowPtr) + r_c = to_host(d_C.colVal) + r_v = to_host(d_C.nzVal) + h_C = to_host(d_C) + @test C ≈ h_C + @test_throws DimensionMismatch CUSPARSE.gemm('N','T',d_A,d_B,'O','O','O') + @test_throws DimensionMismatch CUSPARSE.gemm('T','T',d_A,d_B,'O','O','O') + @test_throws DimensionMismatch CUSPARSE.gemm('T','N',d_A,d_B,'O','O','O') + @test_throws DimensionMismatch CUSPARSE.gemm('N','N',d_B,d_A,'O','O','O') + #=A = sparse(rand(elty,m,k)) + B = sparse(rand(elty,k,n)) + d_A = CudaSparseMatrixCSC(A) + d_B = CudaSparseMatrixCSC(B) + C = A * B + d_C = CUSPARSE.gemm('N','N',d_A,d_B,'O','O','O') + h_C = to_host(d_C) + @test_approx_eq(C,h_C) + @test_throws(DimensionMismatch,CUSPARSE.gemm('N','T',d_A,d_B,'O','O','O')) + @test_throws(DimensionMismatch,CUSPARSE.gemm('T','T',d_A,d_B,'O','O','O')) + @test_throws(DimensionMismatch,CUSPARSE.gemm('T','N',d_A,d_B,'O','O','O')) + @test_throws(DimensionMismatch,CUSPARSE.gemm('N','N',d_B,d_A,'O','O','O'))=# + end end diff --git a/test/gthr.jl b/test/gthr.jl index 5865099..1d84af5 100644 --- a/test/gthr.jl +++ b/test/gthr.jl @@ -7,92 +7,46 @@ n = 35 k = 10 blockdim = 5 -############# -# test_gthr # -############# - -function test_gthr!(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - d_y = CUSPARSE.gthr!(d_x,d_y,'O') - h_x = to_host(d_x) - if VERSION >= v"0.5.0-dev+742" - @test h_x ≈ SparseVector(m,x.nzind,y[x.nzind]) - else - @test h_x ≈ sparsevec(x.rowval,y[x.rowval],m) - end -end - -function test_gthr(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - d_z = CUSPARSE.gthr(d_x,d_y,'O') - h_z = to_host(d_z) - if VERSION >= v"0.5.0-dev+742" - @test h_z ≈ SparseVector(m,x.nzind,y[x.nzind]) - else - @test h_z ≈ sparsevec(x.rowval,y[x.rowval],m) +@testset "gthr and gthrz" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = rand(elty,m) + @testset "gthr!" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + d_y = CUSPARSE.gthr!(d_x,d_y,'O') + h_x = to_host(d_x) + @test h_x ≈ SparseVector(m,x.nzind,y[x.nzind]) + end + + @testset "gthr" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + d_z = CUSPARSE.gthr(d_x,d_y,'O') + h_z = to_host(d_z) + @test h_z ≈ SparseVector(m,x.nzind,y[x.nzind]) + end + + @testset "gthrz!" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + d_x,d_y = CUSPARSE.gthrz!(d_x,d_y,'O') + h_x = to_host(d_x) + h_y = to_host(d_y) + @test h_x ≈ SparseVector(m,x.nzind,y[x.nzind]) + y[x.nzind] = zero(elty) + @test h_y ≈ y + end + + @testset "gthrz" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + d_z,d_w = CUSPARSE.gthrz(d_x,d_y,'O') + h_w = to_host(d_w) + h_z = to_host(d_z) + @test h_z ≈ SparseVector(m,x.nzind,y[x.nzind]) + y[x.nzind] = zero(elty) + @test h_w ≈ y + end end end - -############## -# test_gthrz # -############## - -function test_gthrz!(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - d_x,d_y = CUSPARSE.gthrz!(d_x,d_y,'O') - h_x = to_host(d_x) - h_y = to_host(d_y) - if VERSION >= v"0.5.0-dev+742" - @test h_x ≈ SparseVector(m,x.nzind,y[x.nzind]) - y[x.nzind] = zero(elty) - @test h_y ≈ y - else - @test h_x ≈ sparsevec(x.rowval,y[x.rowval],m) - y[x.rowval] = zero(elty) - @test h_y ≈ y - end -end - -function test_gthrz(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - d_z,d_w = CUSPARSE.gthrz(d_x,d_y,'O') - h_w = to_host(d_w) - h_z = to_host(d_z) - if VERSION >= v"0.5.0-dev+742" - @test h_z ≈ SparseVector(m,x.nzind,y[x.nzind]) - y[x.nzind] = zero(elty) - @test h_w ≈ y - else - @test h_z ≈ sparsevec(x.rowval,y[x.rowval],m) - y[x.rowval] = zero(elty) - @test h_w ≈ y - end -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_gthr!(elty) - println("gthr! took ", toq(), " for ", elty) - tic() - test_gthr(elty) - println("gthr took ", toq(), " for ", elty) - tic() - test_gthrz!(elty) - println("gthrz! took ", toq(), " for ", elty) - tic() - test_gthrz(elty) - println("gthrz took ", toq(), " for ", elty) -end diff --git a/test/gtsv.jl b/test/gtsv.jl index ca7b923..0de2e87 100644 --- a/test/gtsv.jl +++ b/test/gtsv.jl @@ -7,138 +7,108 @@ n = 35 k = 10 blockdim = 5 -############# -# test_gtsv # -############# +@testset "gtsv" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + @testset "gtsv!" begin + dl = rand(elty,m-1) + du = rand(elty,m-1) + d = rand(elty,m) + B = rand(elty,m,n) + d_dl = CudaArray(vcat([0],dl)) + d_du = CudaArray(vcat(du,[0])) + d_d = CudaArray(d) + d_B = CudaArray(B) + d_B = CUSPARSE.gtsv!(d_dl,d_d,d_du,d_B) + C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) + h_B = to_host(d_B) + @test h_B ≈ C\B + end -function test_gtsv!(elty) - dl = rand(elty,m-1) - du = rand(elty,m-1) - d = rand(elty,m) - B = rand(elty,m,n) - d_dl = CudaArray(vcat([0],dl)) - d_du = CudaArray(vcat(du,[0])) - d_d = CudaArray(d) - d_B = CudaArray(B) - d_B = CUSPARSE.gtsv!(d_dl,d_d,d_du,d_B) - C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) - h_B = to_host(d_B) - @test h_B ≈ C\B -end - -function test_gtsv(elty) - dl = rand(elty,m-1) - du = rand(elty,m-1) - d = rand(elty,m) - B = rand(elty,m,n) - d_dl = CudaArray(vcat([0],dl)) - d_du = CudaArray(vcat(du,[0])) - d_d = CudaArray(d) - d_B = CudaArray(B) - d_C = CUSPARSE.gtsv(d_dl,d_d,d_du,d_B) - C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) - h_C = to_host(d_C) - @test h_C ≈ C\B -end - -##################### -# test_gtsv_nopivot # -##################### - -function test_gtsv_nopivot!(elty) - dl = rand(elty,m-1) - du = rand(elty,m-1) - d = rand(elty,m) - B = rand(elty,m,n) - d_dl = CudaArray(vcat([0],dl)) - d_du = CudaArray(vcat(du,[0])) - d_d = CudaArray(d) - d_B = CudaArray(B) - d_B = CUSPARSE.gtsv_nopivot!(d_dl,d_d,d_du,d_B) - C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) - h_B = to_host(d_B) - @test h_B ≈ C\B -end + @testset "gtsv" begin + dl = rand(elty,m-1) + du = rand(elty,m-1) + d = rand(elty,m) + B = rand(elty,m,n) + d_dl = CudaArray(vcat([0],dl)) + d_du = CudaArray(vcat(du,[0])) + d_d = CudaArray(d) + d_B = CudaArray(B) + d_C = CUSPARSE.gtsv(d_dl,d_d,d_du,d_B) + C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) + h_C = to_host(d_C) + @test h_C ≈ C\B + end -function test_gtsv_nopivot(elty) - dl = rand(elty,m-1) - du = rand(elty,m-1) - d = rand(elty,m) - B = rand(elty,m,n) - d_dl = CudaArray(vcat([0],dl)) - d_du = CudaArray(vcat(du,[0])) - d_d = CudaArray(d) - d_B = CudaArray(B) - d_C = CUSPARSE.gtsv_nopivot(d_dl,d_d,d_du,d_B) - C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) - h_C = to_host(d_C) - @test h_C ≈ C\B -end + @testset "gtsv_nopivot!" begin + dl = rand(elty,m-1) + du = rand(elty,m-1) + d = rand(elty,m) + B = rand(elty,m,n) + d_dl = CudaArray(vcat([0],dl)) + d_du = CudaArray(vcat(du,[0])) + d_d = CudaArray(d) + d_B = CudaArray(B) + d_B = CUSPARSE.gtsv_nopivot!(d_dl,d_d,d_du,d_B) + C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) + h_B = to_host(d_B) + @test h_B ≈ C\B + end -######################### -# test_gtsvStridedBatch # -######################### + @testset "gtsv_nopivot" begin + dl = rand(elty,m-1) + du = rand(elty,m-1) + d = rand(elty,m) + B = rand(elty,m,n) + d_dl = CudaArray(vcat([0],dl)) + d_du = CudaArray(vcat(du,[0])) + d_d = CudaArray(d) + d_B = CudaArray(B) + d_C = CUSPARSE.gtsv_nopivot(d_dl,d_d,d_du,d_B) + C = diagm(d,0) + diagm(du,1) + diagm(dl,-1) + h_C = to_host(d_C) + @test h_C ≈ C\B + end -function test_gtsvStridedBatch!(elty) - dla = rand(elty,m-1) - dua = rand(elty,m-1) - da = rand(elty,m) - dlb = rand(elty,m-1) - dub = rand(elty,m-1) - db = rand(elty,m) - xa = rand(elty,m) - xb = rand(elty,m) - d_dl = CudaArray(vcat([0],dla,[0],dlb)) - d_du = CudaArray(vcat(dua,[0],dub,[0])) - d_d = CudaArray(vcat(da,db)) - d_x = CudaArray(vcat(xa,xb)) - d_x = CUSPARSE.gtsvStridedBatch!(d_dl,d_d,d_du,d_x,2,m) - Ca = diagm(da,0) + diagm(dua,1) + diagm(dla,-1) - Cb = diagm(db,0) + diagm(dub,1) + diagm(dlb,-1) - h_x = to_host(d_x) - @test h_x[1:m] ≈ Ca\xa - @test h_x[m+1:2*m] ≈ Cb\xb -end - -function test_gtsvStridedBatch(elty) - dla = rand(elty,m-1) - dua = rand(elty,m-1) - da = rand(elty,m) - dlb = rand(elty,m-1) - dub = rand(elty,m-1) - db = rand(elty,m) - xa = rand(elty,m) - xb = rand(elty,m) - d_dl = CudaArray(vcat([0],dla,[0],dlb)) - d_du = CudaArray(vcat(dua,[0],dub,[0])) - d_d = CudaArray(vcat(da,db)) - d_x = CudaArray(vcat(xa,xb)) - d_y = CUSPARSE.gtsvStridedBatch(d_dl,d_d,d_du,d_x,2,m) - Ca = diagm(da,0) + diagm(dua,1) + diagm(dla,-1) - Cb = diagm(db,0) + diagm(dub,1) + diagm(dlb,-1) - h_y = to_host(d_y) - @test h_y[1:m] ≈ Ca\xa - @test h_y[m+1:2*m] ≈ Cb\xb -end + @testset "gtsvStridedBatch!" begin + dla = rand(elty,m-1) + dua = rand(elty,m-1) + da = rand(elty,m) + dlb = rand(elty,m-1) + dub = rand(elty,m-1) + db = rand(elty,m) + xa = rand(elty,m) + xb = rand(elty,m) + d_dl = CudaArray(vcat([0],dla,[0],dlb)) + d_du = CudaArray(vcat(dua,[0],dub,[0])) + d_d = CudaArray(vcat(da,db)) + d_x = CudaArray(vcat(xa,xb)) + d_x = CUSPARSE.gtsvStridedBatch!(d_dl,d_d,d_du,d_x,2,m) + Ca = diagm(da,0) + diagm(dua,1) + diagm(dla,-1) + Cb = diagm(db,0) + diagm(dub,1) + diagm(dlb,-1) + h_x = to_host(d_x) + @test h_x[1:m] ≈ Ca\xa + @test h_x[m+1:2*m] ≈ Cb\xb + end -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_gtsv!(elty) - println("gtsv! took ", toq(), " for ", elty) - tic() - test_gtsv(elty) - println("gtsv took ", toq(), " for ", elty) - tic() - test_gtsv_nopivot!(elty) - println("gtsv_nopivot! took ", toq(), " for ", elty) - tic() - test_gtsv_nopivot(elty) - println("gtsv_nopivot took ", toq(), " for ", elty) - tic() - test_gtsvStridedBatch!(elty) - println("gtsvStridedBatch! took ", toq(), " for ", elty) - tic() - test_gtsvStridedBatch(elty) - println("gtsvStridedBatch took ", toq(), " for ", elty) + @testset "gtsvStridedBatch" begin + dla = rand(elty,m-1) + dua = rand(elty,m-1) + da = rand(elty,m) + dlb = rand(elty,m-1) + dub = rand(elty,m-1) + db = rand(elty,m) + xa = rand(elty,m) + xb = rand(elty,m) + d_dl = CudaArray(vcat([0],dla,[0],dlb)) + d_du = CudaArray(vcat(dua,[0],dub,[0])) + d_d = CudaArray(vcat(da,db)) + d_x = CudaArray(vcat(xa,xb)) + d_y = CUSPARSE.gtsvStridedBatch(d_dl,d_d,d_du,d_x,2,m) + Ca = diagm(da,0) + diagm(dua,1) + diagm(dla,-1) + Cb = diagm(db,0) + diagm(dub,1) + diagm(dlb,-1) + h_y = to_host(d_y) + @test h_y[1:m] ≈ Ca\xa + @test h_y[m+1:2*m] ≈ Cb\xb + end + end end diff --git a/test/hybsv.jl b/test/hybsv.jl index 54ca129..3b95056 100644 --- a/test/hybsv.jl +++ b/test/hybsv.jl @@ -7,41 +7,32 @@ n = 35 k = 10 blockdim = 5 -############## -# test_hybsv # -############## +@testset "hybsv" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = rand(elty,m,m) + A = triu(A) + x = rand(elty,m) + alpha = rand(elty) + beta = rand(elty) + d_x = CudaArray(x) + d_A = CudaSparseMatrixCSR(sparse(A)) + d_A = CUSPARSE.switch2hyb(d_A) + d_y = CUSPARSE.sv('N','T','U',alpha,d_A,d_x,'O') + h_y = to_host(d_y) + y = A\(alpha * x) + @test y ≈ h_y -function test_hybsv(elty) - A = rand(elty,m,m) - A = triu(A) - x = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_A = CudaSparseMatrixCSR(sparse(A)) - d_A = CUSPARSE.switch2hyb(d_A) - d_y = CUSPARSE.sv('N','T','U',alpha,d_A,d_x,'O') - h_y = to_host(d_y) - y = A\(alpha * x) - @test y ≈ h_y + d_y = UpperTriangular(d_A) \ d_x + h_y = to_host(d_y) + @test h_y ≈ A\x - d_y = UpperTriangular(d_A) \ d_x - h_y = to_host(d_y) - @test h_y ≈ A\x - - d_x = CudaArray(rand(elty,n)) - info = CUSPARSE.sv_analysis('N','T','U',d_A,'O') - @test_throws DimensionMismatch CUSPARSE.sv_solve('N','U',alpha,d_A,d_x,info,'O') - A = sparse(rand(elty,m,n)) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2hyb(d_A) - @test_throws DimensionMismatch CUSPARSE.sv_analysis('T','T','U',d_A,'O') - CUSPARSE.cusparseDestroySolveAnalysisInfo(info) -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_hybsv(elty) - println("hybsv took ", toq(), " for ", elty) + d_x = CudaArray(rand(elty,n)) + info = CUSPARSE.sv_analysis('N','T','U',d_A,'O') + @test_throws DimensionMismatch CUSPARSE.sv_solve('N','U',alpha,d_A,d_x,info,'O') + A = sparse(rand(elty,m,n)) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2hyb(d_A) + @test_throws DimensionMismatch CUSPARSE.sv_analysis('T','T','U',d_A,'O') + CUSPARSE.cusparseDestroySolveAnalysisInfo(info) + end end diff --git a/test/mm.jl b/test/mm.jl index 0c10063..4e8bacd 100644 --- a/test/mm.jl +++ b/test/mm.jl @@ -7,102 +7,199 @@ n = 35 k = 10 blockdim = 5 -############## -# test_csrmm # -############## +@testset "mm" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,k)) + B = rand(elty,k,n) + C = rand(elty,m,n) + alpha = rand(elty) + beta = rand(elty) + @testset "csr" begin + d_B = CudaArray(B) + d_C = CudaArray(C) + d_A = CudaSparseMatrixCSR(A) + @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') + d_D = CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = alpha * A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,d_C,'O') + h_D = to_host(d_D) + D = A * B + C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',alpha,d_A,d_B,'O') + h_D = to_host(d_D) + D = alpha * A * B + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,'O') + h_D = to_host(d_D) + D = A * B + @test D ≈ h_D + d_D = d_A*d_B + h_D = to_host(d_D) + D = A * B + @test D ≈ h_D + @test_throws DimensionMismatch CUSPARSE.mm('T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_B,'O') + end + @testset "csc" begin + d_B = CudaArray(B) + d_C = CudaArray(C) + d_A = CudaSparseMatrixCSC(A) + @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') + d_D = CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = alpha * A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,d_C,'O') + h_D = to_host(d_D) + D = A * B + C + @test D ≈ h_D + d_D = CUSPARSE.mm('N',alpha,d_A,d_B,'O') + h_D = to_host(d_D) + D = alpha * A * B + @test D ≈ h_D + d_D = CUSPARSE.mm('N',d_A,d_B,'O') + h_D = to_host(d_D) + D = A * B + @test D ≈ h_D + d_D = d_A*d_B + h_D = to_host(d_D) + D = A * B + @test D ≈ h_D + @test_throws DimensionMismatch CUSPARSE.mm('T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_B,'O') + end + end +end -for (func,funcs,funch,func2,typ) in ((:test_csrmm,:test_csrmm_symm,:test_csrmm_herm,:test_csrmm2,:CudaSparseMatrixCSR), - (:test_cscmm,:test_cscmm_symm,:test_cscmm_herm,:test_cscmm2,:CudaSparseMatrixCSC)) - @eval begin - function $funcs(elty) - A = sparse(rand(elty,m,m)) - A = A + A.' - B = rand(elty,m,n) - C = rand(elty,m,n) - alpha = rand(elty) - beta = rand(elty) +@testset "mm_symm" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,m)) + A = A + A.' + B = rand(elty,m,n) + C = rand(elty,m,n) + alpha = rand(elty) + beta = rand(elty) + @testset "csr" begin d_B = CudaArray(B) d_C = CudaArray(C) - d_A = Symmetric($typ(A)) + d_A = Symmetric(CudaSparseMatrixCSR(A)) d_C = CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_C,'O') h_C = to_host(d_C) - C = alpha * A * B + beta * C - @test C ≈ h_C + D = alpha * A * B + beta * C + @test D ≈ h_C d_C = d_A.' * d_B h_C = to_host(d_C) - C = A.' * B - @test C ≈ h_C + D = A.' * B + @test D ≈ h_C d_B = CudaArray(rand(elty,k,n)) @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') end - - function $funch(elty) - A = sparse(rand(elty,m,m)) - A = A + A' - B = rand(elty,m,n) - C = rand(elty,m,n) - alpha = rand(elty) - beta = rand(elty) + @testset "csc" begin d_B = CudaArray(B) d_C = CudaArray(C) - d_A = Hermitian($typ(A)) + d_A = Symmetric(CudaSparseMatrixCSC(A)) d_C = CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_C,'O') h_C = to_host(d_C) - C = alpha * A * B + beta * C - @test C ≈ h_C + D = alpha * A * B + beta * C + @test D ≈ h_C + d_C = d_A.' * d_B + h_C = to_host(d_C) + D = A.' * B + @test D ≈ h_C d_B = CudaArray(rand(elty,k,n)) @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') end - - function $func(elty) - A = sparse(rand(elty,m,k)) - B = rand(elty,k,n) - C = rand(elty,m,n) - alpha = rand(elty) - beta = rand(elty) + end +end +@testset "mm_herm" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,m)) + A = A + A' + B = rand(elty,m,n) + C = rand(elty,m,n) + alpha = rand(elty) + beta = rand(elty) + @testset "csr" begin d_B = CudaArray(B) d_C = CudaArray(C) - d_A = $typ(A) + d_A = Hermitian(CudaSparseMatrixCSR(A)) + d_C = CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_C,'O') + h_C = to_host(d_C) + D = alpha * A * B + beta * C + @test D ≈ h_C + d_B = CudaArray(rand(elty,k,n)) @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') - d_D = CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_C,'O') + end + @testset "csc" begin + d_B = CudaArray(B) + d_C = CudaArray(C) + d_A = Hermitian(CudaSparseMatrixCSC(A)) + d_C = CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_C,'O') + h_C = to_host(d_C) + D = alpha * A * B + beta * C + @test D ≈ h_C + d_B = CudaArray(rand(elty,k,n)) + @test_throws DimensionMismatch CUSPARSE.mm!('T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm!('N',alpha,d_A,d_B,beta,d_B,'O') + end + end +end + +@testset "mm2" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,k)) + B = rand(elty,k,n) + C = rand(elty,m,n) + alpha = rand(elty) + beta = rand(elty) + @testset "csr" begin + d_B = CudaArray(B) + d_C = CudaArray(C) + d_A = CudaSparseMatrixCSR(A) + @test_throws DimensionMismatch CUSPARSE.mm2!('N','T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2!('T','N',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2!('T','T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2!('N','N',alpha,d_A,d_B,beta,d_B,'O') + d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,beta,d_C,'O') h_D = to_host(d_D) D = alpha * A * B + beta * C @test D ≈ h_D - d_D = CUSPARSE.mm('N',d_A,d_B,beta,d_C,'O') + d_D = CUSPARSE.mm2('N','N',d_A,d_B,beta,d_C,'O') h_D = to_host(d_D) D = A * B + beta * C @test D ≈ h_D - d_D = CUSPARSE.mm('N',d_A,d_B,d_C,'O') + d_D = CUSPARSE.mm2('N','N',d_A,d_B,d_C,'O') h_D = to_host(d_D) D = A * B + C @test D ≈ h_D - d_D = CUSPARSE.mm('N',alpha,d_A,d_B,'O') + d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,'O') h_D = to_host(d_D) D = alpha * A * B @test D ≈ h_D - d_D = CUSPARSE.mm('N',d_A,d_B,'O') - h_D = to_host(d_D) - D = A * B - @test D ≈ h_D - d_D = d_A*d_B + d_D = CUSPARSE.mm2('N','N',d_A,d_B,'O') h_D = to_host(d_D) D = A * B @test D ≈ h_D - @test_throws DimensionMismatch CUSPARSE.mm('T',alpha,d_A,d_B,beta,d_C,'O') - @test_throws DimensionMismatch CUSPARSE.mm('N',alpha,d_A,d_B,beta,d_B,'O') end - function $func2(elty) - A = sparse(rand(elty,m,k)) - B = rand(elty,k,n) - C = rand(elty,m,n) - alpha = rand(elty) - beta = rand(elty) + @testset "csc" begin d_B = CudaArray(B) d_C = CudaArray(C) - d_A = $typ(A) + d_A = CudaSparseMatrixCSC(A) @test_throws DimensionMismatch CUSPARSE.mm2!('N','T',alpha,d_A,d_B,beta,d_C,'O') @test_throws DimensionMismatch CUSPARSE.mm2!('T','N',alpha,d_A,d_B,beta,d_C,'O') @test_throws DimensionMismatch CUSPARSE.mm2!('T','T',alpha,d_A,d_B,beta,d_C,'O') @@ -130,60 +227,40 @@ for (func,funcs,funch,func2,typ) in ((:test_csrmm,:test_csrmm_symm,:test_csrmm_h end end end - -function test_bsrmm2(elty) - A = sparse(rand(elty,m,k)) - B = rand(elty,k,n) - C = rand(elty,m,n) - alpha = rand(elty) - beta = rand(elty) - d_B = CudaArray(B) - d_C = CudaArray(C) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A,convert(Cint,blockdim)) - @test_throws DimensionMismatch CUSPARSE.mm2('N','T',alpha,d_A,d_B,beta,d_C,'O') - @test_throws DimensionMismatch CUSPARSE.mm2('T','N',alpha,d_A,d_B,beta,d_C,'O') - @test_throws DimensionMismatch CUSPARSE.mm2('T','T',alpha,d_A,d_B,beta,d_C,'O') - @test_throws DimensionMismatch CUSPARSE.mm2('N','N',alpha,d_A,d_B,beta,d_B,'O') - d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,beta,d_C,'O') - h_D = to_host(d_D) - D = alpha * A * B + beta * C - @test D ≈ h_D - d_D = CUSPARSE.mm2('N','N',d_A,d_B,beta,d_C,'O') - h_D = to_host(d_D) - D = A * B + beta * C - @test D ≈ h_D - d_D = CUSPARSE.mm2('N','N',d_A,d_B,d_C,'O') - h_D = to_host(d_D) - D = A * B + C - @test D ≈ h_D - d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,'O') - h_D = to_host(d_D) - D = alpha * A * B - @test D ≈ h_D - d_D = CUSPARSE.mm2('N','N',d_A,d_B,'O') - h_D = to_host(d_D) - D = A * B - @test D ≈ h_D -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_csrmm_symm(elty) - test_cscmm_symm(elty) - println("mm_symm! took ", toq(), " for ", elty) - tic() - test_csrmm_herm(elty) - test_cscmm_herm(elty) - println("mm_herm! took ", toq(), " for ", elty) - tic() - test_csrmm(elty) - test_cscmm(elty) - println("mm took ", toq(), " for ", elty) - tic() - test_csrmm2(elty) - test_cscmm2(elty) - test_bsrmm2(elty) - println("mm2 took ", toq(), " for ", elty) +@testset "bsrmm2" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,k)) + B = rand(elty,k,n) + C = rand(elty,m,n) + alpha = rand(elty) + beta = rand(elty) + d_B = CudaArray(B) + d_C = CudaArray(C) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A,convert(Cint,blockdim)) + @test_throws DimensionMismatch CUSPARSE.mm2('N','T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2('T','N',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2('T','T',alpha,d_A,d_B,beta,d_C,'O') + @test_throws DimensionMismatch CUSPARSE.mm2('N','N',alpha,d_A,d_B,beta,d_B,'O') + d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = alpha * A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm2('N','N',d_A,d_B,beta,d_C,'O') + h_D = to_host(d_D) + D = A * B + beta * C + @test D ≈ h_D + d_D = CUSPARSE.mm2('N','N',d_A,d_B,d_C,'O') + h_D = to_host(d_D) + D = A * B + C + @test D ≈ h_D + d_D = CUSPARSE.mm2('N','N',alpha,d_A,d_B,'O') + h_D = to_host(d_D) + D = alpha * A * B + @test D ≈ h_D + d_D = CUSPARSE.mm2('N','N',d_A,d_B,'O') + h_D = to_host(d_D) + D = A * B + @test D ≈ h_D + end end diff --git a/test/mm.png b/test/mm.png deleted file mode 100644 index 24e16b8a727147cc3e201bb091040d05a7a738d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123710 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

Zr#fXs|!*Q#J#-Hq?-rh1Q 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 diff --git a/test/mv.jl b/test/mv.jl index 9aa8010..343791a 100644 --- a/test/mv.jl +++ b/test/mv.jl @@ -7,192 +7,222 @@ n = 35 k = 10 blockdim = 5 -for (func,funcs,funch,typ) in ((:test_csrmv,:test_csrmv_symm,:test_csrmv_herm,:CudaSparseMatrixCSR), - (:test_cscmv,:test_cscmv_symm,:test_cscmv_herm,:CudaSparseMatrixCSC)) - @eval begin - function $funcs(elty) - A = sparse(rand(elty,m,m)) - A = A + A.' - x = rand(elty,m) - y = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_y = CudaArray(y) - d_A = Symmetric($typ(A)) - d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') - h_y = to_host(d_y) - y = alpha * A * x + beta * y - @test y ≈ h_y - x = rand(elty,n) - d_x = CudaArray(x) - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') +@testset "mv" begin + for elty in [Float32,Float64,Complex64,Complex128] + A = sparse(rand(elty,m,m)) + x = rand(elty,m) + y = rand(elty,m) + alpha = rand(elty) + beta = rand(elty) + @testset "mv_symm" begin + A_s = A + A.' + @testset "csr" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = Symmetric(CudaSparseMatrixCSR(A_s)) + d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_y = to_host(d_y) + z = alpha * A_s * x + beta * y + @test z ≈ h_y + x_ = rand(elty,n) + d_x = CudaArray(x_) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end + @testset "csc" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = Symmetric(CudaSparseMatrixCSC(A_s)) + d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_y = to_host(d_y) + z = alpha * A_s * x + beta * y + @test z ≈ h_y + x_ = rand(elty,n) + d_x = CudaArray(x_) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end end - function $funch(elty) - A = sparse(rand(elty,m,m)) - A = A + A' - x = rand(elty,m) - y = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_y = CudaArray(y) - d_A = Hermitian($typ(A)) - d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') - h_y = to_host(d_y) - y = alpha * A * x + beta * y - @test y ≈ h_y - x = rand(elty,n) - d_x = CudaArray(x) - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + @testset "mv_herm" begin + A_h = A + A' + @testset "csr" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = Hermitian(CudaSparseMatrixCSR(A_h)) + d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_y = to_host(d_y) + z = alpha * A_h * x + beta * y + @test z ≈ h_y + x_ = rand(elty,n) + d_x = CudaArray(x_) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end + @testset "csc" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = Hermitian(CudaSparseMatrixCSC(A_h)) + d_y = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_y = to_host(d_y) + z = alpha * A_h * x + beta * y + @test z ≈ h_y + x_ = rand(elty,n) + d_x = CudaArray(x_) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end end - - function $func(elty) - A = sparse(rand(elty,m,n)) - x = rand(elty,n) - y = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_y = CudaArray(y) - d_A = $typ(A) - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') - h_z = to_host(d_z) - z = alpha * A * x - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,'O') - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z - d_z = d_A*d_x - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z + A = sparse(rand(elty,m,n)) + x = rand(elty,n) + y = rand(elty,m) + alpha = rand(elty) + beta = rand(elty) + @testset "mv" begin + @testset "csr" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = CudaSparseMatrixCSR(A) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') + h_z = to_host(d_z) + z = alpha * A * x + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,'O') + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + d_z = d_A*d_x + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + end + @testset "csc" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = CudaSparseMatrixCSC(A) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') + h_z = to_host(d_z) + z = alpha * A * x + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,'O') + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + d_z = d_A*d_x + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + end + @testset "bsr" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2bsr(d_A,convert(Cint,blockdim)) + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') + h_z = to_host(d_z) + z = alpha * A * x + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,'O') + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + d_z = d_A*d_x + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end + @testset "hyb" begin + d_x = CudaArray(x) + d_y = CudaArray(y) + d_A = CudaSparseMatrixCSR(A) + d_A = CUSPARSE.switch2hyb(d_A) + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') + h_z = to_host(d_z) + z = A * x + beta * y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') + h_z = to_host(d_z) + z = alpha * A * x + y + @test z ≈ h_z + d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') + h_z = to_host(d_z) + z = alpha * A * x + @test z ≈ h_z + d_z = CUSPARSE.mv('N',d_A,d_x,'O') + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + d_z = d_A*d_x + h_z = to_host(d_z) + z = A * x + @test z ≈ h_z + @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') + @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') + end end end end - -function test_bsrmv(elty) - A = sparse(rand(elty,m,n)) - x = rand(elty,n) - y = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_y = CudaArray(y) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2bsr(d_A,convert(Cint,blockdim)) - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') - h_z = to_host(d_z) - z = alpha * A * x - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,'O') - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z - d_z = d_A*d_x - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') -end - -function test_hybmv(elty) - A = sparse(rand(elty,m,n)) - x = rand(elty,n) - y = rand(elty,m) - alpha = rand(elty) - beta = rand(elty) - d_x = CudaArray(x) - d_y = CudaArray(y) - d_A = CudaSparseMatrixCSR(A) - d_A = CUSPARSE.switch2hyb(d_A) - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,beta,d_y,'O') - h_z = to_host(d_z) - z = A * x + beta * y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,d_y,'O') - h_z = to_host(d_z) - z = alpha * A * x + y - @test z ≈ h_z - d_z = CUSPARSE.mv('N',alpha,d_A,d_x,'O') - h_z = to_host(d_z) - z = alpha * A * x - @test z ≈ h_z - d_z = CUSPARSE.mv('N',d_A,d_x,'O') - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z - d_z = d_A*d_x - h_z = to_host(d_z) - z = A * x - @test z ≈ h_z - @test_throws DimensionMismatch CUSPARSE.mv('T',alpha,d_A,d_x,beta,d_y,'O') - @test_throws DimensionMismatch CUSPARSE.mv('N',alpha,d_A,d_y,beta,d_x,'O') -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_csrmv_symm(elty) - test_cscmv_symm(elty) - println("mv_symm took ", toq(), " for ", elty) - tic() - test_csrmv_herm(elty) - test_cscmv_herm(elty) - println("mv_herm took ", toq(), " for ", elty) - tic() - test_csrmv(elty) - test_cscmv(elty) - test_bsrmv(elty) - test_hybmv(elty) - println("mv took ", toq(), " for ", elty) -end diff --git a/test/mv.png b/test/mv.png deleted file mode 100644 index 2e6906d1345ee0b0862ae76ef20ec7c8b04783b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122289 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

jdPHA6!L_{Ha>v_=yc+x4H#z{O1 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 Z)*lSg07#v0Wa~#{;L}M+O^I-E&h^_|H3ot1 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 v"0.5.0-dev+742" - y[x.nzind] = cos(angle)*w[z.nzind] - sin(angle)*z.nzval - @test h_x ≈ SparseVector(m,x.nzind,cos(angle)*z.nzval + sin(angle)*w[z.nzind]) - else - y[x.rowval] = cos(angle)*w[z.rowval] - sin(angle)*z.nzval - @test h_x ≈ sparsevec(x.rowval,cos(angle)*z.nzval + sin(angle)*w[z.rowval],m) + @testset "roti" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + angle = rand(elty) + d_z,d_w = CUSPARSE.roti(d_x,d_y,cos(angle),sin(angle),'O') + h_w = to_host(d_w) + h_z = to_host(d_z) + z = copy(x) + w = copy(y) + w[z.nzind] = cos(angle)*y[x.nzind] - sin(angle)*x.nzval + @test h_z ≈ SparseVector(m,z.nzind, cos(angle)*x.nzval + sin(angle)*y[x.nzind]) + @test h_w ≈ w + end end - @test h_y ≈ y -end - -function test_roti(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = rand(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - angle = rand(elty) - d_z,d_w = CUSPARSE.roti(d_x,d_y,cos(angle),sin(angle),'O') - h_w = to_host(d_w) - h_z = to_host(d_z) - z = copy(x) - w = copy(y) - if VERSION >= v"0.5.0-dev+742" - w[z.nzind] = cos(angle)*y[x.nzind] - sin(angle)*x.nzval - @test h_z ≈ SparseVector(m,z.nzind, cos(angle)*x.nzval + sin(angle)*y[x.nzind]) - else - w[z.rowval] = cos(angle)*y[x.rowval] - sin(angle)*x.nzval - @test h_z ≈ sparsevec(z.rowval, cos(angle)*x.nzval + sin(angle)*y[x.rowval],m) - end - @test h_w ≈ w -end - -types = [Float32,Float64] -for elty in types - tic() - test_roti!(elty) - println("roti! took ", toq(), " for ", elty) - tic() - test_roti(elty) - println("roti took ", toq(), " for ", elty) end diff --git a/test/runtests.jl b/test/runtests.jl index 757ada5..9a1e2c3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,7 +7,7 @@ n = 35 k = 10 blockdim = 5 -@testset "util tests" begin +@testset "util" begin x = sprand(m,n,0.2) d_x = CudaSparseMatrixCSC(x) @test device(x) == -1 @@ -26,7 +26,7 @@ blockdim = 5 @test_throws ArgumentError copy!(d_y,d_x) end -@testset "char tests" begin +@testset "char" begin @test_throws ArgumentError CUSPARSE.cusparseop('Z') @test_throws ArgumentError CUSPARSE.cusparsetype('Z') @test_throws ArgumentError CUSPARSE.cusparsefill('Z') @@ -46,147 +46,129 @@ end end @testset "conversion" begin - function test_make_csc(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSC(x) - h_x = to_host(d_x) - @test h_x == x - @test eltype(d_x) == elty - end - - function test_make_csr(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSR(x) - h_x = to_host(d_x) - @test h_x == x - end + @testset for elty in [Float32, Float64, Complex64, Complex128] + @testset "make_csc" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSC(x) + h_x = to_host(d_x) + @test h_x == x + @test eltype(d_x) == elty + end - function test_convert_r2c(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSR(x) - d_x = CUSPARSE.switch2csc(d_x) - h_x = to_host(d_x) - @test h_x.rowval == x.rowval - @test h_x.nzval ≈ x.nzval - end + @testset "make_csr" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSR(x) + h_x = to_host(d_x) + @test h_x == x + end - function test_convert_r2b(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSR(x) - d_x = CUSPARSE.switch2bsr(d_x,convert(Cint,blockdim)) - d_x = CUSPARSE.switch2csr(d_x) - h_x = to_host(d_x) - @test h_x ≈ x - end + @testset "convert_r2c" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSR(x) + d_x = CUSPARSE.switch2csc(d_x) + h_x = to_host(d_x) + @test h_x.rowval == x.rowval + @test h_x.nzval ≈ x.nzval + end - function test_convert_c2b(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSC(x) - d_x = CUSPARSE.switch2bsr(d_x,convert(Cint,blockdim)) - d_x = CUSPARSE.switch2csc(d_x) - h_x = to_host(d_x) - @test h_x ≈ x - end + @testset "convert_r2b" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSR(x) + d_x = CUSPARSE.switch2bsr(d_x,convert(Cint,blockdim)) + d_x = CUSPARSE.switch2csr(d_x) + h_x = to_host(d_x) + @test h_x ≈ x + end - function test_convert_c2h(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSC(x) - d_x = CUSPARSE.switch2hyb(d_x) - d_y = CUSPARSE.switch2csc(d_x) - CUSPARSE.cusparseDestroyHybMat(d_x.Mat) - h_x = to_host(d_y) - @test h_x.rowval == x.rowval - @test h_x.nzval ≈ x.nzval - end + @testset "convert_c2b" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSC(x) + d_x = CUSPARSE.switch2bsr(d_x,convert(Cint,blockdim)) + d_x = CUSPARSE.switch2csc(d_x) + h_x = to_host(d_x) + @test h_x ≈ x + end - function test_convert_r2h(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSR(x) - d_x = CUSPARSE.switch2hyb(d_x) - d_y = CUSPARSE.switch2csr(d_x) - CUSPARSE.cusparseDestroyHybMat(d_x.Mat) - h_x = to_host(d_y) - @test h_x.rowval == x.rowval - @test h_x.nzval ≈ x.nzval - end + @testset "convert_c2h" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSC(x) + d_x = CUSPARSE.switch2hyb(d_x) + d_y = CUSPARSE.switch2csc(d_x) + CUSPARSE.cusparseDestroyHybMat(d_x.Mat) + h_x = to_host(d_y) + @test h_x.rowval == x.rowval + @test h_x.nzval ≈ x.nzval + end - function test_convert_d2h(elty) - x = rand(elty,m,n) - d_x = CudaArray(x) - d_x = CUSPARSE.sparse(d_x,'H') - d_y = CUSPARSE.full(d_x) - CUSPARSE.cusparseDestroyHybMat(d_x.Mat) - h_x = to_host(d_y) - @test h_x ≈ x - end + @testset "convert_r2h" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSR(x) + d_x = CUSPARSE.switch2hyb(d_x) + d_y = CUSPARSE.switch2csr(d_x) + CUSPARSE.cusparseDestroyHybMat(d_x.Mat) + h_x = to_host(d_y) + @test h_x.rowval == x.rowval + @test h_x.nzval ≈ x.nzval + end - function test_convert_d2b(elty) - x = rand(elty,m,n) - d_x = CudaArray(x) - d_x = CUSPARSE.sparse(d_x,'B') - d_y = CUSPARSE.full(d_x) - h_x = to_host(d_y) - @test h_x ≈ x - end + @testset "convert_d2h" begin + x = rand(elty,m,n) + d_x = CudaArray(x) + d_x = CUSPARSE.sparse(d_x,'H') + d_y = CUSPARSE.full(d_x) + CUSPARSE.cusparseDestroyHybMat(d_x.Mat) + h_x = to_host(d_y) + @test h_x ≈ x + end - function test_convert_c2r(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSC(x) - d_x = CUSPARSE.switch2csr(d_x) - h_x = to_host(d_x) - @test h_x.rowval == x.rowval - @test h_x.nzval ≈ x.nzval - end + @testset "convert_d2b" begin + x = rand(elty,m,n) + d_x = CudaArray(x) + d_x = CUSPARSE.sparse(d_x,'B') + d_y = CUSPARSE.full(d_x) + h_x = to_host(d_y) + @test h_x ≈ x + end - function test_convert_r2d(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSR(x) - d_x = CUSPARSE.full(d_x) - h_x = to_host(d_x) - @test h_x ≈ full(x) - end + @testset "convert_c2r" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSC(x) + d_x = CUSPARSE.switch2csr(d_x) + h_x = to_host(d_x) + @test h_x.rowval == x.rowval + @test h_x.nzval ≈ x.nzval + end - function test_convert_c2d(elty) - x = sparse(rand(elty,m,n)) - d_x = CudaSparseMatrixCSC(x) - d_x = CUSPARSE.full(d_x) - h_x = to_host(d_x) - @test h_x ≈ full(x) - end + @testset "convert_r2d" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSR(x) + d_x = CUSPARSE.full(d_x) + h_x = to_host(d_x) + @test h_x ≈ full(x) + end - function test_convert_d2c(elty) - x = rand(elty,m,n) - d_x = CudaArray(x) - d_x = CUSPARSE.sparse(d_x,'C') - h_x = to_host(d_x) - @test h_x ≈ sparse(x) - end + @testset "convert_c2d" begin + x = sparse(rand(elty,m,n)) + d_x = CudaSparseMatrixCSC(x) + d_x = CUSPARSE.full(d_x) + h_x = to_host(d_x) + @test h_x ≈ full(x) + end - function test_convert_d2r(elty) - x = rand(elty,m,n) - d_x = CudaArray(x) - d_x = CUSPARSE.sparse(d_x) - h_x = to_host(d_x) - @test h_x ≈ sparse(x) - end + @testset "convert_d2c" begin + x = rand(elty,m,n) + d_x = CudaArray(x) + d_x = CUSPARSE.sparse(d_x,'C') + h_x = to_host(d_x) + @test h_x ≈ sparse(x) + end - @testset for func in [ - test_make_csc, - test_make_csr, - test_convert_r2c, - test_convert_c2r, - test_convert_r2b, - test_convert_d2r, - test_convert_d2c, - test_convert_c2d, - test_convert_c2h, - test_convert_r2h, - test_convert_d2h, - test_convert_d2b, - test_convert_c2b, - test_convert_r2d] - for typ in [Float32, Float64, Complex64, Complex128] - func(typ) + @testset "convert_d2r" begin + x = rand(elty,m,n) + d_x = CudaArray(x) + d_x = CUSPARSE.sparse(d_x) + h_x = to_host(d_x) + @test h_x ≈ sparse(x) end end end @@ -202,6 +184,6 @@ if( !isempty(ARGS) ) chosentests = ARGS end -@testset for test in chosentests +for test in chosentests include("$test.jl") end diff --git a/test/sctr.jl b/test/sctr.jl index 4515586..ee05ddf 100644 --- a/test/sctr.jl +++ b/test/sctr.jl @@ -7,45 +7,27 @@ n = 35 k = 10 blockdim = 5 -############# -# test_sctr # -############# +@testset "sctr" begin + @testset for elty in [Float32,Float64,Complex64,Complex128] + x = sparsevec(rand(1:m,k), rand(elty,k), m) + y = zeros(elty,m) + @testset "sctr!" begin + d_x = CudaSparseVector(x) + d_y = CudaArray(y) + d_y = CUSPARSE.sctr!(d_x,d_y,'O') + h_y = to_host(d_y) + y[x.nzind] += x.nzval + @test h_y ≈ y + end + y = zeros(elty,m) -function test_sctr!(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - y = zeros(elty,m) - d_x = CudaSparseVector(x) - d_y = CudaArray(y) - d_y = CUSPARSE.sctr!(d_x,d_y,'O') - h_y = to_host(d_y) - if VERSION >= v"0.5.0-dev+742" - y[x.nzind] += x.nzval - else - y[x.rowval] += x.nzval + @testset "sctr" begin + d_x = CudaSparseVector(x) + d_y = CUSPARSE.sctr(d_x,'O') + h_y = to_host(d_y) + y = zeros(elty,m) + y[x.nzind] += x.nzval + @test h_y ≈ y + end end - @test h_y ≈ y -end - -function test_sctr(elty) - x = sparsevec(rand(1:m,k), rand(elty,k), m) - d_x = CudaSparseVector(x) - d_y = CUSPARSE.sctr(d_x,'O') - h_y = to_host(d_y) - y = zeros(elty,m) - if VERSION >= v"0.5.0-dev+742" - y[x.nzind] += x.nzval - else - y[x.rowval] += x.nzval - end - @test h_y ≈ y -end - -types = [Float32,Float64,Complex64,Complex128] -for elty in types - tic() - test_sctr!(elty) - println("sctr! took ", toq(), " for ", elty) - tic() - test_sctr(elty) - println("sctr took ", toq(), " for ", elty) end diff --git a/test/sv.png b/test/sv.png deleted file mode 100644 index 0159fc337da49fe1f1d244f5e3137cd63767e9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112388 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 F{s$LXNHPEb From 1dd1b34ebea2aafdb12289fa5b6240d18bec472b Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 20 May 2017 15:20:37 -0700 Subject: [PATCH 2/4] Cleanup code for 0.6 - switch to using testsets fulltime - fix import of cudaStream_t from CUDArt.jl - fix depwarns --- src/libcusparse_types.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libcusparse_types.jl b/src/libcusparse_types.jl index 097cbca..0119bf4 100644 --- a/src/libcusparse_types.jl +++ b/src/libcusparse_types.jl @@ -21,8 +21,6 @@ Perform operation on indices only (`CUSPARSE_ACTION_SYMBOLIC`) or on both data and indices (`CUSPARSE_ACTION_NUMERIC`). Used in conversion routines. """ -# perform operation only indices only or -# on both data and indices const cusparseAction_t = UInt32 const CUSPARSE_ACTION_SYMBOLIC = 0 const CUSPARSE_ACTION_NUMERIC = 1 @@ -56,7 +54,6 @@ Determines if a symmetric/Hermitian/triangular matrix has its upper (`CUSPARSE_FILL_MODE_UPPER`) or lower (`CUSPARSE_FILL_MODE_LOWER`) triangle filled. """ -# filling for HE,TR,SY matrices const cusparseFillMode_t = UInt32 const CUSPARSE_FILL_MODE_LOWER = 0 const CUSPARSE_FILL_MODE_UPPER = 1 @@ -66,7 +63,6 @@ const CUSPARSE_FILL_MODE_UPPER = 1 Determines if the diagonal of a matrix is all ones (`CUSPARSE_DIAG_TYPE_UNIT`) or not all ones (`CUSPARSE_DIAG_TYPE_NON_UNIT`). """ -# is the diagonal all ones const cusparseDiagType_t = UInt32 const CUSPARSE_DIAG_TYPE_NON_UNIT = 0 const CUSPARSE_DIAG_TYPE_UNIT = 1 From c0049421742746d78ec05d63293eedc4820f9420 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 20 May 2017 15:33:37 -0700 Subject: [PATCH 3/4] Update REQUIRE too oops --- REQUIRE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REQUIRE b/REQUIRE index 28572d7..e0c630c 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,2 @@ -julia 0.5 +julia 0.6- CUDArt From 3b56898135ea19dfc28c891989babf75945865d4 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 23 May 2017 18:39:23 -0700 Subject: [PATCH 4/4] Actually everything works with 0.5 too --- REQUIRE | 3 ++- src/libcusparse_types.jl | 55 ++++++++++++++++++++-------------------- src/util.jl | 23 +++++++++-------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/REQUIRE b/REQUIRE index e0c630c..28c0472 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,3 @@ -julia 0.6- +julia 0.5 CUDArt +Compat diff --git a/src/libcusparse_types.jl b/src/libcusparse_types.jl index 0119bf4..a33c275 100644 --- a/src/libcusparse_types.jl +++ b/src/libcusparse_types.jl @@ -1,10 +1,12 @@ +using Compat + #enum cusparseStatus_t #error messages from CUSPARSE """ Status messages from CUSPARSE's C API. """ -const cusparseStatus_t = UInt32 +@compat const cusparseStatus_t = UInt32 const CUSPARSE_STATUS_SUCCESS = 0 const CUSPARSE_STATUS_NOT_INITIALIZED = 1 const CUSPARSE_STATUS_ALLOC_FAILED = 2 @@ -21,7 +23,7 @@ Perform operation on indices only (`CUSPARSE_ACTION_SYMBOLIC`) or on both data and indices (`CUSPARSE_ACTION_NUMERIC`). Used in conversion routines. """ -const cusparseAction_t = UInt32 +@compat const cusparseAction_t = UInt32 const CUSPARSE_ACTION_SYMBOLIC = 0 const CUSPARSE_ACTION_NUMERIC = 1 @@ -30,7 +32,7 @@ const CUSPARSE_ACTION_NUMERIC = 1 Parse dense matrix by rows (`CUSPARSE_DIRECTION_ROW`) or columns (`CUSPARSE_DIRECTION_COL`) to compute its number of non-zeros. """ -const cusparseDirection_t = UInt32 +@compat const cusparseDirection_t = UInt32 const CUSPARSE_DIRECTION_ROW = 0 const CUSPARSE_DIRECTION_COL = 1 @@ -42,8 +44,7 @@ There are three choices: * `CUSPARSE_HYB_PARTITION_USER` - set the partition manually in the conversion function. * `CUSPARSE_HYB_PARTITION_MAX` - use the maximum partition, putting the matrix in ELL format. """ -# how to partition the HYB matrix -const cusparseHybPartition_t = UInt32 +@compat const cusparseHybPartition_t = UInt32 const CUSPARSE_HYB_PARTITION_AUTO = 0 const CUSPARSE_HYB_PARTITION_USER = 1 const CUSPARSE_HYB_PARTITION_MAX = 2 @@ -54,7 +55,7 @@ Determines if a symmetric/Hermitian/triangular matrix has its upper (`CUSPARSE_FILL_MODE_UPPER`) or lower (`CUSPARSE_FILL_MODE_LOWER`) triangle filled. """ -const cusparseFillMode_t = UInt32 +@compat const cusparseFillMode_t = UInt32 const CUSPARSE_FILL_MODE_LOWER = 0 const CUSPARSE_FILL_MODE_UPPER = 1 @@ -63,7 +64,7 @@ const CUSPARSE_FILL_MODE_UPPER = 1 Determines if the diagonal of a matrix is all ones (`CUSPARSE_DIAG_TYPE_UNIT`) or not all ones (`CUSPARSE_DIAG_TYPE_NON_UNIT`). """ -const cusparseDiagType_t = UInt32 +@compat const cusparseDiagType_t = UInt32 const CUSPARSE_DIAG_TYPE_NON_UNIT = 0 const CUSPARSE_DIAG_TYPE_UNIT = 1 @@ -72,7 +73,7 @@ const CUSPARSE_DIAG_TYPE_UNIT = 1 Determines if scalar arguments to a function are present on the host CPU (`CUSPARSE_POINTER_MODE_HOST`) or on the GPU (`CUSPARSE_POINTER_MODE_DEVICE`). """ -const cusparsePointerMode_t = UInt32 +@compat const cusparsePointerMode_t = UInt32 const CUSPARSE_POINTER_MODE_HOST = 0 const CUSPARSE_POINTER_MODE_DEVICE = 1 @@ -83,7 +84,7 @@ or solve, on the matrix as-is (`CUSPARSE_OPERATION_NON_TRANSPOSE`), on the matrix's transpose (`CUSPARSE_OPERATION_TRANSPOSE`), or on its conjugate transpose (`CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE`). """ -const cusparseOperation_t = UInt32 +@compat const cusparseOperation_t = UInt32 const CUSPARSE_OPERATION_NON_TRANSPOSE = 0 const CUSPARSE_OPERATION_TRANSPOSE = 1 const CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE = 2 @@ -97,7 +98,7 @@ symmetric (`CUSPARSE_MATRIX_TYPE_SYMMETRIC`), Hermitian (those in [`CompressedSparse`](@ref)), this can be inferred for some function calls. """ -const cusparseMatrixType_t = UInt32 +@compat const cusparseMatrixType_t = UInt32 const CUSPARSE_MATRIX_TYPE_GENERAL = 0 const CUSPARSE_MATRIX_TYPE_SYMMETRIC = 1 const CUSPARSE_MATRIX_TYPE_HERMITIAN = 2 @@ -108,7 +109,7 @@ const CUSPARSE_MATRIX_TYPE_TRIANGULAR = 3 Indicates whether to keep level info in solvers (`CUSPARSE_SOLVE_POLICY_USE_LEVEL`) or whether to not use it (`CUSPARSE_SOLVE_POLICY_NO_LEVEL`). """ -const cusparseSolvePolicy_t = UInt32 +@compat const cusparseSolvePolicy_t = UInt32 const CUSPARSE_SOLVE_POLICY_NO_LEVEL = 0 const CUSPARSE_SOLVE_POLICY_USE_LEVEL = 1 @@ -119,7 +120,7 @@ or one-indexed (`CUSPARSE_INDEX_BASE_ONE`). CUSPARSE.jl supports both. Julia sparse matrices are one-indexed, but you may wish to pass matrices from other libraries which use zero-indexing (e.g. C language ODE solvers). """ -const cusparseIndexBase_t = UInt32 +@compat const cusparseIndexBase_t = UInt32 const CUSPARSE_INDEX_BASE_ZERO = 0 const CUSPARSE_INDEX_BASE_ONE = 1 @@ -149,23 +150,23 @@ CUSPARSE will take. Generated by [`sv_analysis`](@ref) or [`sm_analysis`](@ref) and passed to [`sv_solve!`](@ref), [`sm_solve`](@ref), [`ic0!`](@ref), or [`ilu0!`](@ref). """ -const cusparseSolveAnalysisInfo_t = Ptr{Void} -const bsrsm2Info_t = Ptr{Void} -const bsrsv2Info_t = Ptr{Void} -const csrsv2Info_t = Ptr{Void} -const csric02Info_t = Ptr{Void} -const csrilu02Info_t = Ptr{Void} -const bsric02Info_t = Ptr{Void} -const bsrilu02Info_t = Ptr{Void} +@compat const cusparseSolveAnalysisInfo_t = Ptr{Void} +@compat const bsrsm2Info_t = Ptr{Void} +@compat const bsrsv2Info_t = Ptr{Void} +@compat const csrsv2Info_t = Ptr{Void} +@compat const csric02Info_t = Ptr{Void} +@compat const csrilu02Info_t = Ptr{Void} +@compat const bsric02Info_t = Ptr{Void} +@compat const bsrilu02Info_t = Ptr{Void} -const cusparseContext = Void -const cusparseHandle_t = Ptr{cusparseContext} +@compat const cusparseContext = Void +@compat const cusparseHandle_t = Ptr{cusparseContext} #complex numbers -const cuComplex = Complex{Float32} -const cuDoubleComplex = Complex{Float64} +@compat const cuComplex = Complex{Float32} +@compat const cuDoubleComplex = Complex{Float64} -const CusparseFloat = Union{Float64,Float32,Complex128,Complex64} -const CusparseReal = Union{Float64,Float32} -const CusparseComplex = Union{Complex128,Complex64} +@compat const CusparseFloat = Union{Float64,Float32,Complex128,Complex64} +@compat const CusparseReal = Union{Float64,Float32} +@compat const CusparseComplex = Union{Complex128,Complex64} diff --git a/src/util.jl b/src/util.jl index 0849e6d..ec4f375 100644 --- a/src/util.jl +++ b/src/util.jl @@ -6,10 +6,11 @@ import Base: length, size, ndims, eltype, similar, pointer, stride, ishermitian, isupper, islower import Base.LinAlg: BlasFloat, Hermitian, HermOrSym import CUDArt: device, to_host, free +using Compat -abstract type AbstractCudaSparseArray{Tv,N} <: AbstractSparseArray{Tv,Cint,N} end -const AbstractCudaSparseVector{Tv} = AbstractCudaSparseArray{Tv,1} -const AbstractCudaSparseMatrix{Tv} = AbstractCudaSparseArray{Tv,2} +@compat abstract type AbstractCudaSparseArray{Tv,N} <: AbstractSparseArray{Tv,Cint,N} end +@compat const AbstractCudaSparseVector{Tv} = AbstractCudaSparseArray{Tv,1} +@compat const AbstractCudaSparseMatrix{Tv} = AbstractCudaSparseArray{Tv,2} """ Container to hold sparse vectors on the GPU, similar to `SparseVector` in base Julia. @@ -20,7 +21,7 @@ type CudaSparseVector{Tv} <: AbstractCudaSparseVector{Tv} dims::NTuple{2,Int} nnz::Cint dev::Int - function CudaSparseVector{Tv}(iPtr::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::Int, nnz::Cint, dev::Int) where {Tv} + function CudaSparseVector{Tv}(iPtr::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::Int, nnz::Cint, dev::Int) new(iPtr,nzVal,(dims,1),nnz,dev) end end @@ -40,7 +41,7 @@ type CudaSparseMatrixCSC{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixCSC{Tv}(colPtr::CudaVector{Cint}, rowVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} + function CudaSparseMatrixCSC{Tv}(colPtr::CudaVector{Cint}, rowVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) new(colPtr,rowVal,nzVal,dims,nnz,dev) end end @@ -60,7 +61,7 @@ type CudaSparseMatrixCSR{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixCSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} + function CudaSparseMatrixCSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int}, nnz::Cint, dev::Int) new(rowPtr,colVal,nzVal,dims,nnz,dev) end end @@ -80,7 +81,7 @@ type CudaSparseMatrixBSR{Tv} <: AbstractCudaSparseMatrix{Tv} nnz::Cint dev::Int - function CudaSparseMatrixBSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int},blockDim::Cint, dir::SparseChar, nnz::Cint, dev::Int) where{Tv} + function CudaSparseMatrixBSR{Tv}(rowPtr::CudaVector{Cint}, colVal::CudaVector{Cint}, nzVal::CudaVector{Tv}, dims::NTuple{2,Int},blockDim::Cint, dir::SparseChar, nnz::Cint, dev::Int) new(rowPtr,colVal,nzVal,dims,blockDim,dir,nnz,dev) end end @@ -90,14 +91,14 @@ Container to hold sparse matrices in NVIDIA's hybrid (HYB) format on the GPU. HYB format is an opaque struct, which can be converted to/from using CUSPARSE routines. """ -const cusparseHybMat_t = Ptr{Void} +@compat const cusparseHybMat_t = Ptr{Void} type CudaSparseMatrixHYB{Tv} <: AbstractCudaSparseMatrix{Tv} Mat::cusparseHybMat_t dims::NTuple{2,Int} nnz::Cint dev::Int - function CudaSparseMatrixHYB{Tv}(Mat::cusparseHybMat_t, dims::NTuple{2,Int}, nnz::Cint, dev::Int) where {Tv} + function CudaSparseMatrixHYB(Mat::cusparseHybMat_t, dims::NTuple{2,Int}, nnz::Cint, dev::Int) new(Mat,dims,nnz,dev) end end @@ -108,13 +109,13 @@ and `Hermitian` and `Symmetric` versions of these two containers. A function acc this type can make use of performance improvements by only indexing one triangle of the matrix if it is guaranteed to be hermitian/symmetric. """ -const CompressedSparse{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T},HermOrSym{T,CudaSparseMatrixCSC{T}},HermOrSym{T,CudaSparseMatrixCSR{T}}} +@compat const CompressedSparse{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T},HermOrSym{T,CudaSparseMatrixCSC{T}},HermOrSym{T,CudaSparseMatrixCSR{T}}} """ Utility union type of [`CudaSparseMatrixCSC`](@ref), [`CudaSparseMatrixCSR`](@ref), [`CudaSparseMatrixBSR`](@ref), and [`CudaSparseMatrixHYB`](@ref). """ -const CudaSparseMatrix{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}, CudaSparseMatrixBSR{T}, CudaSparseMatrixHYB{T}} +@compat const CudaSparseMatrix{T} = Union{CudaSparseMatrixCSC{T},CudaSparseMatrixCSR{T}, CudaSparseMatrixBSR{T}, CudaSparseMatrixHYB{T}} Hermitian{T}(Mat::CudaSparseMatrix{T}) = Hermitian{T,typeof(Mat)}(Mat,'U')