Created
May 22, 2020 15:31
-
-
Save maarzt/19167a5019c1d685c483441b7322b986 to your computer and use it in GitHub Desktop.
Benchmark comparing the performance of ImgLib2 Cursor agains LoopBuilder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.imglib2.Cursor; | |
import net.imglib2.img.Img; | |
import net.imglib2.img.array.ArrayImg; | |
import net.imglib2.img.array.ArrayImgs; | |
import net.imglib2.img.cell.CellImg; | |
import net.imglib2.img.cell.CellImgFactory; | |
import net.imglib2.img.planar.PlanarImg; | |
import net.imglib2.img.planar.PlanarImgs; | |
import net.imglib2.loops.LoopBuilder; | |
import net.imglib2.type.numeric.real.FloatType; | |
import net.imglib2.view.Views; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.Fork; | |
import org.openjdk.jmh.annotations.Measurement; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.Warmup; | |
import org.openjdk.jmh.runner.Runner; | |
import org.openjdk.jmh.runner.RunnerException; | |
import org.openjdk.jmh.runner.options.Options; | |
import org.openjdk.jmh.runner.options.OptionsBuilder; | |
import java.util.concurrent.TimeUnit; | |
/** | |
* A benchmark, that compares the performance of two implementations of a copy method. | |
* One method was implemented using ImgLib2 {@link Cursor}. The other method was | |
* implemented using {@link LoopBuilder}. | |
* <p> | |
* The benchmark is done using JMH (https://openjdk.java.net/projects/code-tools/jmh/) | |
* <p> | |
* Benchmark result on a Dell XPS 15 (higher is better): | |
* <pre> | |
* LoopBuilderPerformanceProofBenchmark.benchmarkCursors thrpt 10 6.498 ± 0.120 ops/s | |
* LoopBuilderPerformanceProofBenchmark.benchmarkCursorsArrayImg thrpt 10 167.155 ± 3.356 ops/s | |
* LoopBuilderPerformanceProofBenchmark.benchmarkLoopBuilder thrpt 10 23.532 ± 2.581 ops/s | |
* LoopBuilderPerformanceProofBenchmark.benchmarkLoopBuilderArrayImg thrpt 10 165.178 ± 8.547 ops/s | |
* </pre> | |
* The measurements show that Cursors and LoopBuilder perform equally well, | |
* when only {@link ArrayImg} is used as image type. | |
* But LoopBuilder is four times faster than Cursors, when multiple | |
* image types ({@link ArrayImg}, {@link CellImg}, {@link PlanarImg} are used. | |
*/ | |
@Fork( 1 ) | |
@Warmup( iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS ) | |
@Measurement( iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS ) | |
@State( Scope.Benchmark ) | |
public class LoopBuilderPerformanceDemo | |
{ | |
private static void copyCursors( Img< FloatType > source, Img< FloatType > target ) | |
{ | |
Cursor< FloatType > sourceCursor = Views.flatIterable( source ).cursor(); | |
Cursor< FloatType > targetCursor = Views.flatIterable( target ).cursor(); | |
while ( sourceCursor.hasNext() ) | |
targetCursor.next().set( sourceCursor.next() ); | |
} | |
private static void copyLoopBuilder( Img< FloatType > source, Img< FloatType > target ) | |
{ | |
LoopBuilder.setImages( source, target ).forEachPixel( ( s, t ) -> t.set( s ) ); | |
} | |
private final long[] dimensions = { 100, 100, 100 }; | |
private final Img< FloatType > arrayImg = ArrayImgs.floats( dimensions ); | |
private final Img< FloatType > planarImg = PlanarImgs.floats( dimensions ); | |
private final Img< FloatType > cellImg = new CellImgFactory<>( new FloatType(), 10, 10, 10 ).create( dimensions ); | |
private final Img< FloatType > arrayImgA = ArrayImgs.floats( dimensions ); | |
private final Img< FloatType > arrayImgB = ArrayImgs.floats( dimensions ); | |
private final Img< FloatType > arrayImgC = ArrayImgs.floats( dimensions ); | |
@Benchmark | |
public void benchmarkCursorsArrayImg() | |
{ | |
copyCursors( arrayImgA, arrayImgB ); | |
copyCursors( arrayImgB, arrayImgC ); | |
copyCursors( arrayImgC, arrayImgA ); | |
} | |
@Benchmark | |
public void benchmarkCursors() | |
{ | |
copyCursors( arrayImg, planarImg ); | |
copyCursors( planarImg, cellImg ); | |
copyCursors( cellImg, arrayImg ); | |
} | |
@Benchmark | |
public void benchmarkLoopBuilderArrayImg() | |
{ | |
copyLoopBuilder( arrayImgA, arrayImgB ); | |
copyLoopBuilder( arrayImgB, arrayImgC ); | |
copyLoopBuilder( arrayImgC, arrayImgA ); | |
} | |
@Benchmark | |
public void benchmarkLoopBuilder() | |
{ | |
copyLoopBuilder( arrayImg, planarImg ); | |
copyLoopBuilder( planarImg, cellImg ); | |
copyLoopBuilder( cellImg, arrayImg ); | |
} | |
public static void main( String... args ) throws RunnerException | |
{ | |
Options options = new OptionsBuilder().include( LoopBuilderPerformanceDemo.class.getSimpleName() ).build(); | |
new Runner( options ).run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment