Pregunta C # primera clase de continuación a través de la interoperabilidad de C ++ o de alguna otra manera?


Tenemos una aplicación C # muy cercana a la realización de tareas en tiempo real, de muy alto rendimiento. Este rendimiento se logró principalmente mediante la implementación de multitarea cooperativa en la empresa con un planificador de cosecha propia. Esto a menudo se llama microhilos. En este sistema, todas las tareas se comunican con otras tareas a través de colas.

El problema específico que tenemos parece que solo se puede resolver a través de continuaciones de primera clase que C # no admite.

Específicamente, el problema surge en 2 casos relacionados con colas. Cada vez que una tarea en particular realiza algún trabajo antes de colocar un elemento en una cola. ¿Qué pasa si la cola está llena?

Por el contrario, una tarea diferente puede hacer algún trabajo y luego tener que sacar un elemento de una cola. ¿Qué pasa si esa cola está vacía?

Hemos resuelto esto en el 90% de los casos al vincular las colas con las tareas para evitar que se invoquen las tareas si alguna de sus colas de salida está llena o si la cola de entrada está vacía.

Además, ciertas tareas se convirtieron en máquinas de estado para que puedan manejarlas si una cola está llena / vacía y continuar sin esperar.

El problema real surge en algunos casos extremos donde no es práctico hacer cualquiera de esas soluciones. La idea en ese escenario sería guardar el estado de la pila en el punto y cambiar a una tarea diferente para que pueda hacer el trabajo y luego volver a intentar la tarea de espera cada vez que pueda continuar.

En el pasado, intentamos hacer que la llamada a la espera volviera a llamar al cronograma (recursivamente) para permitir que las otras tareas volvieran a intentar la tarea en espera. Sin embargo, eso condujo a demasiadas situaciones de "punto muerto".

Hubo un ejemplo en alguna parte de un host CLR personalizado para hacer que los subprocesos .NET realmente operen como "fibras", lo que esencialmente permite cambiar el estado de pila entre subprocesos. Pero ahora parece que no puedo encontrar ningún código de muestra para eso. Además, parece que tomará una gran complejidad para hacerlo bien.

¿Alguien tiene otras ideas creativas sobre cómo cambiar entre las tareas de manera eficiente y evitar los problemas anteriores?

¿Hay otros hosts CLR que ofrecen esto, comercial o de otro tipo? ¿Hay alguna biblioteca nativa complementaria que pueda ofrecer alguna forma de continuación para C #?


32
2017-12-31 02:05


origen


Respuestas:


Ahí está el C # 5 CTP, que realiza una transformación de continuación-paso-estilo sobre los métodos declarados con el nuevo async palabra clave y llamadas basadas en el paso de continuación cuando se usa await palabra clave.

Esta no es realmente una nueva característica de CLR, sino más bien un conjunto de directivas para que el compilador realice la transformación de CPS sobre su código y un puñado de rutinas de biblioteca para manipular y programar las continuidades. Registros de activación para async los métodos se colocan en el montón en lugar de la pila, por lo que no están vinculados a un hilo específico.


2
2018-02-15 12:40



No, no voy a trabajar. C # (e incluso IL) es un lenguaje demasiado complejo para realizar tales transformaciones (CPS) de una manera general. Lo mejor que puedes obtener es lo que C # 5 ofrecerá. Dicho esto, es probable que no pueda romper / reanudar con bucles / iteraciones de orden superior, lo cual es realmente lo que quiere de continuaciones de propósito general confirmables.


1
2018-02-15 12:45



El modo de fibra se eliminó de v2 del CLR debido a problemas bajo tensión, ver:

Que yo sepa, el soporte de la fibra aún no se ha vuelto a agregar, aunque después de leer los artículos anteriores, mayo ser agregado nuevamente (sin embargo, el hecho de que nada haya mencionado durante 6-7 años sobre el tema me hace creer que es poco probable).

El soporte de fibra FYI estaba destinado a ser una forma para que las aplicaciones existentes que usan fibras (como SQL Server) alojen el CLR de una manera que les permita maximizar el rendimiento. no como un método para permitir que las aplicaciones .Net creen hundereds de hilos - en pocas palabras, las fibras no son una solución mágica para su problemaSin embargo, si tiene una aplicación que utiliza fibras y desea alojar el CLR, las API de alojamiento administradas proporcionan los medios para que el CLR "funcione bien" con su aplicación. Una buena fuente de información sobre esto sería la documentación de la API de hosting gestionado, o para ver cómo SQL Server aloja el CLR, del cual hay varios artículos altamente informativos a su alrededor.

También tome una lectura rápida de Hilos, fibras, pilas y espacio de direcciones.


1
2018-02-15 13:24



En realidad, decidimos una dirección para ir con esto. Estamos usando el patrón Observer con Message Passsing. Creamos una biblioteca propia para manejar todas las comunicaciones entre "Agentes" que son similares a un proceso de Erlang. Más adelante consideraremos el uso de AppDomains para separar aún más a los Agentes entre sí. Las ideas de diseño se tomaron prestadas del lenguaje de programación Erlang, que tiene un procesamiento multinúcleo y distribuido extremadamente confiable.


1
2018-02-15 15:08



La solución a su problema es usar algoritmos sin bloqueo que permitan el progreso de todo el sistema de al menos una tarea. Necesita utilizar un ensamblador en línea que dependa de la CPU para asegurarse de que tiene CAS atómico (compare-y-swap). Wikipedia tiene un artículo así como los patrones descritos el libro por Douglas Schmidt llamado "Arquitectura de software orientada a patrones, patrones para objetos concurrentes y en red". No me queda claro de inmediato cómo lo hará en el marco de las redes.

Otra forma de resolver su problema es utilizar el patrón publicar-suscriptor o posibles grupos de hilos.

Espero que esto haya sido útil?


0
2018-01-31 21:22