This page was generated from unit-5.5-cuda/poisson_cuda.ipynb.

5.5 Solving the Poisson Equation using CUDAΒΆ

We use the ngscuda library to move compute intense linear algebra operations onto a GPU. The library is now included in NGSolve Linux - distributions, and can be used whenever an accelerator card by NVIDIA is available, and the cuda-runtime is installed.

[1]:
from ngsolve import *
[2]:
mesh = Mesh(unit_square.GenerateMesh(maxh=0.1))
for l in range(4):
    mesh.Refine()
fes = H1(mesh, order=2, dirichlet=".*")
print ("ndof =", fes.ndof)

u, v = fes.TnT()
with TaskManager():
    a = BilinearForm(grad(u)*grad(v)*dx+u*v*dx).Assemble()
    f = LinearForm(x*v*dx).Assemble()

gfu = GridFunction(fes)

jac = a.mat.CreateSmoother(fes.FreeDofs())

with TaskManager():
    inv_host = CGSolver(a.mat, jac, maxsteps=2000)
    gfu.vec.data = inv_host * f.vec
ndof = 119425

Now we import the NGSolve - cuda library.

It provides

  • an UnifiedVector, which allocates memory on both, host and device. The data is updated on demand either on host, or on device.

  • NGSolve - matrices can create their counterparts on the device. In the following, the conjugate gradients iteration runs on the host, but all operations involving big data are performed on the accelerator.

[3]:
try:
    from ngsolve.ngscuda import *

    fdev = UnifiedVector(f.vec)
    adev = a.mat.CreateDeviceMatrix()
    jacdev = jac.CreateDeviceMatrix()

    inv = CGSolver(adev, jacdev, maxsteps=2000)
    res = (inv * fdev).Evaluate()

    diff = Norm(gfu.vec - res)
    print ("diff = ", diff)
except:
    print ("no CUDA library or device available")
no CUDA library or device available