Skip to content

Commit cfb775a

Browse files
committed
LineConvolution: fix issue 77 (part 2/2)
See #77 Fix problems when number of tasks is very high.
1 parent af9bafc commit cfb775a

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

src/main/java/net/imglib2/algorithm/convolution/LineConvolution.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
import net.imglib2.RandomAccess;
1717
import net.imglib2.RandomAccessible;
1818
import net.imglib2.RandomAccessibleInterval;
19-
import net.imglib2.type.Type;
20-
import net.imglib2.type.numeric.RealType;
21-
import net.imglib2.type.numeric.real.DoubleType;
22-
import net.imglib2.type.numeric.real.FloatType;
2319
import net.imglib2.util.IntervalIndexer;
2420
import net.imglib2.util.Intervals;
2521
import net.imglib2.view.Views;
@@ -83,10 +79,15 @@ protected void process( final RandomAccessible< ? extends T > source, final Rand
8379
final long[] dim = Intervals.dimensionsAsLongArray( target );
8480
dim[ direction ] = 1;
8581

86-
final int numTasks = numThreads > 1 ? numThreads * 4 : 1;
82+
final int numTasks = numThreads > 1 ? timesFourAvoidOverflow(numThreads) : 1;
8783
LineConvolution.forEachIntervalElementInParallel( executorService, numTasks, new FinalInterval( dim ), actionFactory );
8884
}
8985

86+
private int timesFourAvoidOverflow( int x )
87+
{
88+
return (int) Math.min((long) x * 4, Integer.MAX_VALUE);
89+
}
90+
9091
/**
9192
* {@link #forEachIntervalElementInParallel(ExecutorService, int, Interval, Supplier)}
9293
* executes a given action for each position in a given interval. Therefor
@@ -110,14 +111,14 @@ public static void forEachIntervalElementInParallel( final ExecutorService servi
110111
final long[] min = Intervals.minAsLongArray( interval );
111112
final long[] dim = Intervals.dimensionsAsLongArray( interval );
112113
final long size = Intervals.numElements( dim );
113-
final long endIndex = size;
114-
final long taskSize = ( size + numTasks - 1 ) / numTasks; // round up
114+
final int boundedNumTasks = (int) Math.max( 1, Math.min(size, numTasks ));
115+
final long taskSize = ( size - 1 ) / boundedNumTasks + 1; // taskSize = roundUp(size / boundedNumTasks);
115116
final ArrayList< Callable< Void > > callables = new ArrayList<>();
116117

117-
for ( int taskNum = 0; taskNum < numTasks; ++taskNum )
118+
for ( int taskNum = 0; taskNum < boundedNumTasks; ++taskNum )
118119
{
119120
final long myStartIndex = taskNum * taskSize;
120-
final long myEndIndex = Math.min( endIndex, myStartIndex + taskSize );
121+
final long myEndIndex = Math.min( size, myStartIndex + taskSize );
121122
final Callable< Void > r = () -> {
122123
final Consumer< Localizable > action = actionFactory.get();
123124
final long[] position = new long[ dim.length ];

src/test/java/net/imglib2/algorithm/convolution/LineConvolutionTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import net.imglib2.util.Intervals;
99
import org.junit.Test;
1010

11+
import java.util.concurrent.Executors;
12+
1113
import static org.junit.Assert.assertArrayEquals;
1214
import static org.junit.Assert.assertTrue;
1315

@@ -45,6 +47,16 @@ public void testConvolve()
4547
assertArrayEquals( expected, result );
4648
}
4749

50+
@Test
51+
public void testNumTasksEqualsIntegerMaxValue() {
52+
byte[] result = new byte[ 1 ];
53+
Img< UnsignedByteType > out = ArrayImgs.unsignedBytes( result, result.length );
54+
Img< UnsignedByteType > in = ArrayImgs.unsignedBytes( new byte[] { 1, 2 }, 2 );
55+
final LineConvolution< UnsignedByteType > convolution = new LineConvolution<>( new ForwardDifferenceConvolverFactory(), 0 );
56+
convolution.process( in, out, Executors.newSingleThreadExecutor(), Integer.MAX_VALUE );
57+
assertArrayEquals( new byte[] { 1 }, result );
58+
}
59+
4860
static class ForwardDifferenceConvolverFactory implements LineConvolverFactory< UnsignedByteType >
4961
{
5062

0 commit comments

Comments
 (0)