2019年のまとめ

去年も書いたので今年も書くことにします。あ、年が明けてしまう(´・ω・`)

振り返り

  • 1月 お仕事
  • 2月 お仕事
  • 3月 お仕事
  • 4月 お仕事
  • 5月 PEZY退職
  • 6月 無職
  • 7月 RICOS入社
  • 8月 お仕事
  • 9月 お仕事
  • 10月 お仕事
  • 11月 お仕事
  • 12月 お仕事

5月にPEZYを退職して、7月から計算科学総合研究所(RICOS)さんにお世話になっています。業務内容としては受注のソフトウェア開発と自社開発になります。まだリリース前なので色々は秘密です(´・ω・`)

ソフトウェアの開発に関してはほぼ完全に任せてもらっていて、サービスの設計から実装までやっている感じです。 DockerやKubernetesPythonなどの技術的な部分は社内で簡単な講習をしたりしていて、いくつかはQiitaにも上がっています。

勉強会

RICOSで主催している勉強会にいくつか参加するようになりました

ricos.connpass.com

微分幾何を最初から勉強していく会です。微分幾何は学部生の頃に解析力学から一般相対論の辺りで勉強し、また理研にいた時に情報幾何的にデータ同化をまとめていた(後述)のもあってある程度なじみがあります。

ricos.connpass.com

新しく入社されて谷村氏に情報幾何の話をしてよと言ったらこうなりました。反省しています。

また無職の期間に書き始めたデータ同化の教科書(?)を完成させるための勉強会を始めました

gitlab.com

博士時代の乱流の力学系的アプローチで培った知識を基に、データ同化の枠組みを力学系+情報幾何の言葉で書き換える事が目的です。 まだ理研時代のノートの変換も完了していない程度の進捗なので全く進みません。 勉強会はconnpassには公開せずにセミパブリックにやっています。興味ある方はTwitterでDMもらえればslackに参加できます。

OSS

年始にJuliaにハマって色々遊んでみました

Rust + Intel-MKLが Windowsでも動くようにしたり

qiita.com

FlatBuffersの勉強にコンパイラを書いたりしました(未完成)

qiita.com

7月から毎週土曜日にRustオンラインもくもく会を開催して、OSS活動の時間に充てるようにしました。

rust-online.connpass.com

最初と最後に報告するだけの雑な運営で、たまに寝過ごして居なかったりしましたが(反省しています)、毎回参加してくれているメンバーもいて助かっています。 主にrust-ndarray/ndarray-linalgrust-math のメンテ時間に充てています。

この年末に accel の再始動を開始したので、来年はこちらへのコミットも増えると思います(希望)

github.com

Rust.Tokyo

docs.google.com

東京でRustのカンファレンスをやると聞いて応募したら採用してもらえたので、数値計算の現状について発表してきました。

2018年のまとめ

晦日らしく今年のまとめ記事です。 これは技術記事では無いのでQiitaでなく久しぶり(4年ぶり)にこちらに書きます。

2018年振り返り

  • 1月:理研AICS(当時、現R-CCS)を退職
  • 2月:内定をもらった社長が逮捕されたので様子見で無職
  • 3月:引き続き無職。東京に引越し
  • 4月:PEZY Computingに入社
  • 5月:お仕事頑張る
  • 6月:お仕事頑張る
  • 7月:お仕事頑張る
  • 8月:お仕事頑張る
  • 9月:お仕事頑張る
  • 10月:お仕事頑張る
  • 11月:お仕事頑張る
  • 12月:Advent Calenderにおわれる

博士号を取得して2年弱ほど理研で研究員として働いてきましたが、PEZYに転職してソフトウェアエンジニアになりました。 まだ9ヶ月ほどですが、正直研究者より向いてるように思っています。 主な業務としてはPEZYプロセッサのコンパイラやランタイム、周辺ツールの開発です。 今までは基本的に数値計算のレイヤーやデータの解析、管理のためのコードを書くことが多く、 コンパイラやDMAを行うような領域はあまり経験がなく苦労も多いですが何とかなっています(多分)。

研究者を辞める事には思うところはありましたが、 大学院時代からソフトウェア関係にも進めるようにOSSやQiitaで活動していたり、想定していたプランではあります。

OSS活動

Rust関連のライブラリを主に作ってきました。 理研に居る間に作っていた自分で数値計算用に使うライブラリ群:

はissueには対応していますが、あまり時間が取れずにほとんど放置になっています。実験的に作ったライブラリ

については注目されたわりに全然管理出来ておらず、rust-numpyについては@kngwyuが引き継いでくれてPyO3対応等、だいぶ使えるようになってるはずです。 accelについては最近rust-cudaというwork groupが立ち上がったのでそちらに乗っかっていこうと思っています。というかaccelについては年明けのLTで話をするので何かしないとヤバい…

forcia.connpass.com

他に今年作ったのは

github.com これはお仕事で必要だったので作りました(PEZYのコンパイラLLVMベース)

github.com 小さな計算グラフのライブラリです。自動微分の習作のために作りました。これでハミルトン系の計算を行う記事をAdCで投稿しています

github.com RustのSIMD機能が安定したのも今年ですね。Rustでモンテカルロシミュレーションを行おうと思ったときにメルセンヌツイスターの実装が無かったので本家のC実装のSFMTをRustに移植しました

他にもいくつか作ってる気がしますが(自分でも把握してない)、大きいのはこの3つです。

2019年の抱負

  • Rustにパッチを投げる
  • 数値計算の論文を書く
  • 定期的な運動を行う

ソフトウェアエンジニアになりましたが、理論物理の博士としての特色を出したり出さなかったりしていきたいと思います。

Beamerによる発表小技集

LaTeX2e美文書作成入門第6版に Beamer, TikZの章が追加(?:4版にはなかった)されたので、 記念に私のBeamer小技を公開してみる。

初級編

handout

\documentclass[12pt,handout]{beamer}

とすると、\pause等のアニメーションを考慮しない、 配布用の資料が作れる。

Logo

\logo{\includegraphics[width=1cm]{figure/logo.png}}

プリアンブルに書くと全ページに表示される。

Theme

お気にいりは標準のこれ:

\usetheme{CambridgeUS}

columns

プレゼンでは良く2行のページを使う:

\begin{columns}
    \begin{column}{.4\textwidth}
        ...
    \end{column}
    \begin{column}{.6\textwidth}
        ...
    \end{column}
\end{columns}

column環境の引数で横幅を指定できる。

block

\begin{block}{定常進行波解}
    \footnotesize
    \begin{itemize}
        \item ...
        ...
    \end{itemize}
\end{block}

強調して表示してくれる。column環境の幅を認識してくれる。 これを使用するのと、単なるitemaize環境だけのだと、 大きく見栄えが異なる。 columnsと組み合わせて使うと便利

\begin{block}{KSEのフィルター方程式}
    \begin{equation*}
        ...
    \end{equation*}
    \begin{itemize}
        \item ...
    \end{itemize}
\end{block}
\pause
\begin{columns}
    \begin{column}{.45\textwidth}
        \begin{block}{対称性}
            ...
        \end{block}
    \end{column}
    \pause
    \begin{column}{.5\textwidth}
        \begin{block}{定常進行波解}
            ...
        \end{block}
    \end{column}
\end{columns}

上のブロック、左下のブロック、右下のブロックと順に説明する。

単なる\pauseでなく、もう少し複雑な表示の切り替えには

\begin{columns}
    \begin{column}{.5\textwidth}
        \begin{block}<1>{span-wisely localized}
            \begin{figure}[h]
                ...
            \end{figure}
        \end{block}
        \begin{block}<1-2>{stream-wisely localized}
            \begin{figure}[h]
                ...
            \end{figure}
        \end{block}
    \end{column}
    \begin{column}{.4\textwidth}
        \begin{block}<1>{wall-normally localized}
            \begin{figure}[h]
                ...
            \end{figure}
        \end{block}
    \end{column}
\end{columns}

のようにする(1:全部,2:左下のみ)。

table of contents

\frame{\tableofcontents}

