Python Numba:不支持单元格变量

Python Numba:不支持单元格变量,python,numba,Python,Numba,我想使用numba来加速此功能: from numba import jit @jit def rownowaga_numba(u, v): wymiar_x = len(u) wymiar_y = len(u[1]) f = [[[0 for j in range(wymiar_y)] for i in range(wymiar_x)] for k in range(9)] cx = [0., 1., 0., -1., 0., 1., -1., -1., 1.]

我想使用numba来加速此功能:

from numba import jit
@jit
def rownowaga_numba(u, v):
    wymiar_x = len(u)
    wymiar_y = len(u[1])
    f = [[[0 for j in range(wymiar_y)] for i in range(wymiar_x)] for k in range(9)]
    cx = [0., 1., 0., -1., 0., 1., -1., -1., 1.]
    cy = [0., 0., 1., 0., -1., 1., 1., -1., -1.]
    w = [4./9, 1./9, 1./9, 1./9, 1./9, 1./36, 1./36, 1./36, 1./36] 
    for i in range( wymiar_x):
        for j in range (wymiar_y):
            for k in range(9):
                up = u[i][j]
                vp = v[i][j]
                udot = (up**2 + vp**2)
                cu = up*cx[k] + vp*cy[k]
                f[k][i][j] =  w[k] + w[k]*(3.0*cu + 4.5*cu**2 - 1.5*udot)
     return f
我用这些数据测试它:

import timeit
import math as m

u = [[m.sin(i) + m.cos(j) for j in range(40)] for i in range(1000)]
y = [[m.sin(i) + m.cos(j) for j in range(40)] for i in range(1000)]

t0 = timeit.default_timer()

for i in range (10):
    f = rownowaga_pypy(u,y)

dt = timeit.default_timer() - t0
print('loop time:', dt)
我得到了这个错误:

    Traceback (most recent call last):
  File "C:\Users\Ricevind\Desktop\PyPy\Skrypty\Rownowaga.py", line 29, in <module>
    f = rownowaga_pypy(u,y)
  File "C:\pyzo2014a\lib\site-packages\numba\dispatcher.py", line 171, in _compile_for_args
    return self.compile(sig)
  File "C:\pyzo2014a\lib\site-packages\numba\dispatcher.py", line 348, in compile
    flags=flags, locals=self.locals)
  File "C:\pyzo2014a\lib\site-packages\numba\compiler.py", line 637, in compile_extra
    return pipeline.compile_extra(func)
  File "C:\pyzo2014a\lib\site-packages\numba\compiler.py", line 356, in compile_extra
    raise e
  File "C:\pyzo2014a\lib\site-packages\numba\compiler.py", line 351, in compile_extra
    bc = self.extract_bytecode(func)
  File "C:\pyzo2014a\lib\site-packages\numba\compiler.py", line 343, in extract_bytecode
    bc = bytecode.ByteCode(func=self.func)
  File "C:\pyzo2014a\lib\site-packages\numba\bytecode.py", line 343, in __init__
    raise NotImplementedError("cell vars are not supported")
NotImplementedError: cell vars are not supported
回溯(最近一次呼叫最后一次):
文件“C:\Users\Ricevind\Desktop\PyPy\Skrypty\Rownowaga.py”,第29行,在
f=rownowaga_pypy(u,y)
文件“C:\pyzo2014a\lib\site packages\numba\dispatcher.py”,第171行,在\u-compile\u中为\u-args
返回self.compile(sig)
文件“C:\pyzo2014a\lib\site packages\numba\dispatcher.py”,第348行,编译
标志=标志,局部变量=自身。局部变量)
文件“C:\pyzo2014a\lib\site packages\numba\compiler.py”,第637行,在compile\u extra中
返回管道.compile_extra(func)
文件“C:\pyzo2014a\lib\site packages\numba\compiler.py”,第356行,在compile\u extra中
提高e
文件“C:\pyzo2014a\lib\site packages\numba\compiler.py”,第351行,在compile\u extra中
bc=self.extract_字节码(func)
文件“C:\pyzo2014a\lib\site packages\numba\compiler.py”,第343行,以提取字节码形式
bc=字节码.字节码(func=self.func)
文件“C:\pyzo2014a\lib\site packages\numba\bytecode.py”,第343行,在\uuu init中__
raise NOTEImplementedError(“不支持单元格变量”)
NotImplementedError:不支持单元格变量

我最感兴趣的是“单元格变量不受支持”的含义,因为Google不会返回有意义的结果。

Numba目前在嵌套列表上的工作效果并不特别好(至少从v0.21开始)。我相信这就是“cell vars”错误所指的,但我不是100%确定。下面,我将所有内容转换为numpy数组,以使numba能够优化代码:

import numpy as np
import numba as nb
import math

def rownowaga(u, v):
    wymiar_x = len(u)
    wymiar_y = len(u[1])
    f = [[[0 for j in range(wymiar_y)] for i in range(wymiar_x)] for k in range(9)]
    cx = [0., 1., 0., -1., 0., 1., -1., -1., 1.]
    cy = [0., 0., 1., 0., -1., 1., 1., -1., -1.]
    w = [4./9, 1./9, 1./9, 1./9, 1./9, 1./36, 1./36, 1./36, 1./36] 
    for i in range( wymiar_x):
        for j in range (wymiar_y):
            for k in range(9):
                up = u[i][j]
                vp = v[i][j]
                udot = (up**2 + vp**2)
                cu = up*cx[k] + vp*cy[k]
                f[k][i][j] =  w[k] + w[k]*(3.0*cu + 4.5*cu**2 - 1.5*udot)
    return f

# Pull these out so that numba treats them as constant arrays
cx = np.array([0., 1., 0., -1., 0., 1., -1., -1., 1.])
cy = np.array([0., 0., 1., 0., -1., 1., 1., -1., -1.])
w = np.array([4./9, 1./9, 1./9, 1./9, 1./9, 1./36, 1./36, 1./36, 1./36]) 

@nb.jit(nopython=True)
def rownowaga_numba(u, v):
    wymiar_x = u.shape[0]
    wymiar_y = u[1].shape[0]
    f = np.zeros((9, wymiar_x, wymiar_y))

    for i in xrange( wymiar_x):
        for j in xrange (wymiar_y):
            for k in xrange(9):
                up = u[i,j]
                vp = v[i,j]
                udot = (up*up + vp*vp)
                cu = up*cx[k] + vp*cy[k]
                f[k,i,j] =  w[k] + w[k]*(3.0*cu + 4.5*cu**2 - 1.5*udot)
    return f
现在,让我们设置一些测试阵列:

u = [[math.sin(i) + math.cos(j) for j in range(40)] for i in range(1000)]
y = [[math.sin(i) + math.cos(j) for j in range(40)] for i in range(1000)]

u_np = np.array(u)
y_np = np.array(y)
首先,让我们验证我的numba代码是否给出了与OP代码相同的答案:

f1 = rownowaga(u, y)
f2 = rownowaga_numba(u_np, y_np)
从ipython笔记本中:

In [13]: np.allclose(f2, np.array(f1))
Out[13]:
True
现在让我们在我的笔记本电脑上计时:

In [15] %timeit f1 = rownowaga(u, y)
1 loops, best of 3: 288 ms per loop


In [16] %timeit f2 = rownowaga_numba(u_np, y_np)
1000 loops, best of 3: 973 µs per loop
因此,我们可以在代码更改最少的情况下获得300倍的速度。请注意,我使用的是0.22之前的Numba夜间构建:

In [16]: nb.__version__
Out[16]:
'0.21.0+137.gac9929d'
这太棒了!:)非常感谢。