『Cython ―Cとの融合によるPythonの高速化』のメモ

# 参考文献
- [『Cython ―Cとの融合によるPythonの高速化』, オライリー・ジャパン, ISBN978-4-87311-727-0][1]
 - 以下では、Cython本と呼ぶ
- [Cython ドキュメント（和訳） — Cython 0.17.1 documentation](http://omake.accense.com/static/doc-ja/cython/index.html)

# Cython概要
- Cythonは、PythonとCもしくはC++の静的型システムを融合したプログラミング言語
  - クレオール型プログラミング言語
    - [クレオール言語(creole languag) - wikipedia][2] : 複数の言語の混成語のこと。
- cython(cが小文字)は、CythonコードをCまたはC++コードに変換するコンパイラ
- Cythonの長所 = Pythonの表現力 + 動的性格 + C言語の性能
- Pythonコードは、そのままCythonコード (いくつかの例外はある) 
 - Cythonキーワード追加で、cythonが効率的なCコードを生成

##Cythonの2面性
 - 陽 : PythonをCにコンパイル
 - 陰 : C/C++とPythonのインターフェース
- Cythonが効果を発揮する領域のひとつに、「CライブラリをPythonでラップする」がある
  (これが[Cython本][1]を読んでいる理由)

##プロファリングの重要性
- プロファイリングにより、I/Oバウンド／ネットワークバウンドだとわかったらCythonは第一の有効な手段でない
 - Cythonが有効なのは**CPUバウンド**な問題である。

- パレートの法則
 - プログラム実行時間の80%はコードのわずか20%で費やされる。
 - 20%はプロファリングをしなければ見つからない
  - **Python組み込みのプロファイリングツールを活用する** 
 
- **メモリバウンド、I/Oバウンド、ネットワークバウンドな処理が主の場合、CythonとPythonの差は小さい**
  - メモリバウンド : 巨大な配列の要素の加算など
  - I/Oバウンド : ファイルをディスクから読み出すなど
  - ネットワークバウンド : ネットワークからデータを受信するなど
 
##型について
- Cの型システムをPythonに持ち込む ⊃ Cのデータ型が持つ制約を持ち込む
 - Python → 無限精度、C → 固定精度
 - CはPythonよりも高速 ←→ Pythonより柔軟性／一般性で劣る 

## Cythonコードのコンパイルと実行
1. IPythonで対話的に
1. インポート時に自動コンパイル
1. Pythonのdistutilsを使って別途コンパイル
1. make, CMake, SConsの標準ビルドシステムに統合する

- 標準的な方法は、「Pythonのdistutilsを使って別途コンパイル」(distutlisとcythonizeを使う方法)とされていた。
 - 今でも本当にそうなのかは調べてみる必要あり 

## IPythonで対話的に
- [Cython本][1]の通りに```%load_ext cythonmagic```とやると以下のエラーが出た

```pycon
%load_ext cythonmagic
...\extensions\cythonmagic.py:21: UserWarning: The Cython magic has been moved to the Cython package
  warnings.warn("""The Cython magic has been moved to the Cython package""")
```

- Stack overflowを見たら解決方法が載っていた

[Cython in Ipython: ERROR: Cell magic `%%cython` not found - Stack Overflow][4]
> you should do:

> ```py
> %load_ext Cython
> ```

> After that, the cython magic should work as expected.

- また、[Cython本][1]では、

> 2回続け[Return]キーを押下してブロックを抜けると

となっているが，抜けられなかった。↓のように延々と改行になる。

```py
In [6]: %%cython
   ...: def fib(int n):
   ...:     cdef int i
   ...:     for i in range(n):
   ...:         print(i)
   ...: 
   ...: 
   ...: 
   ...: 
   ...: 
   ...: 
   ...: 
```

- [Shift] + [Return]で抜けられた

```py
In [7]: %load_ext Cython

In [8]: %%cython
   ...: def fib(int n):
   ...:     cdef int i
   ...:     for i in range(n):
   ...:         print(i)
   ...: # [Shift] + [Return]
```

- [Shift] + [Return]を押下したあと待たされるのは、IPythonがコードブロックをコンパイル～ロードしているため。
- 生成されたソース

> ...\.ipython\cython\_cython_magic_ed5cb5261ba45739ef3878fbe8610564.c

> ```c
/* "_cython_magic_ed5cb5261ba45739ef3878fbe8610564.pyx":3
 * def fib(int n):
 *     cdef int i
 *     for i in range(n):             # <<<<<<<<<<<<<<
 *         print(n)
 *     return n
 */
```

## インポート時に自動コンパイル

- 以下のような fib.pyxを作成しておく
 （fibってなっているが、簡単化のためフィボナッチ数列じゃない適当なものにしている。）

```fib.pyx
def fib(int n):
    cdef int i
    for i in range(n):
        print(i)
```

- import pyximportをすると、fib.pyxをimportできるようになる。

```py
In [21]: import pyximport

In [22]: pyximport.install()
Out[22]: (None, <pyximport.pyximport.PyxImporter at 0x64f2cc0>)

In [23]: import fib

In [24]: fib.fib(10)
0
1
2
3
4
5
6
7
8
9
```

- タブとスペースが混在していたりすると、大量のエラーがでるので注意すること。


[1]:https://www.oreilly.co.jp/books/9784873117270/
[2]:https://ja.wikipedia.org/wiki/クレオール言語
[3]:https://jp.vector.com/vj_xl_driver_library_jp.html
[4]:https://stackoverflow.com/questions/36514338/cython-in-ipython-error-cell-magic-cython-not-found