【问题标题】:Why is this numpy array operation so slow?为什么这个 numpy 数组操作这么慢?
【发布时间】:2011-04-06 13:54:50
【问题描述】:

我是一个 python 初学者,我正在尝试平均两个形状为 (1024,1024) 的 NumPy 2D 数组。这样做非常快:

newImage = (image1 + image2) / 2

但是现在图像有一个“掩码”,如果设置为零,某些元素会失效。这意味着如果元素之一为零,则结果元素也应为零。我的简单解决方案是:

newImage = numpy.zeros( (1024,1024) , dtype=numpy.int16 )

for y in xrange(newImage.shape[0]):
   for x in xrange(newImage.shape[1]):
      val1 = image1[y][x]  
      val2 = image2[y][x]                            
      if val1!=0 and val2!=0:               
         newImage[y][x] = (val1 + val2) / 2

但这真的很慢。我没有计时,但它似乎慢了 100 倍。

我也尝试使用 lambda 运算符和“map”,但这不会返回 NumPy 数组。

【问题讨论】:

    标签: python arrays matrix numpy


    【解决方案1】:

    试试这个:

    newImage = numpy.where(np.logical_and(image1, image2), (image1 + image2) / 2, 0)
    

    如果image1image2 都不等于0,取它们的平均值,否则为零。

    【讨论】:

      【解决方案2】:

      使用原生 Python 代码循环通常比使用循环慢得多 使用快速 C 循环的内置工具。我不熟悉 NumPy;能够 您使用map() 将您的两个输入数组转换为 输出?如果是这样,那应该会更快。

      【讨论】:

        【解决方案3】:

        一般来说,显式for 循环在 Python 中非常低效,不仅对于 numpy 操作。幸运的是,有更快的方法来解决我们的问题。如果内存不是问题,这个解决方案相当不错:

        import numpy as np
        new_image = np.zeros((1024, 1024), dtype=np.int16)
        valid = (image1!=0) & (image2!=0)
        new_image[valid] = (image1+image2)[valid]
        

        另一种使用掩码数组的解决方案,它不会创建数组的副本(它们代表原始image1/2 的视图:

        m1 = np.ma.masked_equal(image1, 0)
        m2 = np.ma.masked_equal(image2, 0)
        new_image = (m1+m2).filled(0)
        

        更新:对于具有大约 1000 个非零条目的数组,第一个解决方案似乎比第二个解决方案快 3 倍。

        【讨论】:

          【解决方案4】:

          numpy 数组访问操作充其量似乎很慢。我看不出有任何理由。构建一个简单的例子就可以清楚地看到:

              import numpy
              # numpy version
              def at(s,n):
                t1=time.time()
                a=numpy.zeros(s,dtype=numpy.int32)
                for i in range(n):
                  a[i%s]=n
                t2=time.time()
                return t2-t1
              # native version
              def an(s,n):
                t1=time.time()
                a=[(i) for i in range(s)]
                for i in range(n):
                  a[i%s]=n
                t2=time.time()
                return t2-t1
          
              # test
              [at(100000,1000000),an(100000,1000000)]
          

          结果:[0.21972250938415527, 0.15950298309326172]

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-01-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-11
            • 1970-01-01
            相关资源
            最近更新 更多