【问题标题】:Cython with dict same as python带有 dict 的 Cython 与 python 相同
【发布时间】:2019-12-13 08:46:46
【问题描述】:

我尝试了一些可用的解决方案,但无法使用以下 Cython 代码获得任何加速。

cython 代码所用的时间与其对应的 python 代码相同。

calculate_sum.pyx

# key_id: it is a string
# values_dict: it is a dictionary with key as str and values as numpy.ndarray consisting of floats
# e.g.: print(values_dict['abc']) will give out numpy.ndarray([0.01, 1.01, 2.05]). values_dict has many such entries.

cpdef dict calculate_sum(str key_id, dict values_dict):
     cdef dict result_dict = {}
     cdef str check_id

     for check_id, values in values_dict.items():
           if check_id != key_id:
                result_dict[check_id] = sum(values)

     return result_dict

setup.py

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('calculate_sum.pyx'))

main.py

import calculate_sum

# ...
# piece of code which computes values_dict
# ...

key_id = 'abc'
sum_value = calculate_sum.calculate_sum(key_id, values_dict)

感谢任何建议/帮助。

【问题讨论】:

  • 您是否对原始程序和 Cython 版本进行了任何基准测试/分析?
  • 没有太多的基准。 python版本运行得更好,所以想知道是否有办法对其进行cythonize
  • 忘了问:您这样做是为了教育目的,还是需要加快实际程序的速度?
  • 这两个问题的答案都是:是的。需要加快代码速度,如果一切顺利,那么将编写一个关于 do's-n-dont's 的教程。
  • 您的程序是否有很多地方都有数组循环,您一次只索引一个元素?如果“是”则 Cython 是正确的工具,如果“否”则 Cython 可能不是正确的工具。 (有时值得将 Numpy 数组操作展开到 Cython 中的循环中,但通常可以将多个操作组合在一起以避免临时操作)。互联网上有关于 Cython 的教程,然后主要处理 Numpy 和循环(因为这是它擅长的)

标签: python cython cythonize


【解决方案1】:

一般来说,我认为 Cython 不会对这段代码有所帮助:它主要是在操作 Python 对象,因此加速往往很小。一些建议:

  • 对于一个 numpy 数组,x.sum()sum(x) 快得多(对于我的 PC 上的快速测试用例,速度大约快 60 倍)。如果您知道这些值将是 Numpy 数组,请直接执行此操作。
  • 可以重写代码以使用字典理解。这可能会提高一点速度(主要是因为它可能能够预先分配正确的大小)。
  • 可能值得在循环中省略if 语句,并计算每个键的总和(然后删除key_id)。计时。

综合:

def calculate_sum(key_id, values_dict):
    result_dict = { key: values.sum() for key, values in values_dict.items() }
    del result_dict[key_id]
    return result_dict

请注意,我已经放弃了所有 Cython 的东西,因为我认为它在这里毫无意义。我对基准测试没有太大兴趣,但我怀疑对sum 的更改将产生主要影响。


您可能想要查看的另一种方法是使用 Pandas(此处的代码未经测试...)。假设您已经使用values = pd.DataFrame.from_dict(values_dict) 创建了一个values DataFrame,那么:

def calculate_sum(key_id, values):
    return values.sum(axis=1).drop(key_id)

这在所有 Numpy 数组长度相同的情况下效果最好(尽管我认为这不是绝对要求)。您的目标是普遍使用 Pandas,而不是频繁地与dict 相互转换。再说一次,Cython 在这里帮不上忙。

【讨论】:

  • 谢谢,这肯定有助于加快速度。我读过 dict 在 cython 方面不是最好的,所以想知道是否有办法。如果我将 sum 替换为 norm 或任何其他操作,那么您认为 cython 可以提供帮助吗?
  • 如果你想要像dict 这样的东西,那么dict 是最好的选择。对于像 norm 这样的标准操作,你最好还是调用 Numpy 函数(在这种情况下 Cython 并没有真正的帮助)。
  • @CodeChannel 请参阅最后的编辑以获取可能比dict更好的数据结构的另一个建议
  • 这是一个有趣的研究方法。将看到它是如何工作的。但据我了解,熊猫不会提供 Cython 的加速。我将尝试解决将 dict 制作为多维数组的问题。
  • 如有必要,您可以访问 Cython 中的底层 Pandas 数据(因为它最终存储在 pd.DataFrame.values 中是一个 numpy 数组)。但是,不要先尝试,因为很多数组操作都是用 C 编写的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 2015-05-29
  • 2016-08-22
  • 2020-03-23
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
相关资源
最近更新 更多