質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • Java

    14093questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Windows 10

    989questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

  • NetBeans

    172questions

    NetBeansは Java、HTML5、PHP、C/C++のアプリケーションのフレームワーク、もしくは統合開発環境(NetBeans IDE)の両方を指します

  • 並列処理

    39questions

    複数の計算が同時に実行される手法

Javaでの並列計算でCPUの稼働率が低くなってしまう

解決済

回答 2

投稿

  • 評価
  • クリップ 3
  • VIEW 861

syncret

score 5

前提・実現したいこと

Javaで並列数値計算を行うプログラムを書いています。
反復的に同じ量を計算するのですが、各反復の結果に応じてパラメータを変化させ、それを使ってまた同じ計算をするというプログラムです。
並列計算は、その一回一回の計算を行う時に毎回行っており、各スレッドで別々の数値データを読み込んで計算を行います。

これをワークステーション(詳細は下記)でCPU稼働率100%弱で効率的に計算したいです。

発生している問題・エラーメッセージ

100スレッド並列で計算するプログラムになっているのですが、実行後しばらくは
想定通り稼働率100%で動いてくれるのですが、途中からCPUが平均して10%程度しか利用されません。
尚、1回の反復で20分かかる程度の重さの計算です。また並列するスレッドの数を30程度やそれ以下に減らしても同様です。

該当のソースコード

//重要でない部分を簡略化したコードでお示ししています
public class Main{
     static int threadNum = 100;

     public static void main(String[] args){
          ...
          // iterationしてパラメータxを更新する
          for(int i=0;i<iterMax;i++){
               x = iterete(x);
          }
     }


     public static double iterate(double x){

          double xnew = 0;//update後のパラメータ
          List<int[]> sampleSet = new ArrayList<int[]>();
          ...//sampleSet.get(i)はi番目のスレッドが担当するデータ番号の組が入るようにする。sampleSet.size()=threadNum
  
          //multi threadで計算する部分
          ExecutorService threadpool = Executors.newCachedThreadPool();
          List<Future<Double>> futures = new ArrayList<>(); 
          List<Double> result = new ArrayList<Double>();
          for(int i = 0; i < threadNum;i++){
              futures.add(threadpool.submit(new EachThreadCal(sampleSet.get(i),x)));
          }

          try{
               threadpool.shutdown();
               for(int i = 0; i < threadNum; i++){
                    //結果の取得
                    result.add(futures.get(i).get());
               }

               for(Double s: result){
                    //結果の表示
                    System.out.println(s);
                    xnew += s;//パラメータは計算結果の平均値、というプログラムなので全部足して後で割ることにしています
               }

          }catch(InterruptedException | ExecutionException e){
               e.printStackTrace();
               threadpool.shutdown();
          }

        return xnew/sampleNum;

     }

}

class EachThreadCal implements Callable<Double>{
    private int[] samples;//担当するサンプルの番号の配列が入る
    private double x;//前回のパラメータの値が入る

    public EachThreadCal(int[] samples,double x){
        this.samples = samples;
        this.x = x;
    }

    @Override
    public Double call() throws Exception {//個々の計算 パラメータxを更新してxnewを計算する部分
        double xnew = 0;
        for(int i=0;i<samples.length;i++){//担当するサンプルデータに対してパラメータxnewを計算して全部足す
             xnew += ...//samples.get(i)番目のデータ(外部から読み込む)とパラメータxを使ってxnew を計算する
        }

        return xnew;
    }
}

試したこと

スレッドの数threadNumを変えて試してみましたが改善しませんでした。
WindowsのタスクマネージャからCPU優先度を最大にしても改善しませんでした。
CPU以外のリソースも不足しているわけではないようです。

補足情報(言語/FW/ツール等のバージョンなど)

【環境】
Product Version: NetBeans IDE 8.1 (Build 201510222201)
Java: 1.8.0_91; Java HotSpot(TM) 64-Bit Server VM 25.91-b14
Runtime: Java(TM) SE Runtime Environment 1.8.0_91-b14
System: Windows 10 version 10.0 running on amd64; MS932; ja_JP (nb)
Processor: Intel(R) Xeon(R) CPU E5-2687W v4 @ 3.00 GHz, 3001Mhz, 12 core, 24 logical processor × 2
メモリ:128 GB

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • syncret

    2017/10/03 13:04

    yohhoy様 ご教示いただきありがとうございます。各スレッドは同じステップ数のシミュレーションを行っているだけなので多少のばらつきはありますがほぼ一定と考えてよろしいかと思います。引き続き、よろしくお願いいたします。

    キャンセル

  • yohhoy

    2017/10/03 13:06 編集

    newFixedThreadPool(n)でn=24または48とすると、CPU利用率遷移と総処理時間は変わりますか?

    キャンセル

  • Stripe

    2017/10/03 21:33

    「このメソッドは、以前に送信されたタスクが実行を完了するのを待機しません。これを実行するには、awaitTerminationを使ってください。」と、shutdown()のリファレンスに書いてますけどね。

    キャンセル

回答 2

checkベストアンサー

+1

回答ではありませんが。

1.Java起動オプションを教えてもらえますか?特にXmx, Xms。
→物理メモリが大きくてもXmxが無指定の場合、物理メモリの1/4しか使用されません。
→Xmsが小さい場合、ヒープ拡張が多発します。

2.Runtime.getRuntime().availableProcessors() の実行結果が全CPU全コア数の合計と一致しますか?(HyperThreadingがONであればそれを含めて)
→「logical processor × 2」とありますが、デュアルCPUのことでしょうか?
→デュアルCPUの場合プロセッサ間通信がボトルネックになることがあります。

