超越Python性能极限:创建C++扩展模块

你是否曾想过如何提高Python代码的性能?或者你是否在处理大规模数据时感到Python的速度有些慢?如果是的话,那么你来对地方了!在本篇文章中,我将带你走进C++的魔幻世界,教你如何创建C++扩展模块,以实现超越Python性能的目标。不要担心,即使你不是C++专家,我也将为你详细解释每一步。

前提条件

在开始之前,确保你已经安装了Visual Studio 2017或更新版本,同时安装了Python开发工作负载。这个工作负载包括Python本地开发工具,这对于创建本地扩展模块是必要的。如果你已经在使用Python,也确保在高级选项下选择了下载调试符号,以便进行Python代码和本地代码的混合模式调试。

创建Python应用程序

首先,我们将创建一个Python应用程序,这将是我们要扩展的Python代码。在Visual Studio中,选择文件 > 新建 > 项目。

搜索Python,选择Python应用程序模板,输入名称和位置,然后点击确定。

在项目的.py文件中,粘贴以下代码,这段代码会计算双曲正切,我们将在后面的步骤中加速它。

from random import random
from time import perf_counter

COUNT = 500000

DATA = [(random() - 0.5) * 3 for _ in range(COUNT)]

e = 2.7182818284590452353602874713527

def sinh(x):
    return (1 - (e ** (-2 * x))) / (2 * (e ** -x))

def cosh(x):
    return (1 + (e ** (-2 * x))) / (2 * (e ** -x))

def tanh(x):
    tanh_x = sinh(x) / cosh(x)
    return tanh_x

def test(fn, name):
    start = perf_counter()
    result = fn(DATA)
    duration = perf_counter() - start
    print('{} took {:.3f} seconds\n\n'.format(name, duration))

if __name__ == "__main__":
    print('Running benchmarks with COUNT = {}'.format(COUNT))

    test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')

通过调整COUNT变量,你可以改变基准测试的运行时间。现在,选择调试 > 以不带调试启动,来运行这个程序。

创建核心C++项目

接下来,我们将创建两个C++项目,分别是superfastcode和superfastcode2,用于扩展Python。

  1. 在解决方案资源管理器中,右键单击解决方案,然后选择添加 > 新建项目。这样,一个Visual Studio解决方案可以同时包含Python和C++项目。

  2. 搜索C++,选择空项目模板,为第一个项目命名superfastcode,然后点击确定。

  3. 创建一个C++文件,右键点击Source Files节点,选择添加 > 新项。选择C++文件,命名为module.cpp,然后点击确定。

  4. 在主工具栏上,使用下拉菜单选择以下配置之一:

    • 对于64位Python运行时,激活x64配置。
    • 对于32位Python运行时,激活Win32配置。
  5. 在解决方案资源管理器中,右键单击C++项目,选择属性,然后按照以下表格中的设置进行配置:

    选项卡 属性
    General 目标名称 指定模块的名称,以便在Python中引用。如果要使用项目名称作为模块名称,请保留默认值$。对于python_d.exe,添加_d以结束名称。
    Advanced > Target File Extension .pyd
    Project Defaults > Configuration Type Dynamic Library (.dll)
    C/C++ > General 附加包含目录 根据你的安装情况添加Python包含目录(例如,c:\Python36\include)。
    C/C++ > Preprocessor 预处理器定义 如果存在,请将_DEBUG值更改为NDEBUG,以匹配CPython的非调试版本。当使用python_d.exe时,保持此值不变。
    C/C++ > Code Generation 运行时库 选择多线程DLL(/MD)以匹配CPython的非调试版本。当使用python_d.exe时,保持此值为多线程调试DLL(/MDd)。
    Basic Runtime Checks 默认
    Linker > General 附加库目录 添加包含.lib文件的Python libs文件夹,根据你的安装情况(例如,c:\Python36\libs)。确保指向包含.lib文件的libs文件夹,而不是包含.py文件的Lib文件夹。
  6. 构建C++项目以确认代码正确。

  7. 如果尚未完成,重复上述步骤创建第二个项目,命名

为superfastcode2。这个项目将在后面的示例中使用。

编写Python扩展模块

我们已经有了一个C++项目,现在让我们开始编写Python扩展模块。

  1. 在superfastcode项目中,打开module.cpp文件,然后将以下代码添加到文件顶部:
#include <Python.h>

这会包括Python头文件,以便在C++代码中使用Python API。

  1. 在文件中,添加以下C++函数,这些函数将成为Python模块的接口:
static PyObject* superfastcode_tanh(PyObject* self, PyObject* args)
{
    // Parse the input arguments
    PyObject* data;
    if (!PyArg_ParseTuple(args, "O", &data))
    {
        PyErr_SetString(PyExc_TypeError, "Invalid input");
        return NULL;
    }

    // Ensure data is a list
    if (!PyList_Check(data))
    {
        PyErr_SetString(PyExc_TypeError, "Input must be a list");
        return NULL;
    }

    // Iterate through the list and apply tanh function
    PyObject* result = PyList_New(0); // Create an empty list
    if (result != NULL)
    {
        Py_ssize_t size = PyList_Size(data);
        for (Py_ssize_t i = 0; i < size; ++i)
        {
            PyObject* item = PyList_GetItem(data, i);
            double x = PyFloat_AsDouble(item);
            if (!PyErr_Occurred())
            {
                double tanh_x = tanh(x);
                PyObject* tanh_item = PyFloat_FromDouble(tanh_x);
                if (tanh_item != NULL)
                {
                    PyList_Append(result, tanh_item);
                    Py_DECREF(tanh_item);
                }
                else
                {
                    PyErr_SetString(PyExc_RuntimeError, "Failed to create float object");
                    Py_DECREF(result);
                    return NULL;
                }
            }
            else
            {
                PyErr_SetString(PyExc_TypeError, "Invalid item in the input list");
                Py_DECREF(result);
                return NULL;
            }
        }
    }

    return result;
}

static PyMethodDef superfastcode_methods[] =
{
    {"tanh", superfastcode_tanh, METH_VARARGS, "Calculate the hyperbolic tangent of a list of numbers."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef superfastcode_module =
{
    PyModuleDef_HEAD_INIT,
    "superfastcode",
    NULL,
    -1,
    superfastcode_methods
};

PyMODINIT_FUNC PyInit_superfastcode(void)
{
    return PyModule_Create(&superfastcode_module);
}

这些代码定义了一个名为superfastcode的Python模块,其中包括一个名为tanh的函数。这个函数将接受一个Python列表作为输入,计算列表中每个数字的双曲正切,并返回一个包含结果的新列表。

  1. 构建superfastcode项目以生成扩展模块。

使用Python中的扩展模块

现在,我们已经创建了一个C++扩展模块,让我们看看如何在Python中使用它。

  1. 在Python中,创建一个新的.py文件,例如test_superfastcode.py,并添加以下代码:
import superfastcode

data = [0.5, 0.6, 0.7, 0.8, 0.9]
result = superfastcode.tanh(data)
print(result)

这个Python脚本导入了我们的superfastcode模块,并使用其中的tanh函数来计算输入列表的双曲正切。

  1. 运行test_superfastcode.py文件,你将看到计算结果。

结论

通过创建C++扩展模块,我们可以将高性能的C++代码与Python集成在一起,实现更快的计算速度。这对于需要处理大量数据或需要高性能计算的应用程序特别有用。希望本文对你有所帮助,让你更好地理解如何创建和使用Python扩展模块。如果你对此有任何疑问或需要进一步的帮助,请随时提问!

本文由作者 王大神 原创发布于 大神网的AI博客。

转载请注明作者:王大神

原文出处:超越Python性能极限:创建C++扩展模块

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 2023年9月19日
下一篇 2023年9月19日

相关推荐

  • Python教程:如何使用Python从一个表格中提取数据到另一个表格

    在现代世界中,数据无处不在,而有效地处理和分析数据对于许多行业至关重要。假设你是一位数据分析师,每天需要处理大量的数据表格,提取其中的关键信息。有一天,你接到了一个任务:需要从一个庞大的数据表格中提…

    2023年10月22日
    00
  • 如何使用Django的管理命令在Azure上运行Python Web应用

    你是否正在开发一个使用Django框架构建的Python Web应用,并希望将它部署到Azure云上?如果是的话,你来对地方了!在本教程中,我们将向你展示如何在Azure上托管你的Python Web应用,并使用Django的管理命令来执行…

    2023年9月19日
    00
  • 如何设置命令行参数和环境变量来优化stable diffusion webui

    你是否曾经想过如何在使用stable diffusion WebUI 时进行自定义设置以优化性能?或者你可能只是想知道如何在不同的硬件配置下运行它?无论你的需求是什么,这篇文章将为你提供有关如何设置命令行参数和环境变量的详…

    2023年9月13日
    00
  • Python错误标准异常总结:让你成为异常处理大师

    嗨,亲爱的Python学习者们!在编写代码时,错误是不可避免的。Python提供了丰富的异常处理机制,以帮助你更好地理解和处理代码中的错误。本文将为你总结Python中的标准异常,让你成为异常处理的大师! 开篇故事 在…

    2023年9月25日
    00
  • 在HomePod上使用Python实现Matter语音控制:详细教程

    王大神是一个对音乐和技术充满热情的自由职业者,他充分利用自由的生活和工作方式。最近,他遇到了一个技术挑战:如何在HomePod上使用Python实现Matter语音控制。这个挑战是因为Matter的开发信息相对有限,但王大神…

    2023年11月21日
    00
  • 如何使用Python自动化定时发微博和推特

    社交媒体已经成为我们生活的一部分,而微博和推特是其中最受欢迎的平台之一。但是,如果你想定期更新你的微博和推特账户,可能会花费大量时间和精力。幸运的是,Python编程语言可以帮助你自动化这个过程,让你的社…

    2023年10月24日
    00
  • 用Python实现服装图像分类

    服装图像分类是机器学习领域中的一个重要任务,它涉及对图像中的不同服装类别进行准确的自动识别。无论是在电子商务领域的商品分类,还是在智能家居中的虚拟试衣间,图像分类都有着广泛的应用。本教程将详细介绍如…

    2023年8月23日
    00
  • FreeBSD在25毫秒内完成启动:革命性的性能提升

    引言 近日,有一个令人瞩目的技术突破在科技界掀起轩然大波:FreeBSD,一款备受推崇的开源操作系统,竟然在AWS Firecracker上实现了令人难以置信的启动速度,仅需25毫秒。这一壮举的背后,是一系列引人注目的性能优…

    2023年9月7日
    00
  • Python与CCXT:虚拟货币量化交易入门指南

    虚拟货币市场的蓬勃发展吸引了越来越多的投资者,但如何在这个高度波动的市场中获得成功?答案之一是量化交易,而Python和CCXT是您的得力工具。本教程将引导您进入虚拟货币量化交易的世界,学习如何使用Python和CCX…

    2023年12月28日
    00
  • 如何打造自己的开发工具箱:一个深入探讨的教程

    当李华从业界前辈那里听说 JetBrains Toolbox 的时候,他的内心被深深吸引了。作为一个对编程充满热情的初学者,李华对此表示了浓厚的兴趣。他想要为自己在 Python 上制作的各种小工具整合成一个完整的工具箱,如同…

    2023年10月9日
    00