Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在Array.AsSpan()上循环更快?_C#_Arrays_Performance_Benchmarking - Fatal编程技术网

C# 为什么在Array.AsSpan()上循环更快?

C# 为什么在Array.AsSpan()上循环更快?,c#,arrays,performance,benchmarking,C#,Arrays,Performance,Benchmarking,为什么在array.AsSpan()上循环要比直接在源数组上循环快 | Method | Mean | Error | StdDev | |--------------- |---------:|---------:|---------:| | ArrayRefIndex | 661.9 us | 12.95 us | 15.42 us | | ArraySpanIndex | 640.4 us | 4.08 us | 3.82 us | public结

为什么在
array.AsSpan()上循环要比直接在源数组上循环快

|         Method |     Mean |    Error |   StdDev |
|--------------- |---------:|---------:|---------:|
|  ArrayRefIndex | 661.9 us | 12.95 us | 15.42 us |
| ArraySpanIndex | 640.4 us |  4.08 us |  3.82 us |
public结构16
{
公共INTA;
公共int B;
公共INTC;
公共int D;
}
公共课程
{
公共常数整数计数=100000;
静态void Main(字符串[]参数)
{
var summary=BenchmarkRunner.Run();
}
[基准]
公共int ArrayRefIndex()
{
Struct16[]myArray=newstruct16[COUNT];
整数和=0;
for(int i=0;i
简短回答

Span保证了编译器可以对CLI指令进行优化的安全性

长答案

如果在反汇编(调试->Windows->反汇编)中打开提供的代码,您将在ArrayRefIndex()中找到以下内容

ref Struct16 value=ref myArray[i];
00007FFC3E860DCC movsxd r8,ecx
00007FFC3E860DCF shl r8,4

00007FFC3E860DD3 lea r8,[rax+r8+10h]//真可爱。“span”标记显示为别名“html”,在保存问题时将其替换为,该替换在此处不适用。您可以增加这些方法中的循环数量吗?就像扔另一个循环0。。。它周围有1000多个。我觉得微秒的范围不够有意义。在那里你会找到一些深刻的解释。Span不进行边界检查的事实可能是“performancegain”。@Joey是真的,但这两种方法都有“很多”开销,比如数组创建和AsSpan调用。最好是将这些内容完全移出测试,只测试实际的循环。@CSharpie:哦,你说得对,我错过了他们在基准方法中创建数组的机会。阿斯潘没事,不过,你不能做任何不同。现在我得到了166对138µs的数据,支持Span now。Span原则上只是指向数组的指针,它不能比数组本身更连续。我看不出这有什么好处。
public struct Struct16
{
    public int A;
    public int B;
    public int C;
    public int D;
}

public class Program
{
    public const int COUNT = 100000;
    
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Program>();
    }

    [Benchmark]
    public int ArrayRefIndex()
    {
        Struct16[] myArray = new Struct16[COUNT];
        int sum = 0;
        for (int i = 0; i < myArray.Length; i++)
        {
            ref Struct16 value = ref myArray[i];
            sum += value.A = value.A + value.B + value.C + value.D;
        }
        return sum;
    }

    [Benchmark]
    public int ArraySpanIndex()
    {
        Struct16[] myArray = new Struct16[COUNT];
        int sum = 0;
        Span<Struct16> span = myArray.AsSpan();
        for (int i = 0; i < span.Length; i++)
        {
            ref Struct16 value = ref span[i];
            sum += value.A = value.A + value.B + value.C + value.D;
        }
        return sum;
    }
}
ref Struct16 value = ref myArray[i];
00007FFC3E860DCC  movsxd      r8,ecx  
00007FFC3E860DCF  shl         r8,4  
00007FFC3E860DD3  lea         r8,[rax+r8+10h] // <----
ref Struct16 value = ref span[i];
00007FFC3E8613FA  movsxd      r8,ecx  
00007FFC3E8613FD  shl         r8,4  
00007FFC3E861401  add         r8,rax  // <----