\section, \subsectionで指定されているタイトルを列挙する。 今回の発表の目次的な。

\section{Method}
\frame{\tableofcontents[currentsection]}

目次の内、今のセクションだけ強調表示したスライドを挿入する。 上記の場合、Methodが強調される。

vspace, hspace

上手く位置が調整できない時の最終手段。 \vspce{-1cm}で左に1cm寄る

応用編

幅を自動取得するbox

\newlength{\bw}
\newcommand{\vcbox}[1]{
    \settowidth{\bw}{#1}
    \parbox{\bw}{#1}
}

\settowidthで引数で指定された物 (\includegaphixとか)のサイズを取得して\bwに保存。 \parboxでボックス化する。

TikZ

おまけ程度に:

\begin{tikzpicture}[domain=0:10]
    ...
\end{tikzpicture}

domainは横軸を決める。 図の左端が0、右端が10になる。

長さの定義

\def\distnode{28}
\def\righttoleft{27.5}

何度も使う場合。

矢印

\draw[->] (0,0) -- (9,0) node[right] {\scriptsize $x$};

x軸

塗り潰す

\fill[blue!20!white] (0,0) -- (4.5,0) -- (4.5,1) -- (0,1);

色はbluewhiteの他に、混合色blue!20!white(青:80%,白:20%)、 あるいはRGB指定した色

\definecolor{redblack}{rgb}{.4,0,0}

(プリアンブルで定義しておく)が指定可能。

曲線

\draw[variable=\t,domain=0:4] plot ({\t},{-\aL*(\t-\bL)*(\t-\bL)+\cL}) node {};

domainvariableの動く範囲。

曲線で指定された領域を塗り潰す

\fill[fill=white!60!green] (0,0.5) --
plot [variable=\t,domain=0:4.08] ({\t},{-\aLs*(\t-\bLs)*(\t-\bLs)+\cLs}) --
plot [variable=\t,domain=4.93:0] ({\t},{-\aUs*(\t-\bUs)*(\t-\bUs)+\cUs}) -- cycle;

Links

LLVMリンク集

最近何かと話題のLLVM(low-level virtual machine)。 今回はLLVM初心者が、どうしてLLVMが魅力的と思ったか、 幾つかリンクを紹介する形でまとめます。

リンク集

LLVM フレームワークで実用的なコンパイラーを作成する: 第 1 回

早速ですが、紹介記事です。曰く:

LLVM (Low Level Virtual Machine) は、 任意のプログラミング言語で作成されたプログラムを コンパイル時、リンク時、実行時に最適化するために設計された、 極めて強力なコンパイラー・インフラストラクチャーフレームワークです。 LLVM は多岐に渡るプラットフォームで動作し、 その最大の特徴である、高速に実行されるコードを生成します。

つまりC/C++に限らず、様々な言語で書かれたコードを それぞれのプラットフォームに最適化されたバイナリにコンパイルする事ができます。

実際にLLVMに基づいたコンパイラが多数開発さています。

コンパイラが存在するDはともかく、 PythonLuaをネイティブコードに変換できる事は非常に魅力的に思えます。

またGCCをフロントエンドとして使用できるため、GCCでサポートされている

で書かれたコードはLLVMの中間表現であるLLVM IRにコンパイルする事ができ、 LLVMの最適化の恩恵を受けられます。 もっともこれらの場合、GCCにより最適化されたバイナリを既に使用できるのですが。

この記事はツール(lli, llvm-config, etc.)の使い方、 LLVM APIによる中間コード(IR)の自動生成までを解説しています。

CUDA LLVM Compiler

nVidiaによるGPGPUのためのフレームワークであるCUDAのコンパイラnvccはLLVMに基づいています。

任意の言語で書いたコードをLLVM IR(正確にはそのサブセットであるNVVM)に変換できれば、 nVidiaの提供するNVVMからPTX(GPU用の低級言語)への変換用バックエンドを用いて GPU上で動作するバイナリを生成する事ができます。

つまりCUDAのような少し特殊な言語を使用せずに、 通常のC/C++GPU用のコードに変換しうるという事です。 実際にFortranで実行している猛者がいます:

また直接NVVM書いている人もいます:

CUDAだけでなくOpenCLでも同様の取り組み(?)が有る様です:

The LLVM Compiler Infrastructure Project

本家のHPです。ニュースやダウンロードはこちらから確認します。 LLVMは非常に活発に開発されており、

  • 2014/01/02 3.4 (最新)
  • 2013/07/17 3.3
  • 2012/12/20 3.2
  • 2012/05/22 3.1
  • 2011/12/01 3.0

のようにおよそ半年毎にリリースがあります。

最後に

今後は公式のドキュメントを元に勉強していこうと思います。

vimでひかえめな自動保存

Vim Advent Calendar 2013、 67日目の記事になります。

御存知の通り、 webapi-vimの出現により vimによって簡単にwebサービスを読み書きができるようになりました。 さらにunite.vimvim-metarwを 使用する事で簡単にインターフェイスを構築できます。

しかし、これらのサービスのAPIの応答は、 一般にローカルに保存する場合に比べ圧倒的に時間がかかります。 さらに現状のvimではajaxのようにスクリプトを非同期実行できない。 もしvim-metarwのwriteで毎回送信する場合、 :wと押すたびに数秒待たされるかもしれない。 かといって手動で送信するのは忘れがち。

つまりアクセスの回数を絞った自動保存機能が欲しい

試行錯誤編

という事で試行錯誤が始まります。 多分autocmdにそれっぽいトリガーがあるだろうと思ってhelpを読む事数十分。。。 (あまり読みなれてない)

BufUnload       Before unloading a buffer.  This is when the
                text in the buffer is going to be freed.  This
                may be after a BufWritePost and before a
                BufDelete.  Also used for all buffers that are
                loaded when Vim is going to exit.
                NOTE: When this autocommand is executed, the
                current buffer "%" may be different from the
                buffer being unloaded "<afile>".
                Don't change to another buffer, it will cause
                problems.
                When exiting and v:dying is 2 or more this
                event is not triggered.

多分これっぽいんだけど、なんか後半に良くわからない事が書いてるorz

めげずに<afile>について調べると、

<afile>  When executing autocommands, is replaced with the file name
         for a file read or write.
<abuf>   When executing autocommands, is replaced with the currently
         effective buffer number (for ":r file" and ":so file" it is
         the current buffer, the file being read/sourced is not in a
         buffer).

つまりバッファがアンロードされる時の現在のバッファ(%)が トリガーが指定されたバッファ(<abuf>)と違うかもしれないという事か!!(オウム返し) :bdeleteで消す場合とか:qaで全部閉じる場合を考えろってことか。

ともかくこれで行ける!? <abuf>はきっとexpand()使うんだろう:

function! s:buffer_infos()
    let file_name = expand("<afile>")
    let buffer_number = expand("<abuf>")
    let buffer_name = bufname(buffer_number)
    echo "File name    : " . file_name
    echo "Buffer number: " . buffer_number
    echo "Buffer name  : " . buffer_name
    let lines = getbufline(buffer_number, 1, '$')
    echo lines
endfunction

augroup test_trigger
    autocmd!
    autocmd BufUnload test.vim call s:save_buffer_to_file()
augroup END

多分これでいけるはず!! :so %してバッファを閉じるぜ!!!

File name    : test.vim
Buffer number: 1
Buffer name  : 
[]

(´・ω・`)ショボーン

bufname({expr})                        *bufname()*
        ...
        If the {expr} is a String, but you want to use it as a buffer
        number, force it to be a Number by adding zero to it: >
            :echo bufname("3" + 0)
        If the buffer doesn't exist, or doesn't have a name, an empty
        string is returned. 

これか?

function! s:buffer_infos()
    let file_name = expand("<afile>")
    let buffer_number = expand("<abuf>")
    let buffer_name = bufname(buffer_number + 0)
    echo "File name    : " . file_name
    echo "Buffer number: " . buffer_number
    echo "Buffer name  : " . buffer_name
    let lines = getbufline(buffer_number, 1, '$')
    echo lines
endfunction
File name    : test.vim
Buffer number: 1
Buffer name  : test.vim
[ "function! s:buffer_infos()", "    let file_name = expand("<afile>")", "    let buffer_number = expand("<abuf>")", "    let buffer_name = bufname(buffer_number)", "    echo "File name    : " . file_name", "    echo "Buffer number: " . buffer_number", "    echo "Buffer name  : " . buffer_name", "    let lines = getbufline(buffer_number, 1, '$')", "    echo lines", "endfunction", "", "augroup test_trigger", "    autocmd!", "    autocmd BufUnload test.vim call s:save_buffer_to_file()", "augroup END", ]

大勝利!!! 別バッファから:bdeleteしても上手く動く (`・ω・´)キリッ

まとめ

最終的に

function! s:send(lines)
    " send data to web service
endfunction

function! s:wrapper()
    let buffer_number = expand("<abuf>")
    let lines = getbufline(buffer_number + 0, 1, '$')
    call s:send(lines)
endfunction

augroup ModestAutoSave
    autocmd!
    autocmd BufUnload * call s:wrapper()
augroup END

とすればいい!パターンの部分は適当に。

おわりに

プラグインとして公開しようと思っていたのですが、 autocmdのパターンの扱い(変数が使えない?)がよくわからなかったので無期限延期しました。 結局すごく短かいですし。

最近vimプラグインを作成し始めた新参なので、 間違い等指摘してもらえると助かります。

ctestの導入

ctestはcmakeに付随するテスト実行支援ツールである。 Boost TestやCppUnitとは異なり、あくまで実行を支援するツールである。 公式のページを見ると、ダッシュボードを導入しないといけないような印象を受けるが、 cmake管理化のプロジェクトであれば単独で使用できる。

何ができるか?

あなたがcmake管理化のプロジェクトを開発中、 テストを書く必要があるとする。 テストを書く事の重要性は耳にタコができるほど聴いたが、面倒な事は面倒だ。

ともあれ、mylibraryの機能Func1のテストコードtestFunc1.cppを書いたとしよう。 残念ながら、テストコードは自分でかかなければならない。 しかし、テストコードのビルドと実行は手伝う事ができる。 もしあなたが以下に説明する設定を施している場合、 あなたは単にテストコードtestFunc1.cppを含むディレクトリの CMakeLists.txtに以下の一行を追加すればいい。

mytest(Func1 S testFunc1.cpp mylibrary)

よりよいテストのためには次の行さらに前に追加するべきだろう:

set(CMAKE_BUILD_TYPE Debug)

これであなたはそのディレクトリで

make

とすれば、このコードをTEST_Func1_Sコンパイルする事ができ、

make test

で実行する事ができる。 テストした結果は

Test project /path/to/mylibrary/test
      Start  1: TEST_Func1_S
 1/1  Test  #1: TEST_Func1_S .....................   Passed    0.02 sec

100% tests passed, 0 tsets failed out of 1

Total Test time (real) = 0.02 sec

のように表示される。 もちろん実行ファイルをそのままターミナルから実行する事も可能である。

これは現在のディレクトリ以下にあるテストを再帰的に実行するので、 プロジェクトの一番上で実行すれば全てのテストが実行される。 実行ファイルが異常終了した場合にはテストが失敗したと見做され、 まとめて表示される。

これによりコードを変更した際の再テストが

cd $PROJECT_HOME
make test

とするだけでよくなる。

使い方

この記事では読者はcmakeの基本的な使い方(add_executableくらい)を知っているとする。 まず先に私のCMakeLists.txtの抜粋を示す。

enable_testing()
add_custom_target(build_test)
add_custom_target(short_test COMMAND "ctest" "-R" "TEST_.*_S")
add_custom_target(long_test COMMAND "ctest" "-V" "-R" "TEST_.*_L" "2>&1" ">" "long.log" "&")
add_dependencies(short_test build_test)
macro(mytest name type src libs)
    set(test_name TEST_${name}_${type})
    add_executable(${test_name} ${src})
    target_link_libraries(${test_name} ${libs})
    add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name})
    add_dependencies(build_test ${test_name})
    unset(test_name)
endmacro(mytest)

やっている事は以下の4つ:

  • ctestの有効化 enable_testing()
  • targetの追加 build_test, short_test, long_test
  • 依存関係の追加 (short_test depends on build_test)
  • mytestマクロの定義

ctestの有効化

enable_testing()

これを行なってcmakeを実行すると各ディレクトリにTestingディレクトリが作成される。 ctestを使用するには必須である。

targetの追加

cmakeではshellスクリプトを実行するターゲットを作成する事ができる。

add_custom_target(short_test COMMAND "ctest" "-R" "TEST_.*_S")

によって

make short_test

は依存する物(build_test)をmakeした後、

ctest -R TEST_.*_S

を実行する。 -Rは名前が正規表現に一致するテストをすべて実行する。 実行ファイル名にSが付いているのはこのためである。 というのも上述のコードは私の数値計算のコードなので、 一秒以内に終るもの(Sort)もあれば、数十分かかる物(Long)もある。

依存関係の追加

make short_test

とした際にbuild_testコンパイルされるようにしたのが、

add_dependencies(short_test build_test)

この行である。 さらにbuild_testが全てのテストに依存するようにしたのが マクロ中の

    add_dependencies(build_test ${test_name})

この行である。 つまり結局

make short_test

とすれば全てのテストがコンパイルされ、実行されるのである。

