[英]Fastest way to convert ubyte [0, 255] array to float array [-0.5, +0.5] with NumPy
問題在標題中,非常簡單。
我有一個文件f
,正在讀取一個ubyte
數組:
arr = numpy.fromfile(f, '>u1', size * rows * cols).reshape((size, rows, cols))
max_value = 0xFF # max value of ubyte
目前,我正在通過3次傳遞對數據進行規范化,如下所示:
arr = images.astype(float)
arr -= max_value / 2.0
arr /= max_value
由於陣列有些大,因此需要花費很短的時間。
如果我可以在1或2次傳遞數據中做到這一點,那就太好了,因為我認為這樣會更快。
我可以通過某種方式執行“復合”矢量運算來減少通過次數嗎?
或者,我還有其他方法可以加快速度嗎?
我做了:
ar = ar - 255/2.
ar *= 1./255
似乎更快:)
不,我沒有定時,它在我的系統上大約快兩倍。 看來ar = ar - 255/2.
快速進行減法和類型轉換。 另外,似乎沒有對標量進行除法優化:一次除法然后對數組進行一堆乘法會更快。 盡管額外的浮點運算可能會增加舍入誤差。
如評論中所述, numexpr可能是實現這一目標的真正快速而簡單的方法。 在我的系統上,這是另一個快兩倍的因素,但這主要是由於numexpr
使用了多個內核,而不是因為它只對數組執行了一次傳遞。 碼:
import numexpr
ar = numexpr.evaluate('(ar - 255.0/2.0) / 255.0')
該查詢表可能比重復計算要快一點:
table = numpy.linspace(-0.5, 0.5, 256)
images = numpy.memmap(f, '>u1', 'r', shape=(size, rows, cols))
arr = table[images]
在我的系統上,與您的系統相比,它節省了10%到15%的時間。
我自己找到了一個更好的解決方案(速度提高了約25%):
arr = numpy.memmap(f, '>u1', 'r', shape=(size, rows, cols))
arr = arr / float(max_value)
arr -= 0.5
我很好奇是否可以改善。
我使用cython.parallel.prange
和下面的代碼,對大型數組的速度提高了50%(對一維數組,但很容易擴展); 我想速度的提高取決於CPU內核的數量:
pilot.pyx
文件:
cimport cython
from cython.parallel import prange
import numpy as np
cimport numpy as np
from numpy cimport float64_t, uint8_t, ndarray
@cython.boundscheck(False)
@cython.wraparound(False)
def norm(np.ndarray[uint8_t, ndim=1] img):
cdef:
Py_ssize_t i, n = len(img)
np.ndarray[float64_t, ndim=1] arr = np.empty(n, dtype='float64')
float64_t * left = <float64_t *> arr.data
uint8_t * right = <uint8_t *> img.data
for i in prange(n, nogil=True):
left[i] = (right[i] - 127.5) / 255.0
return arr
setup.py
文件,用上述代碼構建C擴展模塊:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_module = Extension(
'pilot',
['pilot.pyx'],
extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp'],
)
setup(
name = 'pilot',
cmdclass = {'build_ext': build_ext},
ext_modules = [ext_module],
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.