当前位置: 首页 > 面试题库 >

在Cython中使用字典,尤其是在nogil内部

麹渊
2023-03-14
问题内容

我有一本字典,

my_dict = {'a':[1,2,3], 'b':[4,5] , 'c':[7,1,2])

我想在Cython nogil函数中使用此词典。因此,我试图将其声明为

cdef dict cy_dict = my_dict

到这个阶段还可以。

现在,我需要迭代my_dict的键,如果值在列表中,则对其进行迭代。在Python中,非常简单,如下所示:

 for key in my_dict:
      if isinstance(my_dict[key], (list, tuple)):
          ###### Iterate over the value of the list or tuple
          for value in list:
               ## Do some over operation.

但是,在Cython内部,我也想在nogil内部实现相同的功能。由于nogil内不允许使用python对象,因此我全都陷入了困境。

with nogil:
    #### same implementation of the same in Cython

有人可以帮我吗?


问题答案:

dict没有GIL,就不能使用Python ,因为您可以做的所有事情都涉及到操作Python对象。您最明智的选择是接受您需要的GIL。C
++映射也有一个不太明智的选择,但是可能很难针对您的特定情况进行应用。

您可以with gil:用来重新获取GIL。这里显然存在开销(使用GIL的部分不能并行执行,并且可能会等待GIL的延迟)。但是,如果字典操作只是较大的Cython代码中的一小部分,则可能还不错:

with nogil:
  # some large chunk of computationally intensive code goes here
  with gil:
    # your dictionary code
  # more computationally intensive stuff here

另一个不太明智的选择是使用C 映射(以及其他C 标准库数据类型)。Cython可以包装这些文件并自动将其转换。根据示例数据给出一个简单的示例:

from libcpp.map cimport map
from libcpp.string cimport string
from libcpp.vector cimport vector
from cython.operator cimport dereference, preincrement

def f():
    my_dict = {'a':[1,2,3], 'b':[4,5] , 'c':[7,1,2]}
    # the following conversion has an computational cost to it 
    # and must be done with the GIL. Depending on your design
    # you might be able to ensure it's only done once so that the
    # cost doesn't matter much
    cdef map[string,vector[int]] m = my_dict

    # cdef statements can't go inside no gil, but much of the work can
    cdef map[string,vector[int]].iterator end = m.end()
    cdef map[string,vector[int]].iterator it = m.begin()

    cdef int total_length = 0

    with nogil: # all  this stuff can now go inside nogil   
        while it != end:
            total_length += dereference(it).second.size()
            preincrement(it)

    print total_length

(您需要使用进行编译language='c++')。

这样做的明显缺点是,必须事先知道dict内部的数据类型(不能是任意的Python对象)。但是,由于您无法在nogil块内操作任意Python对象,因此无论如何还是受到很大限制。



 类似资料:
  • 问题内容: 我的问题:我发现,使用原始C ++使用STL映射和向量处理大型数据集通常比使用Cython更快(且内存占用更少)。 我认为速度下降的部分原因是使用Python列表和字典,在Cython中使用较少占用数据结构可能会有一些技巧。例如,此页面(http://wiki.cython.org/tutorials/numpy)显示了如何通过预定义ND数组的大小和类型在Cython中非常快速地创建n

  • 如何在Swift中到达以下字典中的第二个整数(键)?而且,当我这样做的时候,我怎样才能找到第二个字典里的字串呢? 我尝试编写(例如)var test:Int=activeCustomers[1][1],但这不起作用。它说字典里没有一个叫下标的成员。

  • 问题内容: 我的磁盘上只有168MB的文件。这只是一个逗号分隔的单词,id的列表。该单词的长度可以为1-5个字符。有650万行。 我在python中创建了一个字典,将其加载到内存中,因此我可以针对该单词列表搜索传入的文本。当python将其加载到内存中时,它显示已使用的1.3 GB RAM空间。知道为什么吗? 假设我的word文件如下所示… 然后再加上650万。然后,我遍历该文件并创建一个字典(p

  • 问题内容: 我只是从node.js开始。我做了一些ajax的工作,但是没有什么太复杂的,所以回调仍然有点麻烦。我看了看异步,但我所需要的只是顺序运行一些功能。 我基本上有一些东西可以从API中提取一些JSON,然后创建一个新的JSON,然后对此进行处理。显然,我不能只运行它,因为它可以一次运行所有内容并且具有空的JSON。通常,流程必须按顺序运行,但是如果在从API中提取JSON时可以在等待时提取

  • 问题内容: 在此页面上,我看到了一些有趣的东西: 请注意,有一种快速的命令可以(实际上)仅处理str键。 这不会影响算法的复杂性,但是会显着影响以下恒定因素:典型程序完成的速度。 那到底是什么意思呢? 这是否意味着使用字符串作为键总是更快? 如果是,为什么? 更新: 感谢您提供有关优化的建议!但实际上,我对简单的事实更感兴趣,而不是是否或何时进行优化。 更新2: 感谢您的出色回答,在这里我将引用@

  • 问题内容: 我有一个Python字典,例如: 我想检查一个键是否在字典中。我很想知道以下两种情况中哪一种更为可取,为什么? 问题答案: if ‘name’ in mydict: 是首选的pythonic版本。不鼓励使用,并且在Python 3中已删除 此方法。