Python備忘録

個人的なメモ書きです。
（ブックマーク的な）

---

# 高速化
- pypy使う 
https://qiita.com/OKCH3COOH/items/f0c5c4681bc30dddf7f4

- セット（set > dicts >> list）
 - listは.appendであるため遅く、setはhashmapであるため早い  

参照先：https://qiita.com/cof/items/05f6ffc6d4e5b062aaa9

||range(0,10**4*1,1)|range(0,10**4*2,2)|range(0,10**4*3,3)|
|:-:|:-:|:-:|:-:|
|list|10.247|12.593|14.6|
|dict|0.253|0.028|0.028|
|set|0.239|0.024|0.022|

- 標準入力（input < sys.stdin.readline）
 - 標準入力はinput()よりsys.stdin.readline()の方が10倍速い

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|input()	|392.40	|24.36|
|sys.stdin.readline()	|37.09	|1.88|

- 並び替え（sort > sorted）
 - ソートは、sortedよりsortの方が1.4倍速く、keyの指定にはitemgetterを使うとlambdaに比べ1.2倍速くなる

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|sort()	|88.54	|56.98|
|sorted()	|127.03	|7.51|

- ループ（for > while）
 - ループは、forの方がwhileより2倍程度速い

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|for _ in range(N)	|20.63	|0.89|
|for i in range(N)	|25.66	|0.93|
|while i < N	|51.36	|1.44|

- リスト初期化（* > in range）
 - リストの初期化は*演算子の方が、内包表記より8~9倍速い

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|[None] * N	|5.15	|0.41|
|[None for _ in range(N)]	|41.17	|2.05|

- 二次元配列の初期化（* > in range）
 - 二次元配列の初期化は、最初の次元のみ内包表記を使う

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|[[None] * N for _ in range(N)]	|3.07	|1.02|
|[[None for _ in range(N)] for _ in range(N)]	|38.45	|4.80|

- リストの値参照
 - リストの値の参照は、for a in Aのようにインデックスを作らないほうが、rangeを使う場合より4倍速い

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|for i in range(len(A))	|41.14	|0.56|
|for a in A	|11.85	|1.51|

- リストへの値追加
 - 要素の追加は内包表記を使うと、appendに比べ1.5倍速くなる

|	|平均(ms)	|標準偏差(ms)|
|:-:|:-:|:-:|
|append()	|103.99	|2.62|
|A[i] = i	|70.97	|3.93|
|[i for i in range(N)]	|65.83	|3.20|

参照先：https://www.kumilog.net/entry/python-speed-comp

- Stackの追加  
 - dequeのほうが若干早い

|stack_append	|回数10^5	|
|:-:|:-:|
|list_append| 0.016sec|
|deque_append| 0.012sec|

- Stackの取り出し
 - dequeのほうが若干早い

|stack_append	|回数10^5	|
|:-:|:-:|
|list_pop| 0.014sec|
|deque_pop| 0.01sec|

- Queueの追加 
 - list, dequeが早い

|stack_append	|回数10^5	|
|:-:|:-:|
|list_append| 0.01sec|
|deque_append| 0.01sec|
|Queue_append| 0.21sec|

- Queueの取り出し
 - dequeが早い

|stack_append	|回数10^5	|
|:-:|:-:|
|list_pop| 約1.1sec|
|deque_pop| 約0.2sec|
|Queue_pop| 約0.1sec|

-> スタックもキューも、collections.deque を使うのが最適。
参照先：https://qiita.com/saba/items/107c4237206e31acdbef

- whileは使わない  
- たくさんアクセスするなら一時変数を使おう？  
- リスト作るときにfor文使うなら内包表記を使おう  
- if文の条件式を見直そう  
- mapを使おう  
- appendが必要な時にtupleが使えるなら使おう！ 
詳細は以下 
参照先：https://qiita.com/shaka/items/f180ae4dc945dc7b9066

- 後ほど  

詳細は以下 
参照先：http://nobunaga.hatenablog.jp/entry/2018/03/19/081425

- 後ほど 

詳細は以下 
参照先：https://x1.inkenkun.com/archives/861

- csv 読み書き高速化(pickle)  
CSVモジュールでの書き込み時間: 13.190569166113692 [sec]  
pandasモジュールでの読み込み時間: 2.3681932315859324 [sec]  
時間計測:pickleモジュールでの書き込み時間: 0.09422977217429818 [sec]  
時間計測:pickleモジュールでの読み込み時間: 0.024253395266534028 [sec]  
参照先：https://ameblo.jp/hitochan007/entry-12009166114.html

5列 × 3687221行のデータ  
40秒 → 5.6秒
以下参照  
参照先：https://qiita.com/Yuhsak/items/7c8e2b131cc536ef9ba1


# GPUを利用して高速化
- 2.4. Python での 高速計算。 NumPy 互換 GPU 計算ライブラリ cupy  
https://purakaku-python.readthedocs.io/ja/master/chapter_ml/cupy.html
- pythonで簡単にGPU計算ができるCupyを紹介  
https://qiita.com/samacoba/items/d18e6cf09f544477aff4
- Windows10でGPUが使えるPythonを環境構築する  
https://betashort-lab.com/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/python/windows10%E3%81%A7gpu%E3%81%8C%E4%BD%BF%E3%81%88%E3%82%8Bpython%E3%82%92%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%81%99%E3%82%8B/

# メモリ利用最適化
- Python3でリングバッファを作る  

参照先：https://www.blog.danishi.net/2020/04/27/post-3509/

```
class RingBuffer:
    def __init__(self, size):
        self.buffer = [None for i in range(0, size)]
        self.top = 0
        self.bottom = 0
        self.size = size

    def __len__(self):
        return self.bottom - self.top

    def add(self, value):
        self.buffer[self.bottom] = value
        self.bottom = (self.bottom + 1) % len(self.buffer)

    def get(self, index=None):
        if index is not None:
            return self.buffer[index]

        value = self.buffer[self.top]
        self.top =(self.top + 1) % len(self.buffer)
        return value

if __name__ == "__main__":
    rbuf = RingBuffer(5)

    rbuf.add('hoge')
    rbuf.add('fuga')
    rbuf.add('piyo')
    rbuf.add(1)
    rbuf.add(2)
    rbuf.add(3)
    
    print('len:' + str(len(rbuf)))
    print('size:' + str(rbuf.size))
    print('top:' + str(rbuf.top))
    print('bottom:' + str(rbuf.bottom))
    print('-----------')
    print(rbuf.get())
    print(rbuf.get())
    print(rbuf.get())
    print(rbuf.get())
    print(rbuf.get())
    print(rbuf.get())
    print(rbuf.get(rbuf.bottom))
```

# あとで
- Python コードの高速化のアプローチ  
https://qiita.com/zettaittenani/items/3bb25752d6e6a458332e


# 並列処理 & 非同期
- Python 3のmultiprocessingでプロセス間で大量のデータを受け渡しつつnumpyで処理する 
https://qiita.com/kakinaguru_zo/items/f53e2485f15dd0d71f82

- [Python] マルチプロセスな処理を実装して、処理を高速化する 
https://www.yoheim.net/blog.php?q=20170601

- PythonのThread（並列処理）は速度改善効果がないらしいので確認する。
https://arakan-pgm-ai.hatenablog.com/entry/2019/05/02/000000

- 【Python】asyncio（非同期I/O）のイベントループをこねくり回す
https://qiita.com/ynakaDream/items/b63fab24bb30dea6ddb1

# 競プロ関連リンク

https://qiita.com/dekamisako/items/1c104e332351ab9389a6