【问题标题】:What is the fastest way to initialize all elements in an array to NaN?将数组中的所有元素初始化为 NaN 的最快方法是什么?
【发布时间】:2011-01-19 04:52:53
【问题描述】:

在 C# .NET 中,将双精度数组初始化为 NaN 的最快方法是什么?

这是我目前如何初始化一个包含许多元素的数组。

int length = array.Length;
for(int i = 0; i < length; i++)
{
    array[i] = double.NaN;
}

有没有更快的方法?

【问题讨论】:

  • 我喜欢 'Enumerable.Repeat(defaulValue, arrayLength).ToArray()'(从 .NET 3.5 开始可用)
  • 如果你在 Linux 上,内存映射 my device driver 会返回以双精度数组形式填充 NaN 的写时复制页面。 O(1) 无论数组大小如何!

标签: c# .net arrays memory-management nan


【解决方案1】:

用 0xff 的字节值填充数组会产生 NaN。试试这个代码,看看你的机器上什么是最快的。顺便说一句,Memset() 并不总是扣篮:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

class Program {
  static void Main(string[] args) {
    var arr = new double[10 * 1024 * 1024];
    for (int loop = 1; loop < 20; ++loop) {
      var sw1 = Stopwatch.StartNew();
      for (int ix = 0; ix < arr.Length; ++ix)
        arr[ix] = double.NaN;
      sw1.Stop();
      var sw2 = Stopwatch.StartNew();
      memset(arr, 0xff, 8 * arr.Length);
      sw2.Stop();
      Console.WriteLine("Loop: {0}, memset: {1}", sw1.ElapsedMilliseconds, sw2.ElapsedMilliseconds);
    }
    Console.ReadLine();
  }
  [DllImport("msvcrt.dll")]
  private static extern void memset(double[] array, int value, int cnt);
}

【讨论】:

  • 真的希望 C# 中有一个内部方法可以发出 initblk 操作码,或者至少是 mscorlib 中的一个静态方法,JIT 知道它总是会处理作为 initblk 指令。
  • 你运行了这段代码吗?不要忘记使用 Release 构建并且不要在调试器中运行。交换这两个部分对我的机器产生了非常有趣的影响。
  • 这是针对我的吗?我只是说initblk 是一个 CIL 操作码,它实际上是 memset,除了它避免了 P/Invoke 并且它可能在 CLR 中进行了大量优化。
  • 除非有一个非常很好的理由进行这种优化,否则我更喜欢原始的for循环,因为它具有更好的可读性、可维护性和健壮性。顺便说一句,使用 memset 不需要固定数组吗?类似GCHandle gch = GCHandle.Alloc(arr, GCHandleType.Pinned); memset(gch.AddrOfPinnedObject(), 0xff, 8 * arr.Length);
  • pinvoke marshaller 自动固定数组。
【解决方案2】:

你可以多线程,但这仍然是一个 O(N) 问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-13
    • 2014-09-10
    • 2021-12-31
    • 2016-12-18
    • 1970-01-01
    • 2015-02-23
    • 2016-12-20
    • 2011-07-23
    相关资源
    最近更新 更多