Y cuánto más rápido/más lento es en comparación con una variable atómica no impugnada (como la operación atómica <> de C++). Además, ¿cuánto más lento son las variables atómicas impugnadas en relación con el bloqueo no probado? La arquitectura en la que estoy trabajando es x86-64.¿Qué tan rápido es un bloqueo indiscutible?
Respuesta
Hay un project on GitHub con el propósito de medir esto en diferentes plataformas. Desafortunadamente, después de mi tesis de maestría, nunca tuve tiempo de hacer un seguimiento de esto, pero al menos el código rudimentario está ahí.
Mide pthreads y cerraduras OpenMP, en comparación con el __sync_fetch_and_add
intrínseca.
Por lo que recuerdo, esperábamos una diferencia bastante grande entre las cerraduras y operaciones atómicas (~ un orden de magnitud), pero la diferencia real resultó ser muy pequeño.
Sin embargo, medir ahora en mi sistema arroja resultados que reflejan mi conjetura original, es decir que (independientemente de si se usan pthreads o OpenMP) las operaciones atómicas son aproximadamente cinco veces más rápidas, y una operación de incremento bloqueado tarda aproximadamente 35ns (esto incluye adquirir el bloqueo, realizar el incremento y soltar el bloqueo).
depende de la implementación de la cerradura, también depende del sistema. Las variables atómicas no se pueden cuestionar de la misma forma que un bloqueo (ni siquiera si está usando acquire-release semantics), ese es el punto de atomicidad, bloquea el bus para propagar el almacenamiento (dependiendo del modo de barrera de memoria) , pero eso es un detalle de implementación.
operaciones atómicas Sin embargo, la mayoría de las cerraduras de modo de usuario se acaba de terminar, ver this artículo de Intel para algunas figuras de alto rendimiento, cerraduras escalables utilizando operaciones atómicas bajo x86 y x64 (comparados contra CriticalSection
cerraduras de Windows, por desgracia, no hay estadísticas se encuentran para las cerraduras SWR, pero siempre se debe crear un perfil para el propio sistema/entorno).
"Atomic las variables no pueden ser realmente de impugnación de la misma manera como un bloqueo "- si dos hilos (en diferentes núcleos) martillar la misma variable atómica, entonces eso es impugnarlo, ¿no? Depende de la arquitectura/implementación si la impugnación realmente desacelera las cosas. Podrías quizás compararlo con dos hilos en diferentes núcleos martillando la misma variable no atómica, para tener una idea de si la sincronización atómica está tomando algún sentido en algún momento. –
@SteveJessop, definitivamente. Dos núcleos que usan la misma variable provocarán una sincronización excesiva de esa variable. Está limitado en este punto por la latencia/ancho de banda del bus de caché. –
@SteveJessop: se podría llamar así, pero, en mi opinión, su hacer de una manera diferente todos juntos, por lo que realmente no se puede poner en la misma categoría que spin-esperar-reintentar en una cerradura ya adquiridos. – Necrolis
Tengo muchas pruebas de velocidad de bajo nivel por ahí. Sin embargo, lo que significa exactamente la velocidad es muy incierto porque depende mucho de lo que esté haciendo exactamente (incluso sin relación con la operación en sí).
Aquí hay algunos números de un AMD 64-Bit Phenom II X6 3.2Ghz. También he ejecutado esto en chips Intel y los tiempos varían mucho (de nuevo, dependiendo de qué se está haciendo exactamente).
Una GCC __sync_fetch_and_add
, que sería una adición atómica completamente cercada, tiene un promedio de 16ns, con un tiempo mínimo de 4ns. El tiempo mínimo es probablemente más cercano a la verdad (aunque incluso allí tengo un poco de sobrecarga).
Un pstread mutex no contestado (a través de impulso) es 14ns (que también es su mínimo). Tenga en cuenta que esto también es un poco demasiado bajo, ya que el tiempo realmente aumentará si algo más ha bloqueado el mutex, pero no es indiscutible ahora (ya que causará una sincronización de caché).
Un try_lock fallido es 9ns.
No tengo un viejo inc atómico simple ya que en x86_64 esto es solo una operación normal de intercambio. Probablemente cerca del tiempo mínimo posible, entonces 1-2ns.
Llamar notificar sin un camarero en una variable de condición es de 25ns (si algo está esperando aproximadamente 304ns).
Sin embargo, como todas las cerraduras causan ciertas garantías de pedido de CPU, la cantidad de memoria que haya modificado (lo que sea que encaje en la memoria intermedia de la tienda) alterará el tiempo que tardan tales operaciones. Y, obviamente, si alguna vez tienes contienda en un mutex que es tu peor momento. Cualquier devolución al núcleo de Linux puede durar cientos de nanosegundos, incluso si no ocurre ningún cambio de hilo. Por lo general, este es el caso en que los bloqueos atómicos tienen un rendimiento superior ya que nunca implican llamadas al núcleo: el rendimiento promedio de su caso también es el peor de los casos. El desbloqueo de Mutex también incurre en una sobrecarga si hay hilos en espera, mientras que un atómico no.
NOTA: Hacer tales mediciones está plagada de problemas, por lo que los resultados siempre son un poco cuestionables. Mis pruebas intentan minimizar la variación fijando la velocidad de la CPU, estableciendo la afinidad de la CPU por los hilos, ejecutando ningún otro proceso y promediando grandes conjuntos de resultados.
¡Gracias por los números! ¿Qué plataforma has probado? decir "pthread mutex" no dice mucho, ya que eso depende completamente de la implementación. Como el tiempo está cerca de un complemento atómico, asumo que es GNU/Linux, ¿entonces usando un futex? –
Sí, en Linux. No impugnado significa que no toca una llamada al sistema, por lo que el futex no está involucrado en ese caso (no impugnado en la biblioteca NPTL se resuelve por completo en el espacio de usuario sin llamada al sistema). –
En mi opinión, "futex" es el número entero, por lo que está involucrado, pero todo lo que se necesita es un incremento atómico de "futex" (es decir, el número entero) –
- 1. ¿Qué tan rápido es Data.Array?
- 2. ¿Qué tan rápido es LINQ?
- 3. Python: ¿qué tan rápido?
- 4. ¿Por qué es tan rápido Chrome?
- 5. ¿Qué tan rápido es Google App Engine?
- 6. ¿Qué tan caro es el estado de bloqueo?
- 7. Por qué `(map digitToInt). show` es tan rápido?
- 8. ¿Qué tan rápido debe ser un lenguaje interpretado hoy?
- 9. ¿Cómo es un DB basado en documentos tan rápido?
- 10. es Queue.Synchronized más rápido que usar un bloqueo()?
- 11. C: ¿Por qué un fprintf (stdout, ....) es tan lento?
- 12. ¿Qué tan rápido es un método de registro de log4net (depuración, información, etc.)?
- 13. ¿Cómo funciona grep tan rápido?
- 14. ¿Qué tan caro es lanzar un objeto?
- 15. ¿Qué tan seguro es un HTTP POST?
- 16. ¿Cómo es Array.Sort en C# tan súper rápido?
- 17. ¿Qué tan rápido son los nodos EC/2 entre ellos?
- 18. ¿Qué hace que VxWorks sea tan determinista y rápido?
- 19. ¿Qué hace que ApplePC memcpy sea tan rápido?
- 20. ¿Cómo es la búsqueda de Amazon Faceted tan rápido?
- 21. ¿El estilo de Java Groovy es tan rápido como Java?
- 22. ¿Qué tan estable es NSubstitute?
- 23. ¿Qué tan seguro es PHP?
- 24. ¿Qué tan confiable es HTTP_HOST?
- 25. ¿Qué tan único es XAML?
- 26. ¿Qué tan escalable es System.Threading.Timer?
- 27. ¿Qué tan caro es Thread.getStackTrace()?
- 28. ¿Qué tan bueno es VTK?
- 29. ¿Qué tan escalable es ZeroMQ?
- 30. ¿Qué tan confiable es HtmlUnitDriver?
posible duplicado de [Gastos generales de uso de bloqueos en lugar de intrínsecos atómicos] (http://stackoverflow.com/questions/4296876/overhead-of-using-locks-instead-of-atomic-intrinsics) –
@KonradRudolph, I mira que las preguntas son similares pero no exactamente iguales. Éste está más enfocado en los costos fundamentales de las operaciones mientras que el otro es el costo general de dos enfoques para un algoritmo. En realidad, les respondería de manera algo diferente. –
@ edA-qamort-ora-y Como autor de la otra pregunta, puedo afirmar que son lo mismo. La otra pregunta puede ser enunciado * * diferente (en términos de gastos generales), pero lo que en realidad estaba preguntando es “¿Cuánto más rápido que un bloqueo es una operación atómica?” –