Aar*_*nke 8 .net c# intrinsics .net-core
Google快速搜索“内在属性c#”只会返回有关其他属性的文章,例如[Serializable]。显然,这些被称为“固有属性”。
但是,C#中也有一个本身被调用的属性,[Intrinsic]我试图弄清楚它到底是什么以及它如何工作。在.NET文档的“ 公共属性”页面上,或者据我所知,它在文档的其他任何地方都不存在。
该属性用于.NET核心的内部中的几个地方,例如,在将System.Numerics.Vectors文件夹,如Vector2_Intrinsics.cs。程式码片段:
[Intrinsic]
public Vector2(float x, float y)
{
X = x;
Y = y;
}
Run Code Online (Sandbox Code Playgroud)
通过github上的dotnet / corefx存储库进行非常有限的搜索后,这就是我设法找到的东西。
[Intrinsic]标记可能被JIT替换/优化的方法,属性和字段。源代码注释说类似(IntrinsicAttribute.cs):
在某些调用站点上,可以使用jit内在扩展替换对带有此属性标记的方法的调用或对字段的引用。标记有该属性的类型可以由运行时/编译器特殊处理。
对于核心开发人员,[Intrinsic]至少有两个目的:
举一个简单的例子:Enum.HasFlag在某些情况下,JIT优化器可以用简单的按位比较代替,而在另一些情况下则不能。为此,需要将方法标识为Enum.HasFlag,检查一些条件,然后用更优化的实现方式替换它。优化器可以按名称标识该方法,但是出于性能原因,最好在执行字符串比较之前通过一个简单的标志过滤掉方法。
该属性仅与核心开发人员相关。您仅应在内部类中使用它,并且仅在要为其提出非常特定的JIT级别优化的情况下使用。[Intrinsic]仅限于一小组广泛使用的.Net类,由于某种原因,该类无法通过其他方式进行优化。
从评论中:我计划为.NET Core提出一个Color结构,该结构必须与其他内置类型具有相似的行为以保持一致性。
您可能不应该[Intrinsic]在初始建议中使用。通过之后,您可以考虑优化,如果您有一个Color可以从低级优化中受益的有效方案,则可以建议使用[Intrinsic]其某些方法或属性。
以下是如何[Intrinsic]在核心是目前使用:
它定义为众所周知的属性(wellknownattributes.h):
case WellKnownAttribute::Intrinsic:
return "System.Runtime.CompilerServices.IntrinsicAttribute";
Run Code Online (Sandbox Code Playgroud)VM对其进行解析,并将IsJitIntrinsic方法(methodtablebuilder.cpp)的标志设置为true :
if (bmtProp->fIsHardwareIntrinsic || (S_OK == GetCustomAttribute(pMethod->GetMethodSignature().GetToken(),
WellKnownAttribute::Intrinsic,
NULL,
NULL)))
{
pNewMD->SetIsJitIntrinsic();
}
Run Code Online (Sandbox Code Playgroud)此标志用于在方法属性(jitinterface.cpp)中设置另一个标志:
if (pMD->IsJitIntrinsic())
result |= CORINFO_FLG_JIT_INTRINSIC;
Run Code Online (Sandbox Code Playgroud)此标志稍后用于过滤掉显然不是内在(importer.cpp)的方法:
if ((mflags & (CORINFO_FLG_INTRINSIC | CORINFO_FLG_JIT_INTRINSIC)) != 0)
{
const bool isTail = canTailCall && (tailCall != 0);
call = impIntrinsic(newobjThis, clsHnd, methHnd, sig, mflags, pResolvedToken->token, readonlyCall, isTail,
pConstrainedResolvedToken, callInfo->thisTransform, &intrinsicID, &isSpecialIntrinsic);
Run Code Online (Sandbox Code Playgroud)impIntrinsic然后调用lookupNamedIntrinsic以标识(主要是通过名称)真正(不仅可能)进行优化的方法;
毕竟,这些importer都可以基于方法进行优化。例如,针对Enum.HasFlag(importer.cpp)的优化:
case NI_System_Enum_HasFlag:
{
GenTree* thisOp = impStackTop(1).val;
GenTree* flagOp = impStackTop(0).val;
GenTree* optTree = gtOptimizeEnumHasFlag(thisOp, flagOp);
if (optTree != nullptr)
{
// Optimization successful. Pop the stack for real.
impPopStack();
impPopStack();
retNode = optTree;
}
else
{
// Retry optimizing this during morph.
isSpecial = true;
}
break;
}
Run Code Online (Sandbox Code Playgroud)免责声明:据我所知,该属性的行为在任何地方均未得到正确记录,因此可能会发生更改。上面的描述仅与当前掌握在母带中的代码有关,核心的这一部分正在积极开发中,将来可以更改整个过程。
以下是[Intrinsic]基于github存储库历史记录的简短时间表:
在2014年之前的某个时间[JitIntrisic]引入属性是System.Numerics为了支持新处理器指令的一部分(请参阅JitIntrinsicAttribute如何影响代码生成?)。
2016年6月6日,克里斯·麦肯锡(Chris McKinsey)开设了第5626期。“当类型相同时,将enum1.HasFlag(enum2)优化为内联位测试,而无需装箱分配”。当时,Enum.HasFlag存在一个众所周知的性能问题(请参阅什么使Enum.HasFlag如此缓慢?)。
在解决这个问题时,Andy Ayers建议引入一种通用机制来引入JIT内在函数(问题#13813:添加更灵活的方法来指定jit内在函数)
这导致了两个请求:新的jit内在支持为[Intrinsic]和JIT引入了通用机制:优化Enum.HasFlag为实现了它Enum.HasFlag。我建议对它们进行仔细的研究,因为它们对于随之而来的变化具有极大的说明性[Intrinsic]。
稍后,在有关将Vector类移至CoreLib的讨论中,建议[JitIntrinsic]不要在任何地方使用它,而应将其替换/移除:
@jkotas:我们不需要JitIntrinsicAttribute。据我所知,该属性是面向未来的证明,从未用于任何实际用途。我们应该删除它,而改用CoreLib的IntrinsicAttribute。
[JitIntrinsic]其删除,并替换为[Intrinsic](用IntrinsicAttribute替换JitIntrinsicAttribute)。这就是该属性出现的方式Vector2。| 归档时间: |
|
| 查看次数: |
729 次 |
| 最近记录: |