Previous ToC Next

17. FDPS を Crystal から使う

赤木 :というわけで FDPS を Crystal のプログラムから使う話ね。

学生C:一応読者のために FDPS とは何かってのをちょっと。

赤木 :FDPS は、作者のグルー プで開発・公開している、「大規模高性能粒子法プログラム開発のためのフレー ムワーク」というものね。どういう考え方かというと、

つまり、前章で書いたような

をやってくれるものなの。

学生C:MPI による並列化をやってくれるって、どういうことですか? あれだって自分がどの粒子をもってるかとか意識して、相互作用計算とか は自分のとこにない必要なデータはもらってきてとかしないといけないし、 もらってくるっていっても実際にはデータもってるほうが送って、それをこち らが受け取るしで滅茶苦茶面倒くさいじゃないですか?

赤木 :だから、そのへん全部 FDPS の関数がやってくれるわけ。ツリーコー ドで、相互作用計算ややこしいけど、関数としては

    get_tree_acc
を呼んだらあと全部やってくれたじゃない?そういう感じ。

学生C:でも、こちらで粒子クラスとか相互作用関数とか定義するわけでです よね、、、Crystal ならもちろん粒子クラスを渡されたところでコンパイラが なんかするからそれでいいですが、 C だとそんなのできないじゃないですか?

赤木 :まあ C でもできなくはなくて、例えばこちらで定義した粒子クラスを 読み込んでコンパイルするソースプログラムライブラリにすれば いいんだけど、でもそうすると、2種類の粒子を作るとかだとちゃんと違う名 前の関数を生成しないといけないし、ちょっと面倒だしメンテナンスも大変か なあ。というわけで、 FDPS では C++ 使ってるの。C++ では、template とい う機能でクラスを渡すことができるの。 FDPS のサンプルプログラム の例だすわね。

  template<class Tpsys>
  void kick(Tpsys & system,
            const PS::F64 dt) {
      PS::S32 n = system.getNumberOfParticleLocal();
      for(PS::S32 i = 0; i < n; i++) {
          system[i].vel  += system[i].acc * dt;
      }
  }
これ、なんだかよくわからないと思うけど、実際に使うとこは

  PS::ParticleSystem<FPGrav> system_grav;
  ...
  kick(system_grav, dt * 0.5);
