bobuhiro11's diary

2016年総括

31 Dec 2016
[lab]

例年どおり今年一年を振り返ってみることにした. 研究生活,アルバイト,趣味などを,項目ごとに思い出してまとめておく. 今年で,学生生活が終わることになる. ただ,修論と論文誌が残っているので, 年が開けても忙しくなりそう. 来年4月からは,関東に引っ越すことになった. UFJ,宝塚,通天閣にまだ行ってないので,関西にいる間に一度は行っておきたいところ.

研究

今年は,2つの国際会議で発表をした. 1つ目は,ギリシャで開催された会議である. 具体的には,ギリシャ・クレタ島の北部に位置する街イラクリオンで開催されたPDP2016である. これは,研究室に所属してから,初めての海外発表だった. 自分の発表は,会議全体からみて後半のほうだったと思う. 15分くらい拙い英語で発表をした. ただ,時間の都合で質疑応答が省略されたため,ちゃんと伝わったかどうかわからない. 移動の合間にクノッソス遺跡,パルテノン神殿,アテネ国立考古学博物館,ゼウス神殿を観光して周った.

2つ目は,11月にソルトレイクシティで開催された会議SC16である. ワークショップで発表した. 今回は,質問やコメントが3件あったが,ちゃんと答えられなかった. 言いたいことがあっても,なかなか英語が出てこなかった. 観光の時間はあまりなかったが,街の中心部にあるテンプルスクエアでオルガンリサイタルを聴くことができた. 復路で,ソルトレイクシティ発ロサンゼルス行きの飛行機がエンジントラブルか何かで遅れてしまうトラブルがあった.

他には,松本市で開催されたSWoPP2016で発表した. 後輩と一緒に参加して,発表をした. さらに,先輩が表彰受賞のために参加していて,一緒に懇親会で話をした.

  • 2/15-22 PDP2016@ギリシャ
  • 8/8-11 SWoPP2016@松本
  • 9/12-13 旅行@金沢
  • 10/5 GPU Japan@東京
  • 10/5-7 OpenMPCon,IWOMP@奈良
  • 11/13-19 SC16@ソルトレイクシティ

アルバイト

3年くらいお世話になっている梅田の会社で,引き続きアルバイトとして,仕事をしていた. 今年は,サービスそのものの開発の他に,周辺ツールの整備をしていた. まず,サムネイル画像などを配信するためのCDN(Contents Delivery Network)を構築した. Nginxとそのモジュールで画像処理を行い,Amazon CloudFrontで配信した. 次に,Elasticsearchで各種ログを収集する環境を整えた. Amazon RDS,PHP,Nginxなどのログを収集・検索できるようになった. 最後に,cronで管理していたジョブをRundeckで管理するよう置き換えた. ジョブの実行ログをAmazon S3に,プロジェクトの設定をAmazon RDSに,それぞれ格納することで, 冗長構成になっている.

アイドル

しゃちほこ,アプガを中心に,いくつかのライブに参戦した. しゃちほこメンバが髪色を変えてみたり,干され気味の曲をセトリに取り入れてみたり,と満足度が高かった. アプガは,初の武道館ライブをやった.最後の挨拶によると,どうやら2期メンバを募集するらしい.

  • 1/3 アプガ@梅田
  • 5/21-22 しゃちほこ@幕張
  • 7/17 アプガ@天満
  • 7/29 Edge Dub Monkeyz@難波
  • 8/3 しゃちほこ@名古屋
  • 9/10 しゃちほこ@長崎
  • 9/11 しゃちほこ@福岡
  • 10/28 しゃちほこ@難波
  • 11/8 アプガ@東京

バイク

ほぼ毎日乗っているので,徐々に不具合が出てきた. 順次,オイル,フィルター,タイヤ,バッテリ,スパークプラグ,チェーン,スプロケを交換した. 加えて,二輪用ETCを取り付けた.

その他

吹田スタジアムのこけら落としを観戦した. アデミウソンや藤本らが移籍してきて,FW呉屋やDF初瀬がユースから上がってきた. また,途中から宇佐美がブンデス・FCアウクスブルクへ移籍した.

