Подтвердить что ты не робот

Почему логические переменные (booleans) в R требуют 4 байта?

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

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

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


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

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

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

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

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

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


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

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

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

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

Спасибо всем за очень тщательный набор ответов и прозрений.

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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