超越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日

相关推荐

  • 如何使用OpenAI的Web UI API进行文本到图像生成

    嗨,大家好!如果你对使用OpenAI的Web UI API进行文本到图像生成感到困惑,不用担心,我将为你提供一份详细的教程。在这个教程中,我将向你介绍如何设置API,构建请求,获取生成的图像以及如何修改一些重要的参数。…

    2023年9月22日
    00
  • 如何使用Python删除Excel中的指定数据

    大家好,我是王大神。今天,我将向您展示如何使用Python来删除Excel中的指定数据。Excel是一个功能强大的电子表格工具,但有时候我们需要对表格进行清理,删除不需要的数据。Python是一个出色的工具,可以帮助我们…

    2023年10月14日
    00
  • python调用openai.api制作一个chatgpt对话机器人。

    在现代科技的快速发展下,人工智能领域的创新不断涌现,其中自然语言处理(NLP)领域的进步尤为引人注目。OpenAI作为NLP领域的领军者之一,提供了强大的API,使开发者能够轻松构建自己的自然语言处理应用。在本教程…

    2023年3月5日
    00
  • python爬虫爬小姐姐示例代码

    Python 爬虫是一项强大的技能,它可以帮助我们从互联网上自动获取数据。然而,除了用于实际的数据采集,爬虫还经常被用来获取一些有趣的内容,比如小姐姐的照片。本教程将向您展示如何使用 Python 编写一个简单的爬…

    2023年4月11日
    00
  • Stable Diffusion WebUI优质教程:让你的Intel硬件充分发挥潜力

    嗨,大家好!今天我要与大家分享一个令人兴奋的技术——Stable Diffusion WebUI,并告诉你如何在你的Intel硬件上运行它。如果你是一个喜欢尝试新技术的人,那么这篇文章将为你提供宝贵的信息。 什么是Stable Diffusio…

    2023年9月22日
    03
  • 如何创建一个自动化按键和鼠标点击工具

    在日常计算机使用中,我们常常需要进行重复性的操作,例如定时按下某个键盘按键或模拟鼠标点击。这可能涉及到玩游戏、自动化测试、数据录入等各种场景。为了实现这些功能,你可以创建一个自动化按键和鼠标点击工具…

    2023年9月13日
    00
  • 解决Python项目导入问题:如何正确使用Python的模块导入和环境变量

    最近,我在处理一个Python项目时遇到了一个常见的问题,即在移动同事的项目到我的项目中后,导入出现了问题。这个问题可能会困扰很多Python开发者,所以我想和大家分享如何正确解决这个问题。 问题背景 在处理Pytho…

    2023年10月19日
    00
  • 教程:使用Python批量注册自建邮箱账户

    有时候,我们可能需要大量的邮箱账户,用于各种目的,比如测试、订阅、或者是其他项目。在这种情况下,手动一个一个注册邮箱账户会非常繁琐和耗时。但幸运的是,我们可以利用Python编写脚本来自动化这个过程,而且…

    2023年11月2日
    00
  • 从进程池到线程池:实现高效图片下载

    在数字时代,我们每天都能够轻松访问到各种各样的图片,不论是美景、艺术品还是有趣的表情包。然而,有时候我们需要大量的图片数据,例如用于机器学习的训练集或者简单的个人收藏。在这种情况下,如何高效地获取和…

    2023年10月14日
    00
  • python和java哪个更值得学

    计算机编程是一个充满挑战和机遇的领域,而Python和Java是两个备受欢迎的编程语言。无论是初学者还是有一定经验的开发者,选择哪种语言都可能成为一个重要的决策。在本篇教程中,我们将深入研究Python和Java的优缺…

    2023年4月16日
    00