From 7e98702268f0dff818d7748afc65cea0d6e28d55 Mon Sep 17 00:00:00 2001 From: Phillip Allen Lane Date: Mon, 20 Nov 2023 21:59:12 -0600 Subject: [PATCH 1/3] fixed issues with forcollapse error handling --- DotMP-Tests/ParallelTests.cs | 22 +++++++++++++++++ DotMP/{Wrappers.cs => Chunk.cs} | 42 +++++++++++++++++++++++++++++---- DotMP/Exceptions.cs | 12 ++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) rename DotMP/{Wrappers.cs => Chunk.cs} (94%) diff --git a/DotMP-Tests/ParallelTests.cs b/DotMP-Tests/ParallelTests.cs index 29d5430f..e00ed4b3 100644 --- a/DotMP-Tests/ParallelTests.cs +++ b/DotMP-Tests/ParallelTests.cs @@ -1451,6 +1451,18 @@ public void Absent_params_shouldnt_except() Assert.Null(exception); } + /// + /// Verifies that for loops which overflow internal indices should throw an exception. + /// + [Fact] + public void Overflow_for_should_except() + { + Assert.Throws(() => + { + DotMP.Parallel.ParallelForCollapse((0, 256), (0, 256), (0, 256), (0, 256), (i, j, k, l) => { }); + }); + } + /// /// Verifies that invalid parameters throw exceptions. /// @@ -1467,6 +1479,16 @@ public void Invalid_params_should_except() DotMP.Parallel.ParallelFor(-1, 10, i => { }); }); + Assert.Throws(() => + { + DotMP.Parallel.ParallelForCollapse((10, 20), (-1, 10), (i, j) => { }); + }); + + Assert.Throws(() => + { + DotMP.Parallel.ParallelForCollapse((10, 5), (0, 20), (i, j) => { }); + }); + Assert.Throws(() => { DotMP.Parallel.ParallelFor(10, -5, i => { }); diff --git a/DotMP/Wrappers.cs b/DotMP/Chunk.cs similarity index 94% rename from DotMP/Wrappers.cs rename to DotMP/Chunk.cs index 8c92da71..6c9ccfa0 100644 --- a/DotMP/Wrappers.cs +++ b/DotMP/Chunk.cs @@ -5,18 +5,18 @@ * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. - + * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. - + * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ using System; using System.Linq; -using System.Runtime.CompilerServices; +using DotMP.Exceptions; /* jscpd:ignore-start */ namespace DotMP @@ -179,7 +179,41 @@ private enum ActionSelector /// /// Represents the ranges of collapsed loops for future unflattening. /// - private ValueTuple[] ranges; + private ValueTuple[] ranges_prv; + + /// + /// Represents the ranges of collapsed loops for unflattening, ensuring that loops do not have too many iterations. + /// + private ValueTuple[] ranges + { + get => ranges_prv; + set + { + int total_iters = 1; + + try + { + foreach ((int start, int end) in value) + { + if (end < start) + throw new InvalidArgumentsException(string.Format("Start of loop ({0}) must be less than end of loop ({1}).", start, end)); + + if (start < 0 || end < 0) + throw new InvalidArgumentsException(string.Format("Start ({0}) and end ({1}) of loop must both be positive integers.", start, end)); + + total_iters = checked(total_iters * (end - start)); + } + } + catch (OverflowException) + { + throw new TooManyIterationsException(string.Format("Parallel-for loop has too many iterations (exceeds {0}).", int.MaxValue)); + } + finally + { + ranges_prv = value; + } + } + } /// /// Array representing the starting indices. diff --git a/DotMP/Exceptions.cs b/DotMP/Exceptions.cs index 2332cba7..ea5862a6 100644 --- a/DotMP/Exceptions.cs +++ b/DotMP/Exceptions.cs @@ -65,4 +65,16 @@ public class InvalidArgumentsException : Exception /// The message to associate with the exception. public InvalidArgumentsException(string msg) : base(msg) { } } + + /// + /// Exception thrown if a for loop has too many iterations and would cause the schedulers to fail. + /// + public class TooManyIterationsException : Exception + { + /// + /// Constructor with a message. + /// + /// The message to associate with the exception. + public TooManyIterationsException(string msg) : base(msg) { } + } } From e6cb304cfb3005b7a854072da431d9c3e6b57542 Mon Sep 17 00:00:00 2001 From: Phillip Allen Lane Date: Mon, 20 Nov 2023 22:05:41 -0600 Subject: [PATCH 2/3] add documentation for when TooManyIterationsException is thrown --- DotMP/Parallel.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/DotMP/Parallel.cs b/DotMP/Parallel.cs index d1a47eb5..64b6d51e 100644 --- a/DotMP/Parallel.cs +++ b/DotMP/Parallel.cs @@ -204,6 +204,7 @@ public static void For(int start, int end, Action action, IScheduler schedu /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForCollapse((int, int) firstRange, (int, int) secondRange, Action action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange }); @@ -231,6 +232,7 @@ public static void ForCollapse((int, int) firstRange, (int, int) secondRange, Ac /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForCollapse((int, int) firstRange, (int, int) secondRange, (int, int) thirdRange, Action action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange, thirdRange }); @@ -260,6 +262,7 @@ public static void ForCollapse((int, int) firstRange, (int, int) secondRange, (i /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForCollapse((int, int) firstRange, (int, int) secondRange, (int, int) thirdRange, (int, int) fourthRange, Action action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange, thirdRange, fourthRange }); @@ -287,6 +290,7 @@ public static void ForCollapse((int, int) firstRange, (int, int) secondRange, (i /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForCollapse((int, int)[] ranges, Action action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, ranges); @@ -394,6 +398,7 @@ public static void ForReduction(int start, int end, Operations op, ref T redu /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForReductionCollapse((int, int) firstRange, (int, int) secondRange, Operations op, ref T reduce_to, ActionRef2 action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange }); @@ -426,6 +431,7 @@ public static void ForReductionCollapse((int, int) firstRange, (int, int) sec /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForReductionCollapse((int, int) firstRange, (int, int) secondRange, (int, int) thirdRange, Operations op, ref T reduce_to, ActionRef3 action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange, thirdRange }); @@ -460,6 +466,7 @@ public static void ForReductionCollapse((int, int) firstRange, (int, int) sec /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForReductionCollapse((int, int) firstRange, (int, int) secondRange, (int, int) thirdRange, (int, int) fourthRange, Operations op, ref T reduce_to, ActionRef4 action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, new (int, int)[] { firstRange, secondRange, thirdRange, fourthRange }); @@ -492,6 +499,7 @@ public static void ForReductionCollapse((int, int) firstRange, (int, int) sec /// Thrown when not in a parallel region. /// Thrown when nested inside another worksharing region. /// Thrown if any provided arguments are invalid. + /// Thrown if there are too many iterations to handle. public static void ForReductionCollapse((int, int)[] ranges, Operations op, ref T reduce_to, ActionRefN action, IScheduler schedule = null, uint? chunk_size = null) { ForAction forAction = new ForAction(action, ranges); From 7ed086aa4f57c572b7f946b6a4a6fcf0cb6c9784 Mon Sep 17 00:00:00 2001 From: Phillip Allen Lane Date: Mon, 20 Nov 2023 22:09:45 -0600 Subject: [PATCH 3/3] remove TODO, it has been done --- DotMP/Chunk.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DotMP/Chunk.cs b/DotMP/Chunk.cs index 6c9ccfa0..fabffb7d 100644 --- a/DotMP/Chunk.cs +++ b/DotMP/Chunk.cs @@ -454,7 +454,6 @@ private void ComputeIndicesN(int curr_iter, int[] indices) /// /// Executes a chunk using the action selected by ForAction.selector - /// TODO: Optimize this whole function. /// /// A reference to the current iteration. /// The start of the chunk, inclusive.