1. FlyPython首页
  2. Python高级话题

你嫌弃Python 慢吗?这就是让它跑得更快的方法

你讨厌 Python 有多慢吗? 这就是让它跑得更快的方法

图片由来自 Pixabay 的 nugroho dwi hartawan 提供

Python 是一种非常棒的编程语言,也是作者选择的语言。在我看来,Python 是最好的语言学习,因为你正在慢慢地打破你的方式进入计算机科学和编程的世界。

然而,每种编程语言都有它的优点和缺点,这就是为什么我们有这么多优点和缺点的原因。不同的用例需要不同的设计和实现。正如我们所说,没有放之四海而皆准的解决方案。

Python 是一种用户友好、易于学习、免费使用、可移植和易于扩展的编程语言。它适合您的编程风格和需求,涵盖了从面向对象(OOP)到函数式编程方法的各种风格。

另一方面,Python 是一个直译语言语言,它可以设置代码执行速度的上限。它不是非常适合移动开发,它有内存问题,而且由于它是一种动态类型语言,您可以在运行时发现大多数错误。

但并非所有的希望都已破灭。我认为,最关键的问题是速度。但是为什么更快的运行时间这么重要呢?考虑机器学习的用例; 您需要实验和快速迭代。在处理大数据时,让函数在几秒钟内返回,而不是几分钟内返回,是至关重要的。如果您刚刚发明的新的闪亮的神经网络架构不能很好地工作,您应该能够迅速转移到您的下一个想法!

为了解决这个问题,我们可以用另一种语言(例如,c 或 c + +)编写要求高的函数,并利用特定的绑定从 Python 调用这些函数。这是许多数字库(例如 NumPy、 SciPy 等)或深度学习框架(例如 TensorFlow、 PyTorch 等)在 Python 中所做的事情。所以,如果你是一个数据科学家或机器学习工程师想要调用 CUDA 功能,这个故事是为你。我们开始吧!

编组

在这个过程中,我们必须采取的第一步是理解什么是编组,以及它是如何工作的。来自维基百科:

编组是将对象的内存表示转换为适合存储或传输的数据格式的过程。

为什么这对我们的主题很重要?要将数据从 Python 转移到 c 或 c + + ,Python 绑定必须将其转换为适于传输的形式。

在 Python 中,一切都是一个对象。一个整数使用多少字节的内存取决于您所安装的 Python 的版本和您的操作系统,以及其他因素。另一方面,c 中的 uint8 _ t 整数总是使用8位的总内存。因此,我们必须以某种方式调和这两种类型。

编组是 Python 绑定为我们解决的问题,但是在某些情况下我们可能需要介入。这个故事不会是这样的,但是我们会在后面的文章中遇到。

管理内存

C 和 Python 管理内存的方式不同。在 Python 中,当声明一个对象时,Python 会自动为其分配内存。当您不需要该对象时,Python 有一个垃圾收集器,可以销毁未使用或未引用的对象,将内存释放回系统。

在 c 语言中,情况完全不同。是你,程序员,必须分配内存空间来创建一个对象,然后又是你,必须将内存释放回系统。

我们应该考虑到这一点,在语言障碍的同一侧释放不再需要的任何内存。

一个简单的例子

我们现在已经到了准备把脚浸入水中的时候了。完成本节后,您就可以开始使用 Python 绑定和 c 语言了。这绝对是一个初学者教程,但我们将在后面的故事中更深入地讨论更复杂的示例。

你需要什么

对于这个故事,我们需要两样东西:

  • 3.6或更高版本
  • Python 开发工具(例如 Python 3-dev 包)

C 源代码

为了简单起见,我们将创建并构建一个将两个数字相加的 c 库。复制下面的源代码:https://towardsdatascience.com/media/773f6c6255cbefe623b2fbf374e8ed43

接下来,我们需要编译源代码并构建一个共享库:

gcc -shared -Wl,-soname,libcadd -o libcadd.so -fPIC cadd.c

这个命令应该在你的工作目录文件夹中生成一个 libcadd.so 文件。现在你已经准备好进入下一步了。

使用 ctypes 打开 c 库

Ctypes 是 Python 标准库中创建 Python 绑定的工具。作为 Python 标准库的一部分,它非常适合我们的初学者教程,因为您不需要安装任何东西。

要从 Python 脚本中执行 c cadd 函数,请复制下面的源代码:https://towardsdatascience.com/media/277e7bca729f0dd6474e2a2448902fb8

在第7行中,我们创建了前面构建的 c 共享库的句柄。在第12行,我们声明 c cadd 函数的返回类型。这是至关重要的; 我们需要让 ctypes 知道如何对对象进行编组以传递它们,以及希望正确解组它们的类型。

第14行中的 y 变量也是如此。我们需要声明这是 float 类型的。最后,我们可以让 x 保持原样,因为默认情况下,ctypes 认为所有东西都是整数。

我们可以像执行其他 Python 脚本一样执行这个脚本:

python3 padd.py

结果就是一种魔法!

In cadd: int 6 float 2.3 returning  8.3
In Python: int: 6 float 2.3 return val 8.3

恭喜! 您已经从 Python 中调用了一个 c 库函数!

总结

Python 是一种用户友好、易于学习、免费使用、可移植和易于扩展的编程语言。

然而,它也有自己的弱点,其中最突出的就是速度。为了解决这个问题,我们可以用另一种语言(例如,c 或 c + +)编写要求高的函数,并利用特定的绑定从 Python 调用这些函数。

在本文中,我们使用了 ctypes,这是一个 Python 库,可以精确地做到这一点。我们可以从 Python 代码中调用一个 c 库并返回结果。我知道这个功能没有做任何要求,但这只是一个演示。让我们看看我们是否可以在以后的文章中做一些更具挑战性的事情!

原创文章,作者:flypython,如若转载,请注明出处:http://flypython.com/advanced-python/462.html