将数组中的所有元素初始化为 NaN 的最快方法是啥?

Posted

技术标签:

【中文标题】将数组中的所有元素初始化为 NaN 的最快方法是啥?【英文标题】: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) 无论数组大小如何! 【参考方案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) 问题。

【讨论】:

以上是关于将数组中的所有元素初始化为 NaN 的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将数组的所有元素初始化为相同的数字

从 C++ 中的字节数组中提取非零索引的最快方法是啥

将C或C99中的结构数组初始化为所有相同的值[重复]

将现有数组归零的最快方法是啥?

c语言中怎么把一维数组初始化为全零啊,不用循环

查找数组的所有元素是不是不同的最快方法?