Skip to content

Instantly share code, notes, and snippets.

@JohnMGant
Created December 9, 2020 21:10
Show Gist options
  • Select an option

  • Save JohnMGant/97e7a3476f08ecb5f08ccc1be6437b7d to your computer and use it in GitHub Desktop.

Select an option

Save JohnMGant/97e7a3476f08ecb5f08ccc1be6437b7d to your computer and use it in GitHub Desktop.
internal class ConcurrentBatchAdder : IIntegerAdder
{
private const int degreeOfParallelism = 4;
public int Add(int[] values)
{
var countPerSegment = values.Length / degreeOfParallelism + 1;
int[,] segments = SplitIntoSegments(values, countPerSegment);
var sums = new int[degreeOfParallelism];
Action<object> addSegment = segmentIndexParam =>
{
int segmentIndexParamAsInt = (int)segmentIndexParam;
for (var i = 0; i < countPerSegment; i++)
{
sums[segmentIndexParamAsInt] += segments[segmentIndexParamAsInt, i];
}
};
var tasks = new Task[degreeOfParallelism];
for (var i = 0; i < degreeOfParallelism; i++)
{
tasks[i] = Task.Factory.StartNew(addSegment, i);
}
Task.WaitAll(tasks);
int sum = 0;
for (var i = 0; i < sums.Length; i++)
{
sum += sums[i];
}
return sum;
}
private static int[,] SplitIntoSegments(int[] values, int countPerSegment)
{
//if values.Length isn't divisible by the degree of parallelism, the "extra" elements in the rectangular array will be 0
var segments = new int[degreeOfParallelism, countPerSegment];
var segmentIndex = 0;
var itemIndex = 0;
foreach (var value in values)
{
segments[segmentIndex, itemIndex] = value;
if (itemIndex == countPerSegment - 1)
{
segmentIndex += 1;
itemIndex = 0;
}
else
{
itemIndex += 1;
}
}
return segments;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment