Pregunta

¿Está Interlocked.Increment (ref x) más rápido o más lento que x ++ para ints y longs en varias plataformas?

¿Fue útil?

Solución

Es más lento ya que obliga a que la acción se produzca atómicamente y actúa como una barrera de memoria, eliminando la capacidad del procesador para reordenar los accesos de memoria en torno a la instrucción.

Debería usar Interlocked.Increment cuando desee que la acción sea atómica en estado que se puede compartir entre subprocesos; no se pretende que sea un reemplazo completo de x ++.

Otros consejos

En nuestra experiencia, el InterlockedIncrement () et al en Windows son impactos bastante significativos. En un caso de muestra pudimos eliminar el enclavamiento y usar ++ / - en su lugar. Esto solo redujo el tiempo de ejecución de 140 segundos a 110 segundos. Mi análisis es que el enclavamiento fuerza un viaje de ida y vuelta a la memoria (de lo contrario, ¿cómo podrían verlo otros núcleos?). Una lectura / escritura de caché L1 es de aproximadamente 10 ciclos de reloj, pero una lectura / escritura de memoria es más como 100.

En este caso de muestra, calculé el número de operaciones de incremento / decremento en aproximadamente mil millones. Entonces, en una CPU de 2Ghz, esto es algo así como 5 segundos para el ++ / -, y 50 segundos para el enclavamiento. Extienda la diferencia en varios subprocesos, y es cerca de 30 segundos.

Piénselo por un momento y se dará cuenta de que una llamada Increment no puede ser más rápida que una simple aplicación del operador de incremento. Si así fuera, la implementación del compilador del operador de incremento llamaría internamente a Increment , y realizarían lo mismo.

Pero, como puede ver probándolo usted mismo, no realizan lo mismo.

Las dos opciones tienen propósitos diferentes. Use el operador de incremento en general. Use Increment cuando necesite que la operación sea atómica y esté seguro de que todos los demás usuarios de esa variable también están utilizando operaciones entrelazadas. (Si no todos cooperan, entonces realmente no ayuda).

Es más lento. Sin embargo, es la forma general más eficaz que conozco para lograr la seguridad del hilo en variables escalares.

Siempre será más lento porque tiene que realizar un bloqueo del bus de la CPU en lugar de simplemente actualizar un registro. Sin embargo, las CPU modernas logran un rendimiento cercano al registro, por lo que es insignificante incluso en el procesamiento en tiempo real.

Mi prueba de rendimiento:

volátil: 65,174,400

bloqueo: 62,428,600

enclavados: 113,248,900

TimeSpan span = TimeSpan.FromSeconds(5);

object syncRoot = new object();
long test = long.MinValue;

Do(span, "volatile", () => {

    long r = Thread.VolatileRead(ref test);

    r++;

    Thread.VolatileWrite(ref test, r);
});

Do(span, "lock", () =>
{
    lock (syncRoot)
    {
        test++;
    }
});

Do(span, "interlocked", () =>
{
    Interlocked.Increment(ref test);
});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top