È possibile creare una stringa Python utilizzando l'API Python/C, che sarà significativamente più veloce di qualsiasi metodo che utilizza esclusivamente Python, poiché Python stesso è implementato in Python/C. Le prestazioni dipenderanno principalmente dall'efficienza del generatore di numeri casuali. Se siete su un sistema con un casuale (3) implementazione ragionevoli, come ad esempio the one in glibc, un'efficace attuazione della stringa casuale sarebbe simile a questa:
#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);
}
Testing questo codice con benchmark di halex dimostra che è 280x più veloce di il codice originale, e 2,3x più veloce di codice di Halex (sulla mia macchina):
# 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, ...]
Aggiunta di codice C per un progetto è una complicazione, ma per un aumento di velocità 280x di un'operazione critica, potrebbe essere valsa la pena .
Per un ulteriore miglioramento dell'efficienza, esaminare gli RNG più veloci e richiamarli da thread separati per parallelizzare la generazione di numeri casuali in parallelo. Quest'ultimo trarrebbe vantaggio da un meccanismo di sincronizzazione privo di blocco per assicurarsi che la comunicazione tra thread non impoverisca il processo di generazione altrimenti veloce.
Grazie mille. – marshall
@marshall: puoi accelerarlo ulteriormente usando ['b2a_bin (os.urandom (2 ** i/8))' (estensione C scritta in Cython)] (https://gist.github.com/zed/ 3.526.111). Vedi [Moltiplicare un numero enorme di volte random() (Python)] (http://stackoverflow.com/q/12161988/4279) – jfs
@ J.F.Sebastian Grazie! – marshall