threading thread net for book c# .net parallel-processing interlocked atomicity

thread - C#fundamentalmente no portátil?



multithreading c# (5)

He estado usando C # por un tiempo, y recientemente comencé a trabajar para agregar paralelismo a un proyecto paralelo mío. Entonces, de acuerdo con Microsoft, lee y escribe a los enteros e incluso las carrozas son atómicas

Estoy seguro de que estos requisitos de atomicidad funcionan bien en las arquitecturas x86. Sin embargo, en arquitecturas como ARM (que pueden no tener soporte de coma flotante de hardware), parece que estas garantías serán difíciles.

El problema solo se vuelve más significativo por el hecho de que un ''int'' siempre es de 32 bits. Hay muchos dispositivos integrados que no pueden realizar atómicamente una escritura de 32 bits.

Parece que este es un error fundamental en C #. Garantizar la atomicidad de estos tipos de datos no se puede hacer de forma portátil.

¿Cómo se pretende implementar estas garantías de atomicidad en arquitecturas donde no hay FPU ni escrituras de 32 bits?


El futuro sucedió ayer, C # de hecho se transfiere a una gran cantidad de núcleos incrustados. .NET Micro Framework es el escenario típico de implementación. Los números de modelo que veo enumerados como objetivos nativos son AT91, BF537, CortexM3, LPC22XX, LPC24XX, MC9328, PXA271 y SH2.

No sé los detalles de implementación exactos de su conjunto de instrucciones básicas, pero estoy bastante seguro de que estos son todos los núcleos de 32 bits y varios de ellos son núcleos ARM. Escribir código enhebrado para ellos requiere una garantía mínima y las actualizaciones atómicas para palabras correctamente alineadas es una de ellas. Dada la lista de compatibilidad y que las actualizaciones atómicas de 4 bytes para palabras alineadas son triviales para implementar en hardware de 32 bits, confío en que todos de hecho lo admiten.


Hay dos cuestiones con respecto a la "portabilidad":

  1. ¿Se puede producir una implementación práctica de un idioma para varias plataformas?
  2. Se espera que un programa escrito en un idioma se ejecute correctamente en varias plataformas sin modificación

Cuanto más sólidas sean las garantías de un idioma, más difícil será llevarlo a varias plataformas (algunas garantías pueden hacer imposible o impráctico implementar el lenguaje en algunas plataformas), pero es más probable que los programas escritos en el idioma trabajar sin modificaciones en cualquier plataforma para la que exista soporte.

Por ejemplo, una gran cantidad de código de red se basa en el hecho de que (en la mayoría de las plataformas) un carácter sin signo es de ocho bits, y un entero de 32 bits está representado por cuatro caracteres sin signo en orden ascendente o descendente. He usado una plataforma donde char era de 16 bits, sizeof (int) == 1 y sizeof (long) == 2. El autor del compilador podría haber hecho que el compilador simplemente utilizara los 8 bits inferiores de cada dirección, o podría haber agregado una gran cantidad de código adicional para que escribir un puntero ''char'' desplazara la dirección un bit correcto (guardando el lsb), lea el dirección, actualice la mitad alta o baja según la dirección guardada lsb y escríbala de nuevo. Cualquiera de estos enfoques habría permitido que el código de red se ejecutara sin modificaciones, pero hubiera impedido en gran medida la utilidad del compilador para otros fines.

Algunas de las garantías en el CLR significan que no es práctico implementarlo en cualquier plataforma con un tamaño de operación atómica menor a 32 bits. ¿Y qué? Si un microcontrolador necesita más de unas pocas docenas de Kbytes de espacio de código y RAM, la diferencia de costo entre 8 bits y 32 bits es bastante pequeña. Como nadie va a ejecutar ninguna variación del CLR en una parte con 32K de espacio de código y 4K de RAM, a quién le importa si un chip así podría satisfacer sus garantías.

Por cierto, creo que sería útil tener diferentes niveles de características definidas en una especificación C; muchos procesadores, por ejemplo, tienen caracteres de 8 bits que se pueden ensamblar en palabras más largas usando uniones, y hay muchos códigos prácticos que explotan esto. Sería bueno definir estándares para los compiladores que funcionan con tales cosas. También me gustaría ver más estándares en el extremo inferior del sistema, haciendo que algunas mejoras de idiomas estén disponibles para los procesadores de 8 bits. Por ejemplo, sería útil definir sobrecargas para una función que puede tomar un entero de 16 bits calculado en tiempo de ejecución, una variable de 8 bits o una versión expandida en línea con una constante. Para funciones de uso frecuente, puede haber una gran diferencia en la eficiencia entre ellas.


Las garantías de debilitamiento excesivo en aras de la portabilidad frustran el propósito de la portabilidad. Cuanto más fuertes son las garantías, más valiosa es la portabilidad. El objetivo es encontrar el equilibrio correcto entre lo que las plataformas objetivo probables pueden apoyar de manera eficiente con las garantías que serán más útiles para el desarrollo.


No es demasiado difícil garantizar la atomicidad con verificaciones en tiempo de ejecución. Claro, no será tan eficiente como lo sería si su plataforma soportara lecturas y escrituras atómicas, pero eso es una compensación de plataforma.

En pocas palabras: C # (el lenguaje principal, sin contar algunas API específicas de la plataforma) es tan portátil como Java.


Para eso está CLI. Dudo que certifiquen una implementación si no es compatible. Básicamente, C # es portátil para cualquier plataforma que tenga una.