diff --git a/lib/cusparse/conversions.jl b/lib/cusparse/conversions.jl index 69dbaf3f9b..16528465f7 100644 --- a/lib/cusparse/conversions.jl +++ b/lib/cusparse/conversions.jl @@ -328,7 +328,7 @@ for elty in (:Float32, :Float64, :ComplexF32, :ComplexF64) @eval begin function CuSparseMatrixCSC{$elty}(csr::CuSparseMatrixCSR{$elty}; index::SparseChar='O', action::cusparseAction_t=CUSPARSE_ACTION_NUMERIC, algo::cusparseCsr2CscAlg_t=CUSPARSE_CSR2CSC_ALG1) m,n = size(csr) - colPtr = CUDA.zeros(Cint, n+1) + colPtr = CUDA.ones(Cint, n+1) rowVal = CUDA.zeros(Cint, nnz(csr)) nzVal = CUDA.zeros($elty, nnz(csr)) function bufferSize() @@ -348,7 +348,7 @@ for elty in (:Float32, :Float64, :ComplexF32, :ComplexF64) function CuSparseMatrixCSR{$elty}(csc::CuSparseMatrixCSC{$elty}; index::SparseChar='O', action::cusparseAction_t=CUSPARSE_ACTION_NUMERIC, algo::cusparseCsr2CscAlg_t=CUSPARSE_CSR2CSC_ALG1) m,n = size(csc) - rowPtr = CUDA.zeros(Cint,m+1) + rowPtr = CUDA.ones(Cint,m+1) colVal = CUDA.zeros(Cint,nnz(csc)) nzVal = CUDA.zeros($elty,nnz(csc)) function bufferSize() @@ -375,7 +375,7 @@ for (elty, welty) in ((:Float16, :Float32), @eval begin function CuSparseMatrixCSC{$elty}(csr::CuSparseMatrixCSR{$elty}; index::SparseChar='O', action::cusparseAction_t=CUSPARSE_ACTION_NUMERIC, algo::cusparseCsr2CscAlg_t=CUSPARSE_CSR2CSC_ALG1) m,n = size(csr) - colPtr = CUDA.zeros(Cint, n+1) + colPtr = CUDA.ones(Cint, n+1) rowVal = CUDA.zeros(Cint, nnz(csr)) nzVal = CUDA.zeros($elty, nnz(csr)) if $elty == Float16 #broken for ComplexF16? @@ -401,7 +401,7 @@ for (elty, welty) in ((:Float16, :Float32), function CuSparseMatrixCSR{$elty}(csc::CuSparseMatrixCSC{$elty}; index::SparseChar='O', action::cusparseAction_t=CUSPARSE_ACTION_NUMERIC, algo::cusparseCsr2CscAlg_t=CUSPARSE_CSR2CSC_ALG1) m,n = size(csc) - rowPtr = CUDA.zeros(Cint,m+1) + rowPtr = CUDA.ones(Cint,m+1) colVal = CUDA.zeros(Cint,nnz(csc)) nzVal = CUDA.zeros($elty,nnz(csc)) if $elty == Float16 #broken for ComplexF16? @@ -490,7 +490,7 @@ for (fname,elty) in ((:cusparseScsr2bsr, :Float32), nnz_ref = Ref{Cint}(1) mb = cld(m, blockDim) nb = cld(n, blockDim) - bsrRowPtr = CUDA.zeros(Cint,mb + 1) + bsrRowPtr = CUDA.ones(Cint,mb + 1) cudesca = CuMatrixDescriptor('G', 'L', 'N', index) cudescc = CuMatrixDescriptor('G', 'L', 'N', indc) cusparseXcsr2bsrNnz(handle(), dir, m, n, cudesca, csr.rowPtr, @@ -519,7 +519,7 @@ for (fname,elty) in ((:cusparseSbsr2csr, :Float32), nb = cld(n, bsr.blockDim) cudesca = CuMatrixDescriptor('G', 'L', 'N', index) cudescc = CuMatrixDescriptor('G', 'L', 'N', indc) - csrRowPtr = CUDA.zeros(Cint, m + 1) + csrRowPtr = CUDA.ones(Cint, m + 1) csrColInd = CUDA.zeros(Cint, nnz(bsr)) csrNzVal = CUDA.zeros($elty, nnz(bsr)) $fname(handle(), bsr.dir, mb, nb, diff --git a/lib/cusparse/generic.jl b/lib/cusparse/generic.jl index e944645760..7280ef4c23 100644 --- a/lib/cusparse/generic.jl +++ b/lib/cusparse/generic.jl @@ -69,6 +69,13 @@ function densetosparse(A::CuMatrix{T}, fmt::Symbol, index::SparseChar, algo::cus end cusparseDenseToSparse_convert(handle(), desc_dense, desc_sparse, algo, buffer) end + # Issue with the CUDA routine `cusparseDenseToSparse_convert` + if (index == 'O') && (fmt == :csc) && (n == 0) + B.colPtr = CuVector{Cint}([1]) + end + if (index == 'O') && (fmt == :csr) && (m == 0) + B.rowPtr = CuVector{Cint}([1]) + end return B end diff --git a/test/libraries/cusparse/conversions.jl b/test/libraries/cusparse/conversions.jl index 1a5119f289..9b34aefd9c 100644 --- a/test/libraries/cusparse/conversions.jl +++ b/test/libraries/cusparse/conversions.jl @@ -10,7 +10,7 @@ using CUDA J = [2,3,4] |> cu V = Float32[1,2,3] |> cu - dense = rand(3,3) |> cu + dense = rand(Float32, 3,3) |> cu # check defaults @test sparse(I, J, V) isa CuSparseMatrixCSC @@ -39,6 +39,54 @@ using CUDA end end +@testset "sparse -- empty matrix" begin + n, m = 0, 0 + I = [] |> cu + J = [] |> cu + V = Float64[] |> cu + + dense = rand(m,n) |> cu + + # check defaults + @test sparse(I, J, V) isa CuSparseMatrixCSC + @test sparse(dense) isa CuSparseMatrixCSC + + for (fmt, T) in [(:coo, CuSparseMatrixCOO), + (:csc, CuSparseMatrixCSC), + (:csr, CuSparseMatrixCSR), + (:bsr, CuSparseMatrixBSR) + ] + @testset "sparse $T" begin + if fmt != :bsr # bsr not supported + x = sparse(I, J, V; fmt=fmt) + @test x isa T{Float64} + @test size(x) == (0, 0) + + x = sparse(I, J, V, m, n; fmt=fmt) + @test x isa T{Float64} + @test size(x) == (0, 0) + + if fmt == :csc + @test collect(x.colPtr) == [1] + end + if fmt == :csr + @test collect(x.rowPtr) == [1] + end + end + + x = sparse(dense; fmt=fmt) + @test x isa T{Float64} + @test collect(x) == collect(dense) + if fmt == :csc + @test collect(x.colPtr) == [1] + end + if fmt == :csr + @test collect(x.rowPtr) == [1] + end + end + end +end + @testset "unsorted sparse (CUDA.jl#1407)" begin I = [1, 1, 2, 3, 3, 4, 5, 4, 6, 4, 5, 6, 6, 6] J = [4, 6, 4, 5, 6, 6, 6, 1, 1, 2, 3, 3, 4, 5]