Skip to content

Commit

Permalink
Merge pull request #126 from computablee/release/v2.0.0
Browse files Browse the repository at this point in the history
Add GPU functionality
  • Loading branch information
computablee authored Nov 27, 2023
2 parents 2db30d0 + 6fbab81 commit 56ec974
Show file tree
Hide file tree
Showing 19 changed files with 1,939 additions and 29 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/publish_site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x

- name: Build Templates
run: make build

- name: Install Doxygen
run: sudo apt-get install doxygen graphviz -y
shell: bash
Expand All @@ -28,4 +36,4 @@ jobs:
uses: JamesIves/github-pages-deploy-action@v4
with:
token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
folder: docs/html
folder: docs/html
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ docs/*
.vscode
*.opencover.xml
*.sln
AcceleratorHandler.cs
Gpu.cs
ProcessedREADME.md

# User-specific files
Expand Down
39 changes: 19 additions & 20 deletions DotMP-Tests/ParallelTests.cs → DotMP-Tests/CPUTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@
namespace DotMPTests
{
/// <summary>
/// Tests for the DotMP library.
/// CPU tests for the DotMP library.
/// </summary>
public class ParallelTests
public class CPUTests
{
private readonly ITestOutputHelper output;

/// <summary>
/// Constructor to write output.
/// </summary>
/// <param name="output">Output object.</param>
public ParallelTests(ITestOutputHelper output)
public CPUTests(ITestOutputHelper output)
{
this.output = output;
}
Expand Down Expand Up @@ -522,7 +522,7 @@ public void Critical_works()
DotMP.Parallel.ParallelRegion(num_threads: threads, action: () =>
{
for (int i = 0; i < iters; i++)
DotMP.Parallel.Critical(0, () => ++total);
DotMP.Parallel.Critical(() => ++total);
});

total.Should().Be((int)threads * iters);
Expand All @@ -531,14 +531,13 @@ public void Critical_works()

DotMP.Parallel.ParallelRegion(num_threads: 4, action: () =>
{
if (DotMP.Parallel.GetThreadNum() == 0) DotMP.Parallel.Critical(0, () => Thread.Sleep(1000));
if (DotMP.Parallel.GetThreadNum() == 1) DotMP.Parallel.Critical(1, () => Thread.Sleep(1000));
if (DotMP.Parallel.GetThreadNum() == 2) DotMP.Parallel.Critical(0, () => Thread.Sleep(1000));
if (DotMP.Parallel.GetThreadNum() == 3) DotMP.Parallel.Critical(1, () => Thread.Sleep(1000));
if (DotMP.Parallel.GetThreadNum() % 2 == 0) DotMP.Parallel.Critical(() => Thread.Sleep(1000));
if (DotMP.Parallel.GetThreadNum() % 2 == 1) DotMP.Parallel.Critical(() => Thread.Sleep(1000));
});

double elapsed = DotMP.Parallel.GetWTime() - start;
elapsed.Should().BeLessThan(2200);
elapsed.Should().BeLessThan(2.2);
elapsed.Should().BeGreaterThan(2.0);
}

/// <summary>
Expand Down Expand Up @@ -571,7 +570,7 @@ public void Single_works()
{
for (int i = 0; i < 10; i++)
{
DotMP.Parallel.Single(0, () => DotMP.Atomic.Inc(ref total));
DotMP.Parallel.Single(() => DotMP.Atomic.Inc(ref total));
}
});

Expand All @@ -583,7 +582,7 @@ public void Single_works()
{
for (int i = 0; i < 10; i++)
{
DotMP.Parallel.Single(0, () => DotMP.Atomic.Inc(ref total));
DotMP.Parallel.Single(() => DotMP.Atomic.Inc(ref total));
}
});

Expand Down Expand Up @@ -749,7 +748,7 @@ public void Ordered_works()
DotMP.Parallel.ParallelFor(0, 1024, schedule: DotMP.Schedule.Static,
num_threads: threads, action: i =>
{
DotMP.Parallel.Ordered(0, () =>
DotMP.Parallel.Ordered(() =>
{
incrementing[i] = ctr++;
});
Expand Down Expand Up @@ -1111,7 +1110,7 @@ public void Tasking_works()

DotMP.Parallel.ParallelRegion(num_threads: threads, action: () =>
{
DotMP.Parallel.Single(0, () =>
DotMP.Parallel.Single(() =>
{
for (int i = 0; i < threads * 2; i++)
{
Expand Down Expand Up @@ -1139,7 +1138,7 @@ public void Tasking_works()

DotMP.Parallel.ParallelRegion(num_threads: threads, action: () =>
{
DotMP.Parallel.Single(0, () =>
DotMP.Parallel.Single(() =>
{
for (int i = 0; i < tasks_to_spawn; i++)
{
Expand Down Expand Up @@ -1199,7 +1198,7 @@ public void Nested_tasks_work()

DotMP.Parallel.ParallelRegion(num_threads: threads, action: () =>
{
DotMP.Parallel.Single(0, () =>
DotMP.Parallel.Single(() =>
{
DotMP.Parallel.Task(() =>
{
Expand Down Expand Up @@ -1369,7 +1368,7 @@ public void Non_parallel_single_should_except()
{
Assert.Throws<DotMP.Exceptions.NotInParallelRegionException>(() =>
{
DotMP.Parallel.Single(0, () => { });
DotMP.Parallel.Single(() => { });
});
}

Expand All @@ -1381,7 +1380,7 @@ public void Non_parallel_critical_should_except()
{
Assert.Throws<DotMP.Exceptions.NotInParallelRegionException>(() =>
{
DotMP.Parallel.Critical(0, () => { });
DotMP.Parallel.Critical(() => { });
});
}

Expand All @@ -1395,15 +1394,15 @@ public void Nested_worksharing_should_except()
{
DotMP.Parallel.ParallelFor(0, 10, num_threads: 4, action: i =>
{
DotMP.Parallel.Single(0, () => { });
DotMP.Parallel.Single(() => { });
});
});

Assert.Throws<DotMP.Exceptions.CannotPerformNestedWorksharingException>(() =>
{
DotMP.Parallel.ParallelRegion(num_threads: 4, action: () =>
{
DotMP.Parallel.Single(0, () =>
DotMP.Parallel.Single(() =>
{
DotMP.Parallel.For(0, 10, action: i => { });
});
Expand All @@ -1427,7 +1426,7 @@ public void Non_for_ordered_should_except()
{
Assert.Throws<DotMP.Exceptions.NotInParallelRegionException>(() =>
{
DotMP.Parallel.Ordered(0, () => { });
DotMP.Parallel.Ordered(() => { });
});
}

Expand Down
136 changes: 136 additions & 0 deletions DotMP-Tests/GPUTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using DotMP;
using DotMP.GPU;
using FluentAssertions;
using Xunit;
using Xunit.Abstractions;


namespace DotMPTests
{
/// <summary>
/// CPU tests for the DotMP library.
/// </summary>
public class GPUTests
{
/// <summary>
/// Tests to make sure that for loops work in GPU kernels.
/// </summary>
[Fact]
public void GPU_for_works()
{
double[] a = new double[50000];
double[] x = new double[50000];
double[] y = new double[50000];
float[] res = new float[50000];
float[] res_cpu = new float[50000];

random_init(a);
random_init(x);
random_init(y);

{
using var a_gpu = new DotMP.GPU.Buffer<double>(a, DotMP.GPU.Buffer.Behavior.To);
using var x_gpu = new DotMP.GPU.Buffer<double>(x, DotMP.GPU.Buffer.Behavior.To);
using var y_gpu = new DotMP.GPU.Buffer<double>(y, DotMP.GPU.Buffer.Behavior.To);
using var res_gpu = new DotMP.GPU.Buffer<float>(res, DotMP.GPU.Buffer.Behavior.From);

DotMP.GPU.Parallel.ParallelFor(0, a.Length, a_gpu, x_gpu, y_gpu, res_gpu,
(i, a, x, y, res) =>
{
res[i] = (float)(a[i] * x[i] + y[i]);
});
}

for (int i = 0; i < a.Length; i++)
{
res_cpu[i] = (float)(a[i] * x[i] + y[i]);
}

Assert.Equal(res_cpu, res);

double[] a_old = a.Select(a => a).ToArray();

using (var a_gpu = new DotMP.GPU.Buffer<double>(a, DotMP.GPU.Buffer.Behavior.ToFrom))
{
DotMP.GPU.Parallel.ParallelFor(0, a.Length, a_gpu, (i, a) =>
{
a[i]++;
});
}

for (int i = 0; i < a.Length; i++)
{
a_old[i]++;
}

Assert.Equal(a, a_old);
}

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

using (var buf = new Buffer<int>(iters_hit, DotMP.GPU.Buffer.Behavior.ToFrom))
{
DotMP.GPU.Parallel.ParallelForCollapse((258, 512), (512, 600), buf, (i, j, iters_hit) =>
{
iters_hit[i, j]++;
});
}

for (int i = 0; i < 1024; i++)
for (int j = 0; j < 1024; j++)
if (i >= 258 && 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];

using (var buf = new Buffer<int>(iters_hit_3, DotMP.GPU.Buffer.Behavior.ToFrom))
{
DotMP.GPU.Parallel.ParallelForCollapse((35, 64), (16, 100), (10, 62), buf, action: (i, j, k, iters_hit_3) =>
{
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;
}

/// <summary>
/// Randomly initialize an array of type T.
/// </summary>
/// <typeparam name="T">The type to initialize to.</typeparam>
/// <param name="arr">The allocated array to store values into.</param>
private void random_init<T>(T[] arr)
{
Random r = new Random();

for (int i = 0; i < arr.Length; i++)
{
arr[i] = (T)Convert.ChangeType(r.NextDouble() * 128, typeof(T));
}
}
}
}
19 changes: 18 additions & 1 deletion DotMP/DotMP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>DotMP</RootNamespace>
<PackageId>DotMP</PackageId>
<Version>1.6.0</Version>
<Version>2.0-pre1</Version>
<Authors>Phillip Allen Lane,et al.</Authors>
<PackageDescription>A library for fork-join parallelism in .NET, with an OpenMP-like API.</PackageDescription>
<RepositoryUrl>https://github.com/computablee/DotMP</RepositoryUrl>
Expand All @@ -23,4 +23,21 @@
<None Include="../ProcessedREADME.md" Pack="true" PackagePath="." />
</ItemGroup>

<ItemGroup>
<PackageReference Include="ILGPU" Version="1.5.1" />
<PackageReference Include="T4.Build" Version="0.2.4" />

<None Include="GPU/AcceleratorHandler.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>GPU/AcceleratorHandler.tt</DependentUpon>
</None>

<None Include="GPU/Gpu.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>GPU/Gpu.tt</DependentUpon>
</None>
</ItemGroup>

</Project>
Loading

0 comments on commit 56ec974

Please sign in to comment.