Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3b3501e
WIP ParallelIIEstimator
BDoignies Mar 2, 2026
0b9242b
Forgot .h file
BDoignies Mar 2, 2026
04e562a
Ordered evaluation for ParallelIIEstimator
BDoignies Mar 11, 2026
beebcf8
Few more comments
BDoignies Mar 11, 2026
3e9680d
Merge branch 'main' into parallelII
dcoeurjo Mar 12, 2026
1121654
Merge branch 'main' into parallelII
dcoeurjo Mar 12, 2026
933395b
Merge branch 'main' into parallelII
dcoeurjo Mar 13, 2026
f5e2d01
Pre commit fixes
BDoignies Apr 1, 2026
7021794
cmake edit to make sure that DGTAL_WITH_OPENMP has been set
dcoeurjo Apr 3, 2026
07c6535
WIP testing the splitter
dcoeurjo Apr 3, 2026
efee3cb
Adding Axis splitter and concept check
dcoeurjo Apr 9, 2026
57b6f43
Merge branch 'main' into parallelII
dcoeurjo Apr 9, 2026
4fee775
Removing traces.
dcoeurjo Apr 9, 2026
b1650b1
t push
dcoeurjo Apr 9, 2026
2c5da9b
Moved DomainSplitter to kernel package
BDoignies Apr 29, 2026
f84ad03
Updated test for parallel integral invariant and added a bit of doc.
BDoignies Apr 29, 2026
9914bb9
Add include to StdDefs
BDoignies May 18, 2026
ef5af3e
Removing unused parameter
dcoeurjo Jun 7, 2026
55ae444
Removing unsused variable
dcoeurjo Jun 7, 2026
96bf95a
Merge branch 'main' into parallelII
dcoeurjo Jun 7, 2026
648bc3a
Adding header
dcoeurjo Jun 7, 2026
7251dea
Adding header
dcoeurjo Jun 7, 2026
7df9956
Adding header
dcoeurjo Jun 7, 2026
5864887
Fixing doxygen issues
dcoeurjo Jun 7, 2026
3aff584
Merge branch 'main' into parallelII
dcoeurjo Jun 7, 2026
1f34d5b
Documentation edits
dcoeurjo Jun 7, 2026
9db68c4
edits
dcoeurjo Jun 8, 2026
325d0e1
Adding parallel II example and updating the documentation
dcoeurjo Jun 8, 2026
010262f
Adding parallel II example and updating the documentation
dcoeurjo Jun 8, 2026
6b4fa0c
Changelog
dcoeurjo Jun 8, 2026
b367f15
Changelog
dcoeurjo Jun 8, 2026
a2ce45e
Adding multithreading for NormalVectors
dcoeurjo Jun 8, 2026
9db67f3
Enabling axis selection in ParallelII/AxisSplitter
dcoeurjo Jun 12, 2026
4bd6965
Adding illustration
dcoeurjo Jun 12, 2026
0e2c3c3
Enabling openmp parameter in python
dcoeurjo Jun 13, 2026
d0213bb
JPG image
dcoeurjo Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ['--maxkb=3000']
- id: check-symlinks
- id: check-case-conflict
- repo: https://github.com/codespell-project/codespell
Expand Down
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- pre-commit hooks have been activated for sanity checks on files before running the git commit (David Coeurjolly, [#1835](https://github.com/DGtal-team/DGtal/pull/1835))
- Add pre-commit setup instructions to contributing documentation (David Coeurjolly, [#1836](https://github.com/DGtal-team/DGtal/pull/1836))

- *Geometry*
- New multithread version of Integral Invariant estimators using a DomainSplitter. A new parameter has been added in the II shortcuts to enable multithreading when OpenMP has been activated --DGTAL_WITH_OPENMP flag-- (Bastien Doignies, David Coeurjolly, [#1842](https://github.com/DGtal-team/DGtal/pull/1842))

## Changes

- *Documentation*
Expand Down
2 changes: 2 additions & 0 deletions cmake/CheckDGtalOptionalDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ endif()
set(OPENMP_FOUND_DGTAL 0)
if(DGTAL_WITH_OPENMP)
include(openmp)
target_link_libraries(DGtal PUBLIC OpenMP::OpenMP_CXX)
target_compile_definitions(DGtal PUBLIC -DDGTAL_WITH_OPENMP)
set(DGtalLibDependencies ${DGtalLibDependencies} OpenMP::OpenMP_CXX)
set(OPENMP_FOUND_DGTAL 1)
set(DGTAL_WITH_OPENMP 1)
Expand Down
1 change: 1 addition & 0 deletions examples/geometry/surfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if ( DGTAL_WITH_POLYSCOPE_VIEWER )
dvcm-3d
examplePlaneProbingSurfaceLocalEstimator
exampleMaximalSegmentSliceEstimation
parallelIIShortcuts
)
foreach(FILE ${DGTAL_EXAMPLES_POLYSCOPE_SRC})
DGtal_add_example(${FILE})
Expand Down
132 changes: 132 additions & 0 deletions examples/geometry/surfaces/parallelIIShortcuts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
**/

/**
* @file
* @ingroup Examples
* @author David Coeurjolly (david.coeurjolly@cnrs.fr)
* Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), INSA-Lyon, France
*
* @date 2026/06/08
*
*
* This file is part of the DGtal library.
*/

///////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "ConfigExamples.h"

// Helpers
#include "DGtal/base/Common.h"
#include "DGtal/helpers/StdDefs.h"

#include "DGtal/helpers/Shortcuts.h"
#include "DGtal/helpers/ShortcutsGeometry.h"


#ifdef DGTAL_WITH_POLYSCOPE_VIEWER
// Visualization
#include "DGtal/io/viewers/PolyscopeViewer.h"
#include "DGtal/io/colormaps/GradientColorMap.h"
#endif

///////////////////////////////////////////////////////////////////////////////

using namespace DGtal;

// Using standard 3D digital space.
typedef Shortcuts<Z3i::KSpace> SH3;
typedef ShortcutsGeometry<Z3i::KSpace> SHG3;
///////////////////////////////////////////////////////////////////////////////

int main()
{

//! [Parallel-instantiation]
auto params = SH3::defaultParameters() | SHG3::defaultParameters();
params( "polynomial", "goursat" )( "gridstep", 0.125 );
auto implicit_shape = SH3::makeImplicitShape3D ( params );
auto digitized_shape = SH3::makeDigitizedImplicitShape3D( implicit_shape, params );
auto K = SH3::getKSpace( params );
auto surface = SH3::makeDigitalSurface( digitized_shape, K, params );
auto surfels = SH3::getSurfelRange( surface, params );
//! [Parallel-instantiation]

//! [Parallel-run]
trace.info()<< "Input vol domain: "<< digitized_shape->getDomain() << std::endl;
//Sequential
trace.beginBlock("Single thread");
auto curv = SHG3::getIIMeanCurvatures( digitized_shape, surfels, params );
trace.endBlock();

//Parallel
trace.beginBlock("4 threads on default axis");
auto curv_par4 = SHG3::getIIMeanCurvatures( digitized_shape, surfels,
params( "ii-thread-number", 4 ));
trace.endBlock();

//Parallel
trace.beginBlock("8 threads on axis 0");
auto curv_par8_0 = SHG3::getIIMeanCurvatures( digitized_shape, surfels,
params( "ii-thread-number", 8 )
( "ii-split-axis", 0 ) );
trace.endBlock();

//Parallel
trace.beginBlock("8 threads on axis 1");
auto curv_par8_1 = SHG3::getIIMeanCurvatures( digitized_shape, surfels,
params( "ii-thread-number", 8 )
( "ii-split-axis", 1 ) );
trace.endBlock();

//Parallel
trace.beginBlock("8 threads on axis 2");
auto curv_par8_2 = SHG3::getIIMeanCurvatures( digitized_shape, surfels,
params( "ii-thread-number", 8 )
( "ii-split-axis", 2 ) );
trace.endBlock();

//Parallel
trace.beginBlock("16 threads on axis 2");
auto curv_par16 = SHG3::getIIMeanCurvatures( digitized_shape, surfels,
params( "ii-thread-number", 16 )
( "ii-split-axis", 2 ) );
trace.endBlock();
//! [Parallel-run]

#ifdef DGTAL_WITH_POLYSCOPE_VIEWER
PolyscopeViewer viewer;

std::string objectName = "Surfels";
viewer.draw(surfels, objectName); // Draws the object independently
viewer.addQuantity(objectName, "Mean curvature", curv_par8_0);

AxisDomainSplitter<Z3i::Domain> splitter(0);
AxisDomainSplitter<Z3i::Domain>::SplitDomainsInfo splits = splitter(digitized_shape->getDomain(), 8);
HueShadeColorMap<unsigned int> cmap(0,(unsigned int)splits.size());
for(auto i=0; i< splits.size(); ++i)
{
viewer << cmap(i);
viewer << splits[i].domain;
}
viewer.show();
#endif

return 0;
}
// //
///////////////////////////////////////////////////////////////////////////////
2 changes: 2 additions & 0 deletions examples/tutorial-examples/shortcuts-geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ int main( int /* argc */, char** /* argv */ )
//! [dgtal_shortcuts_ssec2_1_6s]
auto params = SH3::defaultParameters() | SHG3::defaultParameters();
params( "colormap", "Tics" );
// To request the parallel II estimator when DGtal is built with OpenMP:
// params( "ii-thread-number", 4 )( "ii-split-axis", 1 );
auto bimage = SH3::makeBinaryImage( examplesPath + "samples/Al.100.vol", params );
auto K = SH3::getKSpace( bimage, params );
auto surface = SH3::makeDigitalSurface( bimage, K, params );
Expand Down
20 changes: 15 additions & 5 deletions src/DGtal/doc/tutorials/moduleShortcuts.dox
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,17 @@ You may choose your traversal order ("Default", "DepthFirst", "BreadthFirst").

@subsubsection dgtal_shortcuts_ssec2_1_6 -> build digital surface -> estimate curvatures -> save OBJ.

This example requires ShortcutsGeometry. It shows how tu use the integral invariant curvature estimator on a digital shape model to estimate its mean or Gaussian curvature.
This example requires ShortcutsGeometry. It shows how to use the integral invariant curvature estimator on a digital shape model to estimate its mean or Gaussian curvature.

The same shortcut methods may also use the parallel integral invariant
estimator when DGtal is built with OpenMP support (`DGTAL_WITH_OPENMP` option). To request it, set
parameter `ii-thread-number` to a value different from `1` before
calling `ShortcutsGeometry::getIINormalVectors`,
`ShortcutsGeometry::getIIMeanCurvatures`,
`ShortcutsGeometry::getIIGaussianCurvatures`, or
`ShortcutsGeometry::getIIPrincipalCurvaturesAndDirections`.
The main axis of the default `AxisDomainSplitter` can be selected with
parameter `ii-split-axis` (default value `0`).

\snippet examples/tutorial-examples/shortcuts-geometry.cpp dgtal_shortcuts_ssec2_1_6s

Expand Down Expand Up @@ -552,10 +562,10 @@ Shortcuts::Point is Z3i::KSpace::Point.
- ShortcutsGeometry::getTrivialNormalVectors: returns the trivial (Trivial) normal vectors to the given surfel range
- ShortcutsGeometry::getCTrivialNormalVectors: returns the convolved trivial (CTrivial) normal vectors to the given surfel range
- ShortcutsGeometry::getVCMNormalVectors: returns the Voronoi Covariance Measure (VCM) normal vectors to the given surfel range
- ShortcutsGeometry::getIINormalVectors: returns the Integral Invariant (II) normal vectors to the given surfel range (embedded in a binary image or a digitized implicit shape)
- ShortcutsGeometry::getIIMeanCurvatures: returns the Integral Invariant (II) mean curvatures onto the given surfel range (embedded in a binary image or a digitized implicit shape)
- ShortcutsGeometry::getIIGaussianCurvatures: returns the Integral Invariant (II) Gaussian curvatures onto the given surfel range (embedded in a binary image or a digitized implicit shape)
- ShortcutsGeometry::getIIPrincipalCurvaturesAndDirections: returns the Integral Invariant (II) principal curvatures values and directions for the given surfel range (embedded in a binary image or a digitized implicit shape)
- ShortcutsGeometry::getIINormalVectors: returns the Integral Invariant (II) normal vectors to the given surfel range (embedded in a binary image or a digitized implicit shape), optionally through the parallel II estimator when `ii-thread-number != 1` (when `DGTAL_WITH_OPENMP` has been set to true).
- ShortcutsGeometry::getIIMeanCurvatures: returns the Integral Invariant (II) mean curvatures onto the given surfel range (embedded in a binary image or a digitized implicit shape), optionally through the parallel II estimator when `ii-thread-number != 1` (when `DGTAL_WITH_OPENMP` has been set to true).
- ShortcutsGeometry::getIIGaussianCurvatures: returns the Integral Invariant (II) Gaussian curvatures onto the given surfel range (embedded in a binary image or a digitized implicit shape), optionally through the parallel II estimator when `ii-thread-number != 1` (when `DGTAL_WITH_OPENMP` has been set to true).
- ShortcutsGeometry::getIIPrincipalCurvaturesAndDirections: returns the Integral Invariant (II) principal curvatures values and directions for the given surfel range (embedded in a binary image or a digitized implicit shape), optionally through the parallel II estimator when `ii-thread-number != 1` (when `DGTAL_WITH_OPENMP` has been set to true).
- ShortcutsGeometry::getCNCMeanCurvatures: returns the Corrected Normal Current (CNC) mean curvatures onto the given faces (as ids of the mesh).
- ShortcutsGeometry::getCNCGaussianCurvatures: returns the Corrected Normal Current (CNC) gaussian curvatures onto the given faces (as ids of the mesh).
- ShortcutsGeometry::getCNCPrincipalCurvaturesAndDirections: returns the Corrected Normal Current (CNC) principal curvatures values and directions for the given face range (as ids of the mesh).
Expand Down
Binary file added src/DGtal/geometry/doc/images/parallelsplit.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 68 additions & 2 deletions src/DGtal/geometry/doc/moduleIntegralInvariant.dox
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace DGtal {

[TOC]

@author Jérémy Levallois
@author Jérémy Levallois, David Coeurjolly

\section II_sectOverview Overview

Expand Down Expand Up @@ -199,6 +199,72 @@ Here is some results in 2d and 3d :
@image html Bunny_128_mean.png "Mean curvature mapped on a Stanford bunny (credit is given to the Stanford Computer Graphics Laboratory https://graphics.stanford.edu/data/3Dscanrep/)"
@image html Bunny_64_k1.png "First principal curvature direction mapped on a Stanford bunny (credit is given to the Stanford Computer Graphics Laboratory https://graphics.stanford.edu/data/3Dscanrep/)"

*/


\section II_sectParallel Parallel Integral Invariant estimators

Each Integral Invariant estimator can run in parallel in DGtal, provided the library is compiled with OpenMP support (`DGTAL_WITH_OPENMP` option).
The interface for computation and parameter setting is the same as for every other integral invariant estimator and can
be used as a drop-in replacement in most cases.

The key idea behind the parallel execution is to first split the surface domain into subdomains, and then run convolutions concurrently
on each of these smaller domains. The splitter type is still specified in the template parameters, while the configured splitter
instance is now passed to the `ParallelIIEstimator` constructor together with the requested thread count. Currently,
DGtal provides RegularDomainSplitter, which splits the outer domain regularly, and AxisDomainSplitter, which splits domains along a
specified dimension. See kernel/domains/DomainSplitter.h for more information and the expected interface.

At the low-level API, a typical construction is:

@snippet tests/geometry/surfaces/testParallelIntegralInvariantEstimator.cpp exampleParallelII-construction


A complete example is detailed in parallelIIShortcuts.cpp using the DGtal Shortcuts (see @ref moduleShortcuts). For example, using this setting:

@snippet geometry/surfaces/parallelIIShortcuts.cpp Parallel-instantiation

Parallel Integral Invariant curvature estimation can be obtained using:

@snippet geometry/surfaces/parallelIIShortcuts.cpp Parallel-run

On an Apple M1 (8 cores), the output shows a speed-up up to 8 threads as expected:
```
Input vol domain: [HyperRectDomain] = [(-85, -85, -85)]x[(85, 85, 85)]
New Block [Single thread]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
EndBlock [Single thread] (25956.2 ms)
New Block [4 threads on default axis]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
- II mean curvature uses ParallelIIEstimator with thread request=4 and split axis=0
EndBlock [4 threads on default axis] (8295.22 ms)
New Block [8 threads on axis 0]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
- II mean curvature uses ParallelIIEstimator with thread request=8 and split axis=0
EndBlock [8 threads on axis 0] (7084.68 ms)
New Block [8 threads on axis 1]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
- II mean curvature uses ParallelIIEstimator with thread request=8 and split axis=1
EndBlock [8 threads on axis 1] (6740.38 ms)
New Block [8 threads on axis 2]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
- II mean curvature uses ParallelIIEstimator with thread request=8 and split axis=2
EndBlock [8 threads on axis 2] (4311.78 ms)
New Block [16 threads on axis 2]
- II mean curvature alpha=0.33
- II mean curvature r=1.51043 (continuous) 12.0835 (discrete)
- II mean curvature uses ParallelIIEstimator with thread request=16 and split axis=2
EndBlock [16 threads on axis 2] (4717 ms)
```

For 8 threads with splits aloing the 0-axis, we obtain:

@image html parallelsplit.jpg "Parallel computation of integral invariants (8-threads)"



*/
}
Loading
Loading