在.NET中,我们给了System.Span<T>
,它可以直接引用连续内存。通常通过为其提供现有数组来构造它。但是,如果我希望能够创建对数组中不连续元素的引用数组,那么该怎么办?
例如,给定:
var array = new double[ 5 ] { 1, 2, 3, 4, 5 };
var span = new Span( array ); // Continuous references, [ 1, 2, 3, 4, 5 ]
如果我想使用array
并创建一个“跨度”,该跨度可以具有不同的值排列,同时仍引用存储在数组中的值怎么办?如:
var discontinuous = new DiscontinuousSpan[3] {
(reference of array[1]),
(reference of array[0]),
(reference of array[4]) };
discontinuous[ 0 ]; // 2 (reference of array[1])
discontinuous[ 1 ]; // 1 (reference of array[0])
discontinuous[ 2 ]; // 5 (reference of array[4])
我看了Span<T>
的文档,并了解它只是指向固定长度内存的指针。但是,在C#7.2中添加了对值类型的引用,不应该不连续地引用数组元素吗?我没有看到任何.NET类型的引用,因此我假设自己使用自定义值类型来实现类似的功能。
说明:主要目标是获得System.Numerics.Vector<T>
的支持,以便我可以对不连续引用执行SIMD。
答案 0 :(得分:0)
因此,您有一个带有数字的数组,并希望有对该数组段的单独引用。但是Span是一种特殊的值类型,无法传递。 因此,您必须存储信息以仅在需要时生成这些单独的跨度...
// Here we store index and length for each desired segment
var mySegments = new (int position, int length)[] { (17, 5), (48, 19), (79, 16) };
然后,当需要访问时...
double [100] Numbers = GetNumbersFromSomwhere();
public double[] GetSegment(int segmentIndex)
{
var segment = mySegments[segmentIndex];
var reference = new Span<double>(Numbers, segment.position, segment.length);
return reference.ToArray();
}
但是,最后的ToArray()将实例化一个新的对象数组(生成GC压力)。因此,也许您可以将数据存储为字节数组(显然考虑了每个double的8个字节的长度),以生成独立的double跨度。后来,终于有了一个像这样的函数来读取特定的double值:
// Converts a Span into a double
// Requires using System.Runtime.CompilerServices.Unsafe
public static double ToDouble(ReadOnlySpan<byte> value)
{
if (value.Length < sizeof(double))
throw new ArgumentOutOfRangeException(nameof(value));
return Unsafe.ReadUnaligned<double>(ref MemoryMarshal.GetReference(value));
}
希望它对您的Vector(固定类型,我按此按钮)有帮助。