我有一個 ctype 結構如下:
class BOX(Structure):
_fields_ = [("x", c_float),
("y", c_float),
("w", c_float),
("h", c_float)]
class DETECTION(Structure):
_fields_ = [("cl", c_int),
("bbox", BOX),
("prob", c_float)]
和 ML 模型通過共享庫的檢測結果
lib = CDLL('./libdetector.so', RTLD_GLOBAL)
detect = lib.detect
detect.argtypes = [...]
detect.restype = POINTER(DETECTION)
dets = detect(...)
我的代碼作業正常,我檢查了結果,它是正確的。但我想通過其置信度分數對檢測進行排序,所以我使用了這一行:
_dets = sorted(dets, key=lambda det: det.prob, reverse=True)
在這一步中,我的計算機記憶體繼續運行,當它已滿時,只有“已殺”訊息會列印到我的控制臺。那么,python 是否sorted不適用于 ctype 結構串列?我可以簡單地使用for loop排序,但每個人都希望保持代碼干凈和美觀,不是嗎?:3
uj5u.com熱心網友回復:
dets是一個指向檢測結構的指標,但沒有關聯的大小。當傳遞給sorted()Python 時,它將開始迭代指標,永遠將物件添加到它想要排序的串列中,如果訪問未提交的記憶體,甚至會崩潰。
例子:
from ctypes import *
class BOX(Structure):
_fields_ = [("x", c_float),
("y", c_float),
("w", c_float),
("h", c_float)]
class DETECTION(Structure):
_fields_ = [("cl", c_int),
("bbox", BOX),
("prob", c_float)]
def __init__(self,prob): # Add some data to differentiate objects
self.prob = prob
def __repr__(self): # Add a display representation
return f'D(prob={self.prob})'
# Create a ctypes array of three DETECTION objects
a = (DETECTION * 3)(DETECTION(1.25), DETECTION(3.5), DETECTION(2.25))
# Create a pointer to the first element of the array
# simulating OP's return value from ctypes.
dets = cast(byref(a),POINTER(DETECTION))
print(dets)
print(dets[0])
print(dets[2])
_dets = sorted(dets, key=lambda det: det.prob, reverse=True) # HANGS
print(_dets)
輸出:
<__main__.LP_DETECTION object at 0x000002032B7FDC40>
D(prob=1.25)
D(prob=2.25)
# On my system hangs here like OP described.
解決方法是您需要知道回傳陣列的大小,并將回傳的指標切片為該已知大小。在這種情況下,陣列大小為三:
_dets = sorted(dets[:3], key=lambda det: det.prob, reverse=True)
輸出:
<__main__.LP_DETECTION object at 0x000001F31763DC40>
D(prob=1.25)
D(prob=2.25)
[D(prob=3.5), D(prob=2.25), D(prob=1.25)]
uj5u.com熱心網友回復:
因此,如果是POINTER(DETECTION)結果,則不是 list。但是 usingsorted 創建一個串列,更重要的是ctypes.c_float,它由物件組成,每個實體需要128 個位元組,另外不要忘記指標的 8 個位元組。因此,如果該底層陣列已經很大,這可能會增加您的記憶體需求......
import numpy.ctypeslib
arr = numpy.ctypeslib.as_array(dect, shape=(n,))
arr.sort(order='prob')
wheren必須是結果陣列的大小。
請注意,生成的 numpy 結構化陣列物件只是底層 buffer 的包裝器。它需要少量的、恒定量的輔助空間——盡管注意,一些numpy函式/方法可能會復制,但它不會像創建ctypes物件串列那么糟糕!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/351249.html
