使用O(1)空间在NumPy中矢量化加减法循环?

时间:2017-04-03 04:09:07

标签: python loops numpy vectorization

使用额外的缓冲区使用NumPy很容易地对此代码进行矢量化:

import numpy.random

def foo(a, b):
    for k in xrange(n):
        bk = b[k]
        b[k] = a[k] - bk
        a[k] += bk

n = 16
x = numpy.random.randn(n)  # some arbitrary input array, this is just for example
y = numpy.random.randn(n)  # some arbitrary input array, this is just for example
foo(x, y)

但有没有办法让NumPy这样做没有分配额外的数组/缓冲区?

编辑:

我打算只在1个向量化操作中执行此操作(以便每个内存位置只写入一次),很抱歉没有提及。

4 个答案:

答案 0 :(得分:2)

怎么样:

a += b
b *= -2
b += a

答案 1 :(得分:0)

这会起作用吗?

import numpy.random

def foo(a, b):
    for k in xrange(n):
        a[k], b[k] = (a[k] + b[k], a[k] - b[k])

n = 16
x = numpy.random.randn(n)  # some arbitrary input array, this is just for example
y = numpy.random.randn(n)  # some arbitrary input array, this is just for example
foo(x, y)

我不认为在单个矢量化操作中可以做你想要的事情,因为不能一次为多个变量赋值......但我认为用元组作弊会使它看起来像是可能的: ]

答案 2 :(得分:0)

向量化本质上意味着在编译代码中而不是在高级语言中执行循环。 Numpy有许多用C语言编写的函数,但我不认为这个特殊情况有一个...所以,滚动你自己 - 如果你可以在你的平台上使用Cython这是直截了当的:

import numpy as np
cimport numpy as np

def c_foo(np.ndarray[np.float_t, ndim=1] a, np.ndarray[np.float_t, ndim=1] b):
    cdef int n = a.shape[0]
    cdef int k
    cdef float bk
    for k in range(n):  # not sure if Cython likes `range` or `xrange` better on Python 2
        bk = b[k]
        b[k] = a[k] - bk
        a[k] += bk

(我没有检查是否因为我的系统上缺少编译器而起作用,但是Cython正确地从这段代码中创建了一个.c文件。)

这看起来像是在音频处理中通常用于分离两个单声道/差分信号中的立体声信号的操作。您可能很幸运,可以在scipy或音频处理库中找到现有的实现。

答案 3 :(得分:0)

这是一种仅在我们控制内存布局时才有效的方法。具体而言,xy必须交错并float

xy = np.random.randn(4, 2)
x, y = xy.T
print(x, y)
print(x-y, x+y)
xyc = xy.view(np.complex)
xyc *= 1+1j
print(x, y)

示例输出:

[ 1.17611837 -0.51923153 -0.35347014  0.17090538] [ 0.76679875  0.49908488  0.55649176  1.01126514]
[ 0.40931962 -1.0183164  -0.9099619  -0.84035975] [ 1.94291712 -0.02014665  0.20302162  1.18217052]
[ 0.40931962 -1.0183164  -0.9099619  -0.84035975] [ 1.94291712 -0.02014665  0.20302162  1.18217052]