簡體   English   中英

使用NumPy將ubyte [0,255]數組轉換為float數組[-0.5,+0.5]的最快方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM