python - 如何有效地将大字符串从 Python 传递到 C++ 扩展方法?

标签 python c++ python-3.x swig python-extensions

简介

我正在从事需要处理大量文本数据的项目。许多相当大(数百 MB)的文本文件。 python 是必需的(不要问为什么)。我想使用 C++ 扩展来提高性能。我决定选择 SWIG。我有一个模式匹配算法,它比通常的 python "string".find("pattern") 快得多。当我看到它用作 python 扩展时要慢得多时,我感到很惊讶。它不应该发生。我想我已经很接近找到原因了,但需要你的帮助。

问题

现在,我写了一个简单的扩展,其中的类包含什么都不做的方法(只需将字符串作为参数并返回数值(函数中没有进行任何处理):

nothing.h:

#ifndef NOTHING_H
#define NOTHING_H

#include <string.h>
#include <iostream>

using namespace std;

    class nothing {
        protected:
            int zm = 5;
        public:
            virtual int do_nothing(const char *empty);
    };

#endif

nothing.cpp

#include "nothing.h"

int nothing::do_nothing(const char *empty) {
    return this->zm;
}

nothing.i

%module nothing
%include <std_string.i>

using std::string;
using namespace std;
%{
    #include "nothing.h"
%}


class nothing {
    protected:
        int zm = 5;
    public:
        virtual int do_nothing(const char *empty);
};

测试.py

import nothing
import time

data = ""
with open('../hugefile', 'rb') as myfile:
    data=myfile.read().decode(errors='replace')

n = len(data)

zm = nothing.nothing()
start = time.time()
res = zm.do_nothing(data)
end = time.time()
print("Nothing time: {}".format(end - start))


zm = nothing.nothing()
start = time.time()
res = data.find("asdasdasd")
end = time.time()
print("Find time   : {}".format(end - start))

编译步骤:

swig -c++ -py3 -extranative -python nothing.i
g++ -fpic -lstdc++ -O3 -std=c++11 -c nothing.cpp nothing_wrap.cxx -I/usr/include/python3.7m
g++ -shared nothing.o nothing_wrap.o -o _nothing.so

输出:

$ python3 test.py
Nothing time: 0.3149874210357666
Find time   : 0.09926176071166992

如您所见,尽管 nothing 应该比 find() 快得多,但它却慢了很多!

知道这是否可以以某种方式解决吗?对我来说,数据看起来像是被转换或复制了。

为什么我认为整个数据都被复制了?因为如果将函数 do_nothing() 稍微更改为(我省略了标题):

int nothing::do_nothing() { // removed the argument
    return this->zm;
}

然后结果如预期:

$ python3 test.py
Nothing time: 4.291534423828125e-06
Find time   : 0.10114812850952148

最佳答案

您可能希望将文件名传递给 C 并在那里打开并搜索它。您正在读取字节,将这些字节转换为 unicode,然后再转换回计时部分内的字节。您可以在此处阅读文档以了解内部结构。

https://docs.python.org/3/c-api/unicode.html

如果文件是 utf-8,则通过删除解码将其保留为字节,或者只传递文件名并将其加载到 C 中。

关于python - 如何有效地将大字符串从 Python 传递到 C++ 扩展方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53990440/

相关文章:

c++ - 将标准输出重定向回控制台

python-3.x - 选择列中两个字符串之间的所有单元格

python - 如何使用纯 Python 扩展 API (python3) 包装 C++ 对象?

python - 使用 django FORM 上传文件的唯一文件名

python - 将 PIL 黑白图像转换为 Numpy 数组时出错

c++ - 没有主要功能的 org babel 缠结文件

c++ - 是否有一种可扩展的方法可以从 C++ 中的数组初始化结构体?

python - 从另一个文件调用函数以在模板中使用

python - 在没有外键的情况下在 SQLalchemy ORM 中指定连接条件

python - 实现记忆化