0

オブジェクト相互作用アルゴリズムの記述プロセスを簡素化するある種のフレームワークを作成しようとしています。(1 つのオブジェクト -- 多くのクライアント (アルゴリズム))

  • たとえば、非常に単純なジョブを実行し、ループで条件が満たされるのを待つアルゴリズムを実装したいと考えています。

    public void MakeVerySimpleJob() { }
    
    public void AsyncLoop()
    { // real algorithm can be more complex, but job is always very simple
        while (true)
        {
            MakeVerySimpleJob();
            WakeUpCondition = "As fast as u can!";
            JobComplete.Set();
            WakeUp.WaitOne();
        }
    }
    
    void main()
    {
        Thread MyThread = new Thread(AsyncLoop);
        MyThread.Start();
    
        var w = new System.Diagnostics.Stopwatch(); w.Start();
        for (int i = 0; i < 100000; i++)
        {
            // waitin for thread
            JobComplete.WaitOne();
            // ok we did it
            WakeUpCondition = null;
            WakeUp.Set();
        }
        w.Stop();
    }
    
    AutoResetEvent JobComplete = new AutoResetEvent(false);
    AutoResetEvent WakeUp = new AutoResetEvent(false);
    

    残念ながら、それは約500ms100000 の単純な仕事を消費します。

  • 私の場合、マルチスレッドは受け入れられませんが、ユーザーにこの方法でアルゴリズムを書くことを強制したくありません。

    // invoke it again and again
    public void PseudoAsyncLoop()
    {
        if (CurrentState == 1) 
        {
            MakeVerySimpleJob();
            CurrentState = 2;
            return;
        }
        else is (CurrentState == some_sate)
        {
        }
    }
    
    int CurrentState = 0;
    
  • だから私は見ますEnumerators。列挙子を使用すると、ユーザーは従来のスタイルで独自のアルゴリズムを実装できます。

    public IEnumerable<bool> PseudoAsyncLoop()
    {
        while (true)
        {
            MakeVerySimpleJob();
            WakeUpCondition = "As fast as u can!";
            yield return true;
        }
    }
    
    public string WakeUpCondition { get; private set; }
    
    void main()
    {
        var MyLoop = PseudoAsyncLoop();
        var LoopEnumerator = MyLoop.GetEnumerator();
    
        var w = new System.Diagnostics.Stopwatch(); w.Start();
        for(int i = 0; i < 100000; i ++)
        {
            LoopEnumerator.MoveNext();
            // ok we did it
            WakeUpCondition = null;
        }
        w.Stop();
    }
    

    今では約3ms、素晴らしいです。しかし、私はそれがすべて間違っていると思います...

私の質問は次のとおりです。

  • 私は正しい方向にいますか?
  • プロのプログラマーは、そのような問題をどのように解決するのでしょうか?
  • マルチスレッド版を最適化する方法がいくつかあるのではないでしょうか?
4

1 に答える 1

1

あなたが何をしているのか、またはその理由を完全には理解していませんが、これが実際にコードを表している場合は、-Slim同期プリミティブの 1 つを使用して高速化できます。はありませんAutoResetEventSlimSemaphoreSlimが、代わりに使用できます。

private readonly SemaphoreSlim JobComplete = new SemaphoreSlim(0, 1);
private readonly SemaphoreSlim WakeUp = new SemaphoreSlim(0, 1);

private void AsyncLoop()
{
    while (true)
    {
        MakeVerySimpleJob();
        WakeUpCondition = "As fast as u can!";
        JobComplete.Release();
        WakeUp.Wait();
    }
}

private void main()
{
    Thread MyThread = new Thread(AsyncLoop);
    MyThread.Start();

    for (int i = 0; i < 100000; i++)
    {
        JobComplete.Wait();
        WakeUpCondition = null;
        WakeUp.Release();
    }
}

これにより、私のマシンでの実行が約 5.5 倍速くなりました。

于 2013-01-30T19:29:52.600 に答える