1. Mathématiques - Informatique
Eurographics 2017
Bruno Lévy
ALICE Géométrie & Lumière
CENTRE INRIA Nancy Grand-Est
The Joy of
Computer Graphics Programming
Bruno Lévy, Inria researcher
2. Introducing myself…
First name: Bruno
Familly name: Lévy
Age: approaching 45
Occupation: Inria ALICE team lead (since 2004)
ALICE = Geometry processing + Fabrication (S. Lefebvre)
Research: navigating between graphics, math. and physics
Code: open-source (geogram),commercial (GOCAD, Vorpaline)
3. Introducing myself…
First name: Bruno
Familly name: Lévy
Age: approaching 45 (born in 1972 = 4004+1)
Occupation: Inria ALICE team lead (since 2004)
ALICE = Geometry processing + Fabrication (S. Lefebvre)
Research: navigating between graphics, math. and physics
Code: open-source (geogram),commercial (GOCAD, Vorpaline)
4. OVERVIEW
1. Introduction, let s talk about programming
2. Graphics: eye candy with GLUP
3. Numerics: cranking the number cruncher
4. Geometry: predicates without the agonizing pain
What s next ? Physics+Mathematics+Computing=?
6. Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
7. Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
Documented open-source* implementations of reference algos.
+ the most important results from my group (2000 to 2017)
Algorithms from >20 research articles
and two ERC projects (GOODSHAPE and VORPALINE)
*Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
8. Part. 1 On Software Design
War stories on the design and implementation
of geogram, graphite and vorpaline
Documented open-source* implementations of reference algos.,
+ the most important results from my group (2000 to 2017)
Algorithms from >20 research articles
and two ERC projects (GOODSHAPE and VORPALINE)
•Mesh parameterization (LSCM, ABF++, PGP)
•Spectral mesh processing (Manifold Harmonics)
•Newton Centroidal Voronoi Tesselation (surfaces and volumes)
•Remeshing, reconstruction, Optimal Transport
•Low-level algorithms (Delaunay, Voronoi, predicates) …
*Geogram (BSD) and Graphite (GLP), Vorpaline is proprietary
9. Part. 1 On Software Design
From my attic: my first computer !
10. Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
11. Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
2017 PC
Core i7 gen3, 3 GHz
16Gb RAM
Approx. 100 GFLOPs
12. Part. 1 On Software Design
1979 Apple ][
6502 processor, 1MHz
64Kb RAM
Approx. 10 FLOPs
2017 PC
Core i7 gen3, 3 GHz
16Gb RAM
Approx. 100 GFLOPs
X 1 million !!!!
38 years
13. Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
14. Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
Where did the 1 million acceleration factor go ?
15. Part. 1 On Software Design
What can you do in 20 seconds ?
3 GHz, 4 cores = 240 billions instructions !!
16. Part. 1 On Software Design
If you cannot do the job in less than 20 seconds
on a modern PC, then there is probably a
problem somewhere
What can you do in 20 seconds ?
3 GHz, 4 cores = 240 billions instructions !!
17. Part. 1 On Software Design
Boots in 20 seconds Boots in 3 minutes
Where did the 1 million acceleration factor go ?
- Lost in abstraction -
18. Part. 1 On Software Design
Abstraction in Programming:
+ Separates concepts
+ Separates specification from Implementation
19. Part. 1 On Software Design
Abstraction in Programming:
+ Separates concepts
+ Separates specification from Implementation
- Sometimes separates things
that should be considered together !!
20. Part. 1 On Software Design
Background on Futuristic Programming
Paul Haeberli - 1994
www.graficaobscura.com/future/index.html
21. Part. 1 On Software Design
Background on Futuristic Programming
Paul Haeberli - 1994
22. Part. 1 On Software Design
Futuristic Programming Priorities
Paul Haeberli - 1994
1. It is something that has NEVER BEEN DONE BEFORE.
2. The USER LIKES to use the program.
3. The program is as FAST as it can be.
4. The program is as SMALL as it can be.
5. The program is BUG-FREE.
6. The program needs NO USER MAINTENANCE.
7. The program requires NO USER DOCUMENTATION.
8. The program requires NO SYSTEM ADMINISTRATOR
23. Part. 1 On Software Design
Geogram/Graphite Programming Priorities
1. Make it as simple as possible (but not simpler)
24. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
Geogram/Graphite Programming Priorities
25. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
Geogram/Graphite Programming Priorities
26. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
Geogram/Graphite Programming Priorities
27. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
Geogram/Graphite Programming Priorities
28. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
Geogram/Graphite Programming Priorities
29. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
30. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
Simplicity is the
ultimate sophistication
31. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
Geogram/Graphite Programming Priorities
Simplicity is the
ultimate sophistication
32. Part. 1 On Software Design
1. Make it as simple as possible (but not simpler)
2. Make it as easy to use as possible
3. Make it as easy to compile as possible
4. Maximize speed
5. Minimize memory consumption
6. Minimize number of lines of code
7. Minimize number of C++ classes
8. Systematically document all classes, all functions, [+Biblio.]
9. Systematically document the implementation of all algorithms
10. Assertion checks everywhere
11. Zero warnings with all compilers / platforms
12. Perform systematic non-regression testing and mem. check.
Geogram/Graphite Programming Priorities
33. Part. 1 On Software Design
Futuristic programming
Usefullness (and coolness) are primary !
34. Part. 1 On Software Design
• Jonathan Shewchuk s Triangle and exact predicates
• Tetgen, MGTetra, MMG3d
• Omar Cornut s ImGUI library
• David Mount s ANN library
• The LUA prog. language
Futuristic programming
Examples of Futuristic codes
Usefullness (and coolness) are primary !
35. Part. 1 On Software Design
Case study: mesh data structures
From several Computer Graphics / Mesh Processing 101 courses
- including (earlier versions of) mine -
36. Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
37. + Benefit of abstraction: layered design
Part. 1 On Software Design
Case study: mesh data structures
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
Halfedges and edgeuses, harmful or useful ?
38. + Benefit of abstraction: layered design
- Separates things that should have been considered together
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
39. + Benefit of abstraction: layered design
- Separates things that should have been considered together
Not the optimal level of granularity
Part. 1 On Software Design
Case study: mesh data structures
Halfedges and edgeuses, harmful or useful ?
Halfedges Design Principles
1. Individual combinatorial elements
can be created/destroyed at any time
in constant time
2. Basic operations (collapse, split, )
3. Higher-level operations on top of them
40. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
41. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
42. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
43. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
44. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
45. Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
46. Objection ! (?) Deletion of one individual element is O(n) instead of constant
In fact: deleting 1 element = wrong granularity level !
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
47. Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
48. Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
49. Deleting a bunch of elements
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
50. Deleting a bunch of elements – operates also in O(n) – right granularity
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
51. Deleting a bunch of elements – operates also in O(n) – right granularity
Part. 1 On Software Design
Case study: mesh data structures
Needs array permutation (not in the STL unfortunately,
but easy to implement, see GEOGRAM::permutation).
Indexed Mesh data structure (no data structure)
52. Indexed Mesh data structure (no data structure)
Summary:
•An array of vertices coordinates
•An array of triangle vertices indices
Part. 1 On Software Design
Case study: mesh data structures
53. •An array of vertices coordinates
•An array of triangle vertices indices
•An array of triangle adjacencies (optional)
•An array of facet first indices (optional)
Part. 1 On Software Design
Case study: mesh data structures
Indexed Mesh data structure (no data structure)
Summary:
54. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
Part. 1 On Software Design
Case study: mesh data structures
55. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
Part. 1 On Software Design
Case study: mesh data structures
56. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
Part. 1 On Software Design
Case study: mesh data structures
57. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
Part. 1 On Software Design
Case study: mesh data structures
58. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
Part. 1 On Software Design
Case study: mesh data structures
59. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
6. Properties/attributes are simply additional arrays
Part. 1 On Software Design
Case study: mesh data structures
60. Benefits of such a
non-datastructure, non-object, non-oriented, (non-)programming
1. Simpler code
2. Less memory;
3. Parallelization #pragma omp parallel for
4. Easy copy: memcpy()
5. Easy I/O: fread()/fwrite()
6. Properties/attributes are simply additional arrays
7. Directly understood by OpenGL: VertexBufferObject
Part. 1 On Software Design
Case study: mesh data structures
61. A mesh = a bunch of arrays (std::vectors)
Part. 1 On Software Design
Case study: mesh data structures
62. A mesh = a bunch of arrays (std::vectors)
How do you iterate on a vector ?
Part. 1 On Software Design
Case study: mesh data structures
63. Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
64. Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
It s a pain to type
Clutters the source-code (less legible)
65. Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
66. Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
now:
for(auto&& i : V) {
do something with i
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
67. A mesh = a bunch of arrays (std::vectors)
How do you iterate on a vector ?
Part. 1 On Software Design
Case study: mesh data structures
Warning: flying tomatoes alert ahead,
(modern C++ lovers might throw tomatoes at me)!
68. Pre-2011:
for(std::vector<Thing>::iterator it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
2011:
for(auto it = V.begin(); it!=V.end(); ++it) {
do something with *it
}
now:
for(auto&& i : V) {
do something with I
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
69. How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
How do you iterate on a vector ?
70. How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only and Fortran programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly* (and also better vectorization)
- 15 additional keystrokes as compared to modern C++ range-for
How do you iterate on a vector ?
*But use ints instead of uints, omp does not like uints
71. How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly
- 15 additional keystrokes as compared to modern C++ range-for
The following code has been approved for
APPROPRIATE AUDIENCES
PG-13
72. How I iterate on a vector:
for(uint i=0; i<V.size(); ++i) {
do something with V[i];
}
Part. 1 On Software Design
Case study: mesh data structures
+ Easy to understand, even by C-only programmers
+ Compatible with all compilers
+ #pragma omp parallel-for friendly
- 15 additional keystrokes as compared to modern C++ range-for
#define FOR(i,N) for(uint i=0; i<(N); ++i)
FOR(i,V.size()) {
do something with V[i];
}
+ Easy to understand, legible
+ Trivial iterations easy to spot
- Macros are evil
[Nicolas Ray]
73. Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
74. Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
Answer:
I m not going to use something else than a vector, because it is the best
choice for the mesh data structure. Why keeping a tuning knob on the
dash board if it is always on the same position ?
modern/generic != futuristic
75. Part. 1 On Software Design
Case study: mesh data structures
Objection:
It is bad because it is not flexible,
what if you want to adapt your algorithm to another container ?
Answer:
I m not going to use something else than a vector, because it is the best
choice for the mesh data structure. Why keeping a tuning knob on the
dash board if it is always on the same position ? (think of the I-Phone)
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
modern/generic != futuristic
76. Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
77. Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
It is even better because it has
nothing else than what you need
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
78. Part. 1 On Software Design
Case study: mesh data structures
modern/generic != futuristic
It is good because it has
everything that you need
It is even better because it has
nothing else than what you need
Work is finished when you have
nothing to add and nothing to remove !
The Nokia N95, a
modern/generic phone.
The I-phone,
a futuristic phone.
79. Part. 1 On Software Design
Case study: mesh data structures
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
80. Part. 1 On Software Design
Case study: mesh data structures
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
Objection: but we loose genericity if we do that ???
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
81. Part. 1 On Software Design
Case study: mesh data structures
A parameter that always has the same value is not a parameter and should be
removed from the API.
A template that is instanced only once should not be a template.
Objection: but we loose genericity if we do that ???
Answer to objection: but we gain a lot, it declutters the
code, makes it more legible, reduces compilation times,
makes C++ compilation error messages more legible.
Why keeping a tuning knob on the dash board if it is always
on the same position ? (think of the I-Phone)
82. Part. 1 On Software Design
Case study: mesh data structures
Rule of thumb:
Make it a parameter not before you need it with at least two different values.
Make it a template not before you need at least two different instanciations.
*regarding compilation time, legibiity of error messages and run-time flex.
83. Part. 1 On Software Design
Case study: mesh data structures
Rule of thumb:
Make it a parameter not before you need it with at least two different values.
Make it a template not before you need at least two different instanciations.
About templates, consider less annoying* alternatives, such as
(1) object oriented programming / virtual functions
(2) or simply a parameter and if() statements
*regarding compilation time, legibility of error messages and run-time flex.
85. Part. 2 Graphics – endangered species
The Windows start menu The I-Phone jack
glBegin(GL_TRIANGLES)
glVertex(… )
glEnd()
OpenGL immediate mode
glPush/Pop/MultMatrix()
glLight()
OpenGL fixed functionality pipeline
86. Part. 2 Graphics – endangered species
glBegin(GL_TRIANGLES)
glVertex(… )
glEnd()
OpenGL immediate mode
glPush/Pop/MultMatrix()
glLight()
OpenGL fixed functionality pipeline
Difficulties for an undergraduate who starts:
(1) Assemble vertex buffer objects
(2) Design vertex and fragment shaders
(3) (+ the Professor, I see nothing syndrom, nothing new here)
R.I.P. R.I.P.
109. Part. 3. Numerics
Numerical problems: least squares
F(xf) = A.x - d = Al.xl + Af.xf - d
2 2
F(xf) minimum Af
t.Af.xf = Af
t.d - Af
tAl.xl
M.x = b
}
}
110. Part. 3. Numerics
Numerical problems: least squares
F(xf) = A.x - d = Al.xl + Af.xf - d
2 2
F(xf) minimum Af
t.Af.xf = Af
t.d - Af
tAl.xl
M.x = b
}
}
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
111. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
112. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
Similarity between a mesh and a sparse matrix:
113. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlBegin(NL_ROW)
nlAddCoefficient(I,j,val)
nlRightHandSide(val)
nlEnd(NL_ROW)
Similarity between a mesh and a sparse matrix:
OpenNL: API inspired by OpenGL immediate mode.
(+ automatic construction of AtA for least-squares)
114. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix: dynamic data structure (can grow)
OpenNL internals
…
…
…
…
…
115. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix NLCRSMatrix
OpenNL internals
nlCompress()
116. Part. 3. Numerics – the OpenNL library.
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
NLSparseMatrix NLCRSMatrix NLCusparseMatrix
OpenNL internals GPU
nlCompress() (optionnal)
117. Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve() Iterative solvers
CG
GMRes
BiCGStab
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
118. Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve() Iterative solvers
Direct solvers
CG
GMRes
BiCGStab
SuperLU
CHOLDMOD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
119. Part. 3. Numerics – the OpenNL library
Numerical problems: least squares
The problem:
(1) construct the linear system (assembly)
(2) solve a linear system
nlSolve()
Iterative solvers
Direct solvers
CG
GMRes
BiCGStab
SuperLU
CHOLDMOD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
Eigen solver ARPACK
120. Part. 3. Numerics – the OpenNL library
OpenNL as a pluggable software module
Following futuristic programming principles:
* OpenNL also available as a single .c,.h pair, portable
to all architectures, easy to compile.
* Object-Oriented abstract matrix interface in C (achieves
run-time CPU/GPU flexibility)
* Dynamically loads CUDA CuBLAS and CuSparse
on demand (as well as CHOLMOD, SUPERLU,ARPACK)
* Double precision (and no single precision).
121. Part. 3. Numerics – the OpenNL library
OpenNL at work Everything available in geogram
GUI in graphite
122. Part. 3. Numerics – the OpenNL library
OpenNL at work
LSCM,
Spectral parameterization.
(600 lines of code for both)
ABF++ (800 lines of code)
PGP, QuadCover, MIP.
(700 lines of code)
Manifold Harmonics, HKS, ADF. (400 lines of code)
Everything available in geogram
GUI in graphite
135. Part 4. Geometry – a difficult dataset
Lots of degeneracies:
Voronoi diagram with degree 4 vertices.
Voronoi cell faces match exactly facets of the initial surface.
137. Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
138. Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
139. Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Sign( d(p,xj) – d(p,xi)) > 0
140. Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
141. Part. 4 Difficulties – predicates
xi
xj
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Compute the intersections
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
142. Part. 4 Difficulties – predicates
xi
xj
Sign( d(p,xj) – d(p,xi)) > 0
Sign( d(p,xj) – d(p,xi)) < 0
Elementary operation: cut a polygon
(or polyhedron) with a bisector
Classify the vertices of the polygon
Compute the intersections - discard
143. Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
144. Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
145. Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
(they are intersections between a
segment and a bisector)
146. Part. 4 Difficulties – predicates
xi
xj
xk Now clipping with the bisector of (xi, xk)
We need to classify all the points, including
these ones !
(they are intersections between a
segment and a bisector)
This generates a new intersection
(between a facet and two bisector)
147. Part. 4 Difficulties – predicates
Three configurations
1) Side(xi,xj,q) where q is a vertex of S
153. Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
Implementations of exact predicates:
- J. Shewchuk s code
- CGAL (Pion, Meyer)
154. Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
Implementations of exact predicates:
- J. Shewchuk s code
- CGAL (Pion, Meyer)
They do not have Side1(), Side2(), Side3() ( exotic predicates )
155. Part. 4 Difficulties – predicates
Three configurations
1) Side1(xi,xj,q)
2) Side2(xi,xj,xk,p1,p2)
3) Side3(xi,xj,xk, xl,p1,p2,p3)
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
156. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Wish list:
• Easy to use
(no Guru needed for each new predicate)
• Reasonably efficient
• Easy to compile/integrate ( Futuristic programming )
(multi_precision.h, multi_precision.cpp and that s all)
157. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a0a1a2a3
x 20
x 21*32x 22*32x 23*32
…
Each number is an array of (32 bits) integers:
Implement +,-,* (reasonably easy)
Sign: look at the leading non-zero component
158. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a limitation :
c = a10 * 210*32 + b0
159. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #1: (dense) multi-precision (GMP)
a limitation :
b000a10
x 20x 210*32
c = a10 * 210*32 + b0
…
160. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Store the exponents of the components
161. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.
162. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.mantissa mantissa
163. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #2: (sparse) multi-precision
b0 | 0a10 | 10
c = a10 * 210*32 + b0
Exp. Exp.mantissa mantissa
These are floating point numbers !!!
164. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
These are floating point numbers !!!
165. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
These are floating point numbers !!!
166. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
They are non-overlapping
These are floating point numbers !!!
167. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x3 x2 x1
…
Each number is represented by the sum of an array of components
They are sorted in decreasing exponents
They are non-overlapping
The sign is determined by the first component (highest exponent)
These are floating point numbers !!!
168. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
169. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
+
Length:
l+m
Length l Length m
170. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
x2 x1Two_sum(double a, double b)
+
*
Length:
l+m
Length:
2*l
A double
Length l
171. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Length: 2*l*m
Expansion * Expansion product implemented by a recursive function
( distillation )
Length l Length m
172. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Length: 2*l*mLength l Length m
173. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Use arithmetic filters
Adaptive precision [Shewchuk] ? Too complicated to get right
Length: 2*l*mLength l Length m
174. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
Idea #3: expansions (Shewchuk)
* …
Expansion * Expansion product implemented by a recursive function
( distillation )
Performance ? 10 to 40 times slower than standard doubles
Use arithmetic filters
Adaptive precision [Shewchuk] ? Too complicated to get right
Quasi-static filters [Meyer and Pion] – FPG generator (easy to use)
Length: 2*l*mLength l Length m
175. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
176. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
(why not templates / metaprogramming ?
would be possible, but specialized language is much better here).
177. Part. 4 Exact Arithmetics
How to implement Side1(), Side2(), Side3() ?
We need an exact number type with +,-,*,Sign()
PCK (Predicate Construction Kit)
multi_precision.h / multi_precision.cpp
A low-level expansion class (allocates expansions on stack)
A high-level C++ number type (+,-,*,Sign overloads)
a compiler that generates the filter with FPG [Meyer and Pion] and the
exact precision version with expansions
So we are done ?
178. Part. 4 Symbolic Perturbation
How to implement Side1(), Side2(), Side3() ?
xi
xj
Not yet !!
179. Part. 4 Symbolic Perturbation
How to implement Side1(), Side2(), Side3() ?
xi
xj
Not yet !!
199. xi
xj
π(i,j) = {p | d2(p,xi) = d2(p,xj)}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
In our case, perturb the
weights of a power diagram.
200. xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
Part. 4 Symbolic Perturbation
In our case, perturb the
weights of a power diagram.
201. xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Part. 4 Symbolic Perturbation
202. xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Symbolic perturbation – Simulation of Simplicity:
Define the weight as a function of ε: wi = εi
Part. 4 Symbolic Perturbation
203. xi
xj
πw(i,j) = {p | d2(p,xi) - wi = d2(p,xj) - wj}
[Voronoi]
[Edelsbrunner et.al]
[Devillers et.al]
The Voronoi diagram is replaced with a power diagram
Symbolic perturbation – Simulation of Simplicity:
Define the weight as a function of ε: wi = εi
The combinatorics is determined by the limit ε →0
Part. 4 Symbolic Perturbation
204. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
Part. 4 Symbolic Perturbation
205. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
206. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
207. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
208. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Order the terms in wi = εi
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
209. How to write side1(), side2(), side3(), side4() ?
d2(q,pj)-wj – d2(q,pi) + wi where:
q = πw(i,k1) ∩ …πw(i,kd) ∩ [p1,p2,p3…pd]
q = (1/d) Q
Keep numerator and denom.
separate (remember, we are
not allowed to divide)
Inject q=(1/d) Q in side1() and mutliply by d to remove the division
Order the terms in wi = εi the constant one is non-perturbed predicate
if zero, the first non-zero one determines the sign
Solve for q in:
q Є πw(i,k1)
…
q Є πw(i,kd)
q Є [p1,p2,p3…pd]
{
Part. 4 Symbolic Perturbation
232. Part 4. Geometry - RVD
If we eliminate the zero components during computations, the length of the
expansions remain reasonable (see observation in Shewchuk’s paper)
237. The PCK (Predicate Construction Kit)
Features:
• Expansion number type – low level API (allocation on stack, efficient)
• High level API with operators (easy to use, less efficient)
• Script to generate FPG filter and exact version with SOS
• Standard predicates (orient2d, 3d, insphere3d, orient4d)
• More exotic predicates for RVD (side1, side2, side3, side 4 in dim 3,4,6,7)
• 3D Delaunay triangulation
• 3D weighted Delaunay triangulation
• Only 6 source files
• multi_precision.(h,cpp)
• predicates.(h,cpp)
• delaunay3d.(h,cpp)
• Fully documented
• No dependency (compiles and runs everywhere*, I got a version on my phone :-)
BSD license (do what you want with it, including business)
*In the IEEE754 world
262. Optimal Transport
Invert Newton Einstein Eqn to go back 14 milliards years in time
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 light years)
263. Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
264. Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
265. Optimal Transport
The millenium simulation project,
Max Planck Institute fur Astrophysik
pc/h : parsec (= 3.2 années lumières)
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
266. Optimal Transport
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
267. Optimal Transport
In 2002, 5 hours of computation
with a supercomputer / 5000 points
Can we do it with 1 000 000 points ?
Yes, if we wait 4500 years
We need a new algorithm.
268. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
269. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
270. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
271. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
272. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
10 million Dirac masses in 90 minutes
273. Towards Early Universe Reconstruction
Numerical Experiment: Performances
2002: several hours of supercomputer time were needed
for computing OT with a few thousand Dirac masses, with a combinatorial
algorithm in O(n2log(n))
2015:
3D version of [Mérigot] (multilevel + BFGS) + several tricks [L 2015]
2016: Damped Newton [Mérigot, Thibert] + several tricks for 3D:
1 million Dirac masses in 240 seconds
10 million Dirac masses in 90 minutes
2017: 10 million Dirac masses in 2 minutes (for specific configurations)
Semi-discrete OT is now scalable ! (new tool in Num. Ana. Toolbox)
277. Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
278. Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
Gains Costs
279. Take-home message
Programming is a great source of fun
Futuristic programming principles
Program speed
Low memory consumption
Lines of code
Classes
Templates
Gains Costs
Measure it !
(profiler, continuous integration)
283. Take-home message: Usefulness is primary
Futuristic design
.cpp
.h
void the_functionality(Data& )
* Make it easy to compile
* Do not bother the user
with internal details (even if
you are proud of them)
284. Take-home message: Usefulness is primary
.cpp
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
GLUP state
variablesVanillaGL
OpenGL ES /
WebGL
GLSL 1.5
GLSL 4.4
matrix stacks
buffers
Shaders
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
.c
CG
GMRes
BiCGStab
SuperLU
CHOLDM
OD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
ARPACK
NLSparseMatrix NLCRSMatrix
nlCompress()
285. Take-home message: Usefulness is primary
.cpp
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
GLUP state
variablesVanillaGL
OpenGL ES /
WebGL
GLSL 1.5
GLSL 4.4
matrix stacks
buffers
Shaders
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
.cpp
CG
GMRes
BiCGStab
SuperLU
CHOLDM
OD
CPU/GPU
Abstraction layer
OpenMP
multicore
CUDA
CuBLAS
CuSparse
ARPACK
NLSparseMatrix NLCRSMatrix
nlCompress()
Algorithms and Data Structures
Mostly arrays (std::vector) and for() loops
Object oriented / virtual functions
Run-time selection of algorithm
Generic programming
For dimension-independent code (RVD)
If() statements
Predicates
286. Futuristic programming – the product
GLUP.h – C API
glupBegin(), glupEnd(), glupVertex()
OpenNL.h – C API
nlBegin(), nlEnd(), nlCoeff(), nlSolve()
Geogram – C++ API
Mesh class, Delaunay, Voronoi,
Remesh, param., repair, reconstruct.
Predicate Construction Kit
Compiler for arbitrary precision
Geometric predicates (C/C++ API)
Graphite: Qt GUI + LUA scripting
Download from gforge.inria.fr, see also links on my webpage
287. Acknowledgements
Eurographics Association
European Research Council
GOODSHAPE ERC-StG-205693
VORPALINE ERC-PoC-334829
ANR MORPHO (Vision), ANR BECASIM (Physics)
ANR MAGA (P.I.: Q. Merigot),
ANR ROOT (P.I.: N. Bonneel) Optimal Transport stuff.
Inria EXPLORAGRAM
Key contributors to Geogram/Graphite:
N. Ray, W.-C. Li, B. Vallet, D. Sokolov, N. Bonneel, R. Zayer, A. Sheffer
MOKA team (Monge-Ampere-Kantorovich)