简体   繁体   English

如何使用numpy提高python代码的性能

[英]How can I improve python code performance using numpy

I have read this blog which shows how an algorithm had a 250x speed-up by using numpy. 我已经阅读了该博客该博客显示了如何通过使用numpy将算法的速度提高250倍。 I have tried to improve the following code by using numpy but I couldn't make it work: 我试图通过使用numpy改进以下代码,但无法使其工作:

    for i in nodes[1:]:
        for lb in range(2, diameter+1):
            not_valid_colors = set()
            valid_colors = set()

            for j in nodes:
                if j == i:
                    break

                if distances[i-1, j-1] >= lb:
                    not_valid_colors.add(c[j, lb])
                else:
                    valid_colors.add(c[j, lb])

                c[i, lb] = choose_color(not_valid_colors, valid_colors)

    return c

Explanation 说明

The code above is part of an algorithm used to calculate the self similar dimension of a graph. 上面的代码是用于计算图的自相似维的算法的一部分。 It works basically by constructing dual graphs G' where a node is connected to each other node if the distance between them is greater or equals to a given value (Lb) and then compute the graph coloring on those dual networks. 它基本上是通过构造对偶图G'来工作的,如果两个图之间的距离大于或等于给定值(Lb),则一个节点彼此连接,然后在这些对偶网络上计算图的着色。

The algorithm description is the following: 算法描述如下:

  1. Assign a unique id from 1 to N to all network nodes, without assigning any colors yet. 为所有网络节点分配一个从1到N的唯一ID,但尚未分配任何颜色。
  2. For all Lb values, assign a color value 0 to the node with id=1, ie C_1l = 0. 对于所有Lb值,将颜色值0分配给id = 1的节点,即C_1l = 0。
  3. Set the id value i = 2. Repeat the following until i = N. 设置id值i =2。重复以下步骤,直到i =N。
    • a) Calculate the distance l_ij from i to all the nodes in the network with id j less than i. a)计算从i到ID小于i的网络中所有节点的距离l_ij。
    • b) Set Lb = 1 b)设置Lb = 1
    • c) Select one of the unused colors C[ j][l_ij] from all nodes j < i for which l_ij ≥ Lb . c)从l_ij≥Lb的所有节点j <i中选择未使用的颜色C [j] [l_ij]之一。 This is the color C[i][Lb] of node i for the given Lb value. 对于给定的Lb值,这是节点i的颜色C [i] [Lb]。
    • d) Increase Lb by one and repeat (c) until Lb = Lb_max. d)将Lb加1,然后重复(c),直到Lb = Lb_max。
    • e) Increase i by 1. e)将i增加1。

I wrote it in python but it takes more than a minute when try to use it with small networks which have 100 nodes and p=0.9. 用python编写了它,但是尝试在具有100个节点且p = 0.9的小型网络上使用它需要一分多钟。

As I'm still new to python and numpy I did not find the way to improve its efficiency. 由于我还是python和numpy的新手,所以没有找到提高其效率的方法。

Is it possible to remove the loops by using the numpy.where to find where the paths are longer than the given Lb? 是否可以使用numpy.where删除循环,以找出路径比给定Lb长的地方? I tried to implement it but didn't work... 我尝试实现它,但是没有用...

if you want to go to numpy, you can just change the lists into arrays, for example distances[i-1][j-1] becomes distances[i-1, j-1] after you declare distances as a numpy array. 如果要转到numpy,则可以将列表更改为数组,例如,在将distances[i-1, j-1]声明为numpy数组后distances[i-1, j-1] distances[i-1][j-1]变为distances[i-1, j-1] same with c[i][lb] . c[i][lb] About valid_colors and not_valid_colors you should think a bit more because with numpy arrays you cannot append things: the array have fixed length, so you should fix a maximum size before. 关于valid_colorsnot_valid_colors您应该多考虑一点,因为对于numpy数组,您无法追加内容:该数组具有固定的长度,因此您应该在此之前固定一个最大大小。 Another idea is that after you have everything in numpy, you can cythonize your code http://docs.cython.org/src/tutorial/cython_tutorial.html it means that all your loops will become very fast. 另一个想法是,在将所有内容放入numpy之后,您可以对代码http://docs.cython.org/src/tutorial/cython_tutorial.html进行cythonize处理,这意味着所有循环都将变得非常快。 In any case, if you don't want cython and you look at the blog, you see that distances is declared as an array in the main() 无论如何,如果您不想要cython并查看博客,您会看到在main()中将distances声明为数组

Vectorized operations with numpy arrays are fast since actual calculations are done with underlying libraries such as BLAS and LAPACK without Python overheads. 使用numpy数组进行矢量化运算的速度很快,因为实际的计算是使用BLASLAPACK等基础库完成的,而没有Python开销。 With loop-intensive operations, you will not see those benefits. 使用循环密集型操作,您将看不到这些好处。

You usually have to figure out a way to vectorize operations (usually possible with a smart use of array slicing). 通常,您必须找出一种向量化操作的方法(通常可以通过巧妙地使用数组切片来实现)。 Some operations are inherently loop-intensive, however, and sometimes it is not easy to vectorize them (which seems to be the case for your code). 但是,某些操作本质上是循环密集型的,有时对它们进行矢量化并不容易(对于您的代码来说似乎是这种情况)。

In those cases, you can first try Numba , which generates optimized machine code from a Python function without any modifications. 在这种情况下,您可以先尝试Numba ,它无需任何修改即可从Python函数生成优化的机器代码。 (You just annotate the function and it will automatically do it for you). (您只需注释该功能,它将自动为您完成该功能)。 I do not have a lot of experience with it, and have not tried using this for complicated functions. 我没有很多经验,也没有尝试将其用于复杂功能。

If this does not work, then you can use Cython , which converts Python-like code (with typed variables) into efficient C code automatically and generates a Python extension module that you can import and use in Python. 如果这不起作用,则可以使用Cython ,后者将类似Python的代码(带有类型变量)自动转换为高效的C代码,并生成一个Python扩展模块,您可以在Python中导入和使用它。 That will usually give you at least an order of magnitude (usually two orders of magnitude) speedup for loop-intensive operations. 对于循环密集型操作,这通常至少会提高一个数量级(通常为两个数量级)。 I generally find Cython easy to use since unlike pure C, one can access your numpy arrays directly in Cython code. 我通常认为Cython易于使用,因为与纯C不同,Cython可以直接在Cython代码中访问numpy数组。

I recommend using Anaconda Python distribution , since you will be able to install these packages easily. 我建议使用Anaconda Python发行版 ,因为您将能够轻松安装这些软件包。 I'm sorry I don't have a specific answer for your code. 抱歉,您的代码没有具体答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM