[C++]一時ファイル生成を不要に。Gnuplotライブラリ更新(3)。

以前から公開しているC++GnuplotライブラリADAPT-GPM2に対して、estshorter様から新機能のプルリクエストを頂きめでたくマージされたので、その情報+αを書き留めておく。

簡潔に言うと、Gnuplotにプロットするデータを送るために、従来は一時ファイルが作成されていたところ、これを作成しないようにするオプションが追加された。内部的にはGnuplot 5.2以降で追加されたdata blockを用いており、パイプ経由でデータを入力する方式である。

GPMCanvas2D d("output filename");
d.EnableInMemoryDataTransfer(true);

のようにすることでこのオプションが有効になり、一時ファイルが作られなくなる。当然だがGnuplot 5.2以上が必要である。悲しいかな私はとある理由によって未だ5.0を使っているので、せっかく作ってもらったこの機能もなかなか活用できない。Gnuplotって複数のバージョンの導入はできるんだっけ……。

また私の方でちょっと改良して、処理を数倍高速化させた。

個人的な動機

Gnuplotを使うとき、データの入力にテキストファイルを介さなければならないのは長らく悩みのタネだった。私がDISLINやPLPlotなど様々なライブラリを探し回っていた大きな原因はこの一時ファイルだったのだ。

私の研究分野は1000万位のサンプルが記録されている巨大なデータをしばしば扱う。対象によっては膨れ上がって億を軽く超えてしまうこともある。あまり一般的なデータ解析ツールを使ったことがないのだが、普通のデータベースなどで扱うにはちょっと躊躇ってしまうサイズだろうと思う。このデータの巨大化は私が統計解析ライブラリを自作した理由の一つでもある。例えばビッグデータ解析によく用いられるライブラリと言うとpandasが有名だが、調べた限りpandasでもまだ足りないようだ。pandas以上の速度とpandasでは不可能な処理、速度と柔軟性の両立のためには自作するしかなかった。おかげで今ではたかだか億単位なら特に困らなくなった。

ただ問題はその後だ。Gnuplotで1000万件のデータをどうプロットするのか、という話である。テキストファイルに1000万件も記録するとファイル入出力だけで多大な時間がかかったりするし、ファイルサイズが数百MBもの大きさを持ってしまう。億を超えると更に問題だ。このあたりの問題は例えばpythonのmatplotlibなどでも解決しないようだ。あちらも膨大なデータのプロットは著しく遅いらしいのだ。pythonを真面目に導入している同期が愚痴っていた。
普段はヒストグラムなどに直してから描画するので問題は表面化していなかったが、たまに散布図を描こうとするとひどく時間がかかったりする。わざわざデータを間引いて描画することも多かった。

ただ今回一時ファイルに頼らない方法を導入してもらい(それを私がちょこちょこ弄って高速化し)、幾分改善された。私の環境では1000万件のプロットに一時ファイルの場合で40秒ほどを要していたところ、11秒まで短縮された。GB前後の一時ファイルが作られないだけでも大きい上、有意義な速度向上まで果たせた。もうちょっと向上させる方法はある気がするが、費用対効果が薄そうなのでこのあたりで満足しておく。