问题出在标题上,非常简单。
我有一个文件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次数据传递中做到这一点会很棒,因为我认为这会更快。
我可以通过某种方式执行“复合”矢量操作来减少传球次数吗? 或者,还有其他方法让我加快速度吗?
答案 0 :(得分:4)
我做了:
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')
答案 1 :(得分:2)
此查找表可能比重复计算快一点:
table = numpy.linspace(-0.5, 0.5, 256)
images = numpy.memmap(f, '>u1', 'r', shape=(size, rows, cols))
arr = table[images]
在我的系统上,与你的相比,它可以节省10%到15%的时间。
答案 2 :(得分:1)
我自己找到了一个更好的解决方案(快了大约25%):
arr = numpy.memmap(f, '>u1', 'r', shape=(size, rows, cols))
arr = arr / float(max_value)
arr -= 0.5
我很好奇是否可以改进。
答案 3 :(得分:0)
对于大型数组,使用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],
)