Почему логика (логическое значение) в R требует 4 байта? - PullRequest
31 голосов
/ 07 февраля 2012

Для вектора логических значений, почему R выделяет 4 байта, когда битовый вектор будет потреблять 1 бит на запись? (См. этот вопрос для примеров.)

Теперь я понимаю, что R также облегчает хранение значений NA, но разве это нельзя сделать с помощью дополнительного битового вектора? Другими словами, почему недостаточно просто использовать дешевую двухбитную структуру данных?

Для чего бы то ни было, Matlab использует 1 байт для логики, хотя это не облегчает значения NA. Я не уверен, почему MathWorks не удовлетворен однобитовой функциональностью, а тем более двухбитной структурой данных, но у них есть причудливые маркетологи ... [Я собираюсь доить два бита за все, что стоит в этом вопросе , ; -)]


Обновление 1. Я думаю, что предложенные причины архитектуры имеют некоторый смысл, но это кажется немного постфактум. Я не проверял 32-битный или 16-битный R, чтобы увидеть, насколько велики их логики - это могло бы оказать некоторую поддержку этой идее. Кажется, из руководства по внутренним ресурсам R это логично векторы (LGLSXP) и целые числа (INTSXP) - 32 бита на каждой платформе. Я могу понять универсальный размер для целых чисел, независимо от размера слова. Точно так же хранение логики также, кажется, не зависит от размера слова. Но это так БОЛЬШОЙ. :)

Кроме того, если аргумент размера слова настолько силен, мне кажется странным, что Matlab (я думаю, что это 32-битный Matlab) потребляет всего 1 байт - интересно, выбрал ли MathWorks более эффективный объем памяти с компромиссом за сложность программирования и некоторые другие затраты на поиск объектов подслов.

Кроме того, есть, конечно, и другие варианты: как отмечает Брайан Диггс, пакет bit облегчает битовые векторы, что было очень полезно для решения проблемы в приведенном выше вопросе (ускорение задачи в 8X-10X было получено преобразование из 4 байтов logical значений в битовые векторы). Хотя скорость доступа к памяти важна, перемещение 30-31 дополнительных неинформативных битов (с точки зрения теории информации) расточительно. Например, можно использовать что-то вроде трюков памяти, используемых для целых чисел , описанных здесь - захватить кучу дополнительной памяти (V ячеек) и затем обрабатывать вещи на уровне битов (а-ля bit()). Почему бы не сделать это и сохранить 30 бит (1 для значения, 1 для NA) для длинного вектора?

Поскольку булевы значения влияют на мою оперативную память и скорость вычислений, я собираюсь перейти на использование bit, но это потому, что в некоторых случаях экономия пространства на 97% имеет значение. :)

Я думаю, что ответ на этот вопрос придет от кого-то с более глубоким пониманием дизайна R или внутренних органов. Лучшим примером является то, что Matlab использует другой размер для их логики, и размеры слов памяти не будут решением в этом случае. Python может быть похож на R, для чего это стоит.

Подобный способ выражения может быть следующим: почему LGLSXP будет 4 байта на всех платформах? (Как правило, CHARSXP меньше, и это не сработает? Почему бы не пойти еще меньше и просто перераспределить?) ( Обновлено Идея использования CHARSXP, скорее всего, фальшива, потому что операции с CHARSXP не так полезны, как операции с целыми числами, например, sum. Использование той же структуры данных, что и у символов, может сэкономить место, но ограничит возможности использования существующих методов. Более подходящим соображением является использование меньших целых чисел, как описано ниже.)


Обновление 2. Здесь были даны несколько очень хороших и поучительных ответов, особенно относительно того, как должен реализовать поиск и обработку логических значений для целей скорости и эффективности программирования. Я думаю, что ответ Томми особенно правдоподобен в отношении , почему выглядит так в R, который, кажется, возникает из 2 предпосылок:

  1. Для поддержки сложения на логическом векторе (обратите внимание, что «логический» определяется языком / средой программирования и не совпадает с логическим), лучше всего использовать повторное использование кода для добавления целых чисел.В случае R целые числа занимают 4 байта.В случае Matlab наименьшее целое число составляет 1 байт (т.е. int8).Это объяснило бы, почему что-то другое было бы неприятным для логики.[Для тех, кто не знаком с R, он поддерживает множество числовых операций над логиками, таких как sum(myVector), mean(myVector) и т. Д.]

  2. Поддержка старых версий делает чрезвычайно трудным что-то делатькроме того, что было сделано в R и S-Plus в течение длительного времени.Более того, я подозреваю, что в первые дни S, S-Plus и R, если кто-то делал много логических операций, он делал их в C, а не пытался так много работать с логикой в ​​R.

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

Спасибо всемдля очень тщательного набора ответов и идей.

Ответы [ 3 ]

16 голосов
/ 07 февраля 2012

Даже не зная R, я подозреваю, что по той же причине, что и С, потому что гораздо быстрее загрузить размер, равный размеру собственного слова процессора.

Загрузка одного бита будет медленной, особенно из битового поля, поскольку вам придется маскировать биты, которые не относятся к вашему конкретному запросу. Одним словом вы можете просто загрузить его в реестр и покончить с этим. Поскольку разница в размере обычно не является проблемой, по умолчанию используется переменная размера слова. Если пользователь хочет что-то еще, всегда есть возможность выполнить сдвиг битов, требуемый вручную.

Что касается упаковки, то, по крайней мере, на некоторых процессорах это вызовет сбой при чтении с невыровненного адреса. Таким образом, хотя вы можете объявить структуру с одним byte в окружении двух int, byte может быть дополнен до 4 байтов размером независимо. Опять же, я ничего не знаю о R, в частности, но я подозреваю, что поведение может быть таким же по причинам производительности.

Адресация одного байта в массиве является более сложной задачей, скажем, у вас есть массив bitfield и вы хотите указать в нем бит x, код будет выглядеть примерно так:

bit b = (bitfield[x/8] >> (x % 8)) & 1

для получения 0 или 1 для запрошенного вами бита. По сравнению с прямой адресацией массива из логического массива, получающего значение x: bool a = array[x]

15 голосов
/ 07 февраля 2012

Зная немного о R и S-Plus, я бы сказал, что R, скорее всего, сделал это для совместимости с S-Plus, а S-Plus, скорее всего, сделал это, потому что это было проще всего сделать ....

По сути, логический вектор идентичен целочисленному вектору, поэтому sum и другие алгоритмы для целых чисел работают практически без изменений на логических векторах.

В 64-битном S-Plus,целые числа 64-битные и, следовательно, также логические векторы!Это 8 байт на логическое значение ...

@ Итератор, конечно, правильно, что логический вектор должен быть представлен в более компактной форме.Поскольку уже существует векторный тип raw, который является 1-байтовым, может показаться очень простым изменение использовать этот тип и для логики.И 2 бита на значение, конечно, были бы еще лучше - я бы, вероятно, сохранил их как два отдельных битовых вектора (TRUE / FALSE и NA / Valid), а битовый вектор NA мог бы быть NULL, если нет NA ...

Во всяком случае, это в основном мечта, поскольку существует так много пакетов RAPI (пакетов, которые используют API-интерфейсы RC / FORTRAN), которые могут сломаться ...

10 голосов
/ 07 февраля 2012

Другие ответы получены по (вероятным) архитектурным причинам того, что логические векторы реализованы, занимая то же пространство, что и целые числа.Я хотел указать на пакет bit, в котором реализована однобитная (без NA) логика.

...