2010-05-25 7 views
7

Duplicar posible:
Functional programming and multicore architecture¿Por qué los lenguajes funcionales son una bendición para los entornos de múltiples hilos?

escucho mucho acerca de los lenguajes funcionales, y cómo se adapta bien porque no hay un estado en torno a una función; y, por lo tanto, esa función puede ser masivamente paralelizada.

Sin embargo, esto tiene poco sentido para mí porque casi todos los programas prácticos del mundo real necesitan/tienen que ocuparse del estado. También me parece interesante que la mayoría de las principales bibliotecas de escalamiento, es decir, MapReduce, están escritas típicamente en lenguajes imperativos como C o C++.

me gustaría escuchar desde el campo funcional en este bombo que estoy oyendo está viniendo ....

+0

@James: Gracias. Se agregó una h adicional. –

+0

Me atrevo a aventurar que las bibliotecas de escalamiento no están escritas en C/C++ porque se adapta bien al problema ... sino que es posible escribir un código de mayor rendimiento. – spender

+2

@spender: Estoy de acuerdo en que es una especie de duplicado. Sin embargo, todas las respuestas a esa pregunta básicamente dicen "bueno, es porque en los programas funcionales no tienes un estado mutable". Esta pregunta es: "¿cómo conciliar la inmutabilidad con el modelado de problemas del mundo real, que generalmente requiere al menos algún estado mutable" (vale, eso no está explícitamente en esta pregunta, pero creo que eso es lo que implica la forma en que es redactado, podría estar equivocado). No creo que ninguna de las respuestas a la otra pregunta responda satisfactoriamente. –

Respuesta

9

Es importante agregar una palabra: "no hay estado compartido".

Cualquier programa significativo (en cualquier idioma) cambia el estado del mundo. Pero (algunos) los lenguajes funcionales hacen que sea imposible acceder al mismo recurso desde múltiples hilos simultáneamente. La ausencia de estado compartido hace que el multihilo sea seguro.

+0

+1 - primera respuesta aquí que aborda la raíz de mi acertijo. –

6

Los lenguajes funcionales como Haskell, Scheme y otros tienen lo que se denomina "funciones puras". Una función pura es una función sin efectos secundarios. No modifica ningún otro estado en el programa. Esto es por definición threadsafe.

Por supuesto, puede escribir funciones puras en idiomas imperativos. También encontrará lenguajes multi-paradigma como Python, Ruby e incluso C# donde puede hacer una programación imperativa, programación funcional o ambas cosas.

Pero el punto de Haskell (etc.) es que no se puede escribir una función no pura. Bueno, eso no es estrictamente cierto, pero es mayormente cierto.

De manera similar, muchos idiomas imperativos tienen objetos inmutables por la misma razón. Un objeto inmutable es aquel cuyo estado no cambia una vez creado. De nuevo, por definición, un objeto inmutable es threadsafe.

+0

Sí, pero también podrías hacerlo con idiomas imperativos ... de ahí mi confusión. No es como el análisis estático para tal cosa es difícil. –

4

Estás hablando de dos cosas diferentes y no te das cuenta.

Sí, la mayoría de los programas del mundo real han estado en algún lugar , pero si usted quiere hacer multihilo, ese estado no debería ser todas partes, y de hecho, el menor número de lugares que se encuentra, el mejor. En los programas funcionales, el valor predeterminado es no tener estado, y puede introducir el estado exactamente donde lo necesita y en ningún otro lugar. Esas partes que están tratando con el estado no serán tan fácilmente multiproceso, pero como todo el resto de su programa está libre de efectos secundarios y por lo tanto no importa en qué orden se ejecuten esas partes, elimina una gran barrera para la paralelización. .

+0

¿Entonces está diciendo que se trata más de un estilo de programación que de un lenguaje en sí mismo? –

+1

@Billy ONeal: es mucho más que solo el estilo de programación. FP voltea el modelo de programación. De manera imperativa, la mayoría de las cosas son mutables por defecto y debes hacer un esfuerzo extra para evitar la mutación. En FP, la mayoría de las cosas son inmutables por defecto y hay que hacer un esfuerzo para hacer algo mutable. Es un cambio de 180 grados en el pensamiento y el enfoque. –

+0

@Billy ONeal: en gran medida, se trata de un estilo de programación, pero un lenguaje puede afectar realmente a su estilo de programación. El beneficio de los lenguajes funcionales es que soportan muy bien este estilo de programación. Las cosas que son naturales en los lenguajes funcionales son más torpes en los lenguajes imperativos, y viceversa. También hay algunos beneficios adicionales para los lenguajes funcionales que se ramifican a partir de esto, como el STM que es extremadamente fácil cuando ciertas partes de su programa * están garantizadas * y no tienen efectos secundarios. – Chuck

1

