用最快的方法填充数组为单个值

17

我想用一个单一的值填充一个二维数组,但是希望以最快的方式完成,因为这个二维数组的长度将总共达到超过20万,而且随着时间的推移,会有超过200个这样的数组。我研究了Buffer.BlockCopy和Array.Copy,但是它们都将数组作为源/目标,而我只有目标数组,源是一个单一的值。

如何用单一的值填充数组是最快的方法?


1
有一些不同的方法,这个人列出了一些比较常见的方式 -- 他甚至还友善地进行了基准测试: http://www.dotnetperls.com/initialize-array 即使它们是原始类型,将200K个项目保留在内存中也会占用大量内存 -- 你为什么需要所有200K个项目以恒定的时间访问(每个项目)? - debracey
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - user613326
3个回答

13

我找到的最快方法是使用Array.Copy,每次循环时复制大小加倍。无论您用单个值还是数组值填充数组,速度基本相同。

在我的测试中,对于 20,000,000 个数组项,该函数比 for 循环快两倍。

using System;

namespace Extensions
{
    public static class ArrayExtensions
    {
        public static void Fill<T>(this T[] destinationArray, params T[] values)
        {
            if (destinationArray == null)
                throw new ArgumentNullException(nameof(destinationArray));

            Array.Copy(values, destinationArray, Math.Min(values.Length, destinationArray.Length));

            if (values.Length >= destinationArray.Length)
                return;

            int arrayToFillHalfLength = destinationArray.Length / 2;
            int copyLength;

            for (copyLength = values.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
            {
                Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
            }

            Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
        }
    }
}

我在https://grax32.com/2011/11/initialize-array-to-value-in-c-very.htmlhttps://grax32.com/2014/04/better-array-fill-function.html上写了一篇博客。

2
我需要填充一个 [,] 数组,所以我复制了你的 Fill 扩展方法,并将签名更改为public static void Fill<T>(this T[,] destinationArray, T[,] value)然后像这样调用它:myLargeArray.Fill(new [,] { { double.NaN }, { double.NaN }});它完美地工作了。谢谢! - Kabua

2

有关相关信息,请参见C#中memset的等效物是什么?

如上述问题所提到的(非常接近重复此问题),使用for循环通常是最好的选择,除非您想涉及非托管代码

因此,这应该非常快:

int[] arr = new int[MAX_ELEMENTS];
for (int i = 0; i < arr.Length; ++i)
{
    array[i] = MY_VALUE;
}

对于与性能相关的所有事情,先让某些东西工作,然后测量瓶颈所在。强调“测量”。试图猜测瓶颈通常是一个坏主意(:


1

Array.Copy 比 for 循环更容易优化,因此请使用它。

void FillArray<T>(T[] arr, T fillValue)
{
    int i = 0;
    if (arr.Length > 16) {
    {
        do {
            array[i++] = fillValue;
        } while (i < arr.Length)
        while (i + 16 < arr.Length) {
            Array.Copy(arr, 0, arr, i, 16);
            i = i + 16;
        }
    }
    while (i < arr.Length)
    {
        array[i++] = fillValue;
    }
}

我很想看到这种方法和朴素的for循环在不同类型和数组大小下的性能比较。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接