Как эффективно передать большую строку из Python в метод расширения C ++? - PullRequest
0 голосов
/ 31 декабря 2018

Введение

Я работаю над проектом, в котором необходимо обработать много текстовых данных.Многие довольно большие (сотни МБ) текстовые файлы.Питон является требованием (не спрашивайте почему).Я хочу использовать расширения C ++ для повышения производительности.Я решил пойти с SWIG.У меня есть алгоритм сопоставления с образцом, который намного быстрее, чем обычная строка Python ".Я был удивлен, когда увидел, что он намного медленнее, когда используется как расширение для 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

ничто.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);
};

test.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

Как видите, несмотря на то, что ничего не должно быть намного быстрее, чем найти () это намного медленнее!

Любая идея, если это можно как-то решить? Для меня это выглядит как данные преобразуются или копируются.

Почему я думаю, что все данные копируются? Потому чтоесли немного изменить функцию do_nothing () на (я опускаю заголовки):

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

Тогда результат будет таким, как ожидалось:

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

1 Ответ

0 голосов
/ 01 января 2019

Возможно, вы захотите передать имя файла в C, открыть и найти его там.Вы читаете байты, конвертируете эти байты в юникод, а затем конвертируете обратно в байты внутри временной части.Вы можете прочитать документацию здесь, чтобы понять внутреннее.в к.

...