ndarrayのfortran flagと実際のメモリ配列について
実験¶
import numpy as np
2x2のndarrayを生成する。
a = np.array([[1,2], [3,4]])
a
.T
で転置を取ると行と列が入れ替わる。
a.T
元のndarrayの.flags
を表示すると、C_CONTIGUOUS
がTrue
となっている一方、F_CONTIGUOUS
がFalseとなっていることが分かる。C_CONTIGUOUS
はC形式配列であるかを表すフラグであり、F_CONTIGUOUS
はFortran形式配列であるかを表すフラグである。
a.flags
一方.T
を呼んだ後のndarrayの.flags
を表示すると、C_CONTIGUOUS
がFalse
に変化し、一方F_CONTIGUOUS
がTrueとなっている。
a.T.flags
np.save
での保存時の形式¶
.T
で転置を取ると.flags
のC形式配列であるかFortran形式配列であるかのフラグが入れ替わることが分かったが、実際の格納形式がどうなっているかを知るために、np.save
を用いて保存した.npy
ファイルに対して!hexdump -Cv
を実行することでバイナリの中身を調べる。ここでhexdump
コマンドの-C
はASCII表示を行うためのオプションであり、-v
は全データを表示するためのオプションである(おそらくBSD系のhexdumpのみ)。
まず、np.save
で転置前後のndarray
を保存する。
np.save("a.npy", a)
np.save("a.T.npy", a.T)
これらをnp.load
で再度読み込み直すと、.flags
は読み込んだ後も保持されていることが分かる。
np.load("a.npy").flags
np.load("a.T.npy").flags
ディスクへダンプした際の実際の格納形式がどうなっているかをhexdumpコマンドを用いて調べる。
!hexdump -Cv a.npy
!hexdump -Cv a.T.npy
ヘッダーのfortran_order
が変化していることが分かる。更にbashのプロセス置換で両者のdiffを見てみる。
%%bash
diff <(hexdump -Cv a.npy) <(hexdump -Cv a.T.npy)
ヘッダーのみ差分が存在し、実際のデータが格納されている後半部は変化していないことが分かる。
転置した状態のまま保存する方法¶
ndarrayに対して.copy()
を呼んだ上で保存すれば良い。下記に実例を示す。
まず、.copy()
を呼んだ後の.flags
を表示する。
a.T.copy().flags
転置したにもかかわらずC_CONTIGUOUS
がTrueになっていることが分かる。
更にこのndarrayをnp.save
で保存し、hexdump
で中身を見てみる。
np.save("a.T.copy.npy", a.T.copy())
!hexdump -C a.T.copy.npy
C_CONTIGUOUS
がTrue、F_CONTIGUOUS
がFalseになっていたことからも分かるように、ヘッダーのfortran_order
がFalseになっている。
当然、再度np.load
で読み込んだ場合でもこの.flags
は保たれている。
np.load("a.T.copy.npy").flags
元のndarrayと、転置した上で.copy()
を呼んだ後のndarrayをnp.save
したバイナリを比較してみる。
%%bash
diff <(hexdump -Cv a.npy) <(hexdump -Cv a.T.copy.npy)
両者ともにC形式配列となっているため、純粋にデータ部の並びのみが異なる。
同様に転置を取った場合と、その上で.copy()
を呼んだ場合のバイナリを比較してみる。
%%bash
diff <(hexdump -Cv a.T.npy) <(hexdump -Cv a.T.copy.npy)
この場合、ヘッダーもデータ部も異なっていることが分かる。
なぜこの記事を書いたか¶
とある.npy
ファイルのデータ部分を直接読み込むCプログラムを触っていた際に、.T
で転置した.npy
を読み込んでも読み込んだデータ部分が全く変化していないということが発生したためである。
当該プログラムではヘッダーのfortran_order
を完全に無視していたため、.T
しただけのndarrayを保存した.npy
ではデータ部分が転置されておらず、意図しない動作となってしまっていた。これを解決するためには前述のように.copy()
を呼んだ上で保存した.npy
ファイルを読み込む必要があった。
コメント
Comments powered by Disqus