scikit-fem: InteriorBasis slow for Hex1

While working with MeshHex on #279 and #281, I noticed that InteriorBasis seemed slow for MeshHex and ElementHex1.

I solved a Laplace equation (like ex13) and this was the bottleneck; e.g. for mesh.p.shape[1] == basis.N == 34001:

  • load: 0.6 s
  • InteriorBasis: 82.5 s
  • asm: 8.2s
  • preconditioner: 0.05 s (pyamgcl.amgcl)
  • solve: 0.36 s (solver_iter_pcg)

So the algebraic multigrid #264 is great and assembly is O. K. but building the basis is slow.

I’ve started to quantify this by comparing the time for InteriorBasis with MeshTet and ElementTetP1 using .init_tensor with the same points (and so same basis.N but with five times as many tetrahedral elements).

 from pathlib import Path
from time import time

from matplotlib.pyplot import subplots
import numpy as np

import skfem

number = []
tetrahedral = []
hexahedral = []
for n in range(2, 15):
    times = []
    points = [np.arange(n)]*3
    for cls, elt in [(skfem.MeshTet, skfem.ElementTetP1()),
                     (skfem.MeshHex, skfem.ElementHex1())]:
        mesh = cls.init_tensor(*points)
        tic = time()
        basis = skfem.InteriorBasis(mesh, elt)
        times.append(time() - tic)
    number.append(basis.N)
    tetrahedral.append(times[-2])
    hexahedral.append(times[-1])

fig, ax = subplots()
fig.suptitle('InteriorBasis')
ax.loglog(number, hexahedral, linestyle='none', marker='s',
        label=skfem.MeshHex.name)
ax.loglog(number, tetrahedral, linestyle='none', marker='^',
        label=skfem.MeshTet.name)
ax.set_xlabel('basis.N')
ax.set_ylabel('time / s')
ax.legend()
fig.savefig(Path(__file__).with_suffix('.png'))

The hexahedral case is a hundred times slower.

hex_basis

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 22 (22 by maintainers)

Most upvoted comments

Great. Let’s dig further into it.

It seems to me also that both of these Mapping classes need some additional love, possibly partial rewrite to get rid of these dimension-dependent parts and use more np.einsum.