3.CPUやマザーボードの温度を測ることはできますか? Thermal Throttling に触れていませんか?
→Thermal Throttling を超えた場合、一時的にクロック数を落とされてしまいます。
こちらのようなツールをインストールすることは可能ですか?

4.以下のプログラムを同じJava起動オプションで実行した場合、CPU使用率が100%になりますか?

public static void main(String... args){
  int vcpu = Runtime.getRuntime().availableProcessors();
  System.out.println("vCPU: " + vcpu);
  ExecutorService service = Executors.newFixedThreadPool(vcpu);
  List<Future<Double>> futures = new ArrayList<>();
  for(int i = 0; i < 100000; i++){
    futures.add(service.submit(() -> IntStream.range(1, 100000).mapToDouble(Math::sin).sum()));
  }
  service.shutdown();
  System.out.println("dummy: " + futures.stream().mapToDouble(future -> {
    try{ return future.get(); }catch(Exception e){ return 0.0d; }
  }).sum());
}

■余談
「100スレッド並列で計算するプログラムになっているのですが」とありますが、100スレッド並列で計算しているわけではありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/05 10:41 編集

    newCachedThreadPool()はワーカスレッド数上限無しのThreadPoolExecutorを返すため、結果的に 100タスク投入=100スレッド並列計算 になっているかと思います。
    http://d.hatena.ne.jp/masa_to/20110306/1299423229

    キャンセル

  • 2017/10/05 12:15

    すみません。そのとおりですね。
    正しくは「100スレッドが同時に計算処理されるわけではありません」ですね。

    キャンセル

  • 2017/10/11 20:18

    mosa様 ご丁寧に検討下さりありがとうございました。指摘いただいた点を調べたところどうやらXmxの指定が小さすぎたことが原因のようで、無事ちゃんと動くようになりました。この度はありがとうございました。

    キャンセル

0

newCachedThreadPool は可変個スレッドなので、コンテキストスイッチにコストが掛かってるんじゃないかと思います。newFixedThreadPool(threadNum) だとどうなりますか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/29 22:17

    コンテキストスイッチのコストでCPU使用率が上がることはあれど、下がることはないのでは?

    キャンセル

  • 2017/09/30 00:05

    CPU の飽和状態を見ながらスレッド数を調整するので期待以上にスレッドが溢れコンテキストスイッチ時のオーバーヘッドの方が大きくなり CPU が遊んでるんじゃないかと予想していいます。

    キャンセル

  • 2017/09/30 00:34

    CPU使用率を計測する際、コンテキストスイッチのオーバーヘッド分は計測されないんですか? 今回、CPU使用率が100%付近から10%付近まで落ちるそうですが、この時90%がコンテキストスイッチのオーバーヘッドであると言うことですか?

    キャンセル

  • 2017/09/30 20:51

    いま気付きましたが、↑に書かれている shutdown が原因ぽいですね。一番最初に終了したタスクが shutdown を実行する事で次のアサインがされてないのでしょうね。

    キャンセル

  • 2017/10/02 14:56

    mattn様 Stripe様
    ご検討下さりありがとうございます。newFixedThreadPool(threadNum)も試してみましたが、解決しないようです。shutdownについては上記に追記いたしました。引き続き、よろしくお願いいたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    重複しない乱数の発生方法(Collections.shuffleの処理速度)

    リストをシャッフルする Collections.shuffle というメソッドがありますが、かなり大量のリスト(1000以上)をシャッフルするとなるとやはり処理時間がかかるでし

  • 解決済

    メソッド作成時の不要な変数とは。

    public class MesoddoA { double kakezan(int a, int b, int c){ int d = a * b * c; return 

  • 解決済

    Javaでそれぞれの英単語のTFIDFの求め方がわかりません。

    Javaを独学で勉強中のJava初心者です。Javaで英文テキストファイルを読み込みそれぞれの英単語のTFIDFを表示させるプログラムを作りたいのですが、どうしてもうまくできません

  • 解決済

    s2chronosにおけるスレッド制御について

    s2chronosですが、以下のようにプログラム例にならって書いても、 CloneTaskアノテーションで指定した数だけスレッドが走ってしまいます。 全くThreadPoolS

  • 解決済

    ファイルの書き出し

    前提・実現したいこと csvファイルから読み込んだものをソートして別のcsvファイルに書き出しを行いたいです。 発生している問題・エラーメッセージ 書き出しが行われない。

  • 解決済

    配列の分割方法について

    問題点 以下のような配列 String str[]={"ABC","DEFG","HI","KLM"} というのがあったとして、これを new_str[]={"A","B",・・・

  • 解決済

    javaのリフレクションで、フィールドの型と名前と値を取得したい

    前提・実現したいこと 標準入力で指定したクラスのフィールドの型と名前と値を取得したいです。 以下のようなエラーがでて、フィールドの値が取得できないです。 どうしたらいいのでしょ

  • 解決済

    java 配列の出力

    3、6種類のアルファベット "u,d,c,s,t,b" から成るn文字の文字列のうち、"uud"という並びが含まれる文字列を全て列挙するプログラムを作成してください この問題が

同じタグがついた質問を見る

  • Java

    14093questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Windows 10

    989questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

  • NetBeans

    172questions

    NetBeansは Java、HTML5、PHP、C/C++のアプリケーションのフレームワーク、もしくは統合開発環境(NetBeans IDE)の両方を指します

  • 並列処理

    39questions

    複数の計算が同時に実行される手法