Skip to content

Commit

Permalink
Added MemoryBufferStrides sample project.
Browse files Browse the repository at this point in the history
  • Loading branch information
MoFtZ committed Feb 23, 2023
1 parent f3d55e4 commit 971bb70
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Samples/ILGPU.Samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibDeviceKernel", "LibDevic
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorSampleApp", "BlazorSampleApp\BlazorSampleApp.csproj", "{1A909DA2-15AE-466F-8BBE-C3F676C39812}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MemoryBufferStrides", "MemoryBufferStrides\MemoryBufferStrides.csproj", "{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -345,6 +347,10 @@ Global
{1A909DA2-15AE-466F-8BBE-C3F676C39812}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A909DA2-15AE-466F-8BBE-C3F676C39812}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A909DA2-15AE-466F-8BBE-C3F676C39812}.Release|Any CPU.Build.0 = Release|Any CPU
{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -407,6 +413,7 @@ Global
{9CB52A85-9ACB-4B7E-95C5-75E9023EF5EC} = {25BA2234-5778-40BC-9386-9CE87AB87D1F}
{029C809E-4EBF-4437-A4B2-BA7E14A9C023} = {C1D99632-ED4A-4B08-A14D-4C8DB375934F}
{1A909DA2-15AE-466F-8BBE-C3F676C39812} = {30F390DB-B823-40A2-A881-382B9EF36C07}
{2EF99A5B-9AAE-44A8-BB41-923DF66A7EAB} = {C1D99632-ED4A-4B08-A14D-4C8DB375934F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {30E502BD-3826-417F-888F-1CE19CF5C6DA}
Expand Down
3 changes: 3 additions & 0 deletions Samples/MemoryBufferStrides/AssemblyAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System;

[assembly: CLSCompliant(true)]
16 changes: 16 additions & 0 deletions Samples/MemoryBufferStrides/MemoryBufferStrides.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(LibrarySamplesTargetFrameworks)</TargetFrameworks>
<OutputType>Exe</OutputType>
<LangVersion>8.0</LangVersion>
</PropertyGroup>

<PropertyGroup>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Src\ILGPU\ILGPU.csproj" />
</ItemGroup>
</Project>
214 changes: 214 additions & 0 deletions Samples/MemoryBufferStrides/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// ---------------------------------------------------------------------------------------
// ILGPU Samples
// Copyright (c) 2023 ILGPU Project
// www.ilgpu.net
//
// File: Program.cs
//
// This file is part of ILGPU and is distributed under the University of Illinois Open
// Source License. See LICENSE.txt for details.
// ---------------------------------------------------------------------------------------

using ILGPU;
using ILGPU.Runtime;
using System;
using System.Linq;

namespace MemoryBufferStrides
{
class Program
{
#region Stride1D

static void Stride1DKernel(
Index1D index,
ArrayView1D<int, Stride1D.Dense> denseView,
ArrayView1D<int, Stride1D.Infinite> infiniteView,
ArrayView1D<int, Stride1D.General> generalView)
{
// The general view could advance outside the range of the original data,
// so check that we are within bounds.
var generalLinearIdx = generalView.Stride.ComputeElementIndex(index);
int generalViewValue;
if (generalLinearIdx < generalView.AsContiguous().Length)
generalViewValue = generalView[index];
else
generalViewValue = 0;

// Show the contents of the views.
Interop.WriteLine("[{0}] = Dense= {1}, Infinite= {2}, General= {3}",
index.X,
denseView[index],
infiniteView[index],
generalViewValue);
}

/// <summary>
/// Example of using Stride1D.
/// </summary>
static void UsingStride1D(Accelerator accelerator)
{
Console.WriteLine("Using Stride1D");
var values = Enumerable.Range(0, 16).ToArray();

// Stride1D.Dense means that as the X index increases by 1, it will advance
// to the next element in the array.
using var denseBuffer = accelerator.Allocate1D(values);

// Stride1D.Infinite means that as the X index never advances, and always
// returns element at index 0.
// Creates an single element array, that we use to feed all indices.
var infiniteValue = new int[] { 42 };
using var infiniteBuffer = accelerator.Allocate1D<int, Stride1D.Infinite>(
1,
new Stride1D.Infinite());
infiniteBuffer.View.CopyFromCPU(ref infiniteValue[0], 1);

// Stride1D.General allows for a user-defined striding. For this example, we
// allocate a number of elements, and then tell the view to advance X
// elements at a time.
const int Advance = 4;
var generalView = denseBuffer.View.AsGeneral(
new Stride1D.General(Advance));

var kernel = accelerator.LoadAutoGroupedStreamKernel<
Index1D,
ArrayView1D<int, Stride1D.Dense>,
ArrayView1D<int, Stride1D.Infinite>,
ArrayView1D<int, Stride1D.General>>(
Stride1DKernel);
kernel(
(int)denseBuffer.Length,
denseBuffer.View,
infiniteBuffer.View,
generalView);

accelerator.Synchronize();
Console.WriteLine();
}

#endregion

#region Stride2D

static void Stride2DKernel(
Index2D index,
ArrayView2D<int, Stride2D.DenseX> denseXView,
ArrayView2D<int, Stride2D.DenseY> denseYView)
{
Interop.WriteLine("[{0}, {1}] = DenseX= {2}, DenseY= {3}",
index.Y,
index.X,
denseXView[index],
denseYView[index]);
}

/// <summary>
/// Example of using Stride2D.DenseX and Stride2D.DenseY.
/// </summary>
static void UsingStride2D(Accelerator accelerator)
{
Console.WriteLine("Using Stride2D");

// Prepare a flat list of values, and re-interpret the values as either
// Stride2D.DenseX or Stride2D.DenseY, in order to show the difference.
var flatValues = Enumerable.Range(0, 15).ToArray();
using var inputBuffer = accelerator.Allocate1D(flatValues);

// Stride2D.DenseX indicates that to get to X + 1 you add 1 because that is
// the "most dense" dimension. The "next dense" dimension is Y, so to get to
// Y + 1, you have to skip over all the all X values.
//
// xStride | -|
// yStride | -------------|
// X0 X1 X2 X3 X4 X0 X1 X2 X3 X4 X0 X1 X2 X3 X4 X5
// Y0 Y1 Y2
//
// This is also known as row-major order, and is the standard layout of .NET
// arrays.
var denseXValues = new int[,]
{ // Row Major
{ 0, 1, 2, 3, 4 }, // --> --> --> --> -->
{ 5, 6, 7, 8, 9 }, // --> --> --> --> -->
{ 10, 11, 12, 13, 14 }, // --> --> --> --> -->
};
var dim = new Index2D(denseXValues.GetLength(1), denseXValues.GetLength(0));
var denseXView = inputBuffer.View.As2DDenseXView(dim);

// Stride2D.DenseY indicates that to get to Y + 1 you add 1 because that is
// the "most dense" dimension. The "next dense" dimension is X, so to get to
// X + 1, you have to skip over all the all Y values.
//
// xStride | -------------|
// yStride | -|
// X0 X1 X2
// Y0 Y1 Y2 Y3 Y4 Y0 Y1 Y2 Y3 Y4 Y0 Y1 Y2 Y3 Y4
//
// This is also known as column-major order.
var denseYView = inputBuffer.View.As2DDenseYView(dim);

var kernel = accelerator.LoadAutoGroupedStreamKernel<
Index2D,
ArrayView2D<int, Stride2D.DenseX>,
ArrayView2D<int, Stride2D.DenseY>>(
Stride2DKernel);

kernel(dim, denseXView, denseYView);
accelerator.Synchronize();

Console.WriteLine();

// .NET 2D arrays use the row-major order layout, matching Stride2D.DenseX.
//
// For row-major order, we expect the output for each (Y, X) index to match
// what we would get from a .NET array.
//
// var denseXValues = new int[,]
// { // Row Major
// { 0, 1, 2, 3, 4 }, // --> --> --> --> -->
// { 5, 6, 7, 8, 9 }, // --> --> --> --> -->
// { 10, 11, 12, 13, 14 }, // --> --> --> --> -->
// };
//
// Since Stride2D.DenseY is column-major order, we instead expect each (X, Y)
// index to match what we would get from a .NET array.
//
var denseYValues = new int[,]
{ // Column Major
{ 0, 1, 2 }, // | /| /|
{ 3, 4, 5 }, // | / | / |
{ 6, 7, 8 }, // | / | / |
{ 9, 10, 11 }, // | / | / |
{ 12, 13, 14 }, // |/ |/ |
};
Console.WriteLine("Using Stride2D - .NET Values");
for (var y = 0; y < dim.Y; y++)
for (var x = 0; x < dim.X; x++)
Console.WriteLine($"[{y}, {x}] = DenseX= {denseXValues[y, x]}, DenseY= {denseYValues[x, y]}");

Console.WriteLine();
}

#endregion

/// <summary>
/// Demonstrates memory buffer and array view striding.
/// </summary>
static void Main()
{
// Create main context
using var context = Context.CreateDefault();

// For each available device...
foreach (var device in context)
{
// Create accelerator for the given device
using var accelerator = device.CreateAccelerator(context);
Console.WriteLine($"Performing operations on {accelerator}");

UsingStride1D(accelerator);
UsingStride2D(accelerator);
}
}
}
}

0 comments on commit 971bb70

Please sign in to comment.