2017-07-25 80 views
3

此代碼重新排列534x713 RGBA4紋理中的位。爲什麼Cython中這個循環太慢了?

cpdef bytes toDDSrgba4(bytearray data): 
    cdef bytes new_data = b'' 

    cdef int pixel 
    cdef int red 
    cdef int green 
    cdef int blue 
    cdef int alpha 
    cdef int new_pixel 
    cdef int i 

    for i in range(len(data) // 2): 
     pixel = int.from_bytes(data[2*i:2*i+2], "big") 

     red = (pixel >> 12) & 0xF 
     green = (pixel >> 8) & 0xF 
     blue = (pixel >> 4) & 0xF 
     alpha = pixel & 0xF 

     new_pixel = (red << 8) | (green << 4) | blue | (alpha << 12) 

     new_data += (new_pixel).to_bytes(2, "big") 

    return new_data 

它一樣快,因爲它是Python的等價物,它是這樣的:

def toDDSrgba4(data): 
    new_data = b'' 

    for i in range(len(data) // 2): 
     pixel = int.from_bytes(data[2*i:2*i+2], "big") 

     red = (pixel >> 12) & 0xF 
     green = (pixel >> 8) & 0xF 
     blue = (pixel >> 4) & 0xF 
     alpha = pixel & 0xF 

     new_pixel = (red << 8) | (green << 4) | blue | (alpha << 12) 

     new_data += (new_pixel).to_bytes(2, "big") 

    return new_data 

他們兩人都是很慢。

我已經寫了非常複雜的調酒甚至不是最優化和測試了這種質地的代碼,它仍然waaay比這更快。

+0

也許把所有'新數據'放到一個列表中,而不是在每一步中連接它,然後在最後加入它。 – khelwood

+0

好的,我會試試。 – AboodXD

回答

4

您正在使用+=追加到bytes對象。這真的很慢,因爲它每次都需要複製整個現有的bytes對象。

不要這樣做。一個更好的選擇是使用bytearray,並且最後只從bytearray中構建一個bytes對象。

+0

Wooooooow,現在更快的方式waaaaay,謝謝。 :d – AboodXD

0

from_bytes和to_bytes方式太慢我想。嘗試而不是from_bytes:

pixel = (data[2*i]) << 8 | (data[2*i+1]) 

它真的比你的代碼更快,我測試過它。 但to_bytes我無法想象現在的快速版本。

+0

速度相同,整個功能大約需要30秒才能執行。 – AboodXD

+0

不,我已閱讀關於to_bytes()是多快的文章。 – AboodXD

+0

這很奇怪。在python版本中,我的代碼速度提高了15%。不知道如何嘗試使用電子琴。 – CrazyElf