python - 如何加速矩阵码

标签 python performance numpy

我有以下简单代码,它估计 h x n 二进制矩阵具有特定属性的概率。它以指数时间运行(开始时很糟糕)但令我惊讶的是即使对于 n = 12 和 h = 9,它也如此缓慢。

#!/usr/bin/python

import numpy as np
import itertools

n = 12
h = 9

F = np.matrix(list(itertools.product([0,1],repeat = n))).transpose()

count = 0
iters = 100
for i in xrange(iters):
    M =  np.random.randint(2, size=(h,n))
    product = np.dot(M,F)
    setofcols = set()
    for column in product.T:
        setofcols.add(repr(column))
    if (len(setofcols)==2**n):
        count = count + 1
print count*1.0/iters

我已经使用 n = 10 和 h = 7 对其进行了分析。输出相当长,但这里是花费更多时间的行。

        23447867 function calls (23038179 primitive calls) in 35.785 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.002    0.001    0.019    0.010 __init__.py:1(<module>)
        1    0.001    0.001    0.054    0.054 __init__.py:106(<module>)
        1    0.001    0.001    0.022    0.022 __init__.py:15(<module>)
        2    0.003    0.002    0.013    0.006 __init__.py:2(<module>)
        1    0.001    0.001    0.003    0.003 __init__.py:38(<module>)
        1    0.001    0.001    0.001    0.001 __init__.py:4(<module>)
        1    0.001    0.001    0.004    0.004 __init__.py:45(<module>)
        1    0.001    0.001    0.002    0.002 __init__.py:88(<module>)
   307200    0.306    0.000    1.584    0.000 _methods.py:24(_any)
   102400    0.026    0.000    0.026    0.000 arrayprint.py:22(product)
   102400    1.345    0.000   32.795    0.000 arrayprint.py:225(_array2string)
307200/102400    1.166    0.000   33.350    0.000 arrayprint.py:335(array2string)
   716800    0.820    0.000    1.162    0.000 arrayprint.py:448(_extendLine)
204800/102400    1.699    0.000    5.090    0.000 arrayprint.py:456(_formatArray)
   307200    0.651    0.000   22.510    0.000 arrayprint.py:524(__init__)
   307200   11.783    0.000   21.859    0.000 arrayprint.py:538(fillFormat)
  1353748    1.920    0.000    2.537    0.000 arrayprint.py:627(_digits)
   102400    0.576    0.000    2.523    0.000 arrayprint.py:636(__init__)
   716800    2.159    0.000    2.159    0.000 arrayprint.py:649(__call__)
   307200    0.099    0.000    0.099    0.000 arrayprint.py:658(__init__)
   102400    0.163    0.000    0.225    0.000 arrayprint.py:686(__init__)
   102400    0.307    0.000   13.784    0.000 arrayprint.py:697(__init__)
   102400    0.110    0.000    0.110    0.000 arrayprint.py:713(__init__)
   102400    0.043    0.000    0.043    0.000 arrayprint.py:741(__init__)
        1    0.003    0.003    0.003    0.003 chebyshev.py:87(<module>)
        2    0.001    0.000    0.001    0.000 collections.py:284(namedtuple)
        1    0.277    0.277   35.786   35.786 counterfeit.py:3(<module>)
   205002    0.222    0.000    0.247    0.000 defmatrix.py:279(__array_finalize__)
   102500    0.747    0.000    1.077    0.000 defmatrix.py:301(__getitem__)
   102400    0.322    0.000   34.236    0.000 defmatrix.py:352(__repr__)
   102400    0.100    0.000    0.508    0.000 fromnumeric.py:1087(ravel)
   307200    0.382    0.000    2.829    0.000 fromnumeric.py:1563(any)
      271    0.004    0.000    0.005    0.000 function_base.py:3220(add_newdoc)
        1    0.003    0.003    0.003    0.003 hermite.py:59(<module>)
        1    0.003    0.003    0.003    0.003 hermite_e.py:59(<module>)
        1    0.001    0.001    0.002    0.002 index_tricks.py:1(<module>)
        1    0.003    0.003    0.003    0.003 laguerre.py:59(<module>)
        1    0.003    0.003    0.003    0.003 legendre.py:83(<module>)
        1    0.001    0.001    0.001    0.001 linalg.py:10(<module>)
        1    0.001    0.001    0.001    0.001 numeric.py:1(<module>)
   102400    0.247    0.000   33.598    0.000 numeric.py:1365(array_repr)
   204800    0.321    0.000    1.143    0.000 numeric.py:1437(array_str)
   614400    1.199    0.000    2.627    0.000 numeric.py:2178(seterr)
   614400    0.837    0.000    0.918    0.000 numeric.py:2274(geterr)
   102400    0.081    0.000    0.186    0.000 numeric.py:252(asarray)
   307200    0.259    0.000    0.622    0.000 numeric.py:322(asanyarray)
        1    0.003    0.003    0.004    0.004 polynomial.py:54(<module>)
   513130    0.134    0.000    0.134    0.000 {isinstance}
   307229    0.075    0.000    0.075    0.000 {issubclass}
