2

WindowsXPで実行されている固定容量チャネルを介して通信するJavaスレッド(フローベースプログラミング)のネットワークがあります。「グリーン」スレッド(プリエンプティブではない)の経験に基づいて私たちが期待したのは、チャネルが大きくなった場合、スレッドがコンテキストを切り替える頻度が少なくなる(したがってCPU時間が短縮される)ということです。ただし、チャネルサイズを増やしても、実行時間に違いはないことがわかりました。起こっているように見えるのは、チャネルがいっぱいまたは空ではない場合でも(つまり、スレッドを一時停止する必要がない場合でも)Javaがスレッドを切り替えることを決定することです。これは、明らかな利点がないためにCPU時間を消費します。また、スレッドの優先順位を変更しても、目に見える違いはありません。

私の質問は、不要なコンテキストスイッチを作成しないようにJavaを説得する方法があるかどうかですが、スレッドを切り替えることが本当に必要になるまで切り替えを延期します-Javaのディスパッチングロジックを変更する方法はありますか?それとも、私が注意を払っていなかった何かに反応しているのでしょうか?!または、他の非同期メカニズム、たとえばスレッドファクトリ、Runnable(s)、デーモン(!)もあります。これまでのところ、私の特派員の誰も答えを思い付いていないので、答えは自明ではないようです(最近の2人のCS教授を含む)。あるいは、私がそれを知らないことを人々が想像できないほど明白な何かを見逃しているのかもしれません...

ここに送信コードと受信コードを追加しました-あまりエレガントではありませんが、機能しているようです...;-)疑問に思われるかもしれませんが、「送信」のgoLockロジックが問題の原因である可能性があると思いましたが、削除しました一時的に何の違いもありませんでした。送受信用のコードを追加しました...

public synchronized Packet receive() {

if (isDrained()) {
    return null;
}

while (isEmpty()) {


  try {
    wait();
  } catch (InterruptedException e) {        
    close();
    return null;

  }     

  if (isDrained()) {

    return null;
  }

}

if (isDrained()) {     
  return null;
}
if (isFull()) {
  notifyAll(); // notify other components waiting to send
}
Packet packet = array[receivePtr];
array[receivePtr] = null;
receivePtr = (receivePtr + 1) % array.length;
//notifyAll(); // only needed if it was full
usedSlots--;

packet.setOwner(receiver);

if (null == packet.getContent()) {
  traceFuncs("Received null packet");
} else {
  traceFuncs("Received: " + packet.toString());
}


return packet;

}

synchronized boolean send(final Packet packet, final OutputPort op) {

sender = op.sender;

if (isClosed()) {

  return false;
}

while (isFull()) {


  try {
    wait();
  } catch (InterruptedException e) {        
    indicateOneSenderClosed();       
    return false;
  }

  sender = op.sender;

}

if (isClosed()) {

  return false;
}

try {
  receiver.goLock.lockInterruptibly();
} catch (InterruptedException ex) {
  return false;
}

try {
  packet.clearOwner();
  array[sendPtr] = packet;
  sendPtr = (sendPtr + 1) % array.length;
  usedSlots++; // move this to here
  if (receiver.getStatus() == StatusValues.DORMANT || receiver.getStatus() == StatusValues.NOT_STARTED) {
    receiver.activate(); // start or wake up if necessary
  } else {
    notifyAll(); // notify receiver
    // other components waiting to send to this connection may also get
    // notified,
    // but this is handled by while statement 
  }

  sender = null;
  Component.network.active = true;
} finally {
  receiver.goLock.unlock();

}
return true;

}


質問してくれてありがとう!私はSunフォーラムで同じ質問について話し合っていますが、これがそのフォーラムでの最後の投稿です。

現時点での最善の推測は、この効果はWindowsのスケジューリングロジックに起因するということです。

Microsoftは、UMSを導入しているため、この領域を改善する必要があることを認めているようです。「UMSは、マルチプロセッサまたはマルチコアシステムで多数のスレッドを同時に効率的に実行する必要がある高性能要件のあるアプリケーションに推奨されます。...UMSが利用可能です。 64ビットバージョンのWindows7およびWindowsServer2008 R2以降。この機能は、32ビットバージョンのWindowsでは使用できません。」うまくいけば、Javaはいくつかの後のリリースでUMSを利用するでしょう。

ご協力いただきありがとうございます!

4

3 に答える 3

4

グリーンスレッドはなくなりました(Solarisはまだサポートしているかもしれませんが、私はそれを疑っています)。さらに、Javaはスレッドを切り替えませんが、OSはそれを行います。Javaが行う唯一のことは、OSに信号を送ることであり、OS関数を使用してスレッドがアイドル/待機/ブロックしていることを通知します。したがって、プログラムが同期ポイントに到達した場合、Thread.wait / sleepを実行すると、CPUが不要になったことを通知します。

その上、OSはタイムスライスを維持し、他のスレッドがCPUを待機している場合でも、スレッドからCPUを削除します。

ここでさらにコードを公開できますか?

于 2009-11-19T01:15:32.343 に答える
1

私は少し恥ずかしいです-今日の午後、私が心配していたネットワークは、2つのプロセスと2つのプロセスしかなかったので、単純すぎるのではないかと突然思い浮かびました。そのため、Windowsはプロセッサのバランスを保つために一生懸命努力していた可能性があります。それで、Windowsにたくさんのプロセスを与えたらどうなるのだろうと思いました。

2つのネットワークを設定しました。

a)50コンポーネントを生成します50コンポーネントを破棄します-つまり、高度に並列化されたネットワーク-合計で100スレッドになります

b)50コンポーネントを生成します1コンポーネントを破棄します-つまり、高度に「ファンネル化された」ネットワーク-51スレッドになります

それぞれを接続容量10で6回、接続容量100で6回実行しました。1回の実行で合計50 * 20,000の情報パケット、合計1,000,000パケットが生成され、約1分間実行されました。

4つのケースの平均は次のとおりです。a)接続容量が10〜59.151秒の場合。a)接続容量が100〜52.008秒の場合。

b)接続容量が10〜76.745秒の場合。b)接続容量が100〜60.667秒の場合。

したがって、接続容量が違いを生むように見えます!そして、JavaFBPのパフォーマンスはかなり良いようです...少し急いでいることをお詫びします-しかし、マルチコアマシンでのマルチスレッドについてもう少し深く考えさせられたのかもしれません... ;-)

改めてお詫び申し上げます。このトピックについての考えを提供してくれたすべての人に感謝します。

于 2009-12-02T15:26:55.423 に答える
0

申し訳ありませんが、これが完全に偽物である場合、Java1.1以降のJavaはグリーンスレッドを実行しないと確信しています。少なくともウィキペディアもそう言っています。

これにより、優先順位の使用が制限されますが、ほとんどの場合、目に見えるパフォーマンスの向上も達成できませんでした。

于 2009-11-19T00:27:28.733 に答える