- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找处理 PointF 类型数组的快速方法。用下面的代码转换它们给出了一个跨度,所以我可以使用 fma、avx 和 sse 内在函数来加速代码。此功能在我的机器上正常工作。问题在于安全。在不同平台上执行此类转换是否安全? Microsoft 文档说,大端架构可以在拆分或合并值时反转值:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
public static class PontFExtension
{
public static Span<float> AsSingleSpan(this PointF[] points)
{
var span = new Span<PointF>(points);
return MemoryMarshal.Cast<PointF, float>(span);
}
}
最佳答案
简短的回答是否定的,因为 PointF
至 Float
是具有不同字段和布局的两个不同结构(即 PointF.X 和 PointF.Y 是 PointF 结构上的字段)。它可能适用于一种操作系统和 .Net 版本,但可能无法适用于其他版本。
我提供了三种跨操作系统和 .Net 版本安全实现目标的方法,确保您在 Span<float[]>
中获得 X 和 Y。 (参见实现多维)或在 Span<float>
中交替(请参阅实现单一维度)。
字节顺序
我提供的实现不会导致操作系统之间的字节顺序问题 - 即使类型被序列化并以一种格式(例如 Big)写入网络流并由 .Net 在另一种格式(例如 Little)中读取另一边 - 因为 .Net BCL 检查并相应地旋转位。
我不能对你使用 Marshal.Cast
的实现说同样的话因为 (i) 它是一种可能会根据 OS/.Net 版本产生不可预测结果的解决方案,并且 (ii) 我对内在函数的了解还不够多,无法发表意见 Marshal.Cast
.如果我是你,我会保持简单并使用我建议的方法之一。
基准
Linq 是预期中最慢的。 AsSpanPtr 实现的“Ref”(迭代器引用)实现速度提高了 4 倍。以下 BenchmarkDotNet 结果是使用相同的集合进行 10M 次迭代。
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|------- |----------:|----------:|----------:|------:|--------:|
| Ptr | 6.762 ms | 0.0731 ms | 0.0648 ms | 1.00 | 0.00 |
| Ref | 27.169 ms | 0.4086 ms | 0.3822 ms | 4.02 | 0.06 |
| Linq | 31.896 ms | 0.4622 ms | 0.4098 ms | 4.72 | 0.08 |
实现多维
public static class PontFExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<float[]> AsSpanLinq(this PointF[] points)
=> points.Select(x => new float[] { x.X, x.Y }).ToArray().AsSpan();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<float[]> AsSpanRef(this PointF[] points)
{
Span<float[]> floats = new float[points.Length][];
for (int i = 0; i < points.Length; i++)
{
PointF point = points[i];
floats[i] = new[] { point.X, point.Y };
}
return floats;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static Span<float[]> AsSpanPtr(this PointF[] points)
{
Span<float[]> floats = new float[points.Length][];
fixed (PointF* pinned = points)
{
for (int i = 0; i < points.Length; i++)
{
PointF* pnt = &pinned[i];
floats[i] = new[] { (*pnt).X, (*pnt).Y };
}
}
return floats;
}
}
实现 - 单一维度(每行 X 和 Y 交替)
public static unsafe class PontFExtensionSingleDimension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<float> AsSpanLinq(this PointF[] points)
=> points.SelectMany(x => new[] { x.X, x.Y}).ToArray();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<float> AsSpanRef(this PointF[] points)
{
var len = points.Length;
Span<float> floats = new float[len * 2];
for (int i = 0; i < len; i++)
{
var pnt = points[i];
floats[i*2] = pnt.X; floats[i*2+1] = pnt.Y;
}
return floats;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static Span<float> AsSpanPtr(this PointF[] points)
{
var len = points.Length;
Span<float> floats = new float[len * 2];
fixed (PointF* pinned = points)
{
for (int i = 0; i < len; i++)
{
PointF* pnt = &pinned[i];
floats[i*2] = (*pnt).X; floats[i*2+1] = (*pnt).Y ;
}
}
return floats;
}
}
关于C# - MemoryMarshal.Cast() 能否在 Linux 和 Windows 上转换任何具有兼容字节序的结构或原语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73748519/
序 大家好呀,我是summo,这次来写写我在上班空闲(摸鱼)的时候做的一个小网站的事。去年阿里云不是推出了个活动嘛,2核2G的云服务器一年只要99块钱,懂行的人应该知道这个价格在业界已经是非常良心了
我尝试根据给定的级别顺序(BFS 顺序)构造 BST。我知道这是可能的,但我不知道我该怎么写。问题是我必须使用 BFS 序列。所以,我不能在这里使用递归,我必须迭代地编写我的程序......我发现这有
我是一名优秀的程序员,十分优秀!