Funciones de orden superior. Considere una operación de reducción simple, sumando los elementos de una matriz. En un lenguaje imperativo, los programadores suelen escribirse a sí mismos un ciclo y realizar reducciones de un elemento a la vez.

Pero ese código no es fácil de hacer multi-threaded. Cuando escribes un ciclo, estás asumiendo un orden de operaciones y tienes que deletrear cómo pasar de un elemento al siguiente. Te gustaría decir "suma la matriz" y hacer que el compilador, el tiempo de ejecución o lo que sea, tome la decisión sobre cómo trabajar a través de la matriz, dividir la tarea según sea necesario entre múltiples núcleos y combinar esos resultados . Entonces, en lugar de escribir un bucle, con algún código de adición incrustado dentro de él, una alternativa es pasar algo que representa "adición" en una función que puede hacer la división. Tan pronto como hagas eso, estarás escribiendo funcionalmente. Está pasando una función (adición) a otra función (el reductor).Si escribe de esta manera, no solo obtiene un código más legible, sino que cuando cambia la arquitectura o desea escribir para una arquitectura heterogénea, no tiene que cambiar el verano, solo el reductor. En la práctica, es posible que tenga muchos algoritmos diferentes que todos comparten un reductor, por lo que este es un gran beneficio.

Esto es solo un ejemplo simple. Es posible que desee construir sobre esto. Funciones para aplicar otras funciones en matrices 2D, funciones para aplicar funciones a estructuras de árbol, funciones para combinar funciones para aplicar funciones (por ejemplo, si tiene una estructura jerárquica con árboles arriba y matrices a continuación) y así sucesivamente.

+0

Sí, entiendo eso. Pero también hay muchas formas de manejar este problema en lenguajes imperativos, es decir, grupos de hilos. Sí, está escribiendo funcionalidad, pero no veo cómo eso es diferente en los lenguajes funcionales que no sean "alguien que ya me escribió ese tipo de funcionalidad en particular" –

+1

No, esto es completamente ortogonal a los grupos de subprocesos. No estoy hablando del código para administrar los hilos, sino la interfaz. La forma de iniciar una operación 'reduce' es pasarle una función como argumento. Esa es una programación funcional. MapReduce es funcional. Toma dos argumentos, una función de mapa y una función de reducción. Las funciones que actúan sobre funciones se llaman funciones de orden superior. De esto se trata la programación funcional. – sigfpe

3

Sin embargo, esto tiene poco sentido para mí porque casi todos los programas prácticos del mundo real necesitan/tienen que encargarse del estado.

¡Estaría sorprendido! Sí, todos los programas necesitan algún estado (E/S en particular) pero a menudo no necesitas mucho más. El hecho de que la mayoría de los programas tengan montones de estados no significa que necesite.

La programación en un lenguaje funcional lo alienta a usar menos estado, y por lo tanto, sus programas se vuelven más fáciles de paralelizar.

Muchos lenguajes funcionales son "impuros", lo que significa que permiten estado. Haskell no, pero Haskell tiene mónadas que básicamente te permiten obtener algo de la nada: obtienes estado usando construcciones sin estado. Las mónadas son un poco complicadas de trabajar, por lo que Haskell te da un fuerte incentivo para restringir el estado a una parte tan pequeña de tu programa como sea posible.

también me parece interesante que la mayoría de las bibliotecas de escala importantes, es decir, MapReduce, son típicamente escritos en lenguajes imperativos como C o C++.

La programación de aplicaciones simultáneas es "difícil" en C/C++. Es por eso que es mejor hacer todas las cosas peligrosas en una biblioteca que está fuertemente probada e inspeccionada. Pero todavía obtienes la flexibilidad y el rendimiento de C/C++.

+0

Estoy pensando en cosas como http://en.wikipedia.org/wiki/Dijkstra's_algorithm. Digamos que quiero escribir una aplicación masivamente paralela para encontrar la forma más rápida de mapear a alguien desde el punto A hasta el punto B. El algoritmo de Dijkstra se basa en una cola. Mientras que en Theroy puedes paralelizar algunos bits del algoritmo, aún existe la pieza de estado (una cola) que se comparte y se requiere para que el algoritmo funcione. Tal es el caso de cada algoritmo de programación dinámica, y tales algoritmos son necesarios para hacer que algunas cosas sean eficientes. –

+1

Ciertamente, los lenguajes funcionales no son una bala de cristal. Algunas veces la respuesta es usar un algoritmo que sea nominalmente menos eficiente, pero más fácil de paralelar (por ejemplo, un algoritmo que pueda expresarse fácilmente en un lenguaje funcional), lo que le permitirá resolver un problema más rápido. Otras veces tiene que construir las cosas simultáneas manualmente [en C/C++/lo que sea]. Pero puede ser una buena estrategia usar lenguajes funcionales siempre que sea posible y recurrir a otras opciones cuando sea necesario. – Artelius

Cuestiones relacionadas