7

XOR bytearray の高速処理が必要です。Python のバリアントで

for i in range(len(str1)): str1[i]=str1[i] ^ 55

動作が非常に遅い
このモジュールは C で書きました。C 言語の知識はほとんどありませんが、何も書いていませんでした。
バリアントで

PyArg_ParseTuple (args, "s", &str))

すべてが期待どおりに機能しますが、要素にnullが含まれている可能性があるため、ss *の代わりに使用する必要がありますが、pythonクラッシュを呼び出すときにsをs *に変更すると

PyArg_ParseTuple (args, "s*", &str)) // crash

私のような初心者は、私の例を使って自分で何かを書きたいと思うかもしれません。そのため、Windows でこの例で使用するすべての情報を持ってきてください。
ページの引数の解析と値の構築http://docs.python.org/dev/c-api/arg.html

test_xor.c

#include <Python.h>

static PyObject* fast_xor(PyObject* self, PyObject* args)
{
    const char* str ;
    int i;

    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;

    for(i=0;i<sizeof(str);i++) {str[i]^=55;};
    return Py_BuildValue("s", str);

}

static PyMethodDef fastxorMethods[] =
{
     {"fast_xor", fast_xor, METH_VARARGS, "fast_xor desc"},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC

initfastxor(void)
{
     (void) Py_InitModule("fastxor", fastxorMethods);
}

test_xor.py

import fastxor
a=fastxor.fast_xor("World") # it works with s instead s*
print a
a=fastxor.fast_xor("Wo\0rld") # It does not work with s instead s*

コンパイル.バット

rem use http://bellard.org/tcc/
tiny_impdef.exe C:\Python26\python26.dll
tcc -shared test_xor.c python26.def -IC:\Python26\include -LC:\Python26\libs -ofastxor.pyd
test_xor.py 
4

5 に答える 5

5

別のアプローチは、 を使用することPyObject_GetBufferです。以下のモジュールfast_xorは、バッファ プロトコルをサポートする任意のオブジェクト、およびfast_xor_inplaceなどの書き込み可能なバッファを持つオブジェクトを定義しますbytearray。このバージョンは を返しますNoneunsigned charデフォルト値が 55の 2 番目の引数も追加しました。

例:

>>> s = 'abc'
>>> b = bytearray(s)
>>> fast_xor(s), fast_xor(s, 0x20)
('VUT', 'ABC')
>>> fast_xor_inplace(b, 0x20)
>>> b
bytearray(b'ABC')

>>> fast_xor_inplace(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BufferError: Object is not writable.

>>> fast_xor(b, 256)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: unsigned byte integer is greater than maximum

ソース:

#include <Python.h>

static PyObject *fast_xor_inplace(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    Py_buffer buffer;
    char *buf;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor_inplace", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_WRITABLE) < 0)
        return NULL;

    buf = buffer.buf;
    for(i=0; i < buffer.len; i++)
        buf[i] ^= arg2;

    PyBuffer_Release(&buffer);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *fast_xor(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    PyObject *result;
    Py_buffer buffer;
    char *buf, *str;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_SIMPLE) < 0)
        return NULL;

    result = PyString_FromStringAndSize(NULL, buffer.len);
    if (result == NULL)
        return NULL;

    buf = buffer.buf;
    str = PyString_AS_STRING(result);
    for(i=0; i < buffer.len; i++)
        str[i] = buf[i] ^ arg2;

    PyBuffer_Release(&buffer);
    return result;
}

static PyMethodDef fastxorMethods[] =
{
     {"fast_xor", fast_xor, METH_VARARGS, "fast xor"},
     {"fast_xor_inplace", fast_xor_inplace, METH_VARARGS, "fast inplace xor"},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initfastxor(void)
{
    Py_InitModule3("fastxor", fastxorMethods, "fast xor functions");
}
于 2013-03-17T13:47:44.473 に答える
0

-loopは使用しないでくださいfor。代わりにリスト内包表記を使用してください。はるかに高速です。

In [1]: import random

In [2]: t = bytearray([random.randint(0,255) for i in xrange(10000)])

In [3]: u = bytearray([b^55 for b in t])

これは非常に高速です。

In [11]: %timeit u = bytearray([b^55 for b in t])
1000 loops, best of 3: 1.36 ms per loop

それは本当に遅いことではありません。1 MB(10 ** 6バイト)の場合、約130ミリ秒かかります。

もちろん、HenryGomersallが答えたようにnumpyを使用するのがより良い解決策です。

于 2013-03-17T10:51:05.390 に答える