今年は,競プロのオンサイトコンテストCODE FESTIVAL本戦に参加した. AからDの4完で,1500点.パーカーラインが1600点だったので届かず. 今年から海外勢が参加していた. touristが圧倒的だった.やはりオンサイトのコンテストは楽しい.

  • 2/14 vs名古屋@吹田
  • 6/25 vs名古屋@吹田
  • 10/30 大阪マラソン@大阪
  • 11/26-27 CODE FESTIVAL2016@東京
  • 12/18 チャリティーマラソン@大阪

RTX1200初期設定

17 Dec 2016
[network]

自宅用にルータRTX1200を買ってきた 1. 中古で2万円弱だった. GUIで設定できるところはGUIで設定し,残りをCUIで設定した 2. 具体的には,PPPoEとフィルタをGUIで設定し,VPNとDDNSをCUIで設定した. 忘れないように,設定内容をまとめておく. なお,工場出荷状態への初期化は, 前面のmicroSDUSBおよびDOWNLOADのボタンをすべて押下しながら, 電源を入れることで行われる. 工場出荷状態では,LAN1ポートが192.168.100.1/24で初期化され,DHCPが有効になっているので, telnetですぐに接続できる. telnetの他にも,コンソールやhttpで接続できるので,適当に接続する.

> show config
ess=**:**:**:**:**:** MAC-Address=**:**:**:**:**:**
login password encrypted *
administrator password encrypted *
# デフォルトゲートウェイ
ip route default gateway pp 1
# LAN1ポートのIPアドレス
ip lan1 address 192.168.100.1/24
# ARPの代理応答
ip lan1 proxyarp on
# フィルタ
ip lan1 secure filter in 100000 ...
# PPPoE
pp select 1
 description pp PRV/PPPoE/0:***
 pp keepalive interval 30 retry-interval=30 count=12
 pp always-on on
 # LAN2ポートを使う
 pppoe use lan2
 pppoe auto disconnect off
 pp auth accept pap chap
 # PPPoE接続時のID,パスワード
 pp auth myname ****@**** ****
 ppp lcp mru on 1454
 ppp ipcp ipaddress on
 ppp ipcp msext on
 ppp ccp type none
 ip pp secure filter in  200003 ...
 ip pp secure filter out 200013 ...
 ip pp nat descriptor 1000
 # DDNS, netvolante
 netvolante-dns use pp server=1 auto
 netvolante-dns hostname host pp server=1 ****.aa0.netvolante.jp
 pp enable 1
# VPN
pp select anonymous
 pp name vpn
 pp bind tunnel1
 # PPP認証方式
 pp auth request mschap-v2
 # VPN接続ユーザ,パスワード
 pp auth username **** ****
 ppp ipcp ipaddress on
 ppp ipcp msext on
 ip pp remote address pool dhcp
 ip pp mtu 1258
 pp enable anonymous
tunnel select 1
 tunnel encapsulation l2tp
 ipsec tunnel 1
  ipsec sa policy 1 1 esp aes-cbc sha-hmac
  ipsec ike keepalive log 1 off
  ipsec ike keepalive use 1 off
  ipsec ike local address 1 192.168.100.1
  # NATトラバーサル
  ipsec ike nat-traversal 1 on
  # 認証鍵,pre-shared key
  ipsec ike pre-shared-key 1 text ****
  ipsec ike remote address 1 any
 l2tp tunnel auth off
 l2tp tunnel disconnect time off
 l2tp keepalive use on
 ip tunnel tcp mss limit auto
 tunnel enable 1
# フィルタ
ip filter 100000 reject * * udp,tcp 135 *
   (略)
# NAT
nat descriptor type 1000 masquerade
nat descriptor masquerade static 1000 101 192.168.100.1 esp
nat descriptor masquerade static 1000 102 192.168.100.1 udp 500
nat descriptor masquerade static 1000 104 192.168.100.1 udp 4500
ipsec auto refresh on
ipsec transport 1 1 udp 1701
dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.100.2-192.168.100.191/24
# DHCP
dns server pp 1
dns server select 500001 pp 1 any . restrict pp 1
dns private address spoof on
snmp sysname yamaha-rtx1200-************
l2tp service on
statistics cpu on
statistics memory on
statistics traffic on

参考


Ansibleのメモ

12 Dec 2016
[ansible]

