Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用NumPy将ubyte[0255]数组转换为浮点数组[-0.5,+;0.5]的最快方法_Python_Arrays_Numpy_Normalization_Vectorization - Fatal编程技术网

Python 使用NumPy将ubyte[0255]数组转换为浮点数组[-0.5,+;0.5]的最快方法

Python 使用NumPy将ubyte[0255]数组转换为浮点数组[-0.5,+;0.5]的最快方法,python,arrays,numpy,normalization,vectorization,Python,Arrays,Numpy,Normalization,Vectorization,问题就在标题里,而且很简单 我有一个文件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_valu

问题就在标题里,而且很简单

我有一个文件
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
使用多核,而不是因为它只在阵列上进行一次传递。代码:

import numexpr
ar = numexpr.evaluate('(ar - 255.0/2.0) / 255.0')

我自己找到了一个更好的解决方案(大约快25%):

我很好奇它是否可以改进。

此查找表可能比重复计算快一点:

table = numpy.linspace(-0.5, 0.5, 256)
images = numpy.memmap(f, '>u1', 'r', shape=(size, rows, cols))
arr = table[images]

在我的系统上,它比你的系统节省了10%到15%的时间。

使用下面的代码,对于大型阵列,我可以获得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

为什么不
arr=(images.astype(float)/max_value)-0.5
@RicardoCárdenes:为什么你会期望它更快?不期望它马上就更快,只是好奇而已。无论如何,对于这一点,我可能会研究一些额外的模块,比如@RicardoCárdenes:哦,我明白了。我没有这样做,因为我看不到无缘无故地分配额外的内存块有任何好处,而不是就地分配,它只是从CPU缓存中逐出数据。那个链接看起来很有趣,谢谢。@Alex:我用
numpy.fromfile
阅读了它,它和我给你看的代码一模一样。是的,每一行都需要几百毫秒,除以
max\u值
是最慢的操作。+1,但我必须指出它不是等价的<代码>断言244.0*(1.0/255.0)==244.0/255.0。如果您不介意依赖性,它正是为这种情况而发明的,而且就性能而言,我打赌它是不可能被打败的。为了公平比较,请确保您在此时清除文件系统缓存,否则,第二次运行时,它将比第一次快得多。在我的系统上,它的速度是我的memmap解决方案的两倍。
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
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],
)