【问题标题】:What is the efficient way to check two memoryviews in loop?循环检查两个内存视图的有效方法是什么?
【发布时间】:2018-01-13 03:54:08
【问题描述】:

我想通过使用 memoryviews 来加速我的代码。这是我使用的两个类:

cdef class child:
    cdef public int[:] move
    def __init__(self, move):
        self.move = move

cdef class parent:
    cdef public:
        list children
        int[:, :] moves
    def __init__(self):
        self.children = []
    def add_children(self, moves):
        cdef int i = 0
        cdef int N = len(moves)
        for i in range(N):
            self.children.append(child(moves[i]))

这是我要检查类是否工作的代码:

temp = []
for i in range(100):
    temp.append([i, i+1])

cdef int[:, :] moves = np.asarray(temp, dtype=np.int32)
a = parent()
a.add_children(moves)
for move in moves:
    for ch in a.children:
        if move == ch.move:
            print('ok')

我希望 100 打印 ok 但我什么也没得到。我知道如果我使用 list(move) == list(ch.move) 我可以获得预期的输出,但我不希望循环中的转换开销。

谁能帮我一个有效的方法?如果有人有任何其他可以提高代码速度的建议,我们将不胜感激。

【问题讨论】:

    标签: python python-3.x loops cython typed-memory-views


    【解决方案1】:

    我可能会使用numpy.array_equal。 (它接受 memoryviews 以及 numpy 数组。)

    if numpy.array_equal(move, ch.move):
      print("OK")
    

    memcmp(另一个答案建议)相比的主要优势是memcmp 不适用于非连续数组(另一个答案承认)。只需取一列 2D memoryview 即可轻松获得不连续的 memoryview。

    【讨论】:

    • 这绝对是更通用的解决方案。但在这种情况下,它并不是“最有效的”——它慢了 50-100%(至少在我的电脑上)。 :)
    • 我也会在我的代码中检查这个。代码的奇怪之处在于我在纯 python 中实现了相同的类,我注意到 Cython 中的代码慢了 10 倍。我可能会在另一个问题中问它。
    【解决方案2】:

    您可以使用 c 库中的memcmp(比较内存的函数):

    from libc.string cimport memcmp
    
    cdef int[:, :] moves = np.asarray(temp, dtype=np.int32)
    cdef int[:] move
    cdef child ch
    a = parent()
    a.add_children(moves)
    for move in moves:
        for ch in a.children:
            if memcmp(&move[0], &ch.move[0], move.nbytes) == 0:
                print('ok')
    

    但是,如果内存视图具有不同的 dtype、字节序或步幅,这可能(可能)导致问题 - 因为 memcmp 只是比较普通内存。

    【讨论】:

    • 谢谢为我工作的兄弟。我不太了解libc 库。你知道介绍一些有用功能的好书或教程吗?
    • 不是真的,我从来没有“正式”学习过 C(或 C++),但有时我会浏览C++ reference documentation,如果我认为应该有一些针对特定用例的功能并且我使用 Cython 或构建我自己的 C 扩展。
    • 我明白了。您想通过在实际项目中体验而不是跟踪教程来学习。我猜这是学习编程的最佳方式。
    • 如果我在某个名为agent.pyx 的文件中使用此代码,并在另一个名为treesearch.py 的文件中使用它,我是否必须在我的代码中处理某事?我问它是因为我已经在使用 agent.py 文件,它工作正常但不够快,我想通过 agent.pyx 模式加速代码。 treesearch 文件处理 Tkinter。
    • 我也可能会尝试使用并行计算。这与 cython 代码有冲突吗?
    猜你喜欢
    • 2010-10-12
    • 2015-06-09
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多