最近,Ansibleを使うようになった.ちょうどAnsibleの解説本「Ansible完全読本」が,Kindle Unlimitedで公開されていたので読んでみた.インストール方法や使い方は省いて,今後ハマりそうな点だけをメモしておく.

  • 設定ファイルは,YAML形式に準拠して記述する. 配列や連想配列を扱う際は,基本的に一行に一要素を記述する. 配列は- ,連想配列はkey: を接頭辞として,要素をその後ろに続けて書く. 空白文字が入っていないと文法エラーになるので,注意する. 例外として,=を使って,連想配列を定義できるが,文法がバラバラになってしまうので,使わない方が良い.
  • 設定ファイルを編集し,その後デーモンを再起動したい場合は,Handlerを使う. Hanlderによって,デーモンが複数回再起動することを防げる.
  • サーバに依存する値を設定ファイルに埋め込みたい場合は,Jinja2モジュールを利用する. このとき,その設定ファイルの名前に,nginx.conf.j2のように,.j2を付与する.
  • 設定ファイルがAnsibleによって編集されたことを明示するために,設定ファイルの先頭にansible_managedをコメントとして,追加しておくと良い. これは,日付などに置換される.
  • 設定ファイルを編集する際に,backup: trueとしておくと,バックアップファイルを作成できる. また,validate: ...としておくと,設定ファイルの文法エラーによるデーモンの起動失敗を未然に防げる.
  • サーバの一覧は,Inventoryファイルとして管理する. Inventoryファイルには,静的Inventoryファイルと動的Inventoryファイルがあり, ファイルに実行権限が付与されているか否かによって解釈が決定する. 静的Inventoryファイルには,ホスト名をテキストで列挙する. 一方,動的Inventoryファイルはスクリプトとして記述し,実行時にホスト名を決定する. また,タスクによって,柔軟にInventoryを操作することもできる. これは,OpenStackのAPIを叩いて新規VMを作成,その後VMを初期化したい場合などに有用である.
  • ansible-playbookコマンドは,Playbookに明示されたタスクに先立って,暗黙的にsetupタスクを実行する. setupタスクは,OSの種類やホスト名などFactと呼ばれるサーバの情報する. 対象サーバがOpenStackやAWS EC2によって管理されている場合には,Factに付加情報を追加できる.
  • Version2以降では,Taskの一層外側にBlockという概念があり, Blockごとにtry,catchおよびfinaly処理のような例外処理を記述できる.
  • さらに,Blockの外側にRoleという概念がある. 基本的には,サービスごとに独立してRoleを管理するのが良い. また,Roleを集めたAnsible Galaxyと呼ばれるリポジトリがある.
  • 共通する処理を繰り返す場合は,with_itemsなどのwith*命令を利用する. ただ,with*命令は,種類が多いので,その都度検索するのが良いかもしれない.
  • 1つサーバでだけ実行したい処理やローカル実行したい処理には,例外的に,run_oncelocal_actionを利用する.
  • SSHの同時接続数は,forksオプションによって設定する(デフォルトは5).
  • Playbookは,step実行や特定tas実行を組み合わせて開発する. もし,既存のモジュールで不十分であれば,Pythonによってモジュールを自作できる.

ディレクトリ構造

サービスごとにRoleを作っていき,site.ymlから呼び出すという構成が良い. ディレクトリ構造が複雑になるので,テンプレートをダウンロードすると良いかもしれない.

site.yml            # Playbookファイル
hosts               # Inventoryファイル
roles/
  role_name/        # Role名
    tasks/
      main.yml      # Roleを構成するタスク
    handlers/
      main.yml      # ハンドラ
    vars/
      main.yml      # 上書きしない変数
    defaults/
      main.yml      # 上書きする変数
    meta/
      main.yml      # Roleの依存関係
    files/
      index.html    # Copyで転送するファイル
    templates/
      nginx.conf.j2 # Jinja2モジュールのテンプレート群

NUMAポリシー

07 Oct 2016
[numa]

NUMA環境で,スレッドやメモリの配置を明示的に指示する方法を調べたので,メモしておく. 1つの筐体に複数のマルチコアCPUを搭載する環境では,メモリはCPUごとに接続される. このような環境では, バスを介して直接つながったメモリ(ローカルメモリ)とCPUの間で,高速にデータを転送できる. 一方,直接つながっていないメモリ(リモートメモリ)にデータを転送するためには, QPI(QuickPath Interconnect)などのインタコネクトを介して, 他のCPUソケットを経由する必要がある. このようにメモリアクセスの仕組みが複数存在する環境は, NUMA(Nun Uniform Memory Access)と呼ばれる.

