清除數組數據的正確姿式

由於某段程序的須要,我須要將一個long數組,不斷地填充數據,而後用完了以後又要清空裏面的數據,以便再次填充。因爲調用及其頻繁,因此我很在乎清除數據的性能。windows

測試代碼

如下程序都是基於下面的測試代碼完成:數組

using System;
using System.Diagnostics;
using System.Numerics;

namespace FillTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var array = new long[2515];
            var Empty = new long[2515];

            Do(() =>
            {
                Fill(array, 0L);
            }
            , "Fill");

            Console.ReadLine();
        }

        static void Fill(long[] array,long value)
        {
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = value;
            }
        }

        static void Do(Action action,string name)
        {
            var wathch = Stopwatch.StartNew();
            for (int i = 0; i < 1000000; i++)
            {
                action();
            }
            
            wathch.Stop();
            Console.WriteLine(name + " 耗時:" + wathch.Elapsed.ToString());
        }
    }
}

一般的,最簡單的辦法就像上面的代碼那樣,來個循環就能夠了。性能

在個人機器中(i5 6500@3.2GHz 、16GB、 Release、 .net core 二、 windows 10),Fill版本消耗1.3秒。測試

雙指令

我不確認此代碼執行時是否使用了SIMD指令,因此我又編寫了一個版本:優化

        static void Fill2(long[] array,long value)
        {
            var i = 0;
            var end = array.Length - 1;
            while (i < end)
            {
                array[i] = value;
                array[i + 1] = value;
                i += 2;
            }

            if((array.Length % 2) == 1){
                array[array.Length - 1] = value;
            }
        }

我竟然發現,僅僅消耗了1.0秒,難道.net默認不會優化這個代碼?spa

Array.Fill

有人會問,你爲何不調用Array自帶的Fill方法呢?我嘗試調用了,遺憾的是,同樣是1.3秒,和個人第一個版本系統。看樣子寫核心代碼的人偷懶了。哈哈.net

CopyTo

網上其實可以查到一些討巧的手法,例如使用一個靜態的數組,內部都是0,當須要填充某個數據時,將這個靜態數組複製到你的數組同樣起到賦值的做用。例如:pwa

Empty.CopyTo(array, 0);

這個版本居然直接達到 0.56秒,幾乎翻兩倍,的確是個好辦法。code

SIMD

在我認爲CopyTo是最快的方法時,我忽然感受個人第二個實現,是否是沒有真正用到SIMD,由於個人印象中,SIMD是很是很是快的,應該不止上升那麼一點點。對象

因此我搬出了Vector對象,我是這麼幹的。

        static void Fill3(long[] array,long value)
        {
            Vector<long> v = new Vector<long>(value);
            var i = 0;
            var end = array.Length - 3;

            while (i < end)
            {
                v.CopyTo(array, i);
                i += 4;
            }

            if ((array.Length % 4) == 3)
            {
                array[array.Length - 3] = value;
                array[array.Length - 2] = value;
                array[array.Length - 1] = value;
            }else if ((array.Length % 4) == 2)
            {
                array[array.Length - 2] = value;
                array[array.Length - 1] = value;
            }
            else if ((array.Length % 4) == 1)
            {
                array[array.Length - 1] = value;
            }
        }

速度提升到 0.36秒。

因此性能無界限,有沒有更快的辦法呢?

後續

一些其餘的嘗試,但都不理想。

        static unsafe void Fill4(long[] array, long value)
        {
            fixed (Int64* destinationBase = array)
            {
                for (int g = 0; g < array.Length; g++)
                {
                    destinationBase[g] = value;
                }
            }
        }//1.2秒

        static void Fill5(long[] array, long value)
        {
            Vector<long> v = new Vector<long>(value);
            var i = 0;
            var end = array.Length - 3;

            while (i < end)
            {
                array[i + 3] = array[i + 2] =array[i + 1] = array[i] = value;
                //array[i+1] = value;
                //array[i+2] = value;
                //array[i+3] = value;

                i += 4;
            }

            if ((array.Length % 4) == 3)
            {
                array[array.Length - 3] = value;
                array[array.Length - 2] = value;
                array[array.Length - 1] = value;
            }
            else if ((array.Length % 4) == 2)
            {
                array[array.Length - 2] = value;
                array[array.Length - 1] = value;
            }
            else if ((array.Length % 4) == 1)
            {
                array[array.Length - 1] = value;
            }
        } //0.8秒
相關文章
相關標籤/搜索