Span<T>
and Span2D<T>
(from the High Performance Community Toolkit) are ref struct
types. This means they can't be passed to lambdas, local functions, or async contexts.
However, consider the following example using a Span2D
:
namespace Example;
public static class ExampleMethod
{
public static void TransformExample<T>(Span2D<T> data)
{
// Breakdown the problem into 4 quadrants and execute them in parallel
var halfRows = data.Height / 2;
var halfCols = data.Width / 2;
TransformQuadrant(data[..halfRows, ..halfCols]); // Top-left quadrant
TransformQuadrant(data[..halfRows, halfCols..]); // Top-right quadrant
TransformQuadrant(data[halfRows.., ..halfCols]); // Bottom-left quadrant
TransformQuadrant(data[halfRows.., halfCols..]); // Bottom-right quadrant
}
private static void TransformQuadrant<T>(Span2D<T> data)
{
// Do something interesting with this quadrant of `data`
}
}
If you try to wrap those 4 calls in some kind of async context, either by making TransformQuadrant
async, or - for example - using:
var tasks = new List<Task>
{
Task.Run(() => TransformQuadrant(data[..halfRows, ..halfCols])),
Task.Run(() => TransformQuadrant(data[..halfRows, halfCols..])),
Task.Run(() => TransformQuadrant(data[halfRows.., ..halfCols])),
Task.Run(() => TransformQuadrant(data[halfRows.., halfCols..]))
};
Task.WaitAll(tasks);
You're greeted with
Error CS1628: Cannot use ref, out, or in parameter 'data' inside an anonymous method, lambda expression, query expression, or local function
Which says, from the MS docs:
CS1628: Cannot use
in
,ref
, orout
parameter inside an anonymous method, lambda expression, or query expression.
So the question is how can one make this type of work parallel/async? I understand Memory<T>
but that implies paying for the conversion to Span<T>
, so I wonder how this can be done without these overheads.