マクロの定義

macro(mytest name type src libs)
    set(test_name TEST_${name}_${type})
    add_executable(${test_name} ${src})
    target_link_libraries(${test_name} ${libs})
    add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name})
    add_dependencies(build_test ${test_name})
    unset(test_name)
endmacro(mytest)

さていよいよマクロの定義である。 macroは最初の引数にマクロの名前を、 以降の引数にマクロの引数を取る。 setでテスト名を生成し、 add_executableで実行ファイルを生成する。 肝心なのがadd_testで、これがテストを定義している。 第一引数がテストの名前、第二引数がテストの実行ファイルである。 この際実行ファイルのパスに注意する。また追加で引数も追加できる。

上述の通りこれをbuild_testの依存関係に追加する事で、 make short_testで一気にmakeできる。

何故複雑な依存関係を構築したか?

ここまでで読者は不思議に思ったに違いない: 依存関係を設定しなくても全てのテストがmakeされるのではないかと。 その通りである。 しかし、ある設定をしている場合、そうはならない。

add_subdirectory(test EXCLUDE_FROM_ALL)

がその正体である。 これはtestディレクトリ以下を追加するが、 makeではtest以下のexecutableはmakeしない、という指示である。 これにより不要なビルドを避ける事で、 ビルド時間を削減するという恩恵が得られる。 上記の設定はこの環境下で行なったための回避策である。

