0

マシンのすべてのコアを実際に利用していないように見えるマルチスレッド プログラムがあります。これがコードであり、どんな入力も高く評価されます。

メインクラス

public class MainClass{
 public static void main(String [] args){
  Work work=new Work();
  work.doIt();
 }
}

2 番目のクラスはタスクを作成し、それらを ExecutorService に渡します。ここに擬似コードを示します。

public class Work{
 public void doIt() throws InterrputedException, Exception{
  map=get some data and put it in the map;
  ArrayList<Future<Integer>> list=new ArrayList<Future<Integer>>();
  ArrayList<WorkCallable>jobs=new ArrayList<WorkCallable>();
  for each entry in the map;
    jobs.add(new WorkCallable(entry);
  int numCores=Runtime.getRuntime().availableProcessors();
  ExecutorService executor=Executors.newFixedThreadPool(numCores);
  int size=jobs.size();
  for(int i=0;i<size;i++){
    Callable<Integer> worker=jobs.get(i);
    Future<Integer> submit=executor.submit(worker);
    list.add(submit);
  }
  executor.shutdown();
  while(!executor.isTerminated()) {}
  do something with the returned data;
}
}

Callable クラス

public class WorkCallable implements Callable<Integer>{
 @Override
 public Integer call() throws Exception{
   Properties props=new Properties();
   props.put("annotators", "tokenize, ssplit, pos");
   StanfordCoreNLP pipeline=new StanfordCoreNLP(props);
   for(String id:entry.keySet()){
   Annotation document=new Annotation(entry.get(id));
   pipeline.annotate(document);

   process the data;
   return an integer value;
 }
}

問題は、実行中のスレッドの数を確認したところ、ごくわずかしか見つからず、エグゼキュータが理想的なコアを利用していないように見えることです!

説明が明確であることを願っています。

更新

  • 使用されるライブラリは、StanfordCoreNLP パッケージで、Callable オブジェクトに渡されたテキストを documentID とそのコンテンツのマップとして処理します。StanfordCoreNLP ライブラリを含めなくても問題なく動作しているため、データの処理は問題ではありません。言い換えれば、ドキュメントの浅い処理はうまく機能し、すべてのコアを利用します。しかし、このパッケージを含めると、そうではありません。
4

2 に答える 2

1

Windows を使用している場合、JVM は NT カーネルをスケジューリングするスレッドを委任します。POSIX タイプのオペレーティング システムは、OS スレッドを直接 JVM にマップし、協調的にスケジュールします。

ただし、何が起こっても、スレッドがコア/プロセッサ全体に均等に割り当てられることを保証することはできません。4 番目のスレッドを開始すると、OS 上の何かがコア 4 で実行されている可能性があるため、別のコアに向けてスケジュールされる可能性があります。または、スケジューラがそれらを同じコアにスタックすることを決定することもできます。

于 2012-08-18T19:55:38.087 に答える
0

この時点で、提供された情報を使用して、スレッド間に競合があると思われるため、一部のスレッドがブロック/待機している可能性があります。これを確認するには、JVisual VM を使用してスレッド ダンプを取得します (Jconsole もオプションです)。JVisual VM は Java アプリケーションを監視するためのユーティリティであり、JDK に付属しています。以前にそれを使用したことがない場合、これは非常に便利で使いやすいので、それについて学ぶための時間の良い投資になるでしょう.

JVisualVMについてはこちら

  1. JVisual VM Take Thread dump を使用してプログラムに接続します。
  2. その時点でのプログラム内のスレッドの状態を提供します。競合やブロックがある場合は、スレッド ダンプを使用して簡単に見つけることができます。
  3. Web にはスレッド ダンプを理解するためのリソースが多数ありますが、スレッド ダンプで何が起こっているのか分からない場合は、ここに自由に貼り付けてください。

@Markoが指摘したように、エグゼキューターのシャットダウンをより効率的に処理できる可能性があります.ExecutorCompletionServiceは要件に適合し、コードをよりエレガントで読みやすくします。ここで ExecutorCompletionService を確認してください。アイドル状態のコアを見つけたら、ECS を使用するようにリファクタリングできます。

于 2012-08-20T12:57:25.617 に答える