Extension for CUDA.jl
Introduction
This is an extension to support QuantumObject.data conversion from standard dense and sparse CPU arrays to GPU (CUDA.jl) arrays.
This extension will be automatically triggered if QuantumToolbox.jl, CUDACore, and cuSPARSE are all loaded:
using QuantumToolbox
using CUDACore, cuSPARSEUser can also trigger the extension by importing the entire CUDA package, since it internally loads both libraries (CUDACore and cuSPARSE):
using QuantumToolbox
using CUDA, CUDA.cuSPARSEWe wrapped several functions in CUDACore and cuSPARSE in order to not only converting QuantumObject.data into GPU arrays, but also changing the element type and word size (32 and 64) since some of the GPUs perform better in 32-bit. The functions are listed as follows (where input A is a QuantumObject):
cu(A; word_size=64): return a newQuantumObjectwithCUDAarrays and specifiedword_size.CuArray(A): IfA.datais a dense array, return a newQuantumObjectwithCUDACore.CuArray.CuArray{T}(A): IfA.datais a dense array, return a newQuantumObjectwithCUDACore.CuArrayunder element typeT.CuSparseVector(A): IfA.datais a sparse vector, return a newQuantumObjectwithcuSPARSE.CuSparseVector.CuSparseVector{T}(A): IfA.datais a sparse vector, return a newQuantumObjectwithcuSPARSE.CuSparseVectorunder element typeT.CuSparseMatrixCSC(A): IfA.datais a sparse matrix, return a newQuantumObjectwithcuSPARSE.CuSparseMatrixCSC.CuSparseMatrixCSC{T}(A): IfA.datais a sparse matrix, return a newQuantumObjectwithcuSPARSE.CuSparseMatrixCSCunder element typeT.CuSparseMatrixCSR(A): IfA.datais a sparse matrix, return a newQuantumObjectwithcuSPARSE.CuSparseMatrixCSR.CuSparseMatrixCSR{T}(A): IfA.datais a sparse matrix, return a newQuantumObjectwithcuSPARSE.CuSparseMatrixCSRunder element typeT.
We suggest to convert the arrays from CPU to GPU memory by using the function cu because it allows different data-types of input QuantumObject.
Here are some examples:
Converting dense arrays
V = fock(2, 0) # CPU dense vectorQuantum Object: type=Ket() dims=[2] size=(2,)
2-element Vector{ComplexF64}:
1.0 + 0.0im
0.0 + 0.0imcu(V)Quantum Object: type=Ket() dims=[2] size=(2,)
2-element CuArray{ComplexF64, 1, CUDA.DeviceMemory}:
1.0 + 0.0im
0.0 + 0.0imcu(V; word_size = 32)Quantum Object: type=Ket() dims=[2] size=(2,)
2-element CuArray{ComplexF32, 1, CUDA.DeviceMemory}:
1.0 + 0.0im
0.0 + 0.0imM = Qobj([1 2; 3 4]) # CPU dense matrixQuantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=false
2×2 Matrix{Int64}:
1 2
3 4cu(M)Quantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=false
2×2 CuArray{Int64, 2, CUDA.DeviceMemory}:
1 2
3 4cu(M; word_size = 32)Quantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=false
2×2 CuArray{Int32, 2, CUDA.DeviceMemory}:
1 2
3 4Converting sparse arrays
V = fock(2, 0; sparse=true) # CPU sparse vectorQuantum Object: type=Ket() dims=[2] size=(2,)
2-element SparseVector{ComplexF64, Int64} with 1 stored entry:
[1] = 1.0+0.0imcu(V)Quantum Object: type=Ket() dims=[2] size=(2,)
2-element CuSparseVector{ComplexF64, Int32} with 1 stored entry:
[1] = 1.0+0.0imcu(V; word_size = 32)Quantum Object: type=Ket() dims=[2] size=(2,)
2-element CuSparseVector{ComplexF32, Int32} with 1 stored entry:
[1] = 1.0+0.0imM = sigmax() # CPU sparse matrixQuantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=true
2×2 SparseMatrixCSC{ComplexF64, Int64} with 2 stored entries:
⋅ 1.0+0.0im
1.0+0.0im ⋅cu(M)Quantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=true
2×2 CuSparseMatrixCSC{ComplexF64, Int32} with 2 stored entries:
⋅ 1.0+0.0im
1.0+0.0im ⋅cu(M; word_size = 32)Quantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=true
2×2 CuSparseMatrixCSC{ComplexF32, Int32} with 2 stored entries:
⋅ 1.0+0.0im
1.0+0.0im ⋅