简介
我正在从事需要处理大量文本数据的项目。许多相当大(数百 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/