Pythonでnumpy.ctypes.data_as()→C側でAccess violation

YOLOLink リポジトリに含まれるdarknet_images.pyに複数画像一括処理を行うbatch_detectionという関数があるのですが、2枚以上の画像を処理させようとするとC側関数実行中にOSError/access violation例外が発生。1枚(要素数1の配列を渡す)は正常に処理されることから、ポインタの渡し間違いという類ではなさそう。

結論

import numpy as np
from ctypes import *

def makeArray():
    arr = numpyの配列を作る
    return arr.ctypes.data_as(ctypes.POINTER(ctypes.c_float))


c_func(makeArray())

みたいに関数でnumpy配列作ってctypesのポインタだけを返している場合、arrのサイスが大きいと関数抜けた時点でarrがガベージコレクションされてしまい、data_as()で得たアドレスはc_funcが呼ばれる前に無効になる可能性がある。

今回のYOLOの件は画像1枚だとたまたまガベコレされなかっただけで、本質的には危険なのでしょう。具体的にはdarknet_images.pyのprepare_batch()関数でbatch_arrayがガベコレされてしまいます。手っ取り早い解決としては、同ファイル内で
  • prepare_batch()の返値にbatch_arrayを含めるようにし、呼び出す側のbatch_detection()はC関数darknet.network_predict_batch()を呼び終えるまでbatch_arrayを保持する
  • prepare_batch()とbatch_detection()を一つの関数にまとめ、batch_arrayがガベコレされないようにする

でしょうか。前者はコード的にあまり美しくなさそうですが。

私と同じ問題にあたる人は稀でしょうが、本質的な理由はWindows/Linux関係なく起こりそう。ctypesのいい勉強になりました。

[参考]

— posted by mu at 07:18 pm   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0086 sec.
prev
2023.2
next
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28