monolithic kernel

numpy の ndarray のメモリレイアウト

March 06, 2019

    numpy でごにょごにょしたベクトルとか行列とかを他の言語に持っていくことになり、いろいろ方法がある中で、ndarray の生データをそのまま受け渡しするのが速いよねということになった。個人的にも速いのは大好きなので、それ自体はいいんだけど、そうなると生データってどうなってるんだっけという話になる。

    結論としては、ndarray.tobytes でバイト列を書き出すとデフォルトではC言語と同じ順序 (Row-major) になる。話としては以上なのだが、自分自身はそんなに頻繁に行列をこねくり回すわけでもなく、扱うたびに混乱するので、もう少しわかりやすい形でメモしておく。

    ここでは分かりやすさのために要素のデータ型を int8 としている。他のデータ型でも並び方は同じで、各要素の表現はコンパイルした環境によって変わるのかな。そこまで追ってないけど、まあ普通にCと同じ表現になる。

    import numpy as np
    
    v = np.array([1,2,3], dtype = 'int8')
    print(v)
    # [1 2 3]
    print(v.shape)
    # (3,)
    print(v.tobytes())
    # b'\x01\x02\x03'
    
    m = np.array([[1,2,3],[4,5,6]], dtype = 'int8')
    print(m)
    # [[1 2 3]
    #  [4 5 6]]
    print(m.shape)
    # (2, 3)
    print(m.tobytes())
    # b'\x01\x02\x03\x04\x05\x06'

    See also