Skip to content

Conversation

@maximelucas
Copy link
Collaborator

add_simplices_from is slow, see #221. Profiling showed about 90% of the time is spent in the line checking existence of the simplex:

if not members or self.has_simplex(members):

has_simplex() now access members through S._edge rather than S.edges.members(s) which is significantly faster (see #221 for timings).

Here, adding 100 triangles seems about 10x faster:

%timeit S.add_simplices_from(list(triangles)[:100]) 
# old -> 9.13 ms ± 28.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# new -> 860 µs ± 5.18 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

The add_simplices_from can probably be improved even more, by rewriting it it without recursion for example. I have written a version but not pushed it because the seped improvement seems negligible in my case (it might not be with larger simplices). Also, it modifies the method much more, so has a larger chance of new bugs. And it changes the order in which simplices are added, so tests would need to be udpated. I would start with this minimal update at first, and maybe use the other version for a second step.

@maximelucas
Copy link
Collaborator Author

maximelucas commented Nov 10, 2022

As a result, random_simplicial_complex() also seems about 10x faster.
For some reason flag_complex() still seems slow though.
However, emulating flag_complex(max_order=2, ps=[0.2]) by computing the triangles and filling 20% by hand now just takes a few minutes:

S = xgi.SimplicialComplex()
S.add_nodes_from(nodes) # instantaneous
S.add_simplices_from(edges)  # 7 s for 18624 edges
S.add_simplices_from(triangles) # 2 min for 61642 triangles

@maximelucas
Copy link
Collaborator Author

Removed unnecessary generator expression in has_simplex, yielding further speed up (thanks profiling).

Timings, wrt to previous speedup. For

S = xgi.SimplicialComplex()
simplices = [{0, 1, 2, 3}, {4}, {5, 6}, {6, 7, 8}]
%timeit S.add_simplices_from(simplices, max_order=2)
# old -> 7.45 µs ± 10.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
# new -> 4.72 µs ± 16.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit xgi.random_simplicial_complex(250, [0.1, 0.001])
# old -> 2.92 s ± 65.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# new -> 1.72 s ± 42.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit S.add_simplices_from(triangles) # 61712 triangles
# old -> 2min 20s ± 331 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# new -> 1min 17s ± 801 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

So we get an additional 2x speedup (especially when adding more simplices).

@maximelucas maximelucas merged commit e47c8ad into main Nov 11, 2022
@maximelucas maximelucas deleted the speedup-simplices branch November 11, 2022 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants