Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features #86

Merged
merged 32 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
42eb6db
move actionref to wrappers file
computablee Oct 10, 2023
05ff396
add minimum viable product for ForAction class
computablee Oct 10, 2023
13e3a3f
plug ForAction into the rest of the scheduler code
computablee Oct 10, 2023
f3e4586
add forcollapse to api, still throws notimplementedexception
computablee Oct 10, 2023
c2f468d
added parallelforcollapse
computablee Oct 10, 2023
5ea96ad
fix bug with collapse in computing indices
computablee Oct 10, 2023
23a0ec7
add test for collapse
computablee Oct 10, 2023
dd8719a
improve test by not having the iterations square
computablee Oct 10, 2023
89727b8
reuse ranges dereference for optimization
computablee Oct 10, 2023
20c14c3
work around doxygen bugs
computablee Oct 10, 2023
067c6ec
make _lock int private
computablee Oct 10, 2023
64bba27
added the other ForCollapse overloads
computablee Oct 10, 2023
3ab580e
fix API bugs with collapse, implement the rest of the ParallelForColl…
computablee Oct 10, 2023
8359ad1
added flags to track reduction/collapse status
computablee Oct 10, 2023
adc2b7b
remove unused is_reduction flag
computablee Oct 10, 2023
658e6a6
implement forreduction internal handler, more refactoring
computablee Oct 10, 2023
8445c85
add forreductioncollapse and parallelforreductioncollapse overloads
computablee Oct 10, 2023
6d6d218
implement more callbacks with the performloop scheduler
computablee Oct 10, 2023
461fbd5
add test for collapse(3)
computablee Oct 10, 2023
6fd1f98
fix bug with collapse(3)
computablee Oct 10, 2023
d0dc31f
add tester for forreductioncollapse
computablee Oct 10, 2023
7c2b5f0
fix typo in documentation
computablee Oct 10, 2023
b7d57f3
initial commit of benchmarks
computablee Oct 11, 2023
ca663a9
update makefile for benchmarks
computablee Oct 11, 2023
fa9f446
update dependabot with benchmarks
computablee Oct 11, 2023
6addd21
implemented the rest of the action runners and did some light optimiz…
computablee Oct 11, 2023
07a79db
finish adding tests for collapse and reductioncollapse
computablee Oct 11, 2023
2d65b8a
add documentation for collapsed for loops
computablee Oct 11, 2023
93baa7a
fix linter and documentation issues
computablee Oct 11, 2023
8c97bdd
remove unused default case
computablee Oct 11, 2023
62e3e85
band-aid fix: add ignore for jscpd
computablee Oct 11, 2023
2d604ef
jscpd ignore (for good reason)
computablee Oct 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,18 @@ updates:
- "nuget"
commit-message:
prefix: "nuget"

- package-ecosystem: "nuget"
directory: "./benchmarks/HeatTransfer/"
schedule:
interval: "weekly"
labels:
- "dependency"
- "nuget"
commit-message:
prefix: "nuget"
groups:
bench:
patterns:
- "BenchmarkDotNet"
- "BenchmarkDotNet.*"
150 changes: 150 additions & 0 deletions DotMP-Tests/ParallelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using DotMP;
using FluentAssertions;
Expand Down Expand Up @@ -146,6 +147,155 @@ public void Dynamic_should_produce_correct_results()
}
}

/// <summary>
/// Tests to make sure that DotMP.Parallel.ForCollapse produces correct results.
/// </summary>
[Fact]
public void Collapse_works()
{
int[,] iters_hit = new int[1024, 1024];

DotMP.Parallel.ParallelForCollapse((256, 512), (512, 600), num_threads: 8, chunk_size: 7, schedule: Schedule.Static, action: (i, j) =>
{
DotMP.Atomic.Inc(ref iters_hit[i, j]);
});

for (int i = 0; i < 1024; i++)
for (int j = 0; j < 1024; j++)
if (i >= 256 && i < 512 && j >= 512 && j < 600)
iters_hit[i, j].Should().Be(1);
else
iters_hit[i, j].Should().Be(0);

iters_hit = null;

int[,,] iters_hit_3 = new int[128, 128, 64];

DotMP.Parallel.ParallelForCollapse((35, 64), (16, 100), (10, 62), num_threads: 8, chunk_size: 3, schedule: Schedule.Dynamic, action: (i, j, k) =>
{
DotMP.Atomic.Inc(ref iters_hit_3[i, j, k]);
});

for (int i = 0; i < 128; i++)
for (int j = 0; j < 128; j++)
for (int k = 0; k < 64; k++)
if (i >= 35 && i < 64 && j >= 16 && j < 100 && k >= 10 && k < 62)
iters_hit_3[i, j, k].Should().Be(1);
else
iters_hit_3[i, j, k].Should().Be(0);

iters_hit_3 = null;

int[,,,] iters_hit_4 = new int[32, 32, 32, 32];

DotMP.Parallel.ParallelForCollapse((1, 31), (10, 16), (5, 20), (21, 30), num_threads: 8, chunk_size: 11, schedule: Schedule.Static, action: (i, j, k, l) =>
{
DotMP.Atomic.Inc(ref iters_hit_4[i, j, k, l]);
});

DotMP.Parallel.ParallelForCollapse(new (int, int)[] { (1, 31), (10, 16), (5, 20), (21, 30) }, num_threads: 8, chunk_size: 11, schedule: Schedule.Static, action: (int[] indices) =>
{
DotMP.Atomic.Inc(ref iters_hit_4[indices[0], indices[1], indices[2], indices[3]]);
});

for (int i = 0; i < 32; i++)
for (int j = 0; j < 32; j++)
for (int k = 0; k < 32; k++)
for (int l = 0; l < 32; l++)
if (i >= 1 && i < 31 && j >= 10 && j < 16 && k >= 5 && k < 20 && l >= 21 && l < 30)
iters_hit_4[i, j, k, l].Should().Be(2);
else
iters_hit_4[i, j, k, l].Should().Be(0);
}

/// <summary>
/// Tests to make sure that DotMP.Parallel.ForReductionCollapse produces correct results.
/// </summary>
[Fact]
public void Reduction_collapse_works()
{
int total_iters_executed = 0;
int[,] iters_hit = new int[1024, 1024];

DotMP.Parallel.ParallelForReductionCollapse((256, 512), (512, 600),
op: Operations.Add, reduce_to: ref total_iters_executed,
num_threads: 8, chunk_size: 7, schedule: Schedule.Static,
action: (ref int total_iters_executed, int i, int j) =>
{
DotMP.Atomic.Inc(ref iters_hit[i, j]);
total_iters_executed += 1;
});

for (int i = 0; i < 1024; i++)
for (int j = 0; j < 1024; j++)
if (i >= 256 && i < 512 && j >= 512 && j < 600)
iters_hit[i, j].Should().Be(1);
else
iters_hit[i, j].Should().Be(0);

total_iters_executed.Should().Be((512 - 256) * (600 - 512));

iters_hit = null;
total_iters_executed = 0;

int[,,] iters_hit_3 = new int[128, 128, 64];

DotMP.Parallel.ParallelForReductionCollapse((35, 64), (16, 100), (10, 62),
op: Operations.Add, reduce_to: ref total_iters_executed,
num_threads: 8, chunk_size: 3, schedule: Schedule.Dynamic,
action: (ref int total_iters_executed, int i, int j, int k) =>
{
DotMP.Atomic.Inc(ref iters_hit_3[i, j, k]);
total_iters_executed += 1;
});

for (int i = 0; i < 128; i++)
for (int j = 0; j < 128; j++)
for (int k = 0; k < 64; k++)
if (i >= 35 && i < 64 && j >= 16 && j < 100 && k >= 10 && k < 62)
iters_hit_3[i, j, k].Should().Be(1);
else
iters_hit_3[i, j, k].Should().Be(0);

total_iters_executed.Should().Be((64 - 35) * (100 - 16) * (62 - 10));

iters_hit_3 = null;
total_iters_executed = 0;

int[,,,] iters_hit_4 = new int[32, 32, 32, 32];

DotMP.Parallel.ParallelForReductionCollapse((1, 31), (10, 16), (5, 20), (21, 30),
op: Operations.Add, reduce_to: ref total_iters_executed,
num_threads: 8, chunk_size: 11, schedule: Schedule.Static,
action: (ref int total_iters_executed, int i, int j, int k, int l) =>
{
DotMP.Atomic.Inc(ref iters_hit_4[i, j, k, l]);
total_iters_executed += 1;
});

total_iters_executed.Should().Be((31 - 1) * (16 - 10) * (20 - 5) * (30 - 21));
total_iters_executed = 0;

DotMP.Parallel.ParallelForReductionCollapse(new (int, int)[] { (1, 31), (10, 16), (5, 20), (21, 30) },
op: Operations.Add, reduce_to: ref total_iters_executed,
num_threads: 8, chunk_size: 11, schedule: Schedule.Static,
action: (ref int total_iters_executed, int[] indices) =>
{
DotMP.Atomic.Inc(ref iters_hit_4[indices[0], indices[1], indices[2], indices[3]]);
total_iters_executed += 1;
});

total_iters_executed.Should().Be((31 - 1) * (16 - 10) * (20 - 5) * (30 - 21));
for (int i = 0; i < 32; i++)
for (int j = 0; j < 32; j++)
for (int k = 0; k < 32; k++)
for (int l = 0; l < 32; l++)
if (i >= 1 && i < 31 && j >= 10 && j < 16 && k >= 5 && k < 20 && l >= 21 && l < 30)
iters_hit_4[i, j, k, l].Should().Be(2);
else
iters_hit_4[i, j, k, l].Should().Be(0);
}

