
Aragaer
14.03.2016
07:17:52
нормальный компилятор при виде деления инта на 2 сразу решит, что можно вместо этого что-то делать с битами
а в прочем в данном конкретном случае время уходит скорее на работу с памятью, чем собссно на деление
>>> timeit.timeit("for x in xrange(100):x&2")
2.5749120712280273
>>> timeit.timeit("for x in xrange(100):x%2")
3.4274349212646484

Google

Aragaer
14.03.2016
07:23:30
мды
чот оно даже не пытается оптимизировать

Pavel
14.03.2016
07:23:50

Aragaer
14.03.2016
07:23:50
а впрочем..
но чот реально время идиотически большое
на С цикл в 100 делений отрабатывает настолько быстро, что time говорит про 0.001 секунды
если распечатывать результаты, то 0.002
и я не очень верю, что питон настолько медленнее

Artem
14.03.2016
07:31:39
так timeit миллион итераций делает по умолчанию

Aragaer
14.03.2016
07:32:16
ага, теперь знаю

Pavel
14.03.2016
07:32:21
>>> timeit.timeit("x%2", "x=1",number=int(1e8))
5.3698593759120286
>>> timeit.timeit("x%2", "x=2",number=int(1e8))
9.634653834336433
>>> timeit.timeit("x&1", "x=1",number=int(1e8))
9.488289771703165
>>> timeit.timeit("x&1", "x=2",number=int(1e8))
9.287430427221892

Aragaer
14.03.2016
07:32:39
$ python -m timeit "map(lambda x: x%2, range(100))"
100000 loops, best of 3: 8.25 usec per loop
$ python -m timeit "map(lambda x: x&2, range(100))"
100000 loops, best of 3: 7.18 usec per loop
$ python -m timeit "map(lambda x: x%2, xrange(100))"
100000 loops, best of 3: 7.9 usec per loop
$ python -m timeit "map(lambda x: x&2, xrange(100))"
100000 loops, best of 3: 6.92 usec per loop

Google

Pavel
14.03.2016
07:34:16
>>> timeit.timeit("x%2", "x=1",number=int(1e8))
5.3698593759120286
>>> timeit.timeit("x%2", "x=2",number=int(1e8))
9.634653834336433
>>> timeit.timeit("x&1", "x=1",number=int(1e8))
9.488289771703165
>>> timeit.timeit("x&1", "x=2",number=int(1e8))
9.287430427221892
байт-код отличается только в том, что вызывается BINARY_MODULO или BINARY_AND. Надо лезть в с-реализацию питон-машины, и смотреть какие там есть оптимизации.

terry
14.03.2016
07:36:46
когда дебажешь код =)
https://vk.com/doc321711679_437340739?hash=c348c8a91ef2bad788&dl=d053b0cdb39da911c7

Pavel
14.03.2016
07:39:52

Whore Amazing
14.03.2016
07:49:28
как я и предполагал, ни select_related, ни prefetch_related кол-во запросов к базе не уменьшили.
а самое смешное, что я даже посмотреть эти запросы не могу, при открытии этой вкладки в DjDT он виснет :^)

parikLS
14.03.2016
07:53:49
дебагер в помощь

Whore Amazing
14.03.2016
07:54:14
кокой?

Aragaer
14.03.2016
07:54:52
да, второй. В третьем нет xrange
и блин, в третьем скорость внезапно офигенная

Pavel
14.03.2016
07:55:24
некрофилы должны страдать. :)

Aragaer
14.03.2016
07:56:17
а разницы по времени нет совсем или она где-то в другом месте

Artem
14.03.2016
07:56:41

Aragaer
14.03.2016
07:56:48
$ python3 -m timeit "map(lambda x: x%2, range(100))"
1000000 loops, best of 3: 0.29 usec per loop
$ python3 -m timeit "map(lambda x: x%2, range(1000))"
1000000 loops, best of 3: 0.332 usec per loop
$ python3 -m timeit "map(lambda x: x&2, range(10000))"
1000000 loops, best of 3: 0.329 usec per loop
а
$ python3 -m timeit "[x%2 for x in range(1000)]"
10000 loops, best of 3: 60.3 usec per loop
$ python3 -m timeit "[x%2 for x in range(100)]"
100000 loops, best of 3: 6.45 usec per loop
$ python3 -m timeit "[x&2 for x in range(100)]"
100000 loops, best of 3: 5.26 usec per loop
и все равно быстрее

Pavel
14.03.2016
08:09:53
и все равно быстрее
тут надо нырять в релизацию PyNumber_And и PyNumber_Remainder, но это надо уметь в С исходниках ориентироваться.

Aragaer
14.03.2016
08:25:19
а чо там ориентироваться

Pavel
14.03.2016
08:26:05

Google

Aragaer
14.03.2016
08:28:54
там есть поиск
а ваще код конечно нетривиальный
https://github.com/yudisin/cleese/blob/3308482af50344690e5bd615e153ad913731f73f/experimental/pico/python/Objects/abstract.c#L15
тут оно не столько арифметикой занимается, сколько разгребает структуры
в этом файле реализация обоих - разгрести структуры и нужную функцию сунуть в нужный слот

Pavel
14.03.2016
08:31:17

Aragaer
14.03.2016
08:32:22
да смысл в том, чтобы из массива nb_methods вытащить запись из нужного слота и вернуть в виде указателя на функцию
там ниже еще тонна проверок на тему того, а есть ли она вообще

Pavel
14.03.2016
08:33:24
61 строка, как я понимаю, то что надо.

Aragaer
14.03.2016
08:34:26
https://github.com/yudisin/cleese/blob/3308482af50344690e5bd615e153ad913731f73f/experimental/pico/python/Objects/intobject.c
это вытаскивание из слота
а тут по комментам видно, как должны называться функции в слотах вроде бы

Aragaer
14.03.2016
08:35:33
(binaryfunc)int_and
эта прямо тут реализована и все почти ок
static PyObject *
int_and(PyIntObject *v, PyIntObject *w)
{
register long a, b;
CONVERT_TO_LONG(v, a);
CONVERT_TO_LONG(w, b);
return PyInt_FromLong(a & b);
}

Pavel
14.03.2016
08:36:21
наёдёшь также про BINARY_MODULO?
PyNumber_Remainder

Aragaer
14.03.2016
08:37:39
nb_remainder уже ищу
а, не, тут же - int_mod
static PyObject *
int_mod(PyIntObject *x, PyIntObject *y)
{
long xi, yi;
long d, m;
CONVERT_TO_LONG(x, xi);
CONVERT_TO_LONG(y, yi);
if (i_divmod(xi, yi, &d, &m) < 0)
return NULL;
return PyInt_FromLong(m);
}

Google

Aragaer
14.03.2016
08:38:59
тут есть проверка деления на ноль, а для & такой проверки нету, так что уже прирост скорости
https://github.com/yudisin/cleese/blob/3308482af50344690e5bd615e153ad913731f73f/experimental/necco/python/Objects/intobject.c#L300
ну и в целом код тоже непростой
полностью честно деление делается
так что разница между x&2 и x%2 в том, что первое это (взять из x значение как лонг и потом &2 и потом завернуть обратно)
а второе это еще и куча проверок дополнительных

Pavel
14.03.2016
08:43:19
и последний вопрос: почему 1%2 в два раза быстрее, чем 21%2?

Aragaer
14.03.2016
08:43:37
а, еще отдельно там фокус с вычислением % когда кто-то из них отрицательный

Pavel
14.03.2016
08:43:56
21%2`и `22%2 и 2%2 выполняются одинаково по времени.

Admin
ERROR: S client not available

Pavel
14.03.2016
08:45:32
делимое меньше делителя, то выполняется быстрее.

Aragaer
14.03.2016
08:45:33
а забавный момент
когда при делении может случиться переполнение?
да не, там в C честно деление написано
там нафиг никто не проверяет кто больше, кто меньше
по-моему

Pavel
14.03.2016
08:54:42
посмотреть, что за дупликаты?

Whore Amazing
14.03.2016
09:01:37
посмотрел. сцук, все нужное.
но черт, запросы занимают 1 секундк, откуда еще полминуты-то берется при загрузке страницы??
олсо, дупликатами он зовет похожие запросы
ну чо я буду делать, если мне нужно запрашивать череду запросов, в которых меняется только номер запрашиваемого элемента ?

Pavel
14.03.2016
09:07:42

Google

Whore Amazing
14.03.2016
09:08:07

Pavel
14.03.2016
09:08:18

Whore Amazing
14.03.2016
09:08:32
не, я в принципе все понимаю, где что
у меня берется кверисет, для каждого элемента которого в свою очередь тоже берется кверисет, и уже для каждого элемента второго кверисета запрашиваются данные из базы
потому так много похожих запросов

Aliaksiej
14.03.2016
09:11:35

Whore Amazing
14.03.2016
09:11:53

Pavel
14.03.2016
09:12:14
каждого элемента второго кверисета запрашиваются данные из базы потому так много похожих запросов
вот в место вызова второго кверисета и попрубуй присунуть select_related.

Whore Amazing
14.03.2016
09:12:41
так он принимает только поля отношений.
а у меня береутся поля с данными.

Pavel
14.03.2016
09:13:33
select_realated("remote__field1", "remote__field2") (или это в prefetch_related так можно?)

Whore Amazing
14.03.2016
09:14:24
ни селект, ни префетч не поддерживают поля с данными, как я понял из опытов.

Dmitriy
14.03.2016
09:14:36

Whore Amazing
14.03.2016
09:15:06

Pavel
14.03.2016
09:15:42
всё они поддерживают.
.select_related('front', 'back', 'back__connected', 'front__connected') \
.prefetch_related('back__connected__parent',
'back__connected__parent__parent',
'back__connected__parent__front',
'back__connected__parent__front__connected',
'front__connected__parent',
'front__connected__parent__parent') \

Dmitriy
14.03.2016
09:15:46
select field1 from table where field2 in ('val1', 'val2')

Whore Amazing
14.03.2016
09:16:05
хм. так. пошел перерывать код.

Pavel
14.03.2016
09:16:39
.select_related('back__connected__parent__parent__name').all()

Whore Amazing
14.03.2016
09:18:08
Cannot find 'post' on Thread object, 'post__post_id' is an invalid parameter to prefetch_related()
даже m2o не смог взять.

Pavel
14.03.2016
09:20:58
а просто select_related('post') что покажет?

Whore Amazing
14.03.2016
09:21:04
то же само
ясен пень, что post поля в thread нет. там же обратный ForeignKey. но он его не хочет кушать.
а, вот оно что, надо определить related_name.