Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 优化字符串生成和测试_Python_Performance - Fatal编程技术网

Python 优化字符串生成和测试

Python 优化字符串生成和测试,python,performance,Python,Performance,我正在尝试运行一个模拟来测试随机变量之间的平均值 二进制字符串 为了加快速度,我用这个 我的代码如下 from Levenshtein import distance for i in xrange(20): sum = 0 for j in xrange(1000): str1 = ''.join([random.choice("01") for x in xrange(2**i)]) str2 = ''.join([random.choi

我正在尝试运行一个模拟来测试随机变量之间的平均值 二进制字符串

为了加快速度,我用这个

我的代码如下

from Levenshtein import distance 
for i in xrange(20):
    sum = 0
    for j in xrange(1000):
        str1 =  ''.join([random.choice("01") for x in xrange(2**i)])
        str2 =  ''.join([random.choice("01") for x in xrange(2**i)])
        sum += distance(str1,str2)
    print sum/(1000*2**i)
我认为最慢的部分是现在的弦乐一代。可以加快速度吗?或者我可以尝试其他速度吗

我也有8个内核,但我不知道利用这些内核有多难


不幸的是,由于C扩展,我不能使用pypy

以下解决方案在运行时方面应该更好

它使用
2**i
随机位()生成一个数字,将其转换为该数字的二进制表示形式的字符串(),将以第3个字符开头的所有内容都带到末尾(因为
bin
的结果前面带有
'0b'
),并在结果字符串前面加上零,以获得所需的长度

str1 = bin(random.getrandbits(2**i))[2:].zfill(2**i)
快速计时最大字符串长度2**20:

from timeit import Timer
>>> t=Timer("''.join(random.choice('01') for x in xrange(2**20))", "import random")
>>> sorted(t.repeat(10,1))
[0.7849910731831642, 0.787418033587528, 0.7894113893237318, 0.789840397476155, 0.7907980049587877, 0.7908638883536696, 0.7911707057912736, 0.7935838766477445, 0.8014726470912592, 0.8228315074311467]
>>> t=Timer("bin(random.getrandbits(2**20))[2:].zfill(2**20)", "import random")
>>> sorted(t.repeat(10,1))
[0.005115922216191393, 0.005215130351643893, 0.005234282501078269, 0.005451850921190271, 0.005531523863737675, 0.005627284612046424, 0.005746794025981217, 0.006217553864416914, 0.014556016781853032, 0.014710766150983545]

这是平均150倍的加速。

您可以使用Python/C API创建Python字符串,这将大大快于任何专门使用Python的方法,因为Python本身是在Python/C中实现的。性能可能主要取决于随机数生成器的效率。如果您所在的系统具有合理的随机(3)实现,例如,有效的随机字符串实现如下所示:

#include <Python.h>

/* gcc -shared -fpic -O2 -I/usr/include/python2.7 -lpython2.7 rnds.c -o rnds.so */

static PyObject *rnd_string(PyObject *ignore, PyObject *args)
{
    const char choices[] = {'0', '1'};
    PyObject *s;
    char *p, *end;
    int size;
    if (!PyArg_ParseTuple(args, "i", &size))
        return NULL;
    // start with a two-char string to avoid the empty string singleton.
    if (!(s = PyString_FromString("xx")))
        return NULL;
    _PyString_Resize(&s, size);
    if (!s)
        return NULL;
    p = PyString_AS_STRING(s);
    end = p + size;
    for (;;) {
      unsigned long rnd = random();
      int i = 31;   // random() provides 31 bits of randomness
      while (i-- > 0 && p < end) {
        *p++ = choices[rnd & 1];
        rnd >>= 1;
      }
      if (p == end)
        break;
    }
    return s;
}

static PyMethodDef rnds_methods[] = {
    {"rnd_string",  rnd_string, METH_VARARGS },
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initrnds(void)
{
    Py_InitModule("rnds", rnds_methods);
}
将C代码添加到项目中是一件复杂的事情,但是对于一个关键操作来说,它的速度提高了280倍,这可能是值得的


为了进一步提高效率,研究更快的RNG,并从不同的线程调用它们,以便并行化随机数生成。后者将受益于无锁同步机制,以确保线程间通信不会阻碍其他快速生成过程。

非常有趣的是,您的C代码只比我的纯python解决方案快3倍。我想这样会更好:)@halex我也很惊讶!和往常一样,诀窍是利用Python的内置功能,如
bin
。我怀疑3倍的加速是使用更快(也不太复杂)的RNG的结果。@marshall不客气。请注意,依次感谢每个响应者并不是StackOverflow的习惯。相反,你会对你认为有用的答案投赞成票,作为回应者。如果你真的尝试了一些建议,也可以提供反馈。我很想知道他们是否解决了你的表现问题。谢谢你的礼节说明,不过感谢别人似乎很礼貌,因为你不知道我是否投了赞成票。很遗憾,我也不能否决这个明显不正确的答案。我使用了python的答案。我认为现在调整Levenshtein函数的C实现和并行化将进一步提高速度。@marshall:您可以进一步使用。看见
# the above code
>>> t1 = Timer("rnds.rnd_string(2**20)", "import rnds")
>>> sorted(t1.repeat(10,1))
[0.0029861927032470703, 0.0029909610748291016, ...]
# original generator
>>> t2 = Timer("''.join(random.choice('01') for x in xrange(2**20))", "import random")
>>> sorted(t2.repeat(10,1))
[0.8376679420471191, 0.840252161026001, ...]
# halex's generator
>>> t3 = Timer("bin(random.getrandbits(2**20-1))[2:].zfill(2**20-1)", "import random")
>>> sorted(t3.repeat(10,1))
[0.007007122039794922, 0.007027149200439453, ...]