Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new imglib2 parallelization approach #83

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
630a8cb
Add utility class to simplify the creation of test images
maarzt Dec 6, 2022
31f054a
Add unit test for class Thresholder
maarzt Dec 6, 2022
6fdf423
Add unit test for class DifferenceOfGaussian
maarzt Dec 1, 2022
481bf0f
Refactor ConnectedComponentsTest and test more methods
maarzt Dec 2, 2022
f5ff37a
Add unit tests for Dilation and Erosion
maarzt Dec 2, 2022
bfaa8bd
Add unit test for class MorphologyUtils
maarzt Dec 2, 2022
6a4f3a2
Add unit test for class ComputeMinMax
maarzt Dec 6, 2022
3184e2f
POM: pin imglib2 version to 5.13.0
maarzt Nov 10, 2021
ac3b901
Change Thresholder implementation to multi-threaded LoopBuilder
maarzt Nov 10, 2021
8397118
Update DifferenceOfGaussian to use multi-threaded LoopBuilder and img…
maarzt Nov 10, 2021
7e28716
Update ConntectedComponenets to make use of the Parallelization context.
maarzt Nov 10, 2021
791c47f
Change TensorEigenValues to use multi-threaded LoopBuilder.
maarzt Nov 10, 2021
4873a47
Change Dilation to use IterableLoopBuilder
maarzt Dec 2, 2022
f294d06
Change Erosion to use IterableLoopBuilder
maarzt Dec 2, 2022
ddba38a
Update MorphologyUtils to use Parallelization framework
maarzt Dec 2, 2022
fe79678
Update DistanceTransform to use parallelization framework
maarzt Dec 2, 2022
3dd9ecd
Chang PartialDerivative to use multi-threaded LoopBuilder
maarzt Dec 2, 2022
23ea534
Update LocalExtrema to use parallelization framework
maarzt Dec 2, 2022
7fe1eaf
Change SubpixelLocalization to use the Parallelization framework
maarzt Dec 6, 2022
5c81783
Update ComputeMinMax to use parallelization framework
maarzt Dec 2, 2022
6d4f829
Add benchmark for LocalExtrema
maarzt Dec 2, 2022
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
Prev Previous commit
Next Next commit
Update DifferenceOfGaussian to use multi-threaded LoopBuilder and img…
…lib2 Parallelization context

Add new methods DifferenceOfGaussian.DoG that don't require an
ExecutorService but use the Parallelization context.

Replace the old implementation with multi-threaded LoopBuilder.
maarzt committed Dec 6, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 8397118f7e8e4124441f3ca5241a229950875b4e
140 changes: 51 additions & 89 deletions src/main/java/net/imglib2/algorithm/dog/DifferenceOfGaussian.java
Original file line number Diff line number Diff line change
@@ -33,26 +33,20 @@
*/
package net.imglib2.algorithm.dog;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import net.imglib2.Cursor;
import net.imglib2.IterableInterval;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.algorithm.gauss3.Gauss3;
import net.imglib2.exception.IncompatibleTypeException;
import net.imglib2.img.Img;
import net.imglib2.loops.LoopBuilder;
import net.imglib2.parallel.Parallelization;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.NumericType;
import net.imglib2.util.Util;
import net.imglib2.view.IntervalView;
import net.imglib2.view.Views;

import java.util.concurrent.ExecutorService;

/**
* Compute Difference-of-Gaussian of a {@link RandomAccessible}.
*
@@ -66,7 +60,7 @@ public class DifferenceOfGaussian
* of sigmaLarger (where {@code sigmaLarger > sigmaSmaller}).
* <p>
* Creates an appropriate temporary image and calls
* {@link #DoG(double[], double[], RandomAccessible, RandomAccessible, RandomAccessibleInterval, ExecutorService)}
* {@link #DoG(double[], double[], RandomAccessible, RandomAccessible, RandomAccessibleInterval)}
* .
* </p>
*
@@ -80,21 +74,18 @@ public class DifferenceOfGaussian
* convolution).
* @param dog
* the Difference-of-Gaussian result image.
* @param service
* service providing threads for multi-threading
*/
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
final double[] sigmaSmaller,
final double[] sigmaLarger,
final RandomAccessible< I > input,
final RandomAccessibleInterval< T > dog,
final ExecutorService service )
final RandomAccessibleInterval< T > dog )
{
final T type = Util.getTypeFromInterval( dog );
final Img< T > g1 = Util.getArrayOrCellImgFactory( dog, type ).create( dog );
final long[] translation = new long[ dog.numDimensions() ];
dog.min( translation );
DoG( sigmaSmaller, sigmaLarger, input, Views.translate( g1, translation ), dog, service );
DoG( sigmaSmaller, sigmaLarger, input, Views.translate( g1, translation ), dog );
}