NUMA環境で,マルチスレッドプログラムをチューイングするためには, スレッドをどのコアに割り当てるか,データをどのメモリに配置するかが重要になる. これらの制御は,numactlコマンドあるいはlibnumaライブラリによって実現できる.

NUMA環境の例

numactlによる制御

ソースコードを修正できない状況(あるいは面倒くさい状況)では, numactlコマンドを使って,アフィニティを設定する. --cpubind=<nodemask>オプションでスレッドをどのノードで実行するか指示し, --membind=<nodemask>オプションでデータをどのノードのメモリに配置するかを指示する. <nodemask>には,--membind=0,1のようにノード番号をカンマ区切りで記述する. 他にも, 優先してメモリを割り当てるノードを指示する--preferred=<nodenumber>オプションや 複数のノードにインタリーブでメモリを割り当てる--interleave=<nodemask>オプションがある. ノード番号などハードウェア情報は,--hardwareオプションで確認できる. また,プロセスに割り当てられたポリシーを確認するには,--showオプションを使う.

# スレッドをノード0,データをノード0および1に配置
$ numactl --cpubind=0 --membind=0,1 ./a.out
# メモリをインタリーブに配置し,numactl --showで確認
$ numactl --interleave=all numactl --show

libnumaによる制御

ソースコードを修正できる状況では,libnumaを使う. numactlはプログラム全体のメモリ割付けを制御するが, libnumaは個々のメモリ領域を個別に制御する. libnumaを利用するには,コードにnuma.hをヘッダを追加し, 共有ライブラリをリンクする(-lnuma). ノード番号の集合<nodemask>は,nodemask_t型変数に格納する. メモリの確保では,どのようにメモリを確保するのかに従って, 適切なnuma_alloc_*ファミリの関数を利用する. メモリの解放には,共通してnuma_free関数を利用する. さらに,numa_run_on_nodeあるいはnuma_run_on_node_mask関数を使うことで, スレッドをどのノードで実行するかを明示できる.

nodemask_t m;              // ノード番号の集合を格納する変数m
nodemask_zero(&m);         // mを初期化
nodemask_set(&m, 2);       // ノード番号2を有効に
nodemask_clr(&m, 2);       // ノード番号2を無効に
nodemask_all_nodes(&m);    // すべてのノードを有効に
nodemask_no_nodes(&m);     // 空集合に
nodemask_isset(&m, 2);     // ノード番号2がセットされていれば真

size_t s = 4 * 1024;       // データサイズ4KB

// 2番目のノードに確保
void *mem1 = numa_alloc_onnode(s, 2);
// すべてのノードにインタリーブに確保
void *mem2 = numa_alloc_interleaaved(s);
// mで示されたノードにインタリーブに確保
void *mem3 = numa_alloc_interleaaved_subset(s, m);
// ローカルメモリに確保
void *mem4 = numa_alloc_local(s);

// メモリ解放
numa_free(mem1,s); numa_free(mem2,s); numa_free(mem3,s); numa_free(mem4,s);

// 現在のスレッドをノード1で実行
numa_run_on_node(1);

// 現在のスレッドをmに含まれるどこかのノードで実行
nodemask_zero(&m);
nodemask_set(&m,1);
nodemask_set(&m,2);
numa_run_on_node_mask(m);

OpenMPによる制御

OpenMPを使ってマルチスレッドを実現している場合には,環境変数によってアフィニティを制御する. 制御方法は,コンパイラごとに異なり,例えば, PGIコンパイラであればMP_BINDおよびMP_BLISTを設定する.

参考


移流方程式の数値解析

26 Apr 2016
[advection]
  • 簡単のため1次元の波で考える
  • 時刻\(t\)における座標 \(x\) の値を \(f(x-ut)\) とする
    • 例えば,正弦波が速度\(u\)でx軸正方向に進むなら,\(f(x-ut) = sin(x-ut)\)
  • この時,\(\frac{\partial f}{\partial t} + u \frac{\partial f}{\partial x} =0 \)が成り立つ.これが移流方程式

1次風上差分法

  • 直線で近似する
  • 数値解析なので,\(x\)は\(\dots,x_{i-1},x_i,x_{i+1},\dots\)のように離散的
  • \(x = x_i\)における\(f\)の近似を\(F_i^n(x)\)とする
    • この手法は直線で近似するので,\(F_i^n(x)=a(x-x_i) + f_i^n, a = \frac{f_i^n - f_{i-1}^n}{\Delta x}\)
  • ただし,\(f_i^n\)は\(x = x_i\)において時間ステップを\(n\)回進めた時の値
    • 1時間ステップあたり時間は\(\Delta t\)だけ進む
  • 時間ステップを進めると,$f_i^{n+1} = F_i^n(x_i-u\Delta t) = a(-u \Delta t) + f_i^n= - \frac{u \Delta t}{\Delta x}(f_i^n - f_{i-1}^n) + f_i^n$
  • プログラムでは,$K=u \frac{\Delta t}{\Delta x}$として以下を繰り返すだけ
  • 図は,矩形波を与えたもの
  • 風下もある
for(i=1; i<99; i++) f_new[i] = -K * (f[i]-f[i-1]) + f[i];
for(i=1; i<99; i++) f[i] = f_new[i];

upwind_difference

Lax Wendroff法

  • 二次関数で近似する
  • $F_i^n(x) = a(x-x_i)^2 + b(x-x_i) + c$で近似する
  • $a,b,c$3つの定数が必要なので,$x$に適当に値を入れて,
    • $F_i^n(x_{i-1}) = a \Delta x ^2 - b \Delta x + c = f_{i-1}^n$
    • $F_i^n(x_{i}) = c = f_{i-1}^n$
    • $F_i^n(x_{i+1}) = a \Delta x ^2 + b \Delta x + c = f_{i+1}^n$
    • ただし,$x_{i+1} - x_{i} = x_{i} - x_{i-1}=\Delta x$
  • これを解いて,
  • 時間ステップを進めると,
  • プログラムでは,風上差分と同様に$K=u \frac{\Delta t}{\Delta x}$として以下を繰り返すだけ
for(i=1; i<99; i++) f_new[i] = f[i] - K*K*(f[i+1]-f[i-1])/2.0 + K*K*(f[i+1]-2*f[i]+f[i-1])/2.0;
for(i=1; i<99; i++) f[i] = f_new[i];

lax_wendroff

CIP法

  • 関数自身に加え,その微分も移流させ,3次関数で近似
  • まず,移流方程式$\frac{\partial f}{\partial t} + u \frac{\partial f}{\partial x} = 0$を$x$で微分する
    • $\frac{\partial g}{\partial t} + u \frac{\partial g}{\partial x} = -g \frac{\partial u}{\partial x}$
  • 次に$f$を$F_i^n(x) = a(x-x_i)^3 + b(x-x_i)^2 c(x-x_i) + d$で近似する
  • $F_i^n(x)$も$x$で微分しておくと,
    • $\frac{d F_i^n(x)}{dx} = 3a(x-x_i)^2 + 2b(x-x_i) + c$
  • $a,b,c,d$4つの定数を適当に求めていく.
    • $F_i^n(x_i) = d = f_i^n$
    • $\frac{d F_i^n(x_i)}{dx} = c = g_i^n$
    • $F_i^n(x_{i-1}) = -a \Delta x^3+b \Delta x^2 - c \Delta x + d = f_{i-1}^n$
    • $\frac{d F_i^n(x_{i-1})}{dx} = 3a \Delta x^2 - 2b \Delta x + c = g_{i-1}^n$
  • これを解いて
  • 時間ステップを進めると,
dx = 1.0;      // dx
d  = -dx;      // -dx
gzi = -dx * K; // -dx * u * dt/dx = -u*dt
for(i=1; i<99; i++){
    a = (g[i] + g[i-1]) / (d*d) + 2.0 * (f[i]-f[i-1])/(d*d*d);
    b = 3.0 * (f[i-1]-f[i])/(d*d) - (2.0*g[i]+g[i-1])/d;
    f_new[i] = ((a*gzi+b)*gzi+g[i])*gzi+f[i];
    g_new[i] = (3.0*a*gzi+2.0*b)*gzi++g[i];
}
for(i=1; i<99; i++){
    f[i] = f_new[i];
    g[i] = g_new[i];
}

cip

参考文献