From bc7db951721e71be4cce52f0ac53971712b33b4b Mon Sep 17 00:00:00 2001 From: Peter Abeles Date: Sat, 23 Sep 2023 20:45:43 -0700 Subject: [PATCH] Fixed low level bug in ConcurrentyOps where it was not clearing the workspace in all situations, resulting in really weird bugs in downstream customers of EJML --- .../src/pabeles/concurrency/ConcurrencyOps.java | 9 +++++++-- .../csc/mult/TestImplMultiplication_MT_DSCC.java | 10 +++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/main/ejml-core/src/pabeles/concurrency/ConcurrencyOps.java b/main/ejml-core/src/pabeles/concurrency/ConcurrencyOps.java index b19ce4eb..eda990d0 100644 --- a/main/ejml-core/src/pabeles/concurrency/ConcurrencyOps.java +++ b/main/ejml-core/src/pabeles/concurrency/ConcurrencyOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2023, Peter Abeles. All Rights Reserved. * * This file is part of Efficient Java Matrix Library (EJML). * @@ -195,6 +195,9 @@ public static void loopBlocks( int start, int endExclusive, GrowArray wor final ForkJoinPool pool = ConcurrencyOps.pool; int numThreads = pool.getParallelism(); + // Make sure there are no stale results, even if nothing is run + workspace.reset(); + int range = endExclusive - start; if (range == 0) // nothing to do here! return; @@ -222,6 +225,9 @@ public static void loopBlocks( int start, int endExclusive, int minBlock, final ForkJoinPool pool = ConcurrencyOps.pool; int numThreads = pool.getParallelism(); + // Make sure there are no stale results, even if nothing is run + workspace.reset(); + int range = endExclusive - start; if (range == 0) // nothing to do here! return; @@ -235,7 +241,6 @@ public static void loopBlocks( int start, int endExclusive, int minBlock, private static void runLoopBlocks( int start, int endExclusive, GrowArray workspace, IntRangeObjectConsumer consumer, ForkJoinPool pool, int blockSize ) { - workspace.reset(); try { pool.submit(new IntRangeObjectTask<>(start, endExclusive, blockSize, workspace, consumer)).get(); } catch (InterruptedException | ExecutionException e) { diff --git a/main/ejml-dsparse/test/org/ejml/sparse/csc/mult/TestImplMultiplication_MT_DSCC.java b/main/ejml-dsparse/test/org/ejml/sparse/csc/mult/TestImplMultiplication_MT_DSCC.java index 5f40500a..d1502ce2 100644 --- a/main/ejml-dsparse/test/org/ejml/sparse/csc/mult/TestImplMultiplication_MT_DSCC.java +++ b/main/ejml-dsparse/test/org/ejml/sparse/csc/mult/TestImplMultiplication_MT_DSCC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2023, Peter Abeles. All Rights Reserved. * * This file is part of Efficient Java Matrix Library (EJML). * @@ -50,8 +50,12 @@ class TestImplMultiplication_MT_DSCC extends EjmlStandardJUnit { mult_s_s(5, 10, 5); mult_s_s(5, 5, 10); } + + // See comment in mult_s_s. This triggered a bug + mult_s_s(10, 10, 0); } + private void mult_s_s( int rowsA, int colsA, int colsB ) { int nz_a = RandomMatrices_DSCC.nonzero(rowsA, colsA, 0.05, 0.7, rand); int nz_b = RandomMatrices_DSCC.nonzero(colsA, colsB, 0.05, 0.7, rand); @@ -62,6 +66,10 @@ private void mult_s_s( int rowsA, int colsA, int colsB ) { DMatrixSparseCSC expected = RandomMatrices_DSCC.rectangle(rowsA, colsB, nz_c, -1, 1, rand); DMatrixSparseCSC found = expected.copy(); + // Make sure the work space is cleaned up. There was a bug where if b has zero columns stitching would + // throw an exception if this wasn't empty + workSpaceMT.grow(); + ImplMultiplication_DSCC.mult(a, b, expected, null, null); ImplMultiplication_MT_DSCC.mult(a, b, found, workSpaceMT); assertTrue(CommonOps_DSCC.checkStructure(found));