使用 cython 在图上执行框覆盖

Posted

技术标签:

【中文标题】使用 cython 在图上执行框覆盖【英文标题】:Perform the box covering on a graph using cython 【发布时间】:2015-10-15 23:19:53 【问题描述】:

我编写了一个 python 脚本来在图上执行框覆盖,但是当我在小图(100 个节点)上运行它时需要一分钟多的时间。 今天有人推荐 cython 来提高它的效率,所以我关注this guide 来修改我拥有的代码。

运行python代码的结果:

In [6]: %timeit test.test()
1000 loops, best of 3: 1.88 ms per loop

按照指南进行操作后,结果如下:

In [7]: %timeit c_test.test()
1000 loops, best of 3: 1.05 ms per loop

性能更好,但我相信它还有很多可以改进的地方。鉴于我今天刚认识 cython,我想问你如何改进这段代码:

import random as rnd
import numpy as np

cimport cython
cimport numpy as np

DTYPE = np.int
ctypedef np.int_t DTYPE_t


def choose_color(not_valid_colors, valid_colors):
    possible_values = list(valid_colors - not_valid_colors)

    if possible_values:
        return rnd.choice(possible_values)
    else:
        return max(valid_colors.union(not_valid_colors)) + 1


@cython.boundscheck(False)
cdef np.ndarray[DTYPE_t, ndim=2] greedy_coloring(np.ndarray[DTYPE_t, ndim=2] distances, int num_nodes, int diameter):
    cdef int  i, lb, j
    cdef np.ndarray[DTYPE_t, ndim=2] c = np.empty((num_nodes+1, diameter+2), dtype=DTYPE)

    c.fill(-1)
    # Matrix C will not use the 0 column and 0 row to
    # let the algorithm look very similar to the paper
    # pseudo-code

    nodes = list(range(1, num_nodes+1))
    rnd.shuffle(nodes)

    c[nodes[0], :] = 0

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

            for j in nodes[:i]:

                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


def test():
    distances = np.matrix('0 3 2 4 1 1; \
                           3 0 1 1 3 2; \
                           2 1 0 2 2 1; \
                           4 1 2 0 4 3; \
                           1 3 2 4 0 1; \
                           1 2 1 3 1 0')

    c = greedy_coloring(distances, 6, 4)

【问题讨论】:

我认为@joon 可能在他的回答中暗示了这一点,但choose_color 处于最内层循环是没有意义的。 是的,你是对的,在最里面的循环中调用choose_color是没有必要的。 【参考方案1】:

在 Cython 中,当您在 Cython 函数中删除更多 Python 调用时,您将获得更快的速度。

例如,在浏览您的代码时,您在greedy_coloring() 的嵌套循环内调用choose_color()。这也应该与函数内部定义的变量一起输入。由于会被反复调用,会带来很大的开销。

您可以使用 cython-a 选项(例如,cython -a file.pyx)来生成一个带注释的 html 文件,该文件直观地显示您的代码的哪一部分正在进行 Python 调用(黄线)。这将极大地帮助您改进 Cython 代码。

我很抱歉缺乏具体的指示 - 希望这会有所帮助。

【讨论】:

以上是关于使用 cython 在图上执行框覆盖的主要内容,如果未能解决你的问题,请参考以下文章

Cython编译独立的可执行文件

使用 Pyinstaller 或 Cython 从 Python 模块创建可执行文件

使用 pyximport reload_support 重新加载 Cython 不起作用

如何最好地将 C++/Cython 项目编译成可执行文件?

在 C++ 中嵌入 Cython

cx_Freeze 无法包含 Cython .pyx 模块