日々精進

新しく学んだことを書き留めていきます

Pandasで読み込むカラムを絞るのと、データ型の最適化で処理が速くなった

DataFrameの処理を高速化する時に、以下を行うと100倍ぐらい速くなった。パフォーマンスチューニングの時はまずこれらをやるといいかも。

  • pd.read_csvで読み込む時に必要なカラムだけ読み込む

  • さらにdtypeも指定してメモリ使用量を削減する

参考:

qiita.com

tensorflowでEstimatorを使って学習する時はtf.set_random_seedを自分で呼んではいけない

注意:tensorflow 1.15.2で確認したので最新版では以下の話は違うかも知れません

すべてのradom seedを固定する関数を作ってそれを呼ぶようにしていたが、学習の再現性がなく困っていた。

Estimatorのコードを読んでみると、なんとEstimatorの中に以下のコードがあり、random seedをセットしていた。しかも、self._config.tf_random_seedの初期値はNoneなので、自分でtf.set_random_seedを実行していてもseedがNoneで上書きされて固定されなくなるという罠・・・

random_seed.set_random_seed(self._config.tf_random_seed)

Estimatorを使う場合は、RunConfig(tf_random_seed=seed)にseedを設定してEstimatorのコンストラクタに渡せばseedを固定できる。

参考: stackoverflow.com

dpkg -i cuda-keyring_1.0-1_all.debの後でapt updateを実行すると「E: Conflicting values set for option Signed-By regarding source」エラー

nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04をベースにDockerImageをビルドしようとしたら、エラーが出たので以下を参考に直そうとしたら今度は掲題のエラーが発生。

www.nemotos.net

掲題のエラーメッセージの全文は以下。

E: Conflicting values set for option Signed-By regarding source https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /: /usr/share/keyrings/cuda-archive-keyring.gpg !=

これの解決策は以下に書いてあるがcuda*.listを削除すると直る。

developer.nvidia.com

自分の場合は以下を実行すると直った。

rm /etc/apt/sources.list.d/cuda.list

multiprocessing.Poolで並列処理をすると、子プロセスで例外が発生した場合エラーメッセージがでない

multiprocessing.Poolでも、apply_asyncを使って子プロセスを起動している場合は子プロセスで発生した例外を親プロセスに伝えられる。詳細は以下参照。

conta.hatenablog.com

自分はmapを使っていたので同様のことができず困った。しかも、子プロセスで例外が発生した場合、子プロセスの処理が止まり、親プロセスに制御が戻ってこなくなる・ログにも何も出ないという状態になって原因が分からず苦労した。。

concurrent.futures.ProcessPoolExecutorを使えばmultiprocessing.Pool.mapと同様の使い方ができ、子プロセスで発生した例外を親プロセスに伝えてくれるのでこれを使うことで解決した。詳細は以下参照。

stackoverflow.com

ただし、out of memoryが発生した場合はBrokenProcessPoolという例外が発生するので原因が分かりにくい。。他にもいくつかの原因でBrokenProcessPoolが発生するらしい。詳細は以下参照。

stackoverflow.com

concurrent.futuresで並列処理をすると、親プロセス終了時に「Error in atexit._run_exitfuncs OSError: handle is closed」エラー

原因は以下。

  • 子プロセスを管理しているオブジェクトはfull gcが実行されるまで生きている
  • 親プロセスが終了すると子プロセスを管理しているオブジェクトは子プロセスに停止命令を送る
  • その時には子プロセスはすでに終了しているので「handle is closed」が出る

不要なエラーメッセージが出るのは嫌だけど、それ以外の害は無いので一旦放置・・

参考: stackoverflow.com

以下を見るとpython3.9では直っているように見える。

bugs.python.org

yieldと通常のreturnは併用できない

同じ関数の中で、ifで分岐してこの場合はgeneratorとして使う、この場合は普通に値を返す、ということはできないらしい。

ja.stackoverflow.com

しょうがないのでgeneratorがほしい場合とそうでない場合で共通の部分を関数に抽出して残りの部分をそれぞれ別の関数として実装した。