csvからparquetに変更してMLパイプラインのパフォーマンスを改善した話
とあるMLパイプラインの実行にかなり時間がかかっていたので調査したところ、ファイルの書き込み処理にかなりの時間がかかっていました。
書き出すファイルフォーマットをcsvからparquetに変更したら1ファイルあたり20分程度処理が高速化され、パイプライン全体で6時間程の短縮になりました。
これまでパフォーマンスとファイルフォーマットの関係性をあまり気にしてこなかったので、いい機会だと思い深掘りしてみました。
前提
今回パフォーマンス改善で検証したファイルは、数十万行、5000列くらいのもの
pandasのto_csv
関数やto_parquet
関数を使用
CSVで20分程度かかっていた処理が、parquetでは2秒くらいになった
列指向フォーマットとは
ファイルフォーマットの分類は
- テキストフォーマット
- 行指向フォーマット
- 列指向(カラムナ)フォーマット
の3種類に分けられるそうで、CSVはテキストフォーマットに分類されるらしいです(行指向に分類しているケースも見る)。
それに対してparquetは列指向フォーマットに分類されます。
この分類自体はよく聞くものの、ファイルのI/O処理におけるパフォーマンスで20分もの差が出る理由を深掘りしたいと思ったのが元々の記事執筆の動機でした。
ただちょっと古めの記事ではあるものの、以下の記事が列指向フォーマットの特徴についてよくまとめられていたので詳細は割愛します。
(一番大事なところ丸投げしてしまいました…)
とりあえず列指向だと圧縮をかけてデータを効率的に管理できるようです。
列指向だとデータを圧縮しやすいみたいなのは聞いたことがあるものの、その方法にも色々なものが存在していて列ごとに最適なものを選択しているようです。
今回のケースにおけるパフォーマンス向上理由の考察
上述したように圧縮方法には色々な方法があります。
ただ総じてカーディナリティが低い列の場合に圧縮効果が高くなる傾向にあるように見えます。
今回使ったデータはnullになることが多いカラムや値が入っていてもカーディナリティが低いカラムが多かったりと、全体的に圧縮が効きやすいようなデータ構造だったように思います。
加えて数十万行 x 5000列くらいのデータ。
このサイズなら列指向で圧縮を効かせた方が効率的に読み書きできるんだろうなと思ってます。
これらは調べた上での考察でしかないので裏取りは取れてませんが、今回のミッションはMLパイプラインの処理時間を短くすることだったのでここまでとします。
また、ファイルサイズにおいても圧縮した効果が見られ、
CSVの時には1.3GBくらいだったファイルサイズがparquetでは130MB程度と、およそ1/10くらいになりました。
ちなみに推論結果はCSVの時と変わらないことは確認できました。
まとめ
ファイルの読み書きにおいて、かなり大きいサイズのファイルであればファイルフォーマットの検討は価値がありそう
特に圧縮が行われやすいようなカーディナリティ低いカラムに対しては効果的
普段ここまでのファイルサイズのものを扱うことが中々ないのでいい勉強になりました
今後はMLパイプラインなどの大規模なデータを扱う時はparquetは有力な選択肢の一つとして考えたいです