2012-01-06 12 views
5

Tarea como encontrar factorial de 2000 donde el uso de BigInteger es una tarea intensiva de la CPU, ¿hay alguna manera de acelerar tales procesos?¿Podemos acelerar las tareas intensivas de CPU en Java?

Ex: finding 2000! Como solo es una tarea única, creo que aquí no hay necesidad de hilo (ya que ejecutar este programa o ejecutar esta tarea en un hilo ambos tienen que realizar cosas de uso intensivo de CPU).

He oído que Java 7 introdujo un nuevo mecanismo paralelo para tareas de cálculo intensivo. Entonces, ¿cómo realizo este tipo de cosas?

+2

un tutorial para el nuevo mecanismo paralelo: http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html – Luciano

+2

Antes que nada: no use BigInteger para multiplicar números grandes. Está utilizando un algoritmo de multiplicación ingenuo que es O (n^2) en lugar de karatsuba, que sería O (n log n). – Voo

+1

@Voo Corrección objetiva minúscula: Karatsuba es 'O (n^1.585)'. FFT es el que se acerca a 'O (n log n)'. – Mysticial

Respuesta

12

Un factorial se puede dividir fácilmente en dos tareas con una fusión final. Este es un tipo de mapa, reduce, si quieres.

Ejemplo:

9! = (7*5*3*1) * (8*6*4*2) 

para que pueda tener dos tareas.

Esto se puede generalizar en cualquier cantidad de tareas paralelas.

Esta solución no tiene nada que ver con Java en específico, se trata de convertir soluciones "normales" a soluciones paralelas.

+0

Esto tiene la ventaja adicional de que estamos multiplicando números mucho más pequeños para la mayor parte del tiempo, que es MUCHO más rápido, incluso si no se paraleliza. Buena idea para dividir las tareas secuenciales dadas a cada CPU más utilizando la misma idea. – Voo

2

Es posible simplemente enviar una consulta a WolframAlpha, y volver una respuesta aproximada dentro de una fracción de segundo (at least for 2,000!, o incluso 10,000,000,000!), que, si sólo se necesita una aproximación para grandes factoriales, es probable que haya más más que suficiente

Aquí hay un artículo de wikipedia sobre el challenges around calculating large factorials, algunos de los cuales ya ha descubierto.

Lo que realmente querrás hacer es intentar reducir la cantidad total de trabajo que hay que hacer. La forma más sencilla de hacerlo es almacenar los resultados en una tabla y hacer una búsqueda. La tabla que contiene todos estos valores puede ser bastante grande, pero ese es un método si el almacenamiento no es una limitación en su situación.

Simplemente tratando de paralelizarlo no le ahorrará en la CPU (a menos que esté calculando una aproximación, a diferencia del número exacto), porque está haciendo la misma cantidad de trabajo total, pero extendiéndolo. Además, paralelizar cualquier cosa implica un poco de sobrecarga (comunicación entre hilos/entre procesos, memoria distribuida si el espacio problemático es lo suficientemente grande, todo tipo de cosas). Los lugares en los que la paralelización de cualquier algoritmo es una gran victoria, es cuando se puede dividir con éxito el problema en partes más pequeñas, y se extendió a cabo esos trozos lo suficientemente eficiente para que el tiempo para ...

  • enviar los trozos a cabo a cabo
  • han calculado los trozos
  • enviar los resultados de vuelta
  • combinar los resultados

... es menos costoso (como se mide en el tiempo, el dinero, el almacenamiento, la electricidad, o lo que su limitado recurso) que hacerlo en serie, y/o que proporciona algún valor (tiempo, dinero, almacenamiento, etc. guardado) para compensar el costo.

Cuestiones relacionadas