símbolo signo poner operadores mayor logicos logicas igual diferente condicional como booleano r memory boolean

signo - símbolo diferente en r



¿Por qué los lógicos(booleanos) en R requieren 4 bytes? (3)

Sabiendo un poco sobre R y S-Plus, diría que R probablemente lo hizo para ser compatible con S-Plus, y S-Plus probablemente lo hizo porque era lo más fácil de hacer ...

Básicamente, un vector lógico es idéntico a un vector entero, por lo que la sum y otros algoritmos para los enteros funcionan prácticamente sin cambios en los vectores lógicos.

En S-Plus de 64 bits, los enteros son de 64 bits y, por lo tanto, también son los vectores lógicos. Eso es 8 bytes por valor lógico ...

@Iterator es por supuesto correcto que un vector lógico debería representarse en una forma más compacta. Como ya existe un tipo de vector sin raw que es de 1 byte, parecería un cambio muy simple utilizarlo también para los lógicos. Y 2 bits por valor serían, por supuesto, incluso mejores: probablemente los mantendría como dos vectores de bits separados (VERDADERO / FALSO y NA / Válido), y el vector de bits NA podría ser NULO si no hay NA ...

De todos modos, eso es más que nada un sueño, ya que hay tantos paquetes de RAPI (paquetes que usan las API RC / FORTRAN) que podrían romperse ...

Para un vector de valores lógicos, ¿por qué R asigna 4 bytes cuando un vector de bits consume 1 bit por entrada? (Consulte esta pregunta para ver ejemplos).

Ahora, me doy cuenta de que R también facilita el almacenamiento de los valores de NA , pero ¿no podría hacerse con un vector de bits adicional? En otras palabras, ¿por qué no basta con usar una estructura de datos barata de dos bits?

Por lo que vale, Matlab usa 1 byte para lógicos, aunque no facilita los valores de NA. No estoy seguro de por qué MathWorks no está satisfecho con la funcionalidad de un bit, y mucho menos con una estructura de datos de dos bits, pero tienen vendedores de pantalones de lujo ... [Voy a ordeñar "dos bits" por todo lo que vale en esta pregunta . ;-)]

Actualización 1. Creo que las razones de arquitectura ofrecidas tienen algún sentido, pero eso se siente un poco ex post facto. No he revisado R de 32 bits o de 16 bits para ver qué tan grandes son sus lógicas, eso podría prestar algún apoyo a la idea. Parece que, según el manual de R Internals, los vectores lógicos (LGLSXP) y los enteros (INTSXP) son 32 bits en cada plataforma. Puedo entender un tamaño universal para enteros, independientemente del tamaño de la palabra. Del mismo modo, el almacenamiento de los lógicos también parece ser independiente del tamaño de la palabra. Pero es tan GRANDE. :)

Además, si el argumento del tamaño de la palabra es tan poderoso, me parece extraño ver a Matlab (creo que es un Matlab de 32 bits) consumir solo 1 byte. Me pregunto si MathWorks eligió ser más eficiente con una compensación por complejidad de programación y alguna otra sobrecarga para encontrar objetos de subpalabras.

Además, hay ciertamente otras opciones en son: como señala Brian Diggs, el paquete de bit facilita los vectores de bits, que fue muy útil para el problema en la pregunta anterior (se obtuvo una aceleración de 8X-10X para la tarea convirtiendo desde 4 bytes logical valores a vectores de bits). Aunque la velocidad de acceso a la memoria es importante, mover 30-31 bits no informativos adicionales (desde la perspectiva de la teoría de la información) es un desperdicio. Por ejemplo, uno podría usar algo así como los trucos de memoria utilizados para los enteros que se describen aquí : tomar un montón de memoria extra (celdas V) y luego procesar cosas en el nivel de bit (a la bit() ). ¿Por qué no hacer eso y guardar 30 bits (1 para el valor, 1 para NA ) para un vector largo?

En la medida en que mi RAM y velocidad computacional se vean afectadas por los booleanos, tengo la intención de cambiar a usar bit , pero eso se debe a que en algunos casos, un ahorro de 97% en el espacio es importante. :)

