将函数放入本地命名空间以加快访问速度将描述符放入accoun

2024-03-29 06:44:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我在一个类中的艰难的循环中使用numpy.random.normal函数。在

class MyClass(MyBaseClass):   
    def run(self):
        while True:
            ...
            self.L.append(numpy.random.normal(0,1))

我知道在Python中使用多个查找非常慢。在numpy.random.normal中有3个查找:首先查找numpy,然后是random,然后是{}。在

所以我决定通过将numpy.random.normal分配给一个局部变量_normal来解决这个问题。在

开始吧:

^{pr2}$

我真正关心的是描述词。当访问一个类中的一个变量时,所有基类都会查找同名的数据描述符。描述如下here

Check objectname.__class__.__dict__for attrname. If it exists and is a data-descriptor, return the descriptor result. Search all bases of objectname.__class__ for the same case.

所以,我想,如果我像上面那样把_normal放在局部空间中,它将查找数据描述符的所有基类。我担心它会成为经济放缓的根源。在

我的担心有道理吗?在

我应该担心在基类中查找描述符所需的时间吗?在

在类中使用某个函数时,有没有更好的方法来加速对位于模块深处的函数的访问?在


在对答案的评论中进行了讨论。在

我决定提供一些似乎很重要的执行细节(对于我的特殊情况)。在

实际上,代码更接近于此(非常简化):

class MyClass(MyBaseClass):

    def __iter__(self):
        return self

    def next(self):
        self.L.append(numpy.random.normal(0,1))   

    def run(self):
        while True:
            self.next()

Tags: 函数runselfnumpytruedefmyclassrandom
2条回答

如果你必须这样做(函数查找实际上是主要的成本吗?随机数生成并不便宜)您应该意识到一个全局+一个attr查找(MyClass._normal)并不比一个全局+三个attr查找(numpy.random.normal)便宜多少。您真正想要的是在循环中获得zero全局或attr查找,这只能通过在函数内定义_normal来实现。如果您真的很想缩短周期,还应该预先绑定list append调用:

class MyClass(MyBaseClass):
    def run(self):
        _normal = numpy.random.normal
        _Lappend = self.L.append
        while True:
            ...
            _Lappend(_normal(0,1))

对比反汇编输出(仅用于append语句):

^{pr2}$

  LOAD_FAST                2 (_Lappend)
  LOAD_FAST                1 (_normal)
  LOAD_CONST               1 (0)
  LOAD_CONST               2 (1)
  CALL_FUNCTION            2
  CALL_FUNCTION            1

更好的方法是向量化生成许多随机法线偏离,并一次性将它们附加到列表中,可以使用size参数对numpy.random.normal执行此操作。在

And I wary of it becoming a source of a slowdown.

Are my concerns justified?

那要看情况了。对于你想要的应用程序,它已经足够快了吗?如果是这样,不要担心。CPython、PyPy、NumPy和moore定律的变化可能会在“减速”成为一个症结之前缓解它的严重程度。在

相关问题 更多 >