为什么这个python类不能与numba jitclass一起使用? [英] Why this python class is not working with numba jitclass?

查看:670
本文介绍了为什么这个python类不能与numba jitclass一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在numpy的帮助下编写了以下代码,并且希望通过numba来提高性能.我不确定为什么它不起作用,因为我已经按照numba系统设置了所有变量.我正在尝试加快此代码的速度,因为将来我将使用大型数据集.

I have written the following code with the help of numpy and I want to improve the performance with numba. I am not sure why it is not working as I have set all the variables as per numba system. I am trying to speed up this code as I would be working with large data sets in the future.

import numpy as np
import math
from numba import jitclass 
from numba import float64,int64

spec =[
       ('spacing',float64),
       ('n_iterations',int64),
       ('np_emptyhouses',float64[:,:]),
       ('np_agenthouses',float64[:,:]),
       ('similarity_threshhold',float64),
       ('n_changes',int64)
       ]

@jitclass(spec)
class geo_schelling_update:

    def __init__(self,n_iterations,spacing,np_agenthouses,np_emptyhouses,similarity_threshhold):
        self.spacing=spacing
        self.n_iterations=n_iterations
        self.np_emptyhouses=np_emptyhouses
        self.np_agenthouses=np_agenthouses
        self.similarity_threshhold=similarity_threshhold

    def distance_vectorize(self,pointA1, pointA2,agent):
        x_square=np.square(pointA1-agent[0])
        y_square=np.square(pointA2-agent[1])
        dist=np.sqrt(np.array(x_square,dtype=np.float32)+np.array(y_square,dtype=np.float32))
        return np.round(dist,4)

    def is_unsatisfied_vectorize(self,x,y):
        race = np.extract(np.logical_and(np.equal(self.np_agenthouses[:,0],x),np.equal(self.np_agenthouses[:,1],y)),self.np_agenthouses[:,2])[0]
        euclid_distance1=round(math.hypot(self.spacing,self.spacing),4)
        euclid_distance2=self.spacing
        total_agents=np.extract(np.logical_or(np.equal(np.round(np.hypot((self.np_agenthouses[:,0]-(x)),(self.np_agenthouses[:,1]-(y))),4),euclid_distance1),np.equal(np.round(np.hypot((self.np_agenthouses[:,0]-(x)),(self.np_agenthouses[:,1]-(y))),4),euclid_distance2)),self.np_agenthouses[:,2])
        if total_agents.size ==0:
            return False
        else:
            return total_agents[total_agents==race].size/total_agents.size<self.similarity_threshhold    

    def move_to_empty(self,x,y):
        race = np.extract(np.logical_and(np.equal(self.np_agenthouses[:,0],x),np.equal(self.np_agenthouses[:,1],y)),self.np_agenthouses[:,2])[0]
        x_new,y_new=self.np_emptyhouses[np.random.choice(self.np_emptyhouses.shape[0],1),:][0]
        self.np_agenthouses=self.np_agenthouses[~(np.logical_and(self.np_agenthouses[:,0]==x, self.np_agenthouses[:,1]==y))]
        self.np_agenthouses=np.vstack([self.np_agenthouses,[x_new,y_new,race]])
        self.np_emptyhouses=self.np_emptyhouses[~(np.logical_and(self.np_emptyhouses[:,0]==x_new, self.np_emptyhouses[:,1]==y_new))]
        self.np_emptyhouses=np.vstack([self.np_emptyhouses,[x,y]])

    def update_helper(self,agent):
        if self.is_unsatisfied_vectorize(agent[0],agent[1]):
            self.move_to_empty(agent[0],agent[1])
            return 1
        else:
            return 0

    def update(self):
        for i in np.arange(self.n_iterations):
            np_oldagenthouses=self.np_agenthouses.copy()
            n_changes=0
            for row in np_oldagenthouses:
                n=self.update_helper(row)
                n_changes+=n
            print(n_changes)
            print(i)
            if n_changes == 0:
                break



np_agenthouses=np.array([[-71.8,    41.4,   2.0],
                        [-71.6, 41.4,   2.0],
                        [-71.6, 41.6,   2.0],
                        [-71.4, 41.6,   1.0],
                        [-71.6, 41.8,   1.0],
                        [-71.4, 41.8,   2.0],
                        [-71.6, 42.0,   2.0],
                        [-71.4, 42.0,   1.0],
                        [-71.4, 41.4,   2.0],
                        [-71.2, 41.4,   1.0]])