Creo que la respuesta a esta pregunta vendrá de alguien con una comprensión más profunda del diseño o internos de R. El mejor ejemplo es que Matlab utiliza un tamaño diferente para su lógica, y el tamaño de la palabra de memoria no sería la respuesta en ese caso. Python puede ser similar a R, por lo que vale.

Una forma relacionada de expresar esto podría ser: ¿por qué LGLSXP tendría 4 bytes en todas las plataformas? (¿Es CHARSXP típicamente más pequeño, y no funcionaría tan bien? ¿Por qué no ir aún más pequeño, y simplemente sobre asignar?) ( Actualizado La idea de usar CHARSXP es probablemente falsa, porque las operaciones en CHARSXP no son tan útiles como aquellos para enteros, como sum . Usar la misma estructura de datos que los caracteres podría ahorrar espacio, pero restringiría los métodos existentes que podrían operar en él. Una consideración más apropiada es el uso de enteros más pequeños, como se explica más adelante).

Actualización 2. Ha habido algunas respuestas muy buenas y esclarecedoras aquí, especialmente en relación con cómo se debe implementar la recuperación y el procesamiento de booleanos para los objetivos de velocidad y eficiencia de programación. Creo que la respuesta de Tommy es particularmente plausible con respecto a por qué aparece así en R, que parece surgir de 2 premisas:

  1. Para admitir la adición en un vector lógico (tenga en cuenta que "lógico" está definido por el lenguaje de programación / entorno, y no es lo mismo que un booleano), lo mejor es reutilizar el código para agregar enteros. En el caso de R, los enteros consumen 4 bytes. En el caso de Matlab, el entero más pequeño es de 1 byte (es decir, int8 ). Esto explicaría por qué algo diferente sería una molestia para escribir para lógicos. [Para aquellos que no están familiarizados con R, admite muchas operaciones numéricas en lógicos, como sum(myVector) , mean(myVector) , etc.]

  2. El soporte heredado hace que sea extremadamente difícil hacer algo diferente a lo que se ha hecho en R y S-Plus desde hace mucho tiempo. Además, sospecho que en los primeros días de S, S-Plus y R, si alguien estaba haciendo muchas operaciones booleanas, las hizo en C, en lugar de tratar de hacer tanto trabajo con lógicas en R.

Las otras respuestas son fantásticas a los efectos de cómo se puede implementar un mejor manejo booleano: no suponga ingenuamente que se puede obtener en un bit individual: es más eficiente cargar una palabra, luego enmascarar los bits que no son de interés, como Dervall ha descrito. Este es un consejo muy, muy útil si uno escribe un código especializado para la manipulación booleana de R (por ejemplo, mi pregunta sobre tabulaciones cruzadas): no itere sobre bits, sino que trabaje a nivel de palabra.

Gracias a todos por un conjunto muy completo de respuestas y puntos de vista.


Se han obtenido otras respuestas según las (probables) razones arquitectónicas de que los vectores lógicos se implementan tomando el mismo espacio que los enteros. Quería señalar el paquete de bit que implementa un lógico de un bit (sin NA ).


Sin conocer R en absoluto, sospecho por la misma razón que C, porque es mucho más rápido cargar un tamaño igual al tamaño de palabra nativo del procesador.

Cargar un solo bit sería lento, especialmente desde un campo de bits, ya que tendría que enmascarar los bits que no se aplican a su consulta en particular. Con una palabra completa, puedes cargarla en un registro y terminarla. Como la diferencia de tamaño generalmente no es un problema, la implementación predeterminada es usar una variable de tamaño de palabra. Si el usuario quiere algo más, siempre existe la opción de hacer el cambio de bit requerido manualmente.

Con respecto al empaque, al menos en algunos procesadores causará que se lea una falla de una dirección no alineada. Entonces, si bien puede declarar una estructura con un solo byte en ella, rodeada por dos int el byte puede ser acolchado para que tenga 4 bytes de tamaño independientemente. Una vez más, no sé nada sobre R en particular, pero sospecho que el comportamiento podría ser el mismo por razones de rendimiento.

Abordar un solo byte en una matriz es bastante más complicado, digamos que tienes un bitfield matriz y quieres direccionar el bit x en él, el código sería algo como esto:

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

para obtener 0 o 1 para el bit que solicitó. En comparación con el direccionamiento directo de una matriz booleana obteniendo el número de valor x: bool a = array[x]