Макет Python с низким значением в памяти - PullRequest
5 голосов
/ 04 февраля 2010

Мой вопрос: откуда берутся эти шаблоны (ниже)?

Я узнал (где-то), что в Python есть уникальные «копии», если это правильное слово, для маленьких целых чисел. Например:

>>> x = y = 0
>>> id(0)
4297074752
>>> id(x)
4297074752
>>> id(y)
4297074752
>>> x += 1
>>> id(x)
4297074728
>>> y
0

Когда я смотрю на ячейки памяти в целых числах, рано появляется простой шаблон:

>>> N = id(0)
>>> for i in range(5):
...     print i, N - id(i)
... 
0 0
1 24
2 48
3 72
4 96
>>> bin(24)
'0b11000'

Мне не понятно, почему это выбрано в качестве приращения. Более того, я не могу объяснить эту модель выше 256:

>>> prev = 0
>>> for i in range(270):
...     t = (id(i-1), id(i))
...     diff = t[0] - t[1]
...     if diff != prev:
...         print i-1, i, t, diff
...         prev = diff
... 
-1 0 (4297074776, 4297074752) 24
35 36 (4297073912, 4297075864) -1952
36 37 (4297075864, 4297075840) 24
76 77 (4297074904, 4297076856) -1952
77 78 (4297076856, 4297076832) 24
117 118 (4297075896, 4297077848) -1952
118 119 (4297077848, 4297077824) 24
158 159 (4297076888, 4297078840) -1952
159 160 (4297078840, 4297078816) 24
199 200 (4297077880, 4297079832) -1952
200 201 (4297079832, 4297079808) 24
240 241 (4297078872, 4297080824) -1952
241 242 (4297080824, 4297080800) 24
256 257 (4297080464, 4297155264) -74800
257 258 (4297155072, 4297155288) -216
259 260 (4297155072, 4297155336) -264
260 261 (4297155048, 4297155432) -384
261 262 (4297155024, 4297155456) -432
262 263 (4297380280, 4297155384) 224896
263 264 (4297155000, 4297155240) -240
264 265 (4297155072, 4297155216) -144
266 267 (4297155072, 4297155168) -96
267 268 (4297155024, 4297155144) -120

Есть мысли, подсказки, места для поиска?

Редактировать: а что особенного в 24?

Обновление: стандартная библиотека имеет sys.getsizeof(), которая возвращает 24, когда я вызываю ее с 1 в качестве аргумента. Это много байтов, но на 64-битной машине у нас есть 8 байтов для каждого типа, значения и количества ссылок. Также см. здесь и ссылку на C API здесь .

Потратил некоторое время с «источником» в ссылке от Питера Хансена в комментариях. Не удалось найти определение типа int (кроме объявления *int_int), но я нашел:

#define NSMALLPOSINTS       257
#define NSMALLNEGINTS       5

Ответы [ 6 ]

8 голосов
/ 04 февраля 2010

Предварительно выделяются целые числа с низким значением, целые числа с высоким значением выделяются при каждом вычислении.Целые числа, которые появляются в исходном коде, являются одним и тем же объектом.В моей системе

>>> id(2) == id(1+1)
True
>>> id(1000) == id(1000+0)
False
>>> id(1000) == id(1000)
True

Вы также заметите, что идентификаторы зависят от системы.Это просто адреса памяти, назначенные системным распределителем (или, возможно, компоновщиком, для статических объектов?)константы в коде, который он компилирует, одинаковы, поэтому он выделяет только один объект для обоих.Это было бы недопустимым падением производительности во время выполнения, но во время компиляции это не заметно.(Да, интерпретатор также является компилятором. Большинство интерпретаторов также являются компиляторами, очень немногие - нет.)

2 голосов
/ 04 февраля 2010

Поскольку другие полностью ответили, почему идентификаторы имеют четкий шаблон до 256, я подумал, что отвечу на ваше дополнение: 24 - это размер в байтах целочисленного объекта в python.Когда первые 256 целых чисел выделены, они выполняются так непрерывно в памяти, что приводит к разнице в 24 между каждым адресом памяти.

2 голосов
/ 04 февраля 2010

Кажется, я вспоминаю, что Python внутренне кэширует копии целых чисел <256, чтобы избежать необходимости создавать новые объекты Python для часто используемых случаев. Поэтому, когда вы превышаете 256, вы каждый раз получаете вновь созданные объекты, которые могут казаться «случайным образом» размещенными в памяти (очевидно, их расположение будет иметь смысл для распределителя Python, но, вероятно, не для нас). </p>

2 голосов
/ 04 февраля 2010

Первые 256 дюймов уже выделены

>>> for n in range(1000):
>>>  if id(n) != id(n+0):
>>>   print n
>>>   break

257
1 голос
/ 04 февраля 2010

целых чисел до 256 интернированы, поэтому вы видите там «шаблон». Все остальные целые числа создаются во время выполнения и как таковые распределяются случайным образом id.

0 голосов
/ 04 февраля 2010
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...