5985327/5985305    0.595    0.000    0.595    0.000 {len}
 306988    0.120    0.000    0.120    0.000 {max}
   102400    0.061    0.000    0.061    0.000 {method '__array__' of 'numpy.ndarray' objects}
   102406    0.027    0.000    0.027    0.000 {method 'add' of 'set' objects}
   307200    0.241    0.000    1.824    0.000 {method 'any' of 'numpy.ndarray' objects}
   307200    0.482    0.000    0.482    0.000 {method 'compress' of 'numpy.ndarray' objects}
   204800    0.035    0.000    0.035    0.000 {method 'item' of 'numpy.ndarray' objects}
   102451    0.014    0.000    0.014    0.000 {method 'join' of 'str' objects}
   102400    0.222    0.000    0.222    0.000 {method 'ravel' of 'numpy.ndarray' objects}
   921176    3.330    0.000    3.330    0.000 {method 'reduce' of 'numpy.ufunc' objects}
   102405    0.057    0.000    0.057    0.000 {method 'replace' of 'str' objects}
  2992167    0.660    0.000    0.660    0.000 {method 'rstrip' of 'str' objects}
   102400    0.041    0.000    0.041    0.000 {method 'splitlines' of 'str' objects}
        6    0.003    0.000    0.003    0.001 {method 'sub' of '_sre.SRE_Pattern' objects}
   307276    0.090    0.000    0.090    0.000 {min}
      100    0.013    0.000    0.013    0.000 {numpy.core._dotblas.dot}
   409639    0.473    0.000    0.473    0.000 {numpy.core.multiarray.array}
  1228800    0.239    0.000    0.239    0.000 {numpy.core.umath.geterrobj}
   614401    0.352    0.000    0.352    0.000 {numpy.core.umath.seterrobj}
   102475    0.031    0.000    0.031    0.000 {range}
   102400    0.076    0.000    0.102    0.000 {reduce}
204845/102445    0.198    0.000   34.333    0.000 {repr}

矩阵的乘法似乎只需要一小部分时间。是否可以加快其余部分?

结果

现在有三个答案,但目前似乎有一个错误。我用 n=18、h=11 和 iters=10 测试了剩下的两个。

  • 气泡 - 21 秒,185MB 内存。 “排序”16 秒。
  • hpaulj - 7.5 秒,130MB 内存。 “tolist”3 秒。 “numpy.core.multiarray.array”1.5 秒,“genexpr”(“设置”行)1.5 秒。

有趣的是,矩阵相乘的时间仍然只占总时间的一小部分。

最佳答案

要加快上面的代码,您应该避免循环。

import numpy as np
import itertools

def unique_rows(a):
    a = np.ascontiguousarray(a)
    unique_a = np.unique(a.view([('', a.dtype)]*a.shape[1]))
    return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1]))


n = 12
h = 9
iters=100
F = np.matrix(list(itertools.product([0,1],repeat = n))).transpose()
M =  np.random.randint(2, size=(h*iters,n))
product = np.dot(M,F)
counts = map(lambda x: len(unique_rows(x.T))==2**n, np.split(product,iters,axis=0))
prob=float(sum(counts))/iters

#All unique submatrices M (hxn) with the sophisticated property...
[np.split(M,iters,axis=0)[j] for j in range(len(counts)) if counts[j]==True]

关于python - 如何加速矩阵码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20542552/

相关文章:

python - Pafy Youtube 网址错误

javascript - 对象的属性访问和普通变量访问之间的速度差异是多少?

python - 在Python中将矩阵数据转储到文本文件时插入行和列标签

performance - 如何在多模块项目中计时(分析)maven目标

python - np.nditer 引用类型的返回类型

python - 如何对列的成对点积求和

python - 使用 Plotly 散点图绘制未排序的数据框

Python - 查找字符串中字符串列表第一次出现的索引位置

python - CSV 中的列要在 python 中列出?

c - 普通数组声明和在结构内声明的数组之间的内存和效率差异