son compiladores como Javac lo suficientemente inteligentes como para detectar cuándo un método es una función pura.
No se trata de "lo suficientemente inteligente". Esto se llama análisis de pureza y es demostrablemente imposible en el caso general: es equivalente a resolver el problema de detención.
Ahora, por supuesto, los optimizadores hacen cosas demostrablemente imposibles todo el tiempo, "demostrablemente imposibles en el caso general" no significa que nunca funcione, solo significa que no puede funcionar en todos los casos. Entonces, de hecho, existen algoritmos para verificar si una función es pura o no, es solo que la mayoría de las veces el resultado será "No sé", lo que significa que, por razones de seguridad y corrección, debe asumir que esta función particular podría ser impura.
E incluso en los casos en que se hace el trabajo, los algoritmos son complejos y costosos.
Entonces, ese es el problema # 1: solo funciona para casos especiales .
Problema # 2: Bibliotecas . Para que una función sea pura, solo puede llamar funciones puras (y esas funciones solo pueden llamar funciones puras, y así sucesivamente). Javac obviamente solo sabe sobre Java, y solo sabe sobre el código que puede ver. Entonces, si su función llama a una función en otra unidad de compilación, no puede saber si es pura o no. Si llama a una función escrita en otro idioma, no puede saberlo. Si llama a una función en una biblioteca que aún podría no estar instalada, no puede saberlo. Y así.
Esto solo funciona cuando tiene un análisis de todo el programa, cuando todo el programa está escrito en el mismo idioma y todo se compila de una vez. No puedes usar ninguna biblioteca.
Problema # 3: programación . Una vez que haya descubierto qué partes son puras, todavía tiene que programarlas para separar los hilos. O no. Iniciar y detener subprocesos es muy costoso (especialmente en Java). Incluso si mantiene un grupo de subprocesos y no los inicia o detiene, el cambio de contexto de subprocesos también es costoso. Debe asegurarse de que el cálculo se ejecutará significativamente más tiempo que el tiempo que lleva programar y cambiar de contexto, de lo contrario perderá rendimiento, no lo ganará.
Como probablemente ya haya adivinado, averiguar cuánto tiempo llevará un cálculo es imposible en el caso general (ni siquiera podemos determinar si tomará una cantidad de tiempo finita, y mucho menos cuánto tiempo) y difícil y costoso incluso en El caso especial.
Aparte: Javac y optimizaciones . Tenga en cuenta que la mayoría de las implementaciones de javac en realidad no realizan muchas optimizaciones. La implementación de javac de Oracle, por ejemplo, se basa en el motor de ejecución subyacente para realizar optimizaciones . Esto lleva a otro conjunto de problemas: digamos, javac decidió que una función particular es pura y es lo suficientemente costosa, por lo que la compila para que se ejecute en un hilo diferente. Luego, aparece el optimizador de la plataforma (por ejemplo, el compilador HotSpot C2 JIT) y optimiza toda la función. Ahora, tienes un hilo vacío que no hace nada. O, imagine, nuevamente, javac decide programar una función en un hilo diferente, y el optimizador de plataforma podría optimizarlo completamente, excepto que no puede realizar la alineación a través de los límites del hilo, por lo que ahora se ejecuta innecesariamente una función que podría optimizarse completamente.
Entonces, hacer algo como esto solo tiene sentido si tiene un único compilador que realiza la mayoría de las optimizaciones de una sola vez, para que el compilador conozca y pueda explotar todas las diferentes optimizaciones en diferentes niveles y sus interacciones entre sí.
Tenga en cuenta que, por ejemplo, el compilador JIT HotSpot C2 realidad hace realizar alguna auto-vectorización, que es también una forma de auto-paralelización.