/**
@@ -115,88 +106,59 @@ public static < I extends NumericType< I >, T extends NumericType< T > & NativeT
* dog result image.
* @param dog
* the Difference-of-Gaussian result image.
* @param service
* how many threads to use for the computation.
*/
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
final double[] sigmaSmaller,
final double[] sigmaLarger,
final RandomAccessible< I > input,
final RandomAccessible< T > tmp,
final RandomAccessibleInterval< T > dog )
{
final IntervalView< T > tmpInterval = Views.interval( tmp, dog );
Gauss3.gauss( sigmaSmaller, input, tmpInterval );
Gauss3.gauss( sigmaLarger, input, dog );
LoopBuilder.setImages( dog, tmpInterval ).multiThreaded().forEachPixel( ( d, t ) -> d.sub( t ) );
}

/**
* @deprecated Please use:
*
* <p>
* {@code Parallelization.withExecutor( service ).run( () -> DoG( sigmaSmaller, sigmaLarger, input, dog ) )}
*
* @see Parallelization
*/
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
final double[] sigmaSmaller,
final double[] sigmaLarger,
final RandomAccessible< I > input,
final RandomAccessibleInterval< T > dog,
final ExecutorService service )
{
final IntervalView< T > tmpInterval = Views.interval( tmp, dog );
try
{
Gauss3.gauss( sigmaSmaller, input, tmpInterval, service );
Gauss3.gauss( sigmaLarger, input, dog, service );
}
catch ( final IncompatibleTypeException e )
{
e.printStackTrace();
}
final IterableInterval< T > dogIterable = Views.iterable( dog );
final IterableInterval< T > tmpIterable = Views.iterable( tmpInterval );
final long size = dogIterable.size();
// FIXME find better heuristic?
final int numThreads = Runtime.getRuntime().availableProcessors();
final int numTasks = numThreads <= 1 ? 1 : numThreads * 20;
final long taskSize = size / numTasks;
final ArrayList< Future< Void > > futures = new ArrayList<>();
for ( int taskNum = 0; taskNum < numTasks; ++taskNum )
{
final long fromIndex = taskNum * taskSize;
final long thisTaskSize = ( taskNum == numTasks - 1 ) ? size - fromIndex : taskSize;
if ( dogIterable.iterationOrder().equals( tmpIterable.iterationOrder() ) )
futures.add( service.submit( new Callable< Void >()
{
@Override
public Void call()
{
final Cursor< T > dogCursor = dogIterable.cursor();
final Cursor< T > tmpCursor = tmpIterable.cursor();
dogCursor.jumpFwd( fromIndex );
tmpCursor.jumpFwd( fromIndex );
for ( int i = 0; i < thisTaskSize; ++i )
dogCursor.next().sub( tmpCursor.next() );
return null;
}
} ) );
else
futures.add( service.submit( new Callable< Void >()
{
@Override
public Void call()
{
final Cursor< T > dogCursor = dogIterable.localizingCursor();
final RandomAccess< T > tmpAccess = tmpInterval.randomAccess();
dogCursor.jumpFwd( fromIndex );
for ( int i = 0; i < thisTaskSize; ++i )
{
final T o = dogCursor.next();
tmpAccess.setPosition( dogCursor );
o.sub( tmpAccess.get() );
}
return null;
}
} ) );
}
for ( final Future< Void > f : futures )
{
try
{
f.get();
}
catch ( final InterruptedException e )
{
e.printStackTrace();
}
catch ( final ExecutionException e )
{
e.printStackTrace();
}
}
Parallelization.runWithExecutor( service,
() -> DoG( sigmaSmaller, sigmaLarger, input, dog )
);
}

/**
* @deprecated Please use:
*
* <p>
* {@code Parallelization.withExecutor( service ). run( () -> DoG( sigmaSmaller, sigmaLarger, input, tmp, dog ) ); }
*
* @see Parallelization
*/
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
final double[] sigmaSmaller,
final double[] sigmaLarger,
final RandomAccessible< I > input,
final RandomAccessible< T > tmp,
final RandomAccessibleInterval< T > dog,
final ExecutorService service )
{
Parallelization.runWithExecutor( service,
() -> DoG( sigmaSmaller, sigmaLarger, input, tmp, dog )
);
}

/**