C# Net,最有效的比较

C# Net,最有效的比较,c#,.net,algorithm,performance,optimization,C#,.net,Algorithm,Performance,Optimization,我有两个由N个对象组成的数组,xs和ys。 这些对象是装箱整数。两个数组中都没有空元素。 1>=N

我有两个由N个对象组成的数组,xs和ys。 这些对象是装箱整数。两个数组中都没有空元素。 1>=N<50

我可以将它们与以下代码进行比较:

for (var i = 0; i < N; i++)
{
    if (!xs[i].Equals(ys[i]))
    {
        return false;
    }
}

return true;
(变量i=0;i { 如果(!xs[i].等于(ys[i])) { 返回false; } } 返回true;
我的问题是:使用.Net JIT或CLR技巧或一些转换,我可以进一步优化此算法吗?

如果这些没有装箱,您还有一些选择,而且这基本上只会开始为较大的阵列付费

正如评论中提到的,您可以使用parallel。但是,plinq和TPL可能不会给您带来这样小的阵列带来任何积极的好处,而且肯定会带来更多的开销

public static unsafe bool UnsafeCompare(int[] ary1, int[] ary2)
{
   fixed (int* pAry1 = ary1, pAry2 = ary2)
   {
      var pLen = pAry1 + ary1.Length;
      for (int* p1 = pAry1, p2 = pAry2; p1 < pLen; p1++, p2++)
         if (*p1 != *p2)
            return false;
   }
   return true;
}
不管怎样,如果你真的在追求业绩,我会拿出你的基准,看看什么对你有用

有趣的是,这是memcmp的源代码(或者足够接近)

结果

--- Standard input ------------------------------------------------------------
| Value    |    Average |    Fastest |    Cycles | Garbage | Test |      Gain |
--- Scale 5 ---------------------------------------------------- Time 0.475 ---
| Unsafe   |  54.271 ns |   0.000 ns |   1.850 K | 0.000 B | Pass |   16.95 % |
| Original |  65.349 ns |   0.000 ns |   1.820 K | 0.000 B | Base |    0.00 % |
| Memcmp   | 143.527 ns |   0.000 ns |   1.977 K | 0.000 B | Pass | -119.63 % |
--- Scale 50 --------------------------------------------------- Time 0.483 ---
| Unsafe   |  78.542 ns |   0.000 ns |   1.936 K | 0.000 B | Pass |   36.69 % |
| Original | 124.064 ns |   0.000 ns |   2.038 K | 0.000 B | Base |    0.00 % |
| Memcmp   | 181.076 ns |   0.000 ns |   2.066 K | 0.000 B | Pass |  -45.95 % |
--- Scale 500 -------------------------------------------------- Time 0.620 ---
| Memcmp   | 445.434 ns | 300.000 ns |   3.044 K | 0.000 B | Pass |   44.14 % |
| Unsafe   | 501.585 ns | 300.000 ns |   3.341 K | 0.000 B | Pass |   37.10 % |
| Original | 797.435 ns | 300.000 ns |   4.291 K | 0.000 B | Base |    0.00 % |
--- Scale 5,000 ------------------------------------------------ Time 2.172 ---
| Memcmp   |   3.519 µs |   2.701 µs |  13.625 K | 0.000 B | Pass |   46.95 % |
| Unsafe   |   5.110 µs |   4.502 µs |  19.084 K | 0.000 B | Pass |   22.96 % |
| Original |   6.633 µs |   5.703 µs |  24.364 K | 0.000 B | Base |    0.00 % |
--- Scale 50,000 ---------------------------------------------- Time 25.561 ---
| Memcmp   |  52.378 µs |  35.422 µs | 180.681 K | 0.000 B | Pass |   34.55 % |
| Unsafe   |  74.634 µs |  49.832 µs | 257.216 K | 0.000 B | Pass |    6.74 % |
| Original |  80.031 µs |  62.740 µs | 274.704 K | 0.000 B | Base |    0.00 % |
--- Scale 500,000 --------------------------------------------- Time 38.306 ---
| Memcmp   | 505.916 µs | 447.289 µs |   1.726 M | 0.000 B | Pass |   37.20 % |
| Unsafe   | 662.644 µs | 590.781 µs |   2.262 M | 0.000 B | Pass |   17.75 % |
| Original | 805.634 µs | 675.736 µs |   2.748 M | 0.000 B | Base |    0.00 % |
-------------------------------------------------------------------------------

1-50整数比较需要的时间可以忽略不计-您确定这确实需要优化吗?如果答案是肯定的,最好的选择可能是在其他地方进行优化,以消除一直进行所有这些比较的需要。这段代码本身可能无法进行太多优化(如果有的话)。不首先装箱也会有所帮助。您可以将其并行化,甚至简化,使其具有稳定的返回时间和足够快的平均计时。类似于布尔逻辑的简化。您可能会对不安全的代码做一些令人讨厌的事情(假设这些装箱整数中没有一个用于锁定或以其他方式导致运行时使用头进行任何簿记,因为它们都应该具有相同的类型指针和实例数据(如果它们相等),但我强烈建议不要这样做。正如@Joey所说,首先避免陷入这种情况是可取的,特别是如果这实际上是您的代码的热门路径。为您添加了一些基准测试,尽管我猜调用memcmp的开销和封送要比Compare慢得多使用普通CLR代码对50个整数进行加密。
memcmp (const PTR str1, const PTR str2, size_t count)
{
  register const unsigned char *s1 = (const unsigned char*)str1;
  register const unsigned char *s2 = (const unsigned char*)str2;

  while (count-- > 0)
    {
      if (*s1++ != *s2++)
      return s1[-1] < s2[-1] ? -1 : 1;
    }
  return 0;
}
   ----------------------------------------------------------------------------
Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------
Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134
----------------------------------------------------------------------------
CPU Name         : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
Description      : Intel64 Family 6 Model 42 Stepping 7
Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3401 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB
----------------------------------------------------------------------------
--- Standard input ------------------------------------------------------------
| Value    |    Average |    Fastest |    Cycles | Garbage | Test |      Gain |
--- Scale 5 ---------------------------------------------------- Time 0.475 ---
| Unsafe   |  54.271 ns |   0.000 ns |   1.850 K | 0.000 B | Pass |   16.95 % |
| Original |  65.349 ns |   0.000 ns |   1.820 K | 0.000 B | Base |    0.00 % |
| Memcmp   | 143.527 ns |   0.000 ns |   1.977 K | 0.000 B | Pass | -119.63 % |
--- Scale 50 --------------------------------------------------- Time 0.483 ---
| Unsafe   |  78.542 ns |   0.000 ns |   1.936 K | 0.000 B | Pass |   36.69 % |
| Original | 124.064 ns |   0.000 ns |   2.038 K | 0.000 B | Base |    0.00 % |
| Memcmp   | 181.076 ns |   0.000 ns |   2.066 K | 0.000 B | Pass |  -45.95 % |
--- Scale 500 -------------------------------------------------- Time 0.620 ---
| Memcmp   | 445.434 ns | 300.000 ns |   3.044 K | 0.000 B | Pass |   44.14 % |
| Unsafe   | 501.585 ns | 300.000 ns |   3.341 K | 0.000 B | Pass |   37.10 % |
| Original | 797.435 ns | 300.000 ns |   4.291 K | 0.000 B | Base |    0.00 % |
--- Scale 5,000 ------------------------------------------------ Time 2.172 ---
| Memcmp   |   3.519 µs |   2.701 µs |  13.625 K | 0.000 B | Pass |   46.95 % |
| Unsafe   |   5.110 µs |   4.502 µs |  19.084 K | 0.000 B | Pass |   22.96 % |
| Original |   6.633 µs |   5.703 µs |  24.364 K | 0.000 B | Base |    0.00 % |
--- Scale 50,000 ---------------------------------------------- Time 25.561 ---
| Memcmp   |  52.378 µs |  35.422 µs | 180.681 K | 0.000 B | Pass |   34.55 % |
| Unsafe   |  74.634 µs |  49.832 µs | 257.216 K | 0.000 B | Pass |    6.74 % |
| Original |  80.031 µs |  62.740 µs | 274.704 K | 0.000 B | Base |    0.00 % |
--- Scale 500,000 --------------------------------------------- Time 38.306 ---
| Memcmp   | 505.916 µs | 447.289 µs |   1.726 M | 0.000 B | Pass |   37.20 % |
| Unsafe   | 662.644 µs | 590.781 µs |   2.262 M | 0.000 B | Pass |   17.75 % |
| Original | 805.634 µs | 675.736 µs |   2.748 M | 0.000 B | Base |    0.00 % |
-------------------------------------------------------------------------------