2012-01-06 20 views
9

Tengo una memoria compartida entre procesos múltiples que interpenetra la memoria de cierta manera. Ex:Acceso atómico a la memoria compartida

DataBlock { 
int counter; 
double value1; 
double ... } 

Lo que quiero es que el contador se actualizará/incrementa de forma atómica. Y para que ocurra un lanzamiento de memoria en esa dirección. Si yo interrumpía el uso de memoria compartida, por ejemplo, sería algo así como

std::atomic<int> counter; 
atomic_store(counter, newvalue, std::memory_order_release); // perform release  operation on the affected memory location making the write visible to other threads 

¿Cómo logro esto para una ubicación de memoria aleatoria (interpretado como DataBlock contador> arriba). Puedo garantizar que la dirección esté alineada según lo requerido por la arquitectura (x86 linux)

  1. Haga la actualización atomic - ¿cómo? (es decir, atomicupdate (addr, newvalue))
  2. Sincronización de memoria para multinúcleo - (es decir, memorysync (addr)) - la única forma que puedo ver es usar std :: atomic_thread_fence (std :: memory_order_release) - pero esto "establecerá la memoria orden de sincronización de TODAS las tiendas atómicas y relajadas "- eso es exagerado para mí - Solo quiero que la ubicación del contador esté sincronizada. Aprecie cualquier pensamiento.
+3

Solo estoy especulando, pero tengo la impresión de que el modelo de programación C++ no tiene noción de "procesos" y el modelo de memoria no tiene noción de "memoria compartida", por lo que dudo que el estándar en sí cualquier garantia La memoria compartida es en gran medida una función dependiente de la plataforma, por lo tanto, consulte la documentación de su plataforma. –

+0

¿puedes poner un 'atomic ' en tu DataBlock? Eso debería funcionar siempre que 'atomic ' no esté bloqueado (el estándar explícito menciona memoria compartida entre procesos como un caso de uso para esos). Y no, no se puede simplemente obtener un atómico para una dirección aleatoria (ver http://stackoverflow.com/questions/8749038/how-to-use-stdatomic-efficiently/8749474) @Kerrek SB: en realidad ese escenario se menciona en [atomics.lockfree] en el borrador final. – Grizzly

+0

@Grizzly: ¿Te refieres a la nota no normativa 29.4/3? Muy interesante, no lo sabía. –

Respuesta

-2

puede utilizar el bloqueo & mecanismo Espere a incrementar el contador. Boost Library proporciona un mecanismo de bloqueo y espera. consulte este enlace para reference

9

No puedo responder con autoridad aquí, pero puedo brindar información relacionada que podría ayudar.

  1. Los mutexes se pueden crear en la memoria compartida y/o crearse para ser procesos cruzados. Pthread tiene un indicador de creación especial, no recuerdo si utiliza memoria compartida o si comparte un identificador. El Linux "futex" puede usar memoria compartida directamente (tenga en cuenta que la dirección del usuario puede ser diferente, pero la dirección real subyacente debe ser la misma)

  2. El hardware atómico funciona en la memoria y no en las variables de proceso. Es decir, a su chip no le importará qué programas están modificando las variables, por lo tanto, el átomo de menor nivel será, naturalmente, un proceso cruzado. Lo mismo se aplica a las vallas.

  3. C++ 11 no especifica los átomos atómicos entre procesos. Sin embargo, si están libres de bloqueo (verifique el indicador) es difícil ver cómo un compilador podría implementarlos de modo que el proceso cruzado no funcionaría. Pero estarías poniendo mucha fe en tu cadena de herramientas y plataforma final.

  4. Las dependencias de CPU también hacen un seguimiento de las direcciones de memoria reales, por lo tanto, siempre que su programa sea correcto en una forma enhebrada, también debería ser correcto en su forma multiproceso (con respecto a la visibilidad).

  5. Kerrek es correcta, la máquina abstracta en realidad no menciona múltiples procesos. Sin embargo, sus detalles de sincronización están escritos de tal manera que se aplicarían igualmente a interprocesos como lo hacen a multi-hilo. Esto se relaciona con el # 3: sería difícil para un compilador arruinar esto.

Respuesta corta, no hay una forma que cumpla con los estándares para hacer esto. Sin embargo, apoyándose en la forma en que el estándar define mutli-threads, hay muchas suposiciones que puede hacer para un compilador de calidad.

La pregunta más importante es si un atómico se puede asignar simplemente en la memoria compartida (colocación nueva) y el trabajo. Obviamente, esto solo funcionaría si se tratara de un verdadero hardware atómico. Sin embargo, creo que con un compilador/biblioteca de calidad, los átomos de C++ deberían funcionar en la memoria compartida.

Diviértete comprobando el comportamiento. :)

4

Ya que estás en Linux, puede utilizar el, no es una operación de liberación incorporado __sync_fetch_and_add() en la dirección de counter ... según el gcc-documentation on atomic built-ins, esto también va a poner en práctica una valla de memoria llena atómica gcc, pero dado que en realidad quiere una operación de lectura-modificación-escritura en lugar de simplemente una carga (es decir, incrementar un contador no es solo una carga, sino que tiene que leer, luego modificar y finalmente recuperar el valor), el completo la valla de memoria va a ser una mejor opción para imponer la ordenación correcta de la memoria para esta operación.

+0

'__sync_fetch_and_add()' se puede usar, pero creo que '__sync_sub_and_fetch()' es más adecuado. Disminuye el recuento de referencia y lo libera si baja a cero. Se garantiza que si dos subprocesos disminuyen simultáneamente de 2, solo uno tendrá 0 devuelto (y se liberará). – ugoren

+0

Eso es definitivamente una buena sugerencia también ... un atómico incorporado se usaría para incrementar durante las copias, etc., y otro para disminuir el valor cuando la referencia ya no se use. – Jason

Cuestiones relacionadas