Blog
ブログ

2021年09月27日

【第27回勉強会】CythonによるPythonの高速化と画像の圧縮符号化の概要



第27回勉強会では、CythonによるPythonの高速化と画像の圧縮符号化の概要について発表がありました。


CythonによるPythonの高速化

Pythonは遅い?

Pythonは実行速度の遅いプログラミング言語だと言われることが多いですが、なぜでしょうか?
遅い理由として下記の理由が挙げられます。


  • インタプリタ言語であり実行時に逐次翻訳を行うため、事前にコンパイルされた言語と比較し実行時間が長い
  • 動的型付け言語であり実行時に型の決定をここなうため、事前に型指定された静的型付け言語と比較し実行時間が長い
  • GILによりバイトコードを実行中の単一スレッドに他のスレッドの処理がロックされるため、待ち時間が発生し並列処理の実行時間が長い

  • 一方で、記述やプロトタイピングがしやすいというメリットもあります。
    そこで、Cythonによる高速化です。

    Cythonとは

    CythonnのOverviewページには下記のような説明がなされています。

    “[Cython] is a programming language that makes writing C extensions for the Python language as easy as Python itself. It aims to become a superset of the [Python] language which gives it high-level, object-oriented, functional, and dynamic programming.”


    Cythonの特徴として下記が挙げられます。

  • Pythonとほぼ同じ記述方法が利用できる
  • 事前にコンパイルが必要
  • nogilの指定ができる
  • Pythonのみから呼び出せるdef, Cythonのみから呼び出せるcdef, 両方から呼び出せるcpdefを有するを宣言可能

  • Cythonでどれほど高速になるか

    1. 総和計算

    forループで1から100,000,000までの総和を求め、実行時間を比較します。

    条件 概要 処理時間(sec)
    Python 通常のPython 11.019352902832
    Cython(型指定なし) Python同様の関数をCythonで実行 6.5913169384002686
    Cython(型指定あり) Python同様の関数に型指定しCythonで実行 0.034995079040527344
    Numba(@jit) Python同様の関数をNumbaの@jitデコレータをつけて実行 0.22203302383422852

    型指定なしのCython実行で約2倍、型指定ありでは約300倍高速になりました。
    また、Numbaによる高速化でも約50倍高速になりました。

    2. 竹内関数

    竹内関数は言語処理系のベンチマークに用いられる再帰関数です。
    今回はTarai(14,7,0)での実行時間を比較します。


    条件 概要 処理時間(sec)
    Python 通常のPython 163.40138912200928
    Cython 型指定ありのCython 47.102073431015015

    再帰関数の実行においても、CythonはPythonの3.5倍高速に実行できています。

    Cythonを用いてPythonの高速化ができました。
    一方で、高速化の程度は書き方の影響を大きく受けることがわかりました。
    また、Cython以外の高速化手法についても検討の余地がありそうです。

    画像の圧縮符号化の概要

    画像の情報量

    我々が普段目にしている画像の多くはRGBそれぞれ8bitsで表現されたピクセルの集合体です。
    これを全く圧縮せずに蓄積すると、情報量は解像度x8x3bitsとなり非常に膨大です。
    例えば、FHDでは1920x1080x8x3で約6.2MBとなり、
    iPhoneのカメラでは写真一枚撮影するたび3024x4032x8x3で約36.5MBのストレージが必要です。


    そこで、画像の圧縮符号化が必要となります。

    圧縮符号化には、元の情報を一切毀損しない可逆圧縮と、劣化を許容し高い圧縮効率を発揮する非可逆圧縮があります。
    前述のとおり画像の情報量は膨大なので、非可逆圧縮を用いて圧縮し蓄積することが一般的です。
    劣化の生じる非可逆圧縮では、人間の視覚特性を利用し劣化を目立たせないための工夫がなされています。

    クロマサブサンプリング

    人間の視覚特性の一つとして、輝度変化に敏感で色調変化に鈍感であることが挙げられます。
    そこで、RGB信号をYUV信号に変換し色差信号のみを間引くクロマサブサンプリングによる情報量の削減が用いられます。

    クロマサブサンプリングのサンプリング方式としてはYUV4:4:4, YUV4:2:2, YUV4:2:0等があります。
    YUV4:2:0では、輝度信号Yはそのままで色差信号U,Vをそれぞれ垂直/水平方向に1/2に間引きます。
    これにより、信号を全く間引かないYUV4:4:4と比較し情報量を50%削減できます。

    クロマサブサンプリングを行った画像は下記のようになります。
    左側がYUV4:4:4、右側がYUV4:2:0となっており、情報量を半分にしても拡大しなければあまり差を知覚できないかと思います。

    DCT係数の量子化

    他の人間の視覚特性として、低周波領域の変化に敏感で高周波数領域の変化に鈍感であることが知られています。
    この特性を利用し、一般的な画像圧縮符号方式であるJPEGでは、離散コサイン変換(DCT)を用いて空間周波数に変換し、高周波数成分を粗く量子化し符号化する工夫がなされています。

    実際にはYUV信号を8×8のブロックに分割し処理を行うため、圧縮品質が低い場合ブロックノイズが発生する場合があります。
    JPEGでは圧縮効率と画質のトレードオフを1~100の品質パラメータで制御しています。
    以下が、品質パラメータ10,50,90でのJPEG圧縮結果です。

    おわりに

    今回の勉強会ではPythonが遅い理由や高速化手法、人間の視覚特性と画像の劣化を目立たせない工夫等について発表されました。
    少ない変更でも十分な高速化が達成できることや、画像の劣化がどこに表れやすいかなど新たに知ることができました。

    今回の発表を通して高速化や画像について興味をもたれた方は、さらなる高速化手法や他の圧縮符号化についてもぜひ調べてみてください。

    このページの先頭へ