2016-05-26 17 views
0

私は人生の多くのスレッド、1セル= 1スレッド、それはスレッド間の同期を必要としないので、他のスレッドが前の状態を読み終わらない前に新しい状態を計算し始めません。ここに私のコードは非常に遅い同期

 public class Cell extends Processor{ 
      private static int count = 0; 
      private static Semaphore waitForAll = new Semaphore(0); 
      private static Semaphore waiter = new Semaphore(0); 
      private IntField isDead; 
      public Cell(int n) 
      { 
       super(n); 
       count ++; 
      } 
      public void initialize() 
      { 
       this.algorithmName = Cell.class.getSimpleName(); 
       isDead = new IntField(0); 
       this.addField(isDead, "state"); 
      } 
      public synchronized void step() 
      { 
       int size = neighbours.size(); 
       IntField[] states = new IntField[size]; 
       int readElementValue = 0; 
       IntField readElement; 
       sendAll(new IntField(isDead.getDist())); 
       Cell.waitForAll.release(); 
    //here wait untill all other threads finish reading 
        while (Cell.waitForAll.availablePermits() != Cell.count) { 
        } 
    //here release semaphore neader lower 
       Cell.waiter.release(); 
       for (int i = 0; i < neighbours.size(); i++) { 
        readElement = (IntField) reciveMessage(neighbours.get(i)); 
        states[i] = (IntField) reciveMessage(neighbours.get(i)); 
       } 
       int alive = 0; 
       int dead = 0; 
       for(IntField ii: states) 
       { 
        if(ii.getDist() == 1) 
         alive++; 
        else 
         dead++; 
       } 
       if(isDead.getDist() == 0) 
       { 
        if(alive == 3) 
         isDead.setValue(1); 
        else 
         ; 
       } 
       else 
       { 
        if(alive == 3 || alive == 2) 
         ; 
        else 
         isDead.setValue(0); 
       } 
       try { 
        while(Cell.waiter.availablePermits() != Cell.count) 
        { 
         ; 
         //if every thread finished reading we can acquire this semaphore 
        } 
        Cell.waitForAll.acquire(); 
        while(Cell.waitForAll.availablePermits() != 0) 
         ; 
//here we make sure every thread ends step in same moment 
        Cell.waiter.acquire(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 

あるプロセッサ クラスはthreadを拡張し、私はそれにスイッチを入れた場合runメソッドでstep()メソッドを呼び出します。それは細胞の少量のためにうまく動作しますが、私はabou 36細胞を実行すると、それは非常に遅くなり始めます、どのように私の同期を修復することができますので、woudl高速ですか?

+0

マルチスレッドは、個人的な実験を除いて、この種のことを達成するための良い方法ではありません。ご存知のように、スレッドオーバーヘッドのためにパフォーマンスが恐ろしくなる可能性があります。一方、古いボード全体から新しい状態を計算するシングルスレッドソリューションは、よりうまくいくかもしれません。 – hexafraction

+0

はい、これは個人的な実験のためですが、スレッドは36個しかなく、計算が非常に単純です。なぜ私はそれほど驚いていますか?確かに、2つのセマフォ – whd

+0

1つのセルに1つのスレッドがある場合、なぜインスタンスメソッドCell.step()を同期する必要がありますか?なぜ、複数のスレッドが同じ 'Cell'でこのメソッドへのアクセスを争う必要があるのでしょうか? –

答えて

1

多くのスレッドを使用すると非常に効率的ではありませんが、36がそれほど多くなく、「非常に遅い」との違いを生み出すことが期待されます。問題はあなたの戦略に内在している可能性が高いと思います。特に、私はこのビジー待機には問題がある疑いがある:あなたが何度も何度も条件をテストしてCPUを占有しているため

Cell.waitForAll.release(); 
//here wait untill all other threads finish reading 
while (Cell.waitForAll.availablePermits() != Cell.count) { 
} 

ビジー待機は常にパフォーマンスの問題です。このビジー・ウェイトは、同期オブジェクトの状態をテストする必要があるため、ほとんどの場合よりも悪化します。これは、余分なオーバーヘッドが発生するだけでなく、スレッド間に余分な干渉が発生します。

ビジー待機の代わりに、条件が満たされるまでスレッドを実行を中断させるさまざまな方法の1つを使用します。あなたが実際に行ったことは、貧しい人々のバージョンCyclicBarrierが作成されているようですので、代わりにCyclicBarrierを使用することを検討してください。また、これは学習の練習であるため、Object.wait(),Object.notify()、およびObject.notifyAll() - Javaの組み込み条件変数実装を使用する方法を学ぶことでメリットが得られます。

セマフォを使用することを強くお勧めする場合は、ビジー待機なしで実行できると思います。セマフォを使用するための鍵は、利用可能な許可の数ではなく、スレッドが進めることができることを示すセマフォ(まったく)を取得できることです。指定されたポイントで指定されたセマフォを待機しているスレッドの数を追跡する別の変数を保持している場合、そのポイントに達する各スレッドは、他のすべてのスレッドを解放するかどうかを決定し、セマフォを取得する。

+0

私のために学ぶことがたくさんあるように見えます。 – whd