np_emptyhouses=np.array([[-71.8,  41.3],[-71.8,  41.4],[-71.5,  41.5],
                [-71.5,  41.6],[-71.7,  41.8],[-71.7,  41.9],
                [-71.5,  41.9],[-71.2,  41.4],[-71.6,  41.7]])

spacing=0.1
similarity_threshhold=0.65
n_iterations=100
schelling= geo_schelling_update(n_iterations,
                         spacing,
                         np_agenthouses,
                         np_emptyhouses,similarity_threshhold)
schelling.update() 

这是我遇到的错误:

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Failed in nopython mode pipeline (step: nopython frontend)
Failed in nopython mode pipeline (step: nopython frontend)
Invalid use of Function(<function round_ at 0x000001909ED270D0>) with argument(s) of type(s): (array(float64, 1d, C), Literal[int](4))
 * parameterized
In definition 0:
    All templates rejected with literals.
In definition 1:
    All templates rejected without literals.
This error is usually caused by passing an argument of a type that is unsupported by the named function.
[1] During: resolving callee type: Function(<function round_ at 0x000001909ED270D0>)
[2] During: typing of call at C:/Users/ksharma/Documents/geoschelling/test2.py (42)


File "test2.py", line 42:
    def is_unsatisfied_vectorize(self,x,y):
        <source elided>
        euclid_distance2=self.spacing
        total_agents=np.extract(np.logical_or(np.equal(np.round(np.hypot((self.np_agenthouses[:,0]-(x)),(self.np_agenthouses[:,1]-(y))),4),euclid_distance1),np.equal(np.round(np.hypot((self.np_agenthouses[:,0]-(x)),(self.np_agenthouses[:,1]-(y))),4),euclid_distance2)),self.np_agenthouses[:,2])
        ^

[1] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'is_unsatisfied_vectorize') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[2] During: typing of call at C:/Users/ksharma/Documents/geoschelling/test2.py (57)

[3] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'is_unsatisfied_vectorize') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[4] During: typing of call at C:/Users/ksharma/Documents/geoschelling/test2.py (57)


File "test2.py", line 57:
    def update_helper(self,agent):
        if self.is_unsatisfied_vectorize(agent[0],agent[1]):
        ^

[1] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'update_helper') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[2] During: typing of call at C:/Users/ksharma/Documents/geoschelling/test2.py (68)

[3] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'update_helper') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[4] During: typing of call at C:/Users/ksharma/Documents/geoschelling/test2.py (68)


File "test2.py", line 68:
    def update(self):
        <source elided>
            for row in np_oldagenthouses:
                n=self.update_helper(row)
                ^

[1] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'update') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[2] During: typing of call at <string> (3)

[3] During: resolving callee type: BoundFunction((<class 'numba.types.misc.ClassInstanceType'>, 'update') for instance.jitclass.geo_schelling_update#190b49eec18<spacing:float64,n_iterations:int64,np_emptyhouses:array(float64, 2d, A),np_agenthouses:array(float64, 2d, A),similarity_threshhold:float64,n_changes:int64>)
[4] During: typing of call at <string> (3)

我也在IDE中运行此代码.如果上面的代码不适用于numba,那么使此代码工作以获得相同结果的最佳方法是什么.

Also I am running this code in IDE. If the above code doesn't work with numba then what is the best way to make this code work to get the same result.

推荐答案

问题出在np.round.从文档中还不清楚,但是您可以通过查看,如果您在数组输入上使用该函数,则需要提供所有3个参数.因此以下操作无效:

The issue is with np.round. It's not entirely clear from the documentation, but you can see from looking at the source, that if you are using the function on an array input, you need to provide all 3 arguments. So the following does not work:

nb.jit(nopython=True)
def func(x):
    return np.round(x)

但以下各项可以正常工作:

but the following works as expected:

nb.jit(nopython=True)
def func(x):
    out = np.empty_like(x)
    np.round(x, 0, out)
    return out

请参见文档有关np.around 的完整说明.我要在numba问题追踪器上提出一个问题,因为从查看文档来看这不是很明显.

See the docs for np.around for the full description. I'm going to raise an issue on the numba issue tracker since this isn't obvious from looking at the docs.

这篇关于为什么这个python类不能与numba jitclass一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