1

安全/安全でない/dll の呼び出し速度を比較する実験として、1 メガバイトの長さの char 配列のすべての位置に沿って 200 バイト配列をカウントする文字一致の unsafe とポインターを使用してテストしています。

コードの最適化をオンにしてリリース モードで実行し、安全でないことを許可し、境界チェックを行いません。long char 配列は、呼び出しのオーバーヘッドへの影響を最小限に抑えるために意図的に使用されます。

私が得る時間は

通常 560 ミリ秒

安全でない 830 ミリ秒

dll 205 ミリ秒

unsafe が遅いのはなぜですか??

    byte[] buffer = new Byte[1000000];
    byte[] check = new Byte[1000];
    [DllImport("sortitdev.dll", CallingConvention=CallingConvention.StdCall)]
  //[DllImport("sortitfast.dll", CallingConvention=CallingConvention.StdCall)]      
  //[DllImport("sortitpellas.dll", CallingConvention=CallingConvention.StdCall)]        
    
    public unsafe static extern void sortitt([MarshalAs(UnmanagedType.LPArray)] byte[] buffer);
    
    public MainForm()
    {
        InitializeComponent();
    }
    
    void Button1Click(object sender, EventArgs e)  // do char array matching
    {
        byte match;
        Random rnd = new Random();
        for(int i=0;i<1000000;i++)
            buffer[i]=(byte)rnd.Next(0,256);
        for(int i=0;i<200;i++)
            check[i]=(byte)rnd.Next(0,256);
        Stopwatch sw = Stopwatch.StartNew();
        int kk=0;
        int jq=0;
        while(kk<999000)
        {
            kk++;
            match=0;
            for(jq=0;jq<199;jq++)
                if(buffer[kk+jq]==check[jq])match++;
            buffer[kk]=match;
        }
        sw.Stop();
        textBox1.Text= sw.Elapsed.TotalMilliseconds.ToString();
        sw.Reset();
        sw.Start();
        unsafe
        {
            fixed (byte* bufptr=&buffer[0] , chckptr=&check[0])
            {
                byte* bufptrC=bufptr;  // modifiable pointer
                byte* chckptrC=chckptr;
                byte* bufhldptr;
                byte* chckhldptr;
                int k=999000;
                int jw=0;
                while(k>0)
                {
                    bufhldptr=bufptrC;
                    match=0;
                    chckhldptr=chckptrC;
                    for(jw=0;jw<199;jw++)
                        if(*bufhldptr++==*chckhldptr++)match++;
                    *bufptrC++=match;
                    k--;
                }
            }
            sw.Stop();
            textBox2.Text= sw.Elapsed.TotalMilliseconds.ToString();
        }
        sw.Reset();
        for(int tt=0;tt<200;tt++) buffer[tt]=(byte)tt;
        
        sw.Start();
        unsafe
        {
            fixed(byte* dadata=&buffer[0])
            {
                sortitt(buffer);
            }
        }
        sw.Stop();
        textBox3.Text= sw.Elapsed.TotalMilliseconds.ToString();
        int kll=(int)buffer[1];
        textBox4.Text= kll.ToString();
    }
}
4

1 に答える 1

0

あなたのコードをチェックしましたが、安全でないコードの方が遅いとは思いませんでした。ただし、安全でないコードを書き直しました(かなり迅速に-再確認します)が、これはあなたにとってはるかに簡単になるはずです:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    byte[] buffer = new byte[1000000];
    byte[] check = new byte[200];

    private unsafe void button1_Click(object sender, EventArgs e)  // do char array matching
    {
        Random rnd = new Random();
        rnd.NextBytes(buffer);
        rnd.NextBytes(check);
        Stopwatch sw = Stopwatch.StartNew();

        byte match = 0;
        int kk = 0;
        int jq = 0;

        while (kk < 999000)
        {
            kk++;
            match = 0;
            for (jq = 0; jq < 199; jq++)
                if (buffer[kk + jq] == check[jq])
                    match++;
            buffer[kk] = match;
        }

        sw.Stop();
        textBox1.Text = sw.Elapsed.TotalMilliseconds.ToString();
        sw.Reset();
        sw.Start();

        fixed (byte* pCheck = check, pBuffer = buffer)
        {
            match = 0;
            kk = 0;
            jq = 0;

            while (kk < 999000)
            {
                kk++;
                match = 0;
                for (jq = 0; jq < 199; jq++)
                    if (pBuffer[kk + jq] == pCheck[jq])
                        match++;
                pBuffer[kk] = match;
            }
        }
        sw.Stop();
        textBox2.Text = sw.Elapsed.TotalMilliseconds.ToString();
    }
}

結果:

管理対象: 404 ミリ秒 非安全: 284 ミリ秒

これは、プロジェクトを右クリックし、デバッガーなしで新しいインスタンスを開始することにより、リリースで実行されました。コードもチェックしたところ、両方の方法で同じ結果が得られました。

于 2013-05-24T18:46:50.657 に答える