Skip to content

Commit 0dcd92c

Browse files
committed
Update DifferenceOfGaussian to use multi-threaded LoopBuilder and imglib2 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.
1 parent 5869695 commit 0dcd92c

File tree

1 file changed

+51
-89
lines changed

1 file changed

+51
-89
lines changed

src/main/java/net/imglib2/algorithm/dog/DifferenceOfGaussian.java

Lines changed: 51 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,20 @@
3333
*/
3434
package net.imglib2.algorithm.dog;
3535

36-
import java.util.ArrayList;
37-
import java.util.concurrent.Callable;
38-
import java.util.concurrent.ExecutionException;
39-
import java.util.concurrent.ExecutorService;
40-
import java.util.concurrent.Future;
41-
42-
import net.imglib2.Cursor;
43-
import net.imglib2.IterableInterval;
44-
import net.imglib2.RandomAccess;
4536
import net.imglib2.RandomAccessible;
4637
import net.imglib2.RandomAccessibleInterval;
4738
import net.imglib2.algorithm.gauss3.Gauss3;
48-
import net.imglib2.exception.IncompatibleTypeException;
4939
import net.imglib2.img.Img;
40+
import net.imglib2.loops.LoopBuilder;
41+
import net.imglib2.parallel.Parallelization;
5042
import net.imglib2.type.NativeType;
5143
import net.imglib2.type.numeric.NumericType;
5244
import net.imglib2.util.Util;
5345
import net.imglib2.view.IntervalView;
5446
import net.imglib2.view.Views;
5547

48+
import java.util.concurrent.ExecutorService;
49+
5650
/**
5751
* Compute Difference-of-Gaussian of a {@link RandomAccessible}.
5852
*
@@ -66,7 +60,7 @@ public class DifferenceOfGaussian
6660
* of sigmaLarger (where {@code sigmaLarger > sigmaSmaller}).
6761
* <p>
6862
* Creates an appropriate temporary image and calls
69-
* {@link #DoG(double[], double[], RandomAccessible, RandomAccessible, RandomAccessibleInterval, ExecutorService)}
63+
* {@link #DoG(double[], double[], RandomAccessible, RandomAccessible, RandomAccessibleInterval)}
7064
* .
7165
* </p>
7266
*
@@ -80,21 +74,18 @@ public class DifferenceOfGaussian
8074
* convolution).
8175
* @param dog
8276
* the Difference-of-Gaussian result image.
83-
* @param service
84-
* service providing threads for multi-threading
8577
*/
8678
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
8779
final double[] sigmaSmaller,
8880
final double[] sigmaLarger,
8981
final RandomAccessible< I > input,
90-
final RandomAccessibleInterval< T > dog,
91-
final ExecutorService service )
82+
final RandomAccessibleInterval< T > dog )
9283
{
9384
final T type = Util.getTypeFromInterval( dog );
9485
final Img< T > g1 = Util.getArrayOrCellImgFactory( dog, type ).create( dog );
9586
final long[] translation = new long[ dog.numDimensions() ];
9687
dog.min( translation );
97-
DoG( sigmaSmaller, sigmaLarger, input, Views.translate( g1, translation ), dog, service );
88+
DoG( sigmaSmaller, sigmaLarger, input, Views.translate( g1, translation ), dog );
9889
}
9990

