¿Quién necesita linealización?

13

He estado leyendo sobre las diferencias entre la serialización y la linealización , que son criterios de consistencia para los sistemas replicados, como las bases de datos replicadas. Sin embargo, no sé en qué casos sería necesaria la linealización, a pesar de que es más fuerte que la serialización.

¿Podría pensar en escenarios en los que una propiedad tan fuerte sería realmente necesaria?

Eduardo Bezerra
fuente
Puede consultar en wikipedia: en.wikipedia.org/wiki/… , o en el artículo de Herlihy y Wing: "Linealizabilidad: una condición de corrección para objetos concurrentes".
Eduardo Bezerra

Respuestas:

5

Considere el diseño de estructuras de datos concurrentes, sin espera (o sin bloqueo, que es más débil). En este escenario, generalmente se requiere linealización, aunque en algunos casos, el rendimiento y la escalabilidad se pueden mejorar al satisfacer una condición de corrección más débil. Si una implementación que satisface una condición tan débil es útil, generalmente depende de la aplicación. En contraste, una implementación linealizable siempre es utilizable, porque los diseñadores pueden verla como atómica.

Además, la linealización es una propiedad que no bloquea: nunca se requiere una operación total (definida para todos los estados de objeto) para bloquear. En cambio, la serialización no es una propiedad no bloqueante. Por lo tanto, para aumentar el grado de concurrencia, los diseñadores de estructuras de datos concurrentes siempre confían en la linealización.

Massimo Cafaro
fuente
1
esta no es una buena respuesta, ya que utiliza otro concepto inexplicable para explicar el concepto en duda ... (leer esto es una pérdida de tiempo) ... las respuestas a continuación son mucho mejores ...
Richard
Parece que no leíste la pregunta OP original. El OP no preguntaba qué es la linealización, preguntó "¿Quién necesita la linealización?" Mi respuesta es apropiada, ya que proporciona al OP un escenario de ejemplo (al menos, el OP lo consideró apropiado y lo seleccionó). El hecho de que no sepa qué son las estructuras de datos simultáneas y sin esperas es una cuestión completamente diferente. Por cierto, el OP sabía de lo que estaba hablando. Si tuviéramos que explicar cada concepto que usamos en una respuesta, la respuesta nunca terminará ;-)
Massimo Cafaro
10

He releído a Herlihy y Wing muchas veces en los últimos 15 años. Es una lectura muy difícil. Y eso es lamentable, porque si bien hay algunas sutilezas en los bordes, la idea básica es bastante razonable.

En resumen: la linealización es como la serialización, pero con el requisito adicional de que la serialización respete restricciones de orden adicionales entre las transacciones. El objetivo es permitirle razonar rigurosamente sobre una estructura de datos atómicos individuales en lugar de tener que razonar sobre todo el sistema a la vez.

La linealización también es fácil de lograr: simplemente asocie un mutex con el objeto que desea linealizar. Cada transacción en ese objeto comienza bloqueando el mutex y termina desbloqueando el mutex.

Aquí están las definiciones que usaré:

Un sistema es serializable si se le da un conjunto de transacciones sobre un conjunto de datos, cualquier resultado de ejecutar las transacciones es el mismo que si las transacciones se ejecutaran en un orden secuencial, y las operaciones dentro de cada transacción están contenidas dentro de su transacción en el orden especificado por el código de la transacción.

La serialización no permite la apariencia de intercalación de operaciones entre diferentes transacciones, y requiere que el orden elegido de las transacciones satisfaga la causalidad (si la transacción A escribe el valor x, y la transacción B lee el valor x que A escribió, entonces la transacción A debe preceder a la transacción B en el orden en serie elegido.) Pero no dice nada sobre otras restricciones en el orden de las transacciones (en particular, no dice nada sobre los procesos y el orden en que los procesos perciben los eventos).

Hay otra idea relacionada que agrega restricciones sobre el orden en que los procesos ejecutan las operaciones (pero no habla de transacciones solo de operaciones de lectura / escritura individuales):

Un sistema es secuencialmente consistente si el resultado de cualquier ejecución es el mismo que si las operaciones de todos los procesos se ejecutaran en algún orden secuencial, y las operaciones de cada proceso individual aparecen en esta secuencia en el orden especificado por su programa. ( Lamport, "Cómo hacer una computadora multiprocesador que ejecute correctamente programas multiprocesador", IEEE T Comp 28: 9 (690-691), 1979 ).

Implícito en la definición de consistencia secuencial es que solo aceptamos órdenes secuenciales donde para cada ubicación de memoria (objeto) el orden secuencial de operaciones inducido obedece a la regla de que el valor devuelto por cada operación de lectura a la ubicación xdebe ser el mismo valor escrito por la operación de escritura inmediatamente anterior a la ubicación xen el orden secuencial.

