FireDucksに関するTIPS
本ドキュメントでは、FireDucksを利用して性能を出すためのTipsを紹介します。
Fallbackの回避
現時点でFireDucksがサポートしていないpandas APIは、FireDucksの内部でpandasを呼び出して実行するfallbackという仕組みがあります。 この仕組みにより、ユーザープログラムから見るとFireDucksがそのAPIをサポートしているように見えるため、pandasとの互換性が高まります。 一方で、性能の観点ではpandasを呼び出すためのデータ変換のオーバヘッドがかかります。 FireDucksを用いた際に、思ったほど性能が上がらな場合はfallbackが原因であることが多くあります。
FireDucksの内部でfallbackが起こっているかどうかは、以下のように環境変数FIREDUCKS_FLAGS="-Wfallback"を指定して実行することで確認できます。
$ FIREDUCKS_FLAGS="-Wfallback" python -mfireducks.pandas sample.py
sample.py:3: FallbackWarning: pandas.read_csv 0.006366 sec getobj 0.000001 getattr 0.000010 args 0.000020 call 0.005656 unsupported encoding: shift_jis
df = pd.read_csv("test.csv", encoding="shift_jis")
この例では、read_csvメソッドのencodingオプションの値としてshift_jisをFireDucksがサポートしていないためにfallbackが起こっています。Warningメッセージ中の0.006366 secの部分がこのfallbackにかかった時間を示しており、この行の最後にfallbackが起こった原因が表示されています。 この例ではcsvファイルのエンコーディングを変えることなどで、このfallbackを回避することが可能です。
回避することが困難で性能への影響が大きい場合は、FireDucksでの対応を検討しますのでご相談下さい。
applyメソッドやforループを避ける
DataFrameやSeriesからapplyメソッドやforループなどで、1行や1要素単位でデータを取り出しながら処理を行うと大きなオーバーヘッドが発生します。できる限りDataFrameやSeriesのAPIを組み合わせて記述して下さい(これはpandasでも同様です)。
例えば以下のループではDataFrameを一行ずつ処理しています。
s = 0
for i in range(len(df)):
if df["A"][i] > 2:
s += df["B"][i]
これはDataFrameのAPIを用いると以下のように書き換えることができます。
s = df[df["A"] > 2]["B"].sum()
numpyを利用した高速化を避ける
pandasの高速化テクニックとして、pandasのDataFrameやSeriesをnumpyの配列に変換し、numpyで処理するという方法が取られることがあります。 FireDucksはpandasを高速化の対象としていますので、numpyに変換してしまうと、性能向上の機会を失ってしまうことになります。 FireDucksを利用する場合は、numpyの利用を避け、pandas APIで記述するほうが性能が向上しやすくなります。
最後に
FireDucksを用いて高速化するためには、プログラム中のpandasを利用している部分とそれ以外を切り分けて、pandas以外の部分の実行時間を削減することも重要です。
処理時間のプロファイリング、pandas以外の部分を削減するための検討、FireDucksの性能を引き出すためのプログラム変更など、高速化に関するご相談がございましたら、お気軽にご連絡下さい。