¿Por qué se CAS no se considera equivalente a los bucles-ocupados esperando?

Kilian:

Leer un poco acerca de la programación libre de bloqueo en los últimos días me encontré con la util.java.Randomclase de crearlo de bits utilizando la siguiente rutina:

protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}

De acuerdo con esta respuesta, así:

Los llamados algoritmos sin bloqueo tienden a usar apretado ocupado en espera con una instrucción de CAS, pero el argumento es en situaciones ordinarias tan baja que la CPU lo general tienen que iterate sólo unas pocas veces.

Y Wikipedia :

En lugar de volver a intentar inmediatamente después de una operación de CAS falla, los investigadores han encontrado que el rendimiento total del sistema se puede mejorar de multiprocesador sistemas donde muchos hilos en constante actualización de algunos hilos variables -si compartidos particulares que ven a sus CAS fallan uso de retroceso exponencial, en otras palabras, espera un poco antes de volver a intentar la CAS. [4]

Puede entenderse el artículo de Wikipedia, se ha descubierto pero no es empleado todavía o se trata de una práctica común que las instrucciones CAS artificialmente retroceso después de que hayan fracasado. Es esta la razón tal bucle no se considera peligroso con respecto al uso de la CPU o porque el CAS no se discute constantemente?

Segunda pregunta: ¿hay alguna razón específica referencia a seedse crea o podría también utilizar simplemente la variable del ámbito de la clase?

Peter Cordes:

Múltiples hilos que tratan de CAS es algo (pero no espere libre) sin bloqueo. Uno de los hilos hará progresar cada vez que todo intento con el mismo oldvalor . https://en.wikipedia.org/wiki/Non-blocking_algorithm .

(Ya sea múltiples hilos todos leen el mismo oldvalor o si algunos ven el resultado de CAS de otro hilo depende del momento, y es básicamente lo que determina la cantidad de contención que hay.)

Esto es a diferencia de un bucle normal de ocupado: espere que recién está a la espera de alguna operación desconocida de longitud y podría ser atrapado indefinidamente si se descheduled el hilo que mantiene un bloqueo. En ese caso, que debe de dar marcha atrás si su CAS no puede obtener un bloqueo, ya que sin duda tiene que esperar a que otro hilo que hacer algo antes de que pueda tener éxito.


Por lo general, los algoritmos lockless se utilizan en situaciones de poca contención, donde no es realmente necesario sofisticada exponencial-retroceso. Eso es lo que la respuesta SO ligado está diciendo.

Esta es una clave de diferencia con respecto a la situación mencionada en el artículo de Wiki: donde muchos hilos en constante actualización de alguna variable compartida en particular . Esa es una situación de alta contención, lo que es probablemente mejor dejar que un hilo de hacer un montón de cambios en una fila y mantener la línea caliente en su caché L1d. (Suponiendo que está usando CAS para implementar una operación atómica que el hardware no admite directamente, como un complemento FP doble precisión atómica, donde shared.CAS(old, old+1.0)o algo así. O, como parte de una cola lockless o algo así.)

Si estaba utilizando un bucle CAS que fue altamente contendió en la práctica, que podría ayudar a algunos a rendimiento total de marcha atrás y por ejemplo, ejecutar un x86 pausede instrucciones en caso de fallo antes de volver a intentarlo, a tener menos núcleos martilleo en una línea de caché. O para una cola lockless, si lo encuentra lleno o vacío, entonces eso es básicamente una situación de espera de otro hilo de lo que debería retroceder.


La mayoría de las arquitecturas x86 tienen distintos LL / SC como su RSR atómica primitiva , no un CAS directo al hardware. Edificio CAS de LL / SC puede fallar si falsamente otros hilos están aún leyendo la línea de caché durante el intento de CAS, por lo que podría no puede garantizar que al menos un hilo éxito.

los diseñadores de hardware de esperar que tratan de hacer que la CPU marca LL / SC resisten el fracaso espuria de la contienda, pero no conocen los detalles. En este caso, retroceso podría ayudar a evitar una posible livelock.

(En el hardware donde CAS no puede dejar de forma espuria de la contienda, livelock es imposible que algo así while(!shared.CAS(old, old<<1)){}.)


Manual de optimización de Intel tiene un ejemplo de la espera de una cerradura a ser libre, donde bucle 1 << retry_countveces (hasta un cierto factor de retroceso máximo) Tenga en cuenta que esto es no un bucle normal de CAS eso es parte de un algoritmo lockless; esto es para la implementación de una cerradura.

El retroceso se espera para el bloqueo a ser libres , no sólo para la pelea por el acceso a la línea de caché que contiene la propia cerradura.

  /// Intel's optimization manual
  /// Example 2-2. Contended Locks with Increasing Back-off Example

  /// from section 2.2.4 Pause Latency in Skylake Microarchitecture
  /// (~140 cycles, up from ~10 in Broadwell, thus max backoff should be shorter)
/*******************/
/*Baseline Version */
/*******************/
// atomic {if (lock == free) then change lock state to busy}
while (cmpxchg(lock, free, busy) == fail)
{
   while (lock == busy)
     _mm_pause();
}


/*******************/
/*Improved Version */
/*******************/
int mask = 1;
int const max = 64; //MAX_BACKOFF
while (cmpxchg(lock, free, busy) == fail)
{
   while (lock == busy)
   {
      for (int i=mask; i; --i){
         _mm_pause();
      }
      mask = mask < max ? mask<<1 : max;    // mask <<= 1  up to a max
   }
}

Pensé normalmente cuando la espera de una cerradura, que desea sólo lectura giro en lugar de mantener tratando con cmpxchg. Creo que este ejemplo de Intel es solamente demostrando retroceso, no a otras partes de la forma de optimizar un bloqueo para evitar retrasar el hilo de desbloqueo.

De todos modos, recuerde que es ejemplo no como lo que estamos hablando con una cola lockless o una aplicación CAS-reintento de un complemento atómica o de otro tipo primitivo. Está a la espera de otro hilo para liberar un bloqueo, no solo la falta de usar el nuevo valor que apareció entre leer el valor antiguo y el intento de CAS en un nuevo valor.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=187974&siteId=1
Recomendado
Clasificación