Skip to content

Implement parallel f-vector for polytopes #31245

@kliem

Description

@kliem

This ticket parallelizes the f-vector for polytopes.

Each thread has its private structure with which it does partial jobs. Depending on the parallelization depth, there is one job per face of fixed codimension (usually 1,2 or 3). After everything has finished, the partial f-vectors will be added.

Actually, every face is visited and thus the code could be modified in the future, to explore other properties of faces then just the dimension. The parallelization seems to work well with at least 40 threads (for computations taking long enough such that this pays off, see https://arxiv.org/pdf/1905.01945.pdf).

Also the algorithm does work in other situations (simplicial complex, lattice of flats of a matroid) and this parallel structure could be used for this as well.

On the downside, sig_on()/sig_off() doesn't work with with multiple threads and has to be replaced by a simple sig_check(). Also raising errors in parallel code results in terrible slow down. Hence the errors are replaced by returning the exception value. In case of a bug there won't be any traceback anymore, but at least also no segmenation fault.

Before:

sage: P = P.base_extend(QQ)                                                                                                                                   
sage: P = P.base_extend(QQ)                                                                                                                                   
sage: Q = P.join(P.polar(in_affine_span=True))                                                                                                                
sage: C = CombinatorialPolyhedron(Q)                                                                                                                          
sage: %time C.f_vector()                                                                                                                                      
CPU times: user 111 ms, sys: 186 µs, total: 111 ms
Wall time: 111 ms
(1, 150, 3990, 25590, 69450, 95402, 69450, 25590, 3990, 150, 1)

sage: P = polytopes.Birkhoff_polytope(5)                                                                                                                      
sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector()                                                                                                                                      
CPU times: user 584 ms, sys: 25 µs, total: 584 ms
Wall time: 583 ms
(1, 120, 5040, 50250, 233400, 631700, 1113700, 1367040, 1220550, 817150, 419225, 167200, 52120, 12600, 2300, 300, 25, 1)

# Using the <simple> version of the algorithm.
sage: P = polytopes.associahedron(['A', 11], backend='normaliz')                                                                                              
sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector()                                                                                                                                      
CPU times: user 37.9 s, sys: 17.2 ms, total: 37.9 s
Wall time: 37.9 s
(1, 208012, 1144066, 2735810, 3730650, 3197700, 1790712, 659736, 157080, 23100, 1925, 77, 1)

After (machine has 4 cores):

sage: P = polytopes.permutahedron(5)                                                                                                                          
sage: P = P.base_extend(QQ)                                                                                                                                   
sage: Q = P.join(P.polar(in_affine_span=True))                                                                                                                
sage: C = CombinatorialPolyhedron(Q)                                                                                                                          
sage: %time C.f_vector(num_threads=1)                                                                                                                         
CPU times: user 107 ms, sys: 0 ns, total: 107 ms
Wall time: 107 ms
(1, 150, 3990, 25590, 69450, 95402, 69450, 25590, 3990, 150, 1)

sage: C = CombinatorialPolyhedron(Q)                                                                                                                          
sage: %time C.f_vector(num_threads=2)                                                                                                                         
CPU times: user 108 ms, sys: 0 ns, total: 108 ms
Wall time: 55.6 ms
(1, 150, 3990, 25590, 69450, 95402, 69450, 25590, 3990, 150, 1)

sage: C = CombinatorialPolyhedron(Q)                                                                                                                          
sage: %time C.f_vector(num_threads=4)                                                                                                                         
CPU times: user 147 ms, sys: 52 µs, total: 147 ms
Wall time: 38.6 ms
(1, 150, 3990, 25590, 69450, 95402, 69450, 25590, 3990, 150, 1)

sage: C = CombinatorialPolyhedron(Q)                                                                                                                          
sage: %time C.f_vector(num_threads=8)                                                                                                                         
CPU times: user 236 ms, sys: 0 ns, total: 236 ms
Wall time: 31.2 ms
(1, 150, 3990, 25590, 69450, 95402, 69450, 25590, 3990, 150, 1)

sage: P = polytopes.Birkhoff_polytope(5)                                                                                                                      
sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=1)                                                                                                                         
CPU times: user 354 ms, sys: 0 ns, total: 354 ms
Wall time: 354 ms
(1, 120, 5040, 50250, 233400, 631700, 1113700, 1367040, 1220550, 817150, 419225, 167200, 52120, 12600, 2300, 300, 25, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=2)                                                                                                                         
CPU times: user 363 ms, sys: 0 ns, total: 363 ms
Wall time: 181 ms
(1, 120, 5040, 50250, 233400, 631700, 1113700, 1367040, 1220550, 817150, 419225, 167200, 52120, 12600, 2300, 300, 25, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=4)                                                                                                                         
CPU times: user 459 ms, sys: 0 ns, total: 459 ms
Wall time: 117 ms
(1, 120, 5040, 50250, 233400, 631700, 1113700, 1367040, 1220550, 817150, 419225, 167200, 52120, 12600, 2300, 300, 25, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=8)                                                                                                                         
CPU times: user 776 ms, sys: 154 µs, total: 776 ms
Wall time: 103 ms
(1, 120, 5040, 50250, 233400, 631700, 1113700, 1367040, 1220550, 817150, 419225, 167200, 52120, 12600, 2300, 300, 25, 1)


# Using the <simple> version of the algorithm.
sage: P = polytopes.associahedron(['A', 11], backend='normaliz')                                                                                              
sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=1)                                                                                                                         
CPU times: user 33.5 s, sys: 0 ns, total: 33.5 s
Wall time: 33.5 s
(1, 208012, 1144066, 2735810, 3730650, 3197700, 1790712, 659736, 157080, 23100, 1925, 77, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=2)                                                                                                                         
CPU times: user 34.4 s, sys: 3.49 ms, total: 34.4 s
Wall time: 17.2 s
(1, 208012, 1144066, 2735810, 3730650, 3197700, 1790712, 659736, 157080, 23100, 1925, 77, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=4)                                                                                                                         
CPU times: user 35.9 s, sys: 15.5 ms, total: 35.9 s
Wall time: 9 s
(1, 208012, 1144066, 2735810, 3730650, 3197700, 1790712, 659736, 157080, 23100, 1925, 77, 1)

sage: C = CombinatorialPolyhedron(P)                                                                                                                          
sage: %time C.f_vector(num_threads=8)                                                                                                                         
CPU times: user 1min 6s, sys: 31.3 ms, total: 1min 6s
Wall time: 8.44 s
(1, 208012, 1144066, 2735810, 3730650, 3197700, 1790712, 659736, 157080, 23100, 1925, 77, 1)

CC: @jplab @LaisRast @stumpc5 @tscrim

Component: geometry

Keywords: parallel f-vector

Author: Jonathan Kliem

Branch/Commit: 4c0a4ae

Reviewer: Travis Scrimshaw

Issue created by migration from https://trac.sagemath.org/ticket/31245

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions