作爲支持2D遊戲引擎中精靈半透明的一部分,我需要做的每一幀的事情之一就是將z_index
屬性從後到前排序爲所有的精靈(更多info here)。目前,我cdef class RenderSystem
相關骨架如下所示:通過cython中的cdef class屬性快速排序
#lots of imports...
cdef class RenderSystem:
def __init__(self):
#other irrelevant initialization stuff here
self.sprites = []
def add_sprite(self, Sprite sprite):
self.sprites.append(sprite)
def remove_sprite(self, Sprite, sprite):
self.sprites.remove(sprite)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.initializedcheck(False)
@cython.cdivision(True)
@cython.infer_types(True)
@cython.binding(False)
def update(self):
self.sprites.sort(key=op.attrgetter("z_index"))#op = operator
#render-y OpenGL stuff goes here...
基本上,RenderSystem
對象持有cdef class Sprite
對象的蟒蛇隱藏列表。用戶然後可以間接地從這個列表添加或刪除對象。我的Sprite
類具有cdef public float z_index
屬性,用戶在(-1.0, 1.0]
範圍內設置屬性。 Sprite
將較低的對象z_index
的值呈現在場景中具有較高值z_index
的值後面。我意識到單獨使用sort
函數佔用了我CPU佔用量的很大一部分(13%沒有渲染,> 25%(一個完整核心)渲染)。我知道在cython中,我們有一個qsort
c函數可以用來代替(通過from libc.stdlib cimport qsort
)。然而,閱讀qsort
here,它看起來像qsort
只會命令通過float *z_index_list
,我會失去Sprite
對象和它們的z_indices
之間的關聯。
TL; DR:在cython中,通過給定的屬性對cdef類對象列表進行排序可以超出cpython的內置排序函數的其他更快的方法是什麼?
謝謝你一如既往!使用'key_func'可以省掉一些CPU%(現在9%不渲染,大約與渲染相同的25%)。我會嘗試重構代碼來使用numpy。如果我走的是顛簸路線,這是否允許我保持我的'Sprite'類不變?儘管我的Sprite類有很多數值屬性和固定大小的浮點數組,但它也依賴於一個與OpenGL顯着交互的Texture類。我正在考慮在numpy數組中存儲指向這些對象的uint32_t指針('Sprite'對象及其子''Texture')來解決這個問題... – CodeSurgeon
如果你存儲指向其他Python/Cython類的指針,那麼numpy數組可能不是一個好的解決方案。 – DavidW
不管怎麼說,只是出於好奇而嘗試過numpy,是的,排序性能與您的'key_func'大致相同,除了添加和(尤其是)刪除精靈速度很慢(不是太奇怪,因爲數組是固定大小的,我需要刪除元素在中間,並在末尾添加一個新元素以避免數組中的「洞」)。還有其他建議嗎? – CodeSurgeon