La linealización tiene las buenas intenciones de (a) combinar la noción de transacciones (de la serialización) con la noción de que los procesos esperan que las operaciones que emitan se completen en orden (de consistencia secuencial) y (b) reducir los criterios de corrección para hablar sobre cada objetar de forma aislada, en lugar de obligarlo a razonar sobre el sistema en su conjunto. (Me gustaría poder decir que la implementación de mi objeto es correcta incluso en un sistema donde hay otros objetos que no son linealizables). Creo que Herlihy y Wing podrían haber estado tratando de definir rigurosamente un monitor .

La parte (a) es "fácil": un requisito de coherencia secuencial sería que las transacciones en el objeto emitido por cada proceso aparezcan en la secuencia resultante en el orden especificado por el programa. Un requisito similar a la serialización sería que las transacciones en el objeto sean mutuamente excluyentes (se pueden serializar).

La complejidad proviene del objetivo (b) (poder hablar sobre cada objeto independientemente de todos los demás).

En un sistema con varios objetos, es posible que las operaciones en el objeto B impongan restricciones en el orden en el que creemos que las operaciones fueron invocadas en el objeto A. Si observamos el historial completo del sistema, estaremos limitados a ciertos órdenes secuenciales, y tendrá que rechazar a los demás. Pero queríamos un criterio de corrección que pudiéramos utilizar de forma aislada (razonamiento sobre lo que le sucede al objeto A sin apelar al historial del sistema global).

Por ejemplo: suponga que estoy tratando de discutir sobre la corrección del objeto A, que es una cola, suponga que el objeto B es una ubicación de memoria y suponga que tengo los siguientes historiales de ejecución: Hilo 1: A.enqueue (x), A. dequeue () (devuelve y). Hilo 2: A.enqueue (y), A.dequeue () (devuelve x). ¿Existe un entrelazado de eventos que permita que esta implementación de la cola sea correcta? Si:

Thread 1                           Thread 2
A.enqueue(x)                       ...
...                                A.enqueue(y)
...                                A.dequeue() (returns x)
A.dequeue(y) (returns y)           ...

Pero ahora, ¿qué pasa si el historial ( incluido el objeto B ) es: B comienza con el valor 0. Hilo 1: A.enqueue (x), A.dequeue () (devuelve y), B.write (1). Hilo 2: B.read () (devuelve 1) A.enqueue (y), A.dequeue () (devuelve x).

Thread 1                           Thread 2
A.enqueue(x)                       ...
A.dequeue() (returns y)            ...                       (uh oh!)
B.write(1)                         ...
...                                B.read() (returns 1)
...                                A.enqueue(y)
...                                A.dequeue() (returns x)

Ahora nos gustaría que nuestra definición de "corrección" diga que este historial indica que nuestra implementación de A es defectuosa o que nuestra implementación de B es defectuosa, porque no hay serialización que "tenga sentido" (o bien el Tema 2 debe leerse) un valor de B que aún no se ha escrito, o el subproceso 1 necesita eliminar un valor de A que aún no se ha puesto en cola.) Entonces, aunque nuestra serialización original de las transacciones en A parecía razonable, si nuestra implementación permite un historial como el segundo, entonces es claramente incorrecto.

Por lo tanto, las restricciones que agrega la linealización son bastante razonables (y necesarias incluso para estructuras de datos simples como las colas FIFO). Son cosas como: "su implementación no debe permitir dequeue () un valor que no se pondrá en cola () hasta algún tiempo en el futuro." La linealización es bastante fácil (y natural) de lograr: simplemente asocie un mutex con su objeto, y cada transacción comienza bloqueándose y termina desbloqueándose. El razonamiento sobre la linealización comienza a ser complicado cuando intenta implementar su atomicidad con técnicas sin bloqueo o sin bloqueo o sin esperar en lugar de simples mutexes.

Si está interesado en algunos consejos sobre la literatura, encontré lo siguiente (aunque creo que la discusión sobre el "tiempo real" es una de las pistas falsas que hacen que la linealización sea más difícil de lo necesario). Https: // stackoverflow.com/questions/4179587/difference-between-linearizability-and-serializability

