C# 中的 [Intrinsic] 属性有什么作用? [英] What does the [Intrinsic] attribute in C# do?

查看:22
本文介绍了C# 中的 [Intrinsic] 属性有什么作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Google 上快速搜索instrinsic attribute c#"只会返回关于其他属性的文章,例如 [Serializable].显然,这些被称为内在属性".

A quick Google search for "instrinsic attribute c#" only returns articles about other attributes, such as [Serializable]. Apparently these are called "intrinsic attributes".

但是,C# 中还有一个属性,它本身称为 [Intrinsic],我试图弄清楚它到底是什么以及它是如何工作的.它不存在于 通用属性 .NET 文档的页面,或我能看到的文档中的任何其他地方.

However, there is also an attribute in C# that is itself called [Intrinsic] and I'm trying to figure out what exactly it is and how it works. It doesn't exist on the common attributes page of the .NET Documentation, or anywhere else in the documentation as far as I can see.

此属性在 .NET Core 内部的多个地方使用,例如,在 System.Numerics.Vectors 文件夹,如Vector2_Intrinsics.cs.代码片段:

This attribute is used inside of .NET Core in several places, for example, in the System.Numerics.Vectors folder, such as Vector2_Intrinsics.cs. Code snippet:

[Intrinsic]
public Vector2(float x, float y)
{
    X = x;
    Y = y;
}

推荐答案

以下是我通过 dotnet/corefx github 上的存储库.

Here's what I've managed to find after a very limited search through dotnet/corefx repository on github.

[Intrinsic] 标记可能被 JIT 替换/优化的方法、属性和字段.源代码注释说了类似的话(IntrinsicAttribute.cs):

[Intrinsic] marks methods, properties and fields that can be potentially replaced/optimized by JIT. Source code comments say something similar (IntrinsicAttribute.cs):

对方法的调用或对标有此属性的字段的引用可能会在某些调用站点用 jit 内在扩展替换.使用此属性标记的类型可能会被运行时/编译器特殊处理.

Calls to methods or references to fields marked with this attribute may be replaced at some call sites with jit intrinsic expansions. Types marked with this attribute may be specially treated by the runtime/compiler.

目的

对于核心开发者来说,[Intrinsic] 至少有两个目的:

  • 通知开发者标记的字段、方法或属性的代码可以被VM替换.所以,如果代码发生变化,应该在两个地方都引入变化;
  • 它用作 JIT 优化器的标志,以快速识别可以优化的方法.

举一个粗略的例子:在某些情况下,JIT 优化器可以用简单的按位比较代替 Enum.HasFlag,而在其他情况下则不能.为此,它需要将方法标识为 Enum.HasFlag,检查一些条件并将其替换为更优化的实现.优化器可以通过名称识别方法,但出于性能原因,最好在执行字符串比较之前通过简单的标志过滤掉方法.

To give a rough example: JIT-optimizer can replace Enum.HasFlag with a simple bitwise comparison in some cases and not in the others. To do this it needs to identify the method as Enum.HasFlag, check some conditions and replace it with a more optimal implementation. The optimizer can identify the method by name, but, for performance reasons, it's better to filter out methods by a simple flag before performing string comparisons.

该属性仅与核心开发人员相关.您应该只在内部类中使用它,并且仅在您想为其提出非常具体的 JIT 级优化的情况下使用它.[Intrinsic] 几乎仅限于一小组广泛使用的 .Net 类,由于某种原因,无法通过其他方式对其进行优化.

The attribute is only relevant to core developers. You should only use it in an internal class and only in the case when you want to propose very specific JIT-level optimizations for it. [Intrinsic] is pretty much restricted to a small set of widely used .Net classes, that, for some reason, can't be optimized by other means.

来自评论:我计划为 .NET Core 提出一个 Color 结构,它需要与其他内置类型的行为类似以保持一致性.

from the comments: I'm planning to propose a Color struct for .NET Core which needs to behave similarly to other built-in types for consistency.

您可能不应该在初始提案中使用 [Intrinsic].通过之后,你可以考虑优化,如果你有一个有效的场景,Color 将受益于低级优化,你可以建议在某些情况下使用 [Intrinsic]它的方法或属性.

You should probably not use [Intrinsic] in your initial proposal. After it passes, you can think about optimization, and if you have a valid scenario when Color will benefit from low level optimizations, you can suggest using [Intrinsic] on some of its methods or properties.

以下是 [Intrinsic] 当前在核心中的使用方式:

Here's how [Intrinsic] is currently used in core:

case WellKnownAttribute::Intrinsic:
    return "System.Runtime.CompilerServices.IntrinsicAttribute";  

  • VM 对其进行解析,并将方法的 IsJitIntrinsic 标志设置为 true (methodtablebuilder.cpp):

  • VM parses it and sets the IsJitIntrinsic flag to true for a method (methodtablebuilder.cpp):

    if (bmtProp->fIsHardwareIntrinsic || (S_OK == GetCustomAttribute(pMethod->GetMethodSignature().GetToken(),
                                                WellKnownAttribute::Intrinsic,
                                                NULL,
                                                NULL)))
    {
        pNewMD->SetIsJitIntrinsic();
    }          
    

  • 这个标志用于在方法属性中设置另一个标志(jitinterface.cpp):

    if (pMD->IsJitIntrinsic())
        result |= CORINFO_FLG_JIT_INTRINSIC;
    

  • 此标志稍后用于过滤掉明显不是内在的方法(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);
    

  • impIntrinsic 然后调用 lookupNamedIntrinsic 来识别(主要是通过名称)真正(不仅仅是可能)应该优化的方法;

  • impIntrinsic then calls lookupNamedIntrinsic to identify (mostly by name) methods that really (not just potentially) should be optimized;

    毕竟importer 可以根据方法进行优化.例如,优化 Enum.HasFlag (importer.cpp):

    after all of that importer can perform optimizations based on method. For example, optimization for 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;
        }
    

  • 免责声明:据我所知,该属性的行为没有在任何地方正确记录,因此可能会发生变化.以上描述仅与master中的代码相关,这部分core正在积极开发中,整个流程可以在以后更改.

    DISCLAIMER: as far as I can tell, the attribute's behaviour is not properly documented anywhere and, thus, is subject for change. The description above is only relevant to code currently in master, this part of core is actively developed and the whole process can be changed in the future.

    以下是基于 github 存储库历史的 [Intrinsic] 的简短时间表:

    Here's a short timeline of [Intrinsic] based on github repository history:

    • 在 2014 年之前的某个时间,[JitIntrisic] 属性作为 System.Numerics 的一部分被引入,目的是支持新的处理器指令(参见 JitIntrinsicAttribute 如何影响代码生成?).

    • At some time before 2014 [JitIntrisic] attribute was introduced as a part of System.Numerics with a goal to support new processor instructions (see How does JitIntrinsicAttribute affect code generation?).

    2016 年 6 月 6 日,Chris McKinsey 提出了一个问题 #5626.当类型相同时,将 enum1.HasFlag(enum2) 优化为内联位测试,无需装箱分配".当时,Enum.HasFlag 有一个众所周知的性能问题(参见 是什么让 Enum.HasFlag 如此慢?).

    On June 6, 2016, Chris McKinsey opened an issue #5626. "Optimize enum1.HasFlag(enum2) into inline bittest without boxing allocations when types are the same". At the time, Enum.HasFlag had a well-known performance issues (see What is it that makes Enum.HasFlag so slow?).

    在解决这个问题时,Andy Ayers 建议引入一种通用机制来引入 JIT 内在函数(问题 #13813:添加更灵活的方法来指定 jit 内在函数)

    While working on the issue Andy Ayers suggested to introduce a universal mechanism to introduce JIT intrinsics (Issue #13813: Add more flexible method for specifying jit instrinsics)

    这导致了两个拉取请求:新的 jit 内在支持引入了[Intrinsic]JIT 的一般机制:优化 Enum.HasFlagEnum.HasFlag 实现了它.我建议通读它们,因为它们对 [Intrinsic] 带来的变化非常有说明.

    This led to two pull requests: New jit intrinsic support introduced the general mechanics for [Intrinsic] and JIT: optimize Enum.HasFlag implemented it for Enum.HasFlag. I suggest going through both of them as they are extremely illustrative on the changes that come with [Intrinsic].

    后来,在讨论将 Vector 类移动到CoreLib 有人建议 [JitIntrinsic] 不在任何地方使用,应该替换/删除:

    Later, during the discussion about moving Vector classes to the CoreLib it was suggested that [JitIntrinsic] isn't used anywhere and should be replaced/removed:

    @jkotas:我们不需要 JitIntrinsicAttribute.据我所知,这个属性是面向未来的,从未用于任何真实的事物.我们应该删除它,并使用 CoreLib 中的 IntrinsicAttribute 代替.

    @jkotas: We should not need the JitIntrinsicAttribute. As far as I know, this attribute was future proofing, never used for anything real. We should delete it, and use the IntrinsicAttribute from CoreLib instead.

    • 很快,[JitIntrinsic] 被删除并替换为 [Intrinsic] (将 JitIntrinsicAttribute 替换为 IntrinsicAttribute).这就是这个属性在 Vector2 中的来源.
      • Promptly, [JitIntrinsic] was removed and replace by [Intrinsic] (Replace JitIntrinsicAttribute with IntrinsicAttribute). That's how this attribute came to be in Vector2.
      • 这篇关于C# 中的 [Intrinsic] 属性有什么作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