10091
/**
@@ -115,88 +106,59 @@ public static < I extends NumericType< I >, T extends NumericType< T > & NativeT
115106
* dog result image.
116107
* @param dog
117108
* the Difference-of-Gaussian result image.
118-
* @param service
119-
* how many threads to use for the computation.
120109
*/
121110
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
122111
final double[] sigmaSmaller,
123112
final double[] sigmaLarger,
124113
final RandomAccessible< I > input,
125114
final RandomAccessible< T > tmp,
115+
final RandomAccessibleInterval< T > dog )
116+
{
117+
final IntervalView< T > tmpInterval = Views.interval( tmp, dog );
118+
Gauss3.gauss( sigmaSmaller, input, tmpInterval );
119+
Gauss3.gauss( sigmaLarger, input, dog );
120+
LoopBuilder.setImages( dog, tmpInterval ).multiThreaded().forEachPixel( ( d, t ) -> d.sub( t ) );
121+
}
122+
123+
/**
124+
* @deprecated Please use:
125+
*
126+
* <p>
127+
* {@code Parallelization.withExecutor( service ).run( () -> DoG( sigmaSmaller, sigmaLarger, input, dog ) )}
128+
*
129+
* @see Parallelization
130+
*/
131+
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
132+
final double[] sigmaSmaller,
133+
final double[] sigmaLarger,
134+
final RandomAccessible< I > input,
126135
final RandomAccessibleInterval< T > dog,
127136
final ExecutorService service )
128137
{
129-
final IntervalView< T > tmpInterval = Views.interval( tmp, dog );
130-
try
131-
{
132-
Gauss3.gauss( sigmaSmaller, input, tmpInterval, service );
133-
Gauss3.gauss( sigmaLarger, input, dog, service );
134-
}
135-
catch ( final IncompatibleTypeException e )
136-
{
137-
e.printStackTrace();
138-
}
139-
final IterableInterval< T > dogIterable = Views.iterable( dog );
140-
final IterableInterval< T > tmpIterable = Views.iterable( tmpInterval );
141-
final long size = dogIterable.size();
142-
// FIXME find better heuristic?
143-
final int numThreads = Runtime.getRuntime().availableProcessors();
144-
final int numTasks = numThreads <= 1 ? 1 : numThreads * 20;
145-
final long taskSize = size / numTasks;
146-
final ArrayList< Future< Void > > futures = new ArrayList<>();
147-
for ( int taskNum = 0; taskNum < numTasks; ++taskNum )
148-
{
149-
final long fromIndex = taskNum * taskSize;
150-
final long thisTaskSize = ( taskNum == numTasks - 1 ) ? size - fromIndex : taskSize;
151-
if ( dogIterable.iterationOrder().equals( tmpIterable.iterationOrder() ) )
152-
futures.add( service.submit( new Callable< Void >()
153-
{
154-
@Override
155-
public Void call()
156-
{
157-
final Cursor< T > dogCursor = dogIterable.cursor();
158-
final Cursor< T > tmpCursor = tmpIterable.cursor();
159-
dogCursor.jumpFwd( fromIndex );
160-
tmpCursor.jumpFwd( fromIndex );
161-
for ( int i = 0; i < thisTaskSize; ++i )
162-
dogCursor.next().sub( tmpCursor.next() );
163-
return null;
164-
}
165-
} ) );
166-
else
167-
futures.add( service.submit( new Callable< Void >()
168-
{
169-
@Override
170-
public Void call()
171-
{
172-
final Cursor< T > dogCursor = dogIterable.localizingCursor();
173-
final RandomAccess< T > tmpAccess = tmpInterval.randomAccess();
174-
dogCursor.jumpFwd( fromIndex );
175-
for ( int i = 0; i < thisTaskSize; ++i )
176-
{
177-
final T o = dogCursor.next();
178-
tmpAccess.setPosition( dogCursor );
179-
o.sub( tmpAccess.get() );
180-
}
181-
return null;
182-
}
183-
} ) );
184-
}
185-
for ( final Future< Void > f : futures )
186-
{
187-
try
188-
{
189-
f.get();
190-
}
191-
catch ( final InterruptedException e )
192-
{
193-
e.printStackTrace();
194-
}
195-
catch ( final ExecutionException e )
196-
{
197-
e.printStackTrace();
198-
}
199-
}
138+
Parallelization.runWithExecutor( service,
139+
() -> DoG( sigmaSmaller, sigmaLarger, input, dog )
140+
);
141+
}
142+
143+
/**
144+
* @deprecated Please use:
145+
*
146+
* <p>
147+
* {@code Parallelization.withExecutor( service ). run( () -> DoG( sigmaSmaller, sigmaLarger, input, tmp, dog ) ); }
148+
*
149+
* @see Parallelization
150+
*/
151+
public static < I extends NumericType< I >, T extends NumericType< T > & NativeType< T > > void DoG(
152+
final double[] sigmaSmaller,
153+
final double[] sigmaLarger,
154+
final RandomAccessible< I > input,
155+
final RandomAccessible< T > tmp,
156+
final RandomAccessibleInterval< T > dog,
157+
final ExecutorService service )
158+
{
159+
Parallelization.runWithExecutor( service,
160+
() -> DoG( sigmaSmaller, sigmaLarger, input, tmp, dog )
161+
);
200162
}
201163

202164
/**

0 commit comments

Comments
 (0)