こんな感じ。 PS::ParticleSystem は FDPS のほうで用意した型なんだけど、 これに FPGrav という、これはユーザー側で定義した粒子型なんだけど、 それを渡して、FPGrav を知っている ParticleSystem 型、というのを 作るわけ。で、そのインスタンスが system_grav であると。 そうすると、 kick が呼ばれる行では system_gravはその型だ、 とコンパイラが知っているから、

  template<class Tpsys>
  void kick(Tpsys & system,
のとこで、 system の型である Tpsys は PS::ParticleSystem だ、とコンパイラはわかって、なのでコンパイルできるのね。そのために、 Tpsys はそういう、 kick 書いた時点では未定義で引数のほうの型を使う、 ということをコンパイラに教えるのが

  template<class Tpsys>
だということ。

学生C:なんか無駄に複雑な感じがしますが、、、 Crystal だったら、、、多 分

  def kick(system, dt)
    system.getNumberOfParticleLocal.times{|i|
      system[i].vel  += system[i].acc * dt
    }
  end
とか、 system がそもそも粒子の配列だったら

  def kick(system, dt)
    system.each{|p| p.vel += p.acc * dt}
  end
で、、、だいぶ短いし、本当に計算の中身を書いてるとこは結局1行で同じな んだから、それ以外のとこが簡単なほうがいいし、計算の中身も each とか使 うと簡潔ですよね、、、

赤木 :まあそれは、Crystal というかその文法の元になってる Ruby がそう いうもので、そもそも型は実行時に決まることになっているから何も書かなく ていいからね。 Crystal は文法は可能な限り Ruby だけどコンパイル時に全部型 決めるので、コンパイラが実行をシミュレートするようなことして可能な 限り型決めて、できなかったらエラーにする、となってるから。C++ は逆に、 全部型宣言しないといけない C から出発したから、「型を渡すことができる」 ということを書かないといけなくなっちゃうのね。これは多分、 C言語にあった、型が宣言されてない変数とか引数とか関数は全部 int 型、と いうのと矛盾しないようにかな?

まあでも、C とか C++ を使うしかなかったとこはあって、そもそも Crystal 言語って本当に新しくて、マルチコアの並列化がやっとちょっと動くけど、 それ以前の問題として「京」コンピュータにははいらないから。富岳は Arm で LLVM ベースのコンパイラもあるから原理的にははいるんだけどね、、、 FDPS の開発は2013年に始まってるから。C++ の機能も、新しいのは まだ「京」で動くコンパイラにはなかったりしたから、古い機能だけ 使うとか色々苦労してるのよ。

学生C:Crystal はまあ、我々がちょっと使うくらいはともかく、まだ言語の 開発が途中だし、これからどうなるかも分からないですから、、、

赤木 :そうなの。そういうわけで、「京」とか富岳とかのスパコンで、安心 して使えるのはそもそも Fortran だけで、 C/C++ はまあ動くけどちゃんと性 能出せるかどうかわからない、それ以外はそもそも動かない、みたいな感じだっ たから。「京」では Python でも苦労したみたい。

学生C:富岳というか FX700/FX1000 は大丈夫なんではないですか?

赤木 :そうなるといいわねえ、、、まあ、ラズパイで Crstal コンパイラ動 かして人もいるみたいだから Crystal も動くだけは動くわね。

話がそれたけどそういうわけで FDPS は C++ で書いてあって、使う側から みると、ちゃんとスパコンで動いて MPI での並列化とかもして、クラスとか 渡せば並列化して面倒なことをやってくれる素敵ライブラリなんだけど、 C++ で書いてあって C++ の機能使うから、ユーザープログラムも C++ で書か ないといけなかったのね。

学生C:クラスとか渡すんだからそうなるしかないんじゃないですか?

赤木 :でもね、メモリレイアウトとしては C++ のクラスは C の構造体と互換性維持してるの。つまり、C++ の言語側で使う タグ「とか一切もってないのよ。あと、もうひとつ大事なのは、 C++ のコードの側に C で作った、というか C で作ってなくても Fortran でもあと Crystal でもいいんだけど、 C から呼べるように 書いてある関数であれば、C++ の中からでも呼べるのね。

で、FDPS の考え方としては、

を渡せればいいから、粒子構造体を C 言語で通るように定義して、 それの struct と書いてあるところを class に書換えてやって FDPS に渡し てあと相互作用関数も渡すとFDPS の側ではアプリケーションプログラム が使うライブラリ関数を全部生成できるから、それを C 言語から呼べる ラッパーを経由して呼べばいいわけ。

学生C:すごく複雑な気がしますが、、、

赤木 :まあ、それでも呼べるだけましよ。

学生C:まあそうかもですが、、、

赤木 :この辺はだって、ユーザー側から見れば C のライブラリ関数みたいに 見えるから、それで普通に使えるのね。あと、これの開発を始めた元々の同期 が Fortran 言語のインターフェースを作る、ということだったから、 Fortran のインターフェースも生成できるし Fortran の構造体書くと自動的 に C++ のクラスに変換する機能もあるのよ。

学生C:Fortran なんて今誰か使ってるんですか?なんか古代の言語と思ってました。

赤木 :あら、スパコンでは随分使われてるわよ。日本メーカーだとわりと最 近というか「京」ができてしばらくたっても C++ のコンパイラの出来があんまりそのだったりしたし。

学生C:えええ、、そうなんですか。Fortran にもクラスとかあるんですか?

赤木 :結構昔、Fortran 90 の時に derived data type という名前で C の構 造体にあたるものが導入されて、Fortran 2003 でそれが C++ のクラスと大体 同じように使えるようになった感じ。ただし、テンプレートはないの。 Fortran 202Y には入れるとかの議論はあるみたい。

学生C:はあ、、、

赤木 :まあ、雑談はこれくらいにして、FDPS を呼び出す話ね。 github の古い奴をみると、

  convert_crystal_struct_to_f90.rb
  convert_f90_struct_to_crystal.rb
  convert_f90_if_to_crystal.rb
と ruby のプログラムが3個あって、その辺が基本的な変換するみたいね。こ れを Fortran90 じゃなくて C インターフェースにして欲しいのね。

学生C:はあ、、、まあやりますが。Ruby のままですか? Crystal にします?

赤木 : うーん、Crystal にしてもいいけどまあそのままでも。

学生C:了解です。

FDPSの公開バージョンで、 user_defined.hをみてと。まずこれがでればいいはず。 Fortran だすコードはこれと。

入力は、、、

    1:#===============================
    2:#   MODULE: User defined types
    3:#===============================
    4:module FDPS_vector
    5:lib FDPS
    6:   struct Full_particle #!fdps FP,EPI,EPJ,Force
    7:      #!fdps copyFromForce full_particle (pot,pot) (acc,acc)
    8:      #!fdps copyFromFP full_particle (id,id) (mass,mass) (eps,eps) (pos,pos) 
    9:      #!fdps clear id=keep, mass=keep, eps=keep, pos=keep, vel=keep
   10:      id : Int64  #$fdps id
   11:      mass : Float64     #$fdps charge
   12:      eps : Float64
   13:      pos : Cvec_Float64 #!fdps position
   14:      vel : Cvec_Float64 #!fdps velocity
   15:      pot : Float64
   16:      acc : Cvec_Float64 
   17:    end
   18:end
   19:end
   20:
   21:#   !**** Interaction function (particle-particle)
   22:include Math
   23:def calc_gravity(ep_i,n_ip,ep_j,n_jp,f)
   24:  n_ip.times{|i|
   25:    pi = (ep_i + i).value
   26:    eps2 = pi.eps*pi.eps
   27:    xi = Vec_Float64.new(pi.pos)
   28:    ai =  Vec_Float64.new(0)
   29:    poti = 0_f64
   30:    n_jp.times{|j|
   31:      pj = (ep_j + j).value
   32:      xj = Vec_Float64.new(pj.pos)
   33:      rij = xi - xj
   34:      r2 = rij*rij+eps2
   35:      rinv = 1_f64/sqrt(r2)
   36:      mrinv = pj.mass*rinv
   37:      mr3inv = mrinv*rinv*rinv
   38:      ai -= rij*mr3inv
   39:      poti = poti - mrinv
   40:    }
   41:    pfi = (f+i)
   42:    pfi.value.pot =  pfi.value.pot + poti
   43:    pfi.value.acc =   Vec_Float64.new(pfi.value.acc)+ ai
   44:  }
   45:end
と。なら Ruby のプログラムをちょっと修正して

    1:#
    2:# convert_crystal_struct_to_c.rb
    3:#
    4:def print_header
    5:  print <<-EOF
    6:#pragma once
    7:/* Standard headers */
    8:#include <math.h>
    9:/* FDPS headers */
   10:#include "FDPS_c_if.h"
   11:EOF
   12:end
   13:
   14:$type_conversion_table =<<-EOF
   15:Int64         long long
   16:Float64       double
   17:Cvec_Float64  fdps_f64vec
   18:Cvec_Float32  fdps_f32vec
   19:EOF
   20:
   21:
   22:$type_conversion_hash = $type_conversion_table.split("\n").map{|s|
   23:  a= s.split
   24:  [a[0], a[1..(a.size-1)].join(" ")]}.to_h
   25:
   26:open("crmain.cpp","w"){|f|
   27:       f.print <<EOF
   28:/* Standard headers */
   29:#include <iostream>
   30:#include <fstream>
   31:/* FDPS headers */
   32:#include <particle_simulator.hpp> 
   33:/* User-defined headers */
   34:#include "FDPS_Manipulators.h"
   35:extern "C"{
   36:void crystal_init(void);
   37:void crmain(void);
   38:
   39:}
   40:int main(int argc, char *argv[])
   41:{
   42:   
   43:   //* Initialize fdps_manip
   44:   FDPS_Manipulators::Initialize(argc,argv);
   45:   //* Call Fortran main subroutine
   46:   //   f_main_();
   47:   crystal_init();
   48:   crmain();
   49:   
   50:
   51:   return 0;
   52:
   53:}
   54:EOF
   55:     }
   56:def print_fortran_member(s)
   57:  a = s.split
   58:  ss = "     "
   59:  if a[0][0] != "#"
   60:    # member variable line
   61:    varname = a[0]
   62:    typename = $type_conversion_hash[a[2]]
   63:    raise "unparsable line: #{s}"    if a[1] != ":" || typename == nil
   64:    ss += " "+typename + " "+ varname+";"
   65:    a = a[3..(a.length)]
   66:  end
   67:  if a.length >0
   68:    if a[0] == "#!fdps" || a[0] == "#$fdps"
   69:      a[0] = "//$fdps"
   70:    else
   71:      a[0][0]= "//"
   72:    end
   73:    ss += " "+a.join(" ")
   74:  end
   75:  print ss,"\n"
   76:end
   77:        
   78:      
   79:      
   80:    
   81:print_header
   82:
   83:while s=gets
   84:  if s =~ /struct (.*) #!fdps (.*)/
   85:#    print s
   86:    struct_name = $1.downcase
   87:    struct_types=$2
   88:    lines=[]
   89:    instruct=true
   90:    while instruct
   91:      s=gets
   92:      if s=~/^(\s*)end(\s*)$/
   93:        instruct =false
   94:      else
   95:        lines.push s.chomp
   96:      end
   97:    end
   98:    print "typedef struct #{struct_name}{  //$fdps #{struct_types}\n"
   99:    lines.each{|s| print_fortran_member(s)}
  100:    print "} #{struct_name.capitalize};\n"
  101:  end
  102:end
で、

 gravity> ruby convert_crystal_struct_to_c.rb user_defined.cr
 #pragma once
 /* Standard headers */
 #include <math.h>
 /* FDPS headers */
 #include "FDPS_c_if.h"
 typedef struct full_particle{  //$fdps FP,EPI,EPJ,Force
       //$fdps copyFromForce full_particle (pot,pot) (acc,acc)
       //$fdps copyFromFP full_particle (id,id) (mass,mass) (eps,eps) (pos,pos)
       //$fdps clear id=keep, mass=keep, eps=keep, pos=keep, vel=keep
       long long id; //$fdps id
       double mass; //$fdps charge
       double eps;
       fdps_f64vec pos; //$fdps position
       fdps_f64vec vel; //$fdps velocity
       double pot;
       fdps_f64vec acc;
 } Full_particle;
と、大丈夫かなこれ?あと何をするんだっけ?C言語サンプルの Makefile だ と

  FDPS_c_if.h $(SRC_CXX): $(HDR_USER_DEFINED_TYPE) Makefile
          $(FDPS_C_IF_GENERATOR) user_defined.h --output ./
で色々なものが全部できるはずで、Crystal のだと

  FDPS_cr_if.cr:   FDPS_ftn_if.cpp  convert_f90_if_to_crystal.rb
          ruby convert_f90_if_to_crystal.rb FDPS_ftn_if.cpp > FDPS_cr_if.cr
で Crystal のインターフェース作ってて、 FDPS の C インターフェースでも FDPS_ftn_if.cpp は作ってるからこのままでいいのかな。

これ実行してと、なんかできるけど

  crystal FDPS_cr_if.cr
  In FDPS_cr_if.cr:98:13

    98 | (*pfunc_comp : Bool) : Void
       ^
  Error: expecting token 'CONST', not '*'
コンパイルエラーか。まあそうだよね。FDPS_cr_if.cr をみると、、、

 fun sort_particle=fdps_sort_particle(psys_num : Int32,
            (*pfunc_comp : Bool) : Void

これ括弧も閉じてないし全然変だわ。えーと、これどうなって欲しいんだろ? pfunc_comp の型の宣言を生成するのに失敗していると。 これって、比較関数を C++ の FDPS に渡すやつだから、 ポインタも C++ の構造体へのポインタで、別に意味ないしなんでもいいはず かしら。とりあえず

  fun sort_particle=fdps_sort_particle(psys_num : Int32,
            pfunc_comp : Pointer(T), Pointer(T) -> Bool) : Void
みたいなのがでればいいと。

その辺いいとして、、、あれ、 theta=0近くでないと答あわないというか、 ep-sp の計算壊れてるか。これ SPJmonopole でないといけないから?

あ、だから、

 fdps_calc_force_all
 fdps_calc_force_making_tree
 fdps_calc_force_and_write_back
 fdps_sort_particle
 fdps_calc_force_all_and_write_back
とかの、粒子型とか関数型もらう奴は、とりあえず自動生成しないでユーザー プログラムの中で宣言すればいいか。 I/O にNacsio 使うと、、、あ、ベクトル型が違う問題があるか。 FDPS のは Vec_Float64 というのを作ってるのね。まあとりあえず見苦しいけ どこのままで、粒子 I/O は Particle 型使って、それと Full_particle との 間で変換かければいいか。

コマンドラインオプションに clop は使えるのかな? MPI 使いたいから、

メインプログラムだけは C++ の関数があって、それから Crystal で書いた crmain っていうのを呼び出す形だから、ARGV とかないよね、、、

C++ のメインプログラムには argc, argv があるから、これを渡してなんとか すればいいか。

と、一応動くようになったかな、、、、エネルギーも保存するし。

OpenMP と、あとMPIも、お、動いてますね。

(ここまで1週間くらい)

なんかできた気がします。

赤木 :え、本当に

学生C:まあ作者氏が前に作ったやつが一応動くところまできてて、FDPS の側 が公式に C 言語対応したのでその辺変えたのと、コマンドラインパーザとか Nacsio とか使うようにしたくらいなので。

赤木 :エネルギー保存とかどんな感じ?

学生C:

 gravity> ./mkplummer -Y -n 1024 | env LD_LIBRARY_PATH=../../src/fdps-crystal/ ~/src/fdps-crystal/fdpscr -O p1k-t10.yml -t 5 -d 1 -T 0.5
 FDPS on Crystal test code
      //==================================\\
      ||                                  ||
      || ::::::: ::::::. ::::::. .::::::. ||
      || ::      ::    : ::    : ::       ||
      || ::::::  ::    : ::::::'  `:::::. ||
      || ::      ::::::' ::      `......' ||
      ||     Framework for Developing     ||
      ||        Particle Simulator        ||
      ||     Version 5.0g (2019/09)       ||
      \\==================================//
 
        Home   : https://github.com/fdps/fdps 
        E-mail : fdps-support@mail.jmlab.jp
        Licence: MIT (see, https://github.com/FDPS/FDPS/blob/master/LICENSE)
        Note   : Please cite the following papers.
                 - Iwasawa et al. (2016, Publications of the Astronomical Society of Japan, 68, 54)
                 - Namekata et al. (2018, Publications of the Astronomical Society of Japan, 70, 70)
 
        Copyright (C) 2015 
          Masaki Iwasawa, Ataru Tanikawa, Natsuki Hosono,
          Keigo Nitadori, Takayuki Muranushi, Daisuke Namekata,
          Kentaro Nomura, Junichiro Makino and many others
 ******** FDPS has successfully begun. ********
 ====================================
  Paralleization infomation:
    # of processes is 1
    # of thread is    4
 ====================================
 options # => #<CLOP:0x7fb74eb0ef60
  @dt=0.0078125,
  @dt_dia=1.0,
  @dt_end=5.0,
  @dt_out=2.0,
  @eps=0.05,
  @help=false,
  @init_out=false,
  @n=0,
  @ofname="p1k-t10.yml",
  @tol=0.5,
  @x_flag=false>
 Failed to raise an exception: END_OF_STACK
 [0x7fb74e34da86] ???
 [0x7fb74e319be3] __crystal_raise +35
 [0x7fb74e340fe5] ???
 [0x7fb74e36ee58] ???
 [0x7fb74e375359] ???
 [0x7fb74e3743fd] ???
 [0x7fb74e3631fe] ???
 [0x7fb74e34d950] crmain +256
 [0x55fab157a7af] main +31
 [0x7fb74d1abc87] __libc_start_main +231
 [0x55fab157a83a] ???
 [0x0] ???
 Unhandled exception: Error writing file: Broken pipe (IO::Error)
   from /usr/share/crystal/src/io/evented.cr:82:13 in 'unbuffered_write'
   from /usr/share/crystal/src/io/buffered.cr:144:9 in 'write'
   from /usr/share/crystal/src/io.cr:471:7 in 'write_utf8'
   from /usr/share/crystal/src/string.cr:4961:5 in 'to_s'
   from /usr/share/crystal/src/io.cr:174:5 in '<<'
   from /usr/share/crystal/src/io.cr:188:5 in 'print'
   from /usr/share/crystal/src/kernel.cr:125:3 in 'print'
   from mkplummer.cr:128:20 in 'nacswrite'
   from mkplummer.cr:173:3 in '__crystal_main'
   from /usr/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
   from /usr/share/crystal/src/crystal/main.cr:96:7 in 'main'
   from /usr/share/crystal/src/crystal/main.cr:119:3 in 'main'
   from __libc_start_main
   from _start
   from ???

 gravity> ./mkplummer -Y -n 1024 | env LD_LIBRARY_PATH=../../src/fdps-crystal/ ~/src/fdps-crystal/fdpscr -O p1k-t10.yml -t 5 -d 1 -T 0.25
 FDPS on Crystal test code
      //==================================\\
      ||                                  ||
      || ::::::: ::::::. ::::::. .::::::. ||
      || ::      ::    : ::    : ::       ||
      || ::::::  ::    : ::::::'  `:::::. ||
      || ::      ::::::' ::      `......' ||
      ||     Framework for Developing     ||
      ||        Particle Simulator        ||
      ||     Version 5.0g (2019/09)       ||
      \\==================================//
 
        Home   : https://github.com/fdps/fdps 
        E-mail : fdps-support@mail.jmlab.jp
        Licence: MIT (see, https://github.com/FDPS/FDPS/blob/master/LICENSE)
        Note   : Please cite the following papers.
                 - Iwasawa et al. (2016, Publications of the Astronomical Society of Japan, 68, 54)
                 - Namekata et al. (2018, Publications of the Astronomical Society of Japan, 70, 70)
 
        Copyright (C) 2015 
          Masaki Iwasawa, Ataru Tanikawa, Natsuki Hosono,
          Keigo Nitadori, Takayuki Muranushi, Daisuke Namekata,
          Kentaro Nomura, Junichiro Makino and many others
 ******** FDPS has successfully begun. ********
 ====================================
  Paralleization infomation:
    # of processes is 1
    # of thread is    4
 ====================================
 options # => #<CLOP:0x7fba8a8e4f60
  @dt=0.0078125,
  @dt_dia=1.0,
  @dt_end=5.0,
  @dt_out=2.0,
  @eps=0.05,
  @help=false,
  @init_out=false,
  @n=0,
  @ofname="p1k-t10.yml",
  @tol=0.25,
  @x_flag=false>
 Failed to raise an exception: END_OF_STACK
 [0x7fba8a123a86] ???
 [0x7fba8a0efbe3] __crystal_raise +35
 [0x7fba8a116fe5] ???
 [0x7fba8a144e58] ???
 [0x7fba8a14b359] ???
 [0x7fba8a14a3fd] ???
 [0x7fba8a1391fe] ???
 [0x7fba8a123950] crmain +256
 [0x55f266ce67af] main +31
 [0x7fba88f81c87] __libc_start_main +231
 [0x55f266ce683a] ???
 [0x0] ???
 Unhandled exception: Error writing file: Broken pipe (IO::Error)
   from /usr/share/crystal/src/io/evented.cr:82:13 in 'unbuffered_write'
   from /usr/share/crystal/src/io/buffered.cr:144:9 in 'write'
   from /usr/share/crystal/src/io.cr:471:7 in 'write_utf8'
   from /usr/share/crystal/src/string.cr:4961:5 in 'to_s'
   from /usr/share/crystal/src/io.cr:174:5 in '<<'
   from /usr/share/crystal/src/io.cr:188:5 in 'print'
   from /usr/share/crystal/src/kernel.cr:125:3 in 'print'
   from mkplummer.cr:128:20 in 'nacswrite'
   from mkplummer.cr:173:3 in '__crystal_main'
   from /usr/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
   from /usr/share/crystal/src/crystal/main.cr:96:7 in 'main'
   from /usr/share/crystal/src/crystal/main.cr:119:3 in 'main'
   from __libc_start_main
   from _start
   from ???

 gravity> ./mkplummer -Y -n 1024 | env LD_LIBRARY_PATH=../../src/fdps-crystal/ ~/src/fdps-crystal/fdpscr -O p1k-t10.yml -t 5 -d 1 -T 0.1
 FDPS on Crystal test code
      //==================================\\
      ||                                  ||
      || ::::::: ::::::. ::::::. .::::::. ||
      || ::      ::    : ::    : ::       ||
      || ::::::  ::    : ::::::'  `:::::. ||
      || ::      ::::::' ::      `......' ||
      ||     Framework for Developing     ||
      ||        Particle Simulator        ||
      ||     Version 5.0g (2019/09)       ||
      \\==================================//
 
        Home   : https://github.com/fdps/fdps 
        E-mail : fdps-support@mail.jmlab.jp
        Licence: MIT (see, https://github.com/FDPS/FDPS/blob/master/LICENSE)
        Note   : Please cite the following papers.
                 - Iwasawa et al. (2016, Publications of the Astronomical Society of Japan, 68, 54)
                 - Namekata et al. (2018, Publications of the Astronomical Society of Japan, 70, 70)
 
        Copyright (C) 2015 
          Masaki Iwasawa, Ataru Tanikawa, Natsuki Hosono,
          Keigo Nitadori, Takayuki Muranushi, Daisuke Namekata,
          Kentaro Nomura, Junichiro Makino and many others
 ******** FDPS has successfully begun. ********
 ====================================
  Paralleization infomation:
    # of processes is 1
    # of thread is    4
 ====================================
 options # => #<CLOP:0x7f69411d0f60
  @dt=0.0078125,
  @dt_dia=1.0,
  @dt_end=5.0,
  @dt_out=2.0,
  @eps=0.05,
  @help=false,
  @init_out=false,
  @n=0,
  @ofname="p1k-t10.yml",
  @tol=0.1,
  @x_flag=false>
 Failed to raise an exception: END_OF_STACK
 [0x7f6940a0fa86] ???
 [0x7f69409dbbe3] __crystal_raise +35
 [0x7f6940a02fe5] ???
 [0x7f6940a30e58] ???
 [0x7f6940a37359] ???
 [0x7f6940a363fd] ???
 [0x7f6940a251fe] ???
 [0x7f6940a0f950] crmain +256
 [0x55c9cbb617af] main +31
 [0x7f693f86dc87] __libc_start_main +231
 [0x55c9cbb6183a] ???
 [0x0] ???
 Unhandled exception: Error writing file: Broken pipe (IO::Error)
   from /usr/share/crystal/src/io/evented.cr:82:13 in 'unbuffered_write'
   from /usr/share/crystal/src/io/buffered.cr:144:9 in 'write'
   from /usr/share/crystal/src/io.cr:471:7 in 'write_utf8'
   from /usr/share/crystal/src/string.cr:4961:5 in 'to_s'
   from /usr/share/crystal/src/io.cr:174:5 in '<<'
   from /usr/share/crystal/src/io.cr:188:5 in 'print'
   from /usr/share/crystal/src/kernel.cr:125:3 in 'print'
   from mkplummer.cr:128:20 in 'nacswrite'
   from mkplummer.cr:173:3 in '__crystal_main'
   from /usr/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
   from /usr/share/crystal/src/crystal/main.cr:96:7 in 'main'
   from /usr/share/crystal/src/crystal/main.cr:119:3 in 'main'
   from __libc_start_main
   from _start
   from ???
こんなふうで、Opening Angle である -T でのパラメータ小さくすると小さくなるので大丈夫じゃないですかね。

赤木 :エネルギー保存は 1e-4, 1e-5, 2e-6 くらいなわけね。まあもっともらしいわね。 あ、これ、4スレッドなの?

学生C:はい、 OpenMP 指定を有効にしたらちゃんと複数スレッドで動きました。

赤木 :あら、2年前にはまだガーベージコレクタに問題があって、複数スレッ ドになってると別に Crystal の側は1スレッドでも駄目だったんだけど、 今は大丈夫なのね。ちゃんと速くなる?

学生C:4スレッドで4倍にはなってないですが3倍くらいですかね。1万粒子の時。

赤木 :MPI は?

学生C:同じような感じでした。

赤木 :出力どれくらいだしてるかとかによるから、もうちょっとちゃんと調 べないといけないけど、とりあえずそんなところかしらね。FDPS 使えると いきなり OpenMP と MPI で並列化したプログラムが動くから、大規模計算で もできるかも。

学生C:でも、スパコンに Crystal はいってないのでは?

赤木 :x86 で Linux の機械ならはいるかもしれないし。運用部門とご相談とかね。

学生C:富岳とかは駄目ですか?

赤木 :Crystal 開発側でまだ x86 以外のサポートできてないみたい。ラズパ イとかで動かした人はいるみたいだから、いれれば動くと思うけど。

まあ世界のほとんどのスパコンは x86 だから、とりあえずはそれでなんとかね。

あとは、相互作用計算のところを、今のプログラムでは Crystal で普通に書 いた関数を FDPS の側で呼ぶんだけど、そこを SIMD ユニット使って高速化 したいわね。

これは、FDPS の開発グループで作ってるのがあるから、公開されたら使うこ とでいきましょう。

再帰下降パーサあるから作ってみてくれてもいいけど?

学生C:それはさすがに車輪の再々発明ですよね。

赤木 :まあそうね。

17.1. 課題

  1. crystalfdps を動 かして、1024粒子のプラマーモデルを時間積分し、タイムステップ、 ソフトニング、オープニングアングルをかえるとと エネルギー保存がどう変わるか検討せよ。
  2. OpeMP, MPI での速度を、粒子数を 1万から 100万程度までかえて調べよ。

17.2. まとめ

  1. FDPS を使ってみた。動く気がする。

17.3. 参考資料

FDPS

crystalfdps
Previous ToC Next