/// <summary>
/// Tests to make sure that taskloops produce correct results.
/// </summary>
Expand Down
65 changes: 16 additions & 49 deletions DotMP/Iter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,8 @@ internal static class Iter
/// <typeparam name="T">The type of the local variable for reductions.</typeparam>
/// <param name="ws">The WorkShare object for state.</param>
/// <param name="thread_id">The thread ID.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
internal static void StaticLoop<T>(WorkShare ws, int thread_id, Action<int> omp_fn, ActionRef<T> omp_fn_red, bool is_reduction)
/// <param name="forAction">The function to be executed.</param>
internal static void StaticLoop<T>(WorkShare ws, int thread_id, ForAction<T> forAction)
{
int tid = thread_id;
Thr thr = ws.thread;
Expand All @@ -88,7 +86,7 @@ internal static void StaticLoop<T>(WorkShare ws, int thread_id, Action<int> omp_
ws.SetLocal(ref local);

while (thr.curr_iter < end)
StaticNext(ws, thr, ws.chunk_size, omp_fn, omp_fn_red, is_reduction, ref local);
StaticNext(ws, thr, ws.chunk_size, forAction, ref local);

ws.AddReductionValue(local);
}
Expand All @@ -101,16 +99,14 @@ internal static void StaticLoop<T>(WorkShare ws, int thread_id, Action<int> omp_
/// <param name="ws">The WorkShare object for state.</param>
/// <param name="thr">The Thr object for the current thread.</param>
/// <param name="chunk_size">The chunk size.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
/// <param name="forAction">The function to be executed.</param>
/// <param name="local">The local variable for reductions.</param>
private static void StaticNext<T>(WorkShare ws, Thr thr, uint chunk_size, Action<int> omp_fn, ActionRef<T> omp_fn_red, bool is_reduction, ref T local)
private static void StaticNext<T>(WorkShare ws, Thr thr, uint chunk_size, ForAction<T> forAction, ref T local)
{
int start = thr.curr_iter;
int end = (int)Math.Min(thr.curr_iter + chunk_size, ws.end);

InnerLoop(ref thr.working_iter, ref local, omp_fn, omp_fn_red, start, end, is_reduction);
forAction.PerformLoop(ref thr.working_iter, start, end, ref local);

thr.curr_iter += (int)(ws.num_threads * chunk_size);
}
Expand All @@ -120,11 +116,9 @@ private static void StaticNext<T>(WorkShare ws, Thr thr, uint chunk_size, Action
/// </summary>
/// <typeparam name="T">The type of the local variable for reductions.</typeparam>
/// <param name="ws">The WorkShare object for state.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
/// <param name="forAction">The function to be executed.</param>
/// <param name="schedule">The schedule to use.</param>
internal static void LoadBalancingLoop<T>(WorkShare ws, Action<int> omp_fn, ActionRef<T> omp_fn_red, bool is_reduction, Schedule schedule)
internal static void LoadBalancingLoop<T>(WorkShare ws, ForAction<T> forAction, Schedule schedule)
{
Thr thr = ws.thread;
int end = ws.end;
Expand All @@ -134,11 +128,11 @@ internal static void LoadBalancingLoop<T>(WorkShare ws, Action<int> omp_fn, Acti

if (schedule == Schedule.Guided) while (ws.start < end)
{
GuidedNext(ws, thr, omp_fn, omp_fn_red, is_reduction, ref local);
GuidedNext(ws, thr, forAction, ref local);
}
else if (schedule == Schedule.Dynamic) while (ws.start < end)
{
DynamicNext(ws, thr, omp_fn, omp_fn_red, is_reduction, ref local);
DynamicNext(ws, thr, forAction, ref local);
}

ws.AddReductionValue(local);
Expand All @@ -151,11 +145,9 @@ internal static void LoadBalancingLoop<T>(WorkShare ws, Action<int> omp_fn, Acti
/// <typeparam name="T">The type of the local variable for reductions.</typeparam>
/// <param name="ws">The WorkShare object for state.</param>
/// <param name="thr">The Thr object for the current thread.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
/// <param name="forAction">The function to be executed.</param>
/// <param name="local">The local variable for reductions.</param>
private static void DynamicNext<T>(WorkShare ws, Thr thr, Action<int> omp_fn, ActionRef<T> omp_fn_red, bool is_reduction, ref T local)
private static void DynamicNext<T>(WorkShare ws, Thr thr, ForAction<T> forAction, ref T local)
{
int chunk_start;

Expand All @@ -167,7 +159,7 @@ private static void DynamicNext<T>(WorkShare ws, Thr thr, Action<int> omp_fn, Ac

int chunk_end = (int)Math.Min(chunk_start + ws.chunk_size, ws.end);

InnerLoop(ref thr.working_iter, ref local, omp_fn, omp_fn_red, chunk_start, chunk_end, is_reduction);
forAction.PerformLoop(ref thr.working_iter, chunk_start, chunk_end, ref local);
}

/// <summary>
Expand All @@ -177,11 +169,9 @@ private static void DynamicNext<T>(WorkShare ws, Thr thr, Action<int> omp_fn, Ac
/// <typeparam name="T">The type of the local variable for reductions.</typeparam>
/// <param name="ws">The WorkShare object for state.</param>
/// <param name="thr">The Thr object for the current thread.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
/// <param name="forAction">The function to be executed.</param>
/// <param name="local">The local variable for reductions.</param>
private static void GuidedNext<T>(WorkShare ws, Thr thr, Action<int> omp_fn, ActionRef<T> omp_fn_red, bool is_reduction, ref T local)
private static void GuidedNext<T>(WorkShare ws, Thr thr, ForAction<T> forAction, ref T local)
{
int chunk_start, chunk_size;

Expand All @@ -195,30 +185,7 @@ private static void GuidedNext<T>(WorkShare ws, Thr thr, Action<int> omp_fn, Act

int chunk_end = Math.Min(chunk_start + chunk_size, ws.end);

InnerLoop(ref thr.working_iter, ref local, omp_fn, omp_fn_red, chunk_start, chunk_end, is_reduction);
}

/// <summary>
/// Performs the innermost loop to execute a chunk.
/// </summary>
/// <typeparam name="T">The type of the local variable for reductions.</typeparam>
/// <param name="curr_iter">A reference to the thread's current working iteration.</param>
/// <param name="local">The local variable used for reductions.</param>
/// <param name="omp_fn">The function to be executed.</param>
/// <param name="omp_fn_red">The function to be executed for reductions.</param>
/// <param name="start">The start of the current chunk, inclusive.</param>
/// <param name="end">The end of the current chunk, exclusive.</param>
/// <param name="is_reduction">Whether or not the loop is a reduction loop.</param>
private static void InnerLoop<T>(ref int curr_iter, ref T local, Action<int> omp_fn, ActionRef<T> omp_fn_red, int start, int end, bool is_reduction)
{
if (!is_reduction) for (curr_iter = start; curr_iter < end; curr_iter++)
{
omp_fn(curr_iter);
}
else for (curr_iter = start; curr_iter < end; curr_iter++)
{
omp_fn_red(ref local, curr_iter);
}
forAction.PerformLoop(ref thr.working_iter, chunk_start, chunk_end, ref local);
}
}
}
2 changes: 1 addition & 1 deletion DotMP/Lock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public sealed class Lock
/// <summary>
/// The int acting as the lock.
/// </summary>
volatile internal int _lock;
volatile private int _lock;

/// <summary>
/// Constructs a new lock.
Expand Down
Loading