Lógica Errante
fuente
¿Qué quiere decir con afirmar que `` Creo que Herlihy y Wing pueden haber estado tratando de definir rigurosamente un monitor ''? ¿Podría por favor agregar algunos detalles? (Estoy leyendo el periódico de Herlihy y Wing.)
hengxin
1
No creo que haya querido decir nada profundo. Antes de leer a Herlihy y Wing, todo lo que había leído sobre los monitores estaba operativo. Algo así como "un monitor es un tipo de datos abstractos que implícitamente tiene un mutex y cada método del tipo adquiere el mutex al principio y lo libera al final", seguido de una discusión complicada sobre cuándo está bien wait()y notify(). La linealización ofrece una forma de hablar sobre la corrección de implementaciones de monitor mucho más complicadas / optimizadas.
Wandering Logic
Tiene sentido para mí. Gracias. Hoy he leído la Related Workparte del periódico de Herlihy y Wing. Mencionaron monitorcomo una ilustración de su reclamo que Our notion of linearizability generalizes and unifies similar notions found in specific examples in the literature. Sin embargo, una pregunta general: ¿se ha adoptado ampliamente la noción de linealización en los sistemas multiprocesador (por ejemplo, hardware, compilador, lenguaje de programación y estructuras de datos concurrentes)? (Siendo miope, solo sé cosas como el monitor). Si no, ¿cuáles son los obstáculos? ¿Cuál es el estado del arte?
hengxin
Creo que se considera una propiedad deseable que a veces es demasiado costosa de aplicar. Ver por ejemplo: cursos.csail.mit.edu/6.852/01/papers/p91-attiya.pdf . También en la práctica, creo que la mayoría de los hashmaps concurrentes tienen un bloqueo por cubo, pero no un bloqueo global, y por lo tanto pueden tener un comportamiento extraño cada vez que una inserción / eliminación hace que la tabla hash se redimensione.
Wandering Logic
Gracias por la respuesta larga, pero me temo que no me dijo cuando instrucción atómica era interesante, sino más bien sólo se define y, para el caso, que definió mal: es que no basta con que cada proceso ve en las operaciones La orden en que se emitieron. El orden en todos los procesos también debe ser coherente. Pero corrígeme si me equivoco ...
Eduardo Bezerra
2

Primero, la linealización y la serialización no son directamente comparables. Como muestra la tabla a continuación, la principal diferencia es que en el lado izquierdo, todas las operaciones individuales son atómicas (como tener un Java synchronizedalrededor de cada operación . En el lado derecho, la unidad de atomicidad es una transacción; una operación individual no es atómica Es por eso que la serialización siempre ha sido parte de la literatura de la base de datos, mientras que el lado izquierdo ha sido el tema de la literatura de la memoria del procesador (la operación de lectura / escritura es atómica). memcached) comenzó en el lado izquierdo (get / put es atómico), pero los más nuevos respaldan cada vez más las transacciones (como la llave de Google).

obj. operaciones son atómicas | Las transacciones son atómicas.
-------------------------------- + ----------------- ----------------
Linealidad |
Consistencia secuencial | Serializabilidad
Consistencia causal |
Consistencia de caché |

La linealización requiere que un sistema de objetos en una configuración concurrente se comporte de manera idéntica a un sistema secuencial que maneja una operación (un par de solicitud / respuesta) a la vez, en un universo paralelo, de tal manera que (a) los clientes en ambos universos ver exactamente las mismas respuestas (b) se conserva el orden temporal (más sobre esto a continuación).

La definición de Serializabilidad, como la Consistencia secuencial, solo requiere el primer criterio.

La preservación del orden temporal significa esto: si A: x.op1 () (A es un cliente, x es un objeto y op1 es una operación) finalizó antes de que comenzara otra operación B: y.op2 (), entonces en el universo secuencial Las solicitudes se manejan en el mismo orden. Esto no es necesario en la coherencia secuencial (SC); el objeto puede poner en cola la solicitud de un cliente, responder al cliente y luego evaluarlo más tarde. Además, el objeto puede manejar una solicitud posterior de algún otro cliente fuera de turno, evaluándolo antes de llegar al primero.

La no preservación del orden temporal es un problema. Después de A: x.op1 (), suponga que A levantó el teléfono y le contó a B al respecto, luego B llamó a la llamada x.op2 (). No hay forma de que el sistema sepa acerca de esta cadena de eventos causales, ya que el segundo paso involucra un mensaje que el sistema no rastrea. En muchos casos reales, no es irrazonable que A suponga que una vez que x le haya respondido, la invocación de B puede depender del estado actualizado. Si no se preserva el orden temporal, A y B se sorprenderán. Esto no sucedería en un sistema linealizable.

La segunda propiedad agradable de la preservación del orden temporal es la localidad y la composicionalidad, que un sistema construido de objetos linealizables es en sí mismo linealizable. Por lo tanto, en lugar de tener un almacén de valores clave monolíticos, puede dividirlo en muchas particiones separadas, cada una administrada por su propio servidor KV-store; Si cada uno de ellos es linealizable, toda la base de datos funciona como una tienda KV monolítica linealizable, sin esfuerzo adicional.

Sriram Srinivasan
fuente