なかなか科研費があたらないので、助成金のほうで頑張って稼ごうと足掻いています。
本日2件提出しました。来月も2件提出予定です。
現状、
・企業さんの申請に協力する形で2件(@30弱)
・某M社、E社の助成金(@100, @65)
を提出して結果待ちで、来月〆切のものは、
・某S社、I社の助成金(@100、@200)
とちょっと額が大きいので頑張って書くべし。
Dakotaの並列計算機能について整理してみる。
計算機環境で整理すると、
1)マルチコアワークステーション1ノード向け
2)マルチノードクラスタ向け(ただし各ノードは1~4coreと小規模な場合)
3)マルチノードクラスタ向け(ただし各ノードは8core~とそれなりにまともなHPCの場合)
3-1)バッチファイルシステムが使用できる場合
3-2)バッチファイルシステムが使用できない(しない)場合
Node Placement Methodとしては、
とのことで、以前の記事のような感じで計算できる。
ざっくりと再掲しておくと、
[snip]
APPLIC_PROCS=2 # 1 evaluationあたりのCore数
# Current Eval. Number
num=$(pwd | awk -F. '{print $NF}') # workdir名からEval.番号を取得
CONCURRENCY=4 # Dakotaのconcurrency(inputファイル中で指定した値)
PPN=16 # ノード当たりのcore数
# 剰余演算でjob番号と、OFで利用するcore数などからホスト番号を計算
applic_nodes=$( ( (APPLIC_PROCS+PPN-1) / PPN ) )
relative_node=$( ( (num - 1) % CONCURRENCY*APPLIC_PROCS / PPN ) )
### relativeノードが使える場合(MPIのバージョンによる)
node_list="+n${relative_node}"
for node_increment in $(seq 1 $( (applic_nodes - 1) ) ); do
node_list="$node_list,+n$( (relative_node + node_increment) )"
done
### relativeノードが使えない場合は以下のように、relative番号から実際のホストを対応づける
if [ $relative_node -eq 0 ]; then
node_list="ensis10"
elif [ $relative_node -eq 1 ]; then
node_list="ensis12"
elif [ $relative_node -eq 2 ]; then
node_list="ensis13"
else
node_list="ensis14"
fi### evaluationの実行
mpirun -np $APPLIC_PROCS -host $node_list my_simulation
年度初めのドタバタを終了し、なんとか毎日のリズムが出てきた。
昨年度は練習問題を一生懸命やっていたなぁというのが正直な所で、今年度はちゃんとアウトプットしていきたい。
研究リハビリ第1段として、昨秋にやっていたDakotaのRosenbrock関数(2D)の最適化で(min = 0 at (x1,x2)=(1,1))、ちょっとパラメータの追い込みをしてみる。長岡のY先生曰く、モデル関数でパラメータセットを指定したら、CFDでの本番ではあまりいじらないそうなので、その言にしたがってみる。
設定すべきパラメータはいくつかあるが、まずはMOGAのパラメータセットは共通として、Kriging近似曲面でのSURROGATE でのサンプル数samples = 50/100/200/300/400と変えてやってみる(surrogate_based_global)。ただし、最小値が3つあるので、最後の値になるようにx1,x2の配位を狭めてやってみる。
initial_point -3 -3
lower_bounds -5 -5
upper_bounds 10 10
descriptors 'x1' 'x2'
結果は、以下のとおりで、samples=100がなんか怪しいが200以上であれば良さそう。
samples, x1, x2, fmin, CPUs
50, 1.0585147380, 1.1213159660, 3.4983678384e-3, 2.86341
100, 3.0855104598, 9.5452386907, 4.4111751971, 5.580
200, 0.96201007998, 0.92113517035, 3.3165860016e-3, 7.68196
300, 1.0214072634, 1.0472875769, 2.0701161290e-3, 10.9975
400, 1.0585147380, 1.1213159660, 3.4983678384e-3, 14.3596
moga, 1.0585147380, 1.1213159660, 3.4983678384e-3, 41.47
前から気になっていたOpenCVをいじってみようということで、とりあえずWebカメラのついている家PC(Win10Pro x86_64)に環境構築をトライしてみる。OpenCV3.1.0が年末に公開され、VS2015にも対応したとのことなので、C++の勉強もかねてVS2015 C++での開発を考えよう。
MSから無償公開されているVS2015 Community版をダウンロード・インストール(vs
_community_JPN.exeを落としてきてダブルクリックし、ネットインストールすることになる。カスタムでインストールすると26GBくらい必要と表示された)。なお、インストール時に標準ではC#しか選択されないようなので、カスタムインストールでC++も選択しておく。2016/1現在で、VS2015 Update1が導入される。導入後はPCを再起動しておく。
ここからWindows用のOpenCV for Windows (opencv-3.1.0.exe)をダウンロードする。Githubから落としてくると早いかも。SFはミラーサイトにいきわたっていない?
http://opencv.org/downloads.html
自己解凍ファイル(exe)形式になっているので、ダブルクリックすると、opencvフォルダに展開されるので、フォルダごと適当な場所に置いておく。
今回は、バージョンがわかるようにopencv-3.1.0にリネームして、C:\Users\waku\opencv-3.1.0としておいておく。
なお、OpenCV3.0からAll-in-oneのライブラリ(C:\Users\waku\opencv-3.1.0\build\x64\vc14\lib\opencv_world310(d).lib)になったので、個別のlibが欲しい場合(2系列のように)やstaticライブラリが欲しい場合は、cmakeをつかってrebuildする必要があるとのこと。
VS2015用動的ライブラリが置かれている場所は「C:\Users\Waku\opencv-3.1.0\build\x64\vc14\bin」であるので、これをWindowsのシステム環境変数PATHに追記する。環境変数は、システムのプロパティから設定できる。
VS2015では、プロジェクトがOpenCVを認識できるようにOpenCVの「includeフォルダ」と「libraryフォルダ」を以下のようにして設定する必要がある。
http://chichimotsu.hateblo.jp/entry/2014/11/28/212432を参考に、opencv_libs.hppを作成し、上記のincludeフォルダに入れておく。
http://www.arubeh.com/archives/1102
にあったサンプルコードを以下のようにしてみた。
なお、各プロジェクトのプロパティから、構成プロパティ>C/C++>コード生成>「ランタイムライブラリ」をdebug/releaseに応じて変更する必要があるそうな。
Static Link
#include "stdafx.h"
// Dynamic Linkの場合
#include <opencv2/opencv.hpp> // インクルードファイル指定
//#include <opencv_libs.hpp> // 静的リンクライブラリの指定 (不要)
// Static Linkの場合
//#include <opencv2/opencv.hpp>
//#define _OPENCV_BUILD_STATIC_
//#include "opencv_libs.hpp"
using namespace cv; // 名前空間の指定
int main()
{
//width220, height150の画像を作成
Mat src = Mat::zeros(150, 220, CV_8UC3);
//赤色で画像にHello Worldを描く
putText(src, "Hello World", Point(5, 50), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 200), 2, CV_AA);
//緑色で画像に線を描く
line(src, Point(190, 25), Point(190, 45), Scalar(0, 200, 0), 3);
//要素を直接操作し画像に点を描く
for (int x = 188; x < 192; x++) {
for (int y = 53; y < 57; y++) { // y座標
for (int i = 0; i < 2; i++) { // i < 3にするとBGRすべての要素を200にする
src.at<uchar>(Point(x * 3 + i, y)) = saturate_cast<uchar>(200);
}
}
}
//画像を表示
imshow("", src);
//ウインドウの表示時間(0はキーが押されるまで閉じない)
waitKey(0);
return 0;
}
LINK : fatal error LNK1104: ファイル 'opencv_ts310d.lib' を開くことができません。となりエラーになる?
(以上、STOPです。Cmakeでビルドしなおせということか?)
(01/10追記)
いろいろ調べたところ、OpenCV3.1.0には個別のライブラリではなく、全部入りのopencv_world310(d).libだけがついてくるそうで、リンカの入力にこのライブラリを指定すればOK。また、
#include <opencv_libs.hpp>
のようなstatic libraryの指定も不要らしい..というか、そもそもstatic libraryがついてこないので、camekを使って自前でbuildしなければいけないらしい。
blockMeshDGなんていうツールもあるが、ちょっと調べたら2.3.xから本家のblockMeshコマンドにmultiGrading機能が追加されていたとのことで調べてみた。
従来のblockMeshでは例えば矩形ダクト流れを計算するときに壁面にメッシュを寄せたい場合は、ブロックを分割して壁面側にgradingを近づける必要があったが、新しい機能では、その必要がないということらしい。
1)一様メッシュ
blocks
(
hex (0 1 2 3 4 5 6 7) (100 40 40)
simpleGrading (1
1
1
)
);
2)multiGrading
blocks
(
hex (0 1 2 3 4 5 6 7) (100 40 40)
simpleGrading (
1
// (fraction of the block, fraction of the divisions, grading ratio)
( (0.2 0.3 10) (0.6 0.4 1) (0.2 0.3 0.1) )
( (0.2 0.3 10) (0.6 0.4 1) (0.2 0.3 0.1) )
)
);
上記の例だと、x方向は一様分割で、yおよびz方向は、3つのグレーディングセクションに分かれており(3つの括弧が対応)、それぞれの括弧内は以下のように指定する。
(ブロック全体に占める割合 セクションが占める分割数の割合 グレーディング比)
具体的には、
(0.2 0.3 10)・・・ブロックの2割をセクション化し、分割数40分割の3割を割り当てるとする。比率は10なのでだんだん大きくなるようにする
(0.6 0.4 1)・・・ブロックの6割部分(真ん中のセクション)は一様分割
(0.2 0.3 0.1)・・・ブロックの2割をセクション化し、分割数40の3割を割り当てる。比率は0.1なのでだんだん小さくなるようにする
※ なお、0.2とか0.3というのは割合を指定できればよく、内部で規格化されるので、必ずしも和が1でなくてもよい。
ちょっと時間が開いてしまった。
4ノードの「なんちゃってクラスタ」でdakota+OF並列計算したいときのやり方をまとめておく。
クラスタでの利用にはいくつか(計算したい内容に応じて)方法があるが、ここでは、
という条件で考える。
①dakotaの設定(dakota input file)
dakotaのプロセス自体はserialで実行し、evaluation_concurrencyを実行したいノード数に合わせる。
ポイントは local_evaluation_scheduling staticで、この設定により例えばjob 2の次はjob 6、job10、.....という風にjobの順番が固定で回ってくるようにできる。
[snip]
interface,
###############
fork
asynchronous
evaluation_concurrency = 4
local_evaluation_scheduling static[snip]
②dakotaの設定(OFのドライバーファイルrun_openfoam.sh)
OFのジョブを起動するためのドライバスクリプト中で(shスクリプト)、どのjobがどのノードにmpirunで投入されるかを決める。こんな感じです。
# Cuurent Job number
num=$(pwd | awk -F. '{print $NF}') ←workdir名からjob番号を取得
#echo $num
# Dakota concurrency (be same setting in dakota input file)
CONCURRENCY=4
# Num. of Procs per node
PPN=4
# number of processors per application job
APPLIC_PROCS=4
# relative node on which the job should schedule (floor)
# this is the first of the node block for this job
relative_node=$*1 ←剰余演算でjob番号と、OFで利用するcore数などからホスト番号を計算
#echo $relative_node
# build a node list ←ホスト番号からノード名を設定
if [ $relative_node -eq 0 ]; then
node_list="ensis10"
elif [ $relative_node -eq 1 ]; then
node_list="ensis12"
elif [ $relative_node -eq 2 ]; then
node_list="ensis13"
else
node_list="ensis14"
fi
echo "Evaluation on" $node_list
#for node_increment in `seq 1 $*2`; do
# node_list="$node_list,+n$*3"
#done
./Allrun $node_list $APPLIC_PROCS ←OFの起動スクリプトにノード名とcore数を引き渡す
※ OpenMPIのrelative host indexingの機能を使えば、ノード名を設定しなくてもよさそうだが、なぜかうまくいかないので力技で指定しています。
→OpenMPIのMLに投げたところどうもバグらしい。OpenMPI2.0になるまで待てということらしい。
※ Allrunもちゃんと書き換えて、sHMとかも投入ノードで実行するようにしたほうがよさそうです。今は、master兼computeノード(具体的にはensis10)で実行してしまってるので...。
※ mpirunはsshで実行できるようにしてあります。ここらへんの設定は前にも書きました。
MOGAがやっぱり時間がかかるので、近似応答局面を導入した計算(Surrogate based optimization)の効率化を図ってみる。
テスト問題はBranin function(2D)で、3つの最小点がある。
f(-pi, 12.275)=f(pi,2.275)=f(9.42478,2.475)=0.397887
moga部分は共通で、以下のようなsettingとする。また、Surrogate作成のsamplingはLHS(samples=100)とした。
method
id_method = 'MOGA'
output silent
max_function_evaluations = 5000
moga
fitness_type domination_count
replacement_type below_limit = 6
shrinkage_percentage = 0.9
niching_type distance 0.05 0.05
convergence_type metric_tracker
percent_change = 0.05
num_generations = 10
postprocessor_type
orthogonal_distance 0.05 0.05
population_size = 300
initialization_type unique_random
crossover_type shuffle_random
num_offspring = 2 num_parents = 2
crossover_rate = 0.8
mutation_type replace_uniform
mutation_rate = 0.1
seed = 531
① MOGAのみ(evaluation_concurrency = 4)
<<<<< Function evaluation summary: 1264 total (1264 new, 0 duplicate)
<<<<< Best parameters =
9.4287956783e+00 x1
2.4366909952e+00 x2
<<<<< Best objective function =
3.9970375654e-01
<<<<< Best data captured at function evaluation 1194
<<<<< Iterator moga completed.
<<<<< Environment execution completed.
DAKOTA execution time in seconds:
Total CPU = 0.9 [parent = 0.891864, child = 0.008136]
Total wall clock = 70.9963
② MOGA+Surrogate(Kriging)(evaluation_concurrency = 4)
<<<<< Function evaluation summary (APPROX_INTERFACE): 6328 total (6328 new, 0 duplicate)
obj_fn: 6328 val (6328 n, 0 d), 0 grad (0 n, 0 d), 0 Hess (0 n, 0 d)
<<<<< Function evaluation summary: 105 total (105 new, 0 duplicate)
obj_fn: 105 val (105 n, 0 d), 0 grad (0 n, 0 d), 0 Hess (0 n, 0 d)
<<<<< Best parameters =
9.3747568430e+00 x1
2.4445742729e+00 x2
<<<<< Best objective function =
4.1002862086e-01
<<<<< Best data captured at function evaluation 105
<<<<< Iterator surrogate_based_global completed.
<<<<< Environment execution completed.
DAKOTA execution time in seconds:
Total CPU = 1.22 [parent = 1.22181, child = -0.001814]
Total wall clock = 8.5127
なんか精度がいまいちなので、LHS(samples=200)としてみる。
<<<<< Function evaluation summary (APPROX_INTERFACE): 6288 total (6288 new, 0 duplicate)
obj_fn: 6288 val (6288 n, 0 d), 0 grad (0 n, 0 d), 0 Hess (0 n, 0 d)
<<<<< Function evaluation summary: 205 total (203 new, 2 duplicate)
obj_fn: 205 val (203 n, 2 d), 0 grad (0 n, 0 d), 0 Hess (0 n, 0 d)
<<<<< Best parameters =
9.4443335614e+00 x1
2.5037465699e+00 x2
<<<<< Best objective function =
3.9987220558e-01
<<<<< Best data captured at function evaluation 205
<<<<< Iterator surrogate_based_global completed.
<<<<< Environment execution completed.
DAKOTA execution time in seconds:
Total CPU = 0.97 [parent = 0.963853, child = 0.006147]
Total wall clock = 14.1147
サンプル数が倍になったので、計算時間も倍になったが、精度はおおむねMOGAと同等になった。使ったinputファイルを上げておく。
branin_opt_sbo.in
# Dakota Input File: branin_opt_sbo.in
# moga + surrogate(kriging)
environment
tabular_graphics_data
tabular_graphics_file = 'branin_opt_sbo.dat'
top_method_pointer = 'SBGO'
method
id_method = 'SBGO'
surrogate_based_global
model_pointer = 'SURROGATE'
method_pointer = 'MOGA'
replace_points
max_iterations = 5
output verbose
method
id_method = 'MOGA'
output silent
max_function_evaluations = 5000
moga
fitness_type domination_count
replacement_type below_limit = 6
shrinkage_percentage = 0.9
niching_type distance 0.05 0.05
convergence_type metric_tracker
percent_change = 0.05
num_generations = 10
postprocessor_type
orthogonal_distance 0.05 0.05
population_size = 300
initialization_type unique_random
crossover_type shuffle_random
num_offspring = 2 num_parents = 2
crossover_rate = 0.8
mutation_type replace_uniform
mutation_rate = 0.1
seed = 531
model
id_model = 'SURROGATE'
surrogate global
dace_method_pointer = 'SAMPLING'
gaussian_process
dakota
method
id_method = 'SAMPLING'
model_pointer = 'TRUTH'
sampling
sample_type lhs
samples = 200
seed = 12345
model
id_model = 'TRUTH'
single
variables
continuous_design = 2
initial_point 0 2
lower_bounds -5 0
upper_bounds 10 15
descriptors 'x1' 'x2'
interface
fork
asynchronous evaluation_concurrency = 4
analysis_driver = 'simulator_script'
parameters_file = 'params.in'
results_file = 'results.out'
work_directory directory_tag
copy_files = 'templatedir/*'
named 'workdir' file_save directory_save
aprepro
responses
objective_functions = 1
no_gradients
no_hessians