你是否曾想过如何提高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。
-
在解决方案资源管理器中,右键单击解决方案,然后选择添加 > 新建项目。这样,一个Visual Studio解决方案可以同时包含Python和C++项目。
-
搜索C++,选择空项目模板,为第一个项目命名superfastcode,然后点击确定。
-
创建一个C++文件,右键点击Source Files节点,选择添加 > 新项。选择C++文件,命名为module.cpp,然后点击确定。
-
在主工具栏上,使用下拉菜单选择以下配置之一:
- 对于64位Python运行时,激活x64配置。
- 对于32位Python运行时,激活Win32配置。
-
在解决方案资源管理器中,右键单击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文件夹。 -
构建C++项目以确认代码正确。
-
如果尚未完成,重复上述步骤创建第二个项目,命名
为superfastcode2。这个项目将在后面的示例中使用。
编写Python扩展模块
我们已经有了一个C++项目,现在让我们开始编写Python扩展模块。
- 在superfastcode项目中,打开module.cpp文件,然后将以下代码添加到文件顶部:
#include <Python.h>
这会包括Python头文件,以便在C++代码中使用Python API。
- 在文件中,添加以下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列表作为输入,计算列表中每个数字的双曲正切,并返回一个包含结果的新列表。
- 构建superfastcode项目以生成扩展模块。
使用Python中的扩展模块
现在,我们已经创建了一个C++扩展模块,让我们看看如何在Python中使用它。
- 在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函数来计算输入列表的双曲正切。
- 运行test_superfastcode.py文件,你将看到计算结果。
结论
通过创建C++扩展模块,我们可以将高性能的C++代码与Python集成在一起,实现更快的计算速度。这对于需要处理大量数据或需要高性能计算的应用程序特别有用。希望本文对你有所帮助,让你更好地理解如何创建和使用Python扩展模块。如果你对此有任何疑问或需要进一步的帮助,请随时提问!
未经允许不得转载:大神网 » 超越Python性能极限:创建C++扩展模块