hateblo.vimのmetarw化

pluginのテストのためにこの記事を使用しているため、 情報がおかしい場合があります。 ご注意ください。

hateblo.vimをmetarw化した。

GitHub - termoshtt/hateblo.vim

気にいらなかった挙動は以下の2点

  • 記事名のファイルが所構わず作成される
  • 新規記事を書き始めにくい
:e hateblo:

で起動する。

コードを読む過程でちょっと書き換えすぎたので、 現在整理中。そのうちpull requestをなげる予定。 refactoring部分とmetarw化の部分を分けてrequestすると思う。

まだ不十分な点が多く、

  • New Entryで記事名の入力の際に何も表示されない(入力は成功する)
  • 投稿時にwebの応答を待つため、1秒近く止る

はそのうち改善する。

Entryのtitleとcategoryの指定方法を変えた。 この記事を

:e hateblo:{entry_id}

で開くと({entry_id}は実際には20桁くらいの数値)先頭に、

TITLE:hateblo.vimのmetarw化
CATEGORY:vim

という行が入る。 ここを保存する際に読み込むので、 この行を変更するとタイトルとカテゴリが変更できる。 これならタイトルの入力中に補完が効く。

だいぶ使用できるようになってきた。

投稿した際の遅延だけはどうしようもないのか?