web-dev-qa-db-ja.com

配列を単一の値で埋める最速の方法

2D配列に自分が持っている単一の値を入力したいのですが、2D配列の長さが合計200k以上になり、時間の経過とともにこれらの配列が200以上になるように、できるだけ早く実行したいと思います。 。 Buffer.BlockCopyとArray.Copyを調べましたが、どちらもソース/宛先として配列を取り込んでいます。ここで、私が持っている唯一の配列は宛先であり、ソースは単一の値です。

ソースが配列ではなく単一の値である配列を埋める最も速い方法は何ですか?

15
chadb

私が見つけた最速の方法は、ループを通過するたびにコピーサイズが2倍になるArray.Copyを使用します。配列に単一の値を入力する場合でも、値の配列を入力する場合でも、速度は基本的に同じです。

20,000,000の配列項目を使用した私のテストでは、この関数はforループの2倍の速度です。

using System;

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

            if (value.Length >= destinationArray.Length)
            {
                throw new ArgumentException("Length of value array must be less than length of destination");
            }

            // set the initial array value
            Array.Copy(value, destinationArray, value.Length);

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

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

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

私はこれについて http://coding.grax.com/2011/11/initialize-array-to-value-in-c-very.htmlhttp:// coding.grax.com/2014/04/better-array-fill-function.html

9
Grax

関連情報については、 C#のmemsetに相当するものは何ですか? を参照してください。

その質問で述べたように(これの複製にかなり近い)、 アンマネージコード に入りたくない限り、forループが一般的に最適です。

したがって、これはかなり高速である必要があります。

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

パフォーマンスに関連するすべてのものと同様に、何かを機能させてから、ボトルネックが何であるかを測定します。 「対策」を重視。ボトルネックが何であるかを推測しようとすることは、通常、悪い考えです(:

1
jwd

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ループのパフォーマンス比較を確認したいと思います)

1
Ben Voigt