为什么使用numba导入numpy零功能失败并行化?

时间:2017-11-20 09:11:23

标签: arrays python-2.7 numpy parallel-processing numba

根据Numba docs,应支持numpy数组创建函数onesimport numpy as np。但是,当我从numpy导入零函数时,使用简单函数测试它会导致nopython错误。但是,如果我执行np.zeros并使用from numpy import array from numpy import zeros from numpy.random import rand from numba import njit, prange # @njit() @njit(parallel=True) def prange_test(A): s = 0 z = zeros((3, 3)) for i in prange(A.shape[0]): s += A[i] return s A = rand(10) test = prange_test(A) ,则没有问题。我从numpy得到的功能有什么不同吗?我只想导入我需要的功能,而不是整个numpy库。

此代码段失败:

from numpy import array
from numpy.random import rand
from numba import njit, prange
import numpy as np

@njit(parallel=True)
def prange_test(A):
    s = 0
    z = np.zeros((3, 3))
    for i in prange(A.shape[0]):
        s += A[i]
    return s

A = rand(10)

test = prange_test(A)

此代码段有效:

<rewrite>
    <rules>
      <rule name="Redirect Before Analysis" stopProcessing="true">
        <match url="^analysis" />
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
</rewrite>

我正在使用Numba版本0.35.0,Numpy版本1.13.2 This is the rather long Traceback I get

1 个答案:

答案 0 :(得分:0)

让我们一步一步走

a) @numba.njit( parallel = True )装饰者的 parallel 选项是(cit。)“ experimental 努力自动检测在代码中引入某种形式的并行机会。

b)代码几乎就是numba documentation, using almost exactly the same prange()-constructor code-block, but inside an @autojit decorated example:的代码片段

from numba import autojit, prange

@autojit
def parallel_sum(A):
    sum = 0.0
    for i in prange(A.shape[0]):
        sum += A[i]

    return sum

c)错误消息几乎报告了与 line 12 相关的自动检测转换中出现的问题,只有弱引用可能是 {{ 1}} ,指的是在代码块的中间表示中表达的意图的“自动理解”中的某种问题,其中s += A[i] -index应该被使用 - prange 但是某些类型相关或Var($parfor_index_tuple_var.14) - 解耦相关的问题无法通过 tuple来解决/ strong> -LLVM翻译器。然而,回溯还提到numba.jit有问题来检测call_parallel_gufunc - 构造函数prange的上限,而numba文档到目前为止提到只有CPU指导< / strong>支持并行代码(不是任何{GPU | guvectorize | et al} -non-CPU-kernel(s)),这里有一个更好的文档化MCVE与匹配错误Traceback将被赞赏,而不是弱引用{ {3}}

d)最后但并非最不重要的是,numba要求文档中的强制性步骤 stop = load_range( stop ) 仅使用 (cit。) parallel=True

结合使用

如何进行?

1)按原样测试上面复制的nopython=True - 已发布代码,以查看numba的较新版本是否仍然保留了之前版本中已经有效的所有承诺。即使用numba - 装饰器并将确切的代码副本重新运行到@numba.autojit此测试。

2)测试代码,从第1步开始进行POSACK-ed,这次是在 { POSACK | NACK }- 装饰器下(除了装饰器之外没有其他任何变化) @numba.njit( parallel = True, nopython = True )装饰者政策的影响。

3)测试代码,从第2步开始进行POSACK-ed,这次进行其他修改

概念性评论:

尽管对numba团队充满敬意,但 { POSACK | NACK }-parallel反模式的情况几乎不会比这更糟糕。

除了[PAR] - 进程部分设置非常庞大的开销成本,并且没有什么可以有效地并行计算(只需注意实际的值依赖图...)PNG-picture.可以支付多少钱主要是比原来的表现差。 并行流程调度通常具有完全相反的动机。

如果确实对更智能的代码执行感兴趣,请使用prange()具有更好的性能/成本比:

  • 使用调用界面签名的明确公告删除IR代码的任何残留类型分析相关部分
  • 避免在性能调优代码中进行内存分配,而是预先分配并作为另一个参数传递
  • 扩展调用接口,以避免调用者方面众所周知的事情被推迟到numba自动代码分析中
numba.jit

性能

  @numba.jit( 'float64( float64[:], int64, float64[:,:] )', nogil = True, nopython = True )
  def prange_test( vectorA,       # 
                   vectorAshape0, # avoids numba-code to speculate on type
                   arrayZ         # avoids "local" new memory allocation
                   ):
      sum = 0
      ...
      return sum

基准。总是。始终使用真实大小的数据集。永远不要依赖教科书大小的文物,而是要进入现实世界的尺度。

结果显示, from zmq import Stopwatch; aClk = Stopwatch() def a_just_vectorised_sum( vectorA ): return vectorA.sum() A = np.random.rand( 1000000 ) aClk.start(); s = a_just_vectorised_sum( A ); aClk.stop() 1145L 1190L 1188L 单元格大小的向量大约占1.000.0001,200 [us] ~ 0.0012 [s]小于约sum()单元格1.2 [ns] - ed 这设置了一个标准来比较任何其他实现。