Python автоматически выделяет целые числа на основе базовой системной архитектуры. К сожалению, у меня есть огромный набор данных, который необходимо полностью загрузить в память.
Итак, есть ли способ заставить Python использовать только 2 байта для некоторых целых чисел (эквивалент C++ 'short')?
Если вы выполняете какие-либо манипуляции с этим огромным набором данных, вы, вероятно, захотите использовать Numpy, который поддерживает широкий спектр числовых типов и эффективные операции с их массивами.






Неа. Но вы можете использовать короткие целые числа в массивах:
from array import array
a = array("h") # h = signed short, H = unsigned short
Пока значение остается в этом массиве, оно будет коротким целым числом.
Лучший и более полный ответ, чем мой собственный. :)
Итак, является ли массив ('h') только с одним элементом тем же, что и создание короткого целого числа?
@Arnav: нет. это будет PyObject + короткое целое число.
Спасибо Армину за указание на модуль «массив». Я также нашел модуль 'struct', который упаковывает структуры в стиле c в строку:
Из документации (https://docs.python.org/library/struct.html):
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
Предложение Армина о модуле массива, вероятно, лучше всего. Две возможные альтернативы:
Также стоит понимать, что целочисленный объект Python не имеет 4 байта - это дополнительные накладные расходы. Поэтому, если у вас действительно большое количество коротких замыканий, вы можете сэкономить более двух байтов на число, используя каким-либо образом сокращение C (например, модуль массива).
Некоторое время назад мне приходилось хранить в памяти большой набор целых чисел, а словарь с целочисленными ключами и значениями был слишком большим (у меня было 1 ГБ для структуры данных IIRC). Я перешел на использование IIBTree (от ZODB), и мне удалось его подогнать. (Целые числа в IIBTree - это настоящие целые числа C, а не целые числа Python, и я взломал автоматический переход на IOBTree, когда число было больше 32 бит).
Могу ли я использовать IIBTree без установки всего Zope? Где мне это достать? Что такое IOBTree?
Просто установите ZODB (pypi.python.org/pypi/ZODB3/3.8.0). IOBTree - это дерево BT, которое имеет целочисленные ключи (I) и значения объектов (O).
Вы также можете хранить несколько целых чисел любого размера в одном большом целом числе.
Например, как показано ниже, в python3 в 64-битной системе x86 1024 бита занимают 164 байта памяти. Это означает, что в среднем один байт может хранить около 6,24 бита. А если вы выберете еще большие целые числа, вы сможете получить еще более высокую плотность хранения битов. Например, около 7,50 бит на байт с целым числом 2 ** 20 бит.
Очевидно, вам понадобится некоторая логика оболочки для доступа к отдельным коротким числам, хранящимся в большем целом числе, что легко реализовать.
Одна из проблем с этим подходом заключается в том, что ваш доступ к данным замедлится из-за использования операций с большими целыми числами.
Если вы одновременно обращаетесь к большому пакету последовательно сохраненных целых чисел, чтобы минимизировать доступ к большим целым числам, то более медленный доступ к длинным целым числам не будет проблемой.
Я думаю, что использование numpy будет более простым подходом.
>>> a = 2**1024
>>> sys.getsizeof(a)
164
>>> 1024/164
6.2439024390243905
>>> a = 2**(2**20)
>>> sys.getsizeof(a)
139836
>>> 2**20 / 139836
7.49861266054521
Использование bytearray в python, который в основном представляет собой массив C unsigned char под капотом, будет лучшим решением, чем использование больших целых чисел. Нет накладных расходов на манипулирование байтовым массивом, и у него гораздо меньше накладных расходов на хранилище по сравнению с большими целыми числами. С байтовыми массивами можно получить плотность хранения 7,99+ бит на байт.
>>> import sys
>>> a = bytearray(2**32)
>>> sys.getsizeof(a)
4294967353
>>> 8 * 2**32 / 4294967353
7.999999893829228
Вы можете использовать int NumyPy как np.int8 или np.int16.
просто предупреждаю: C++ короткий, а не 2 байта шириной. Это зависит от реализации.