Sie sind auf Seite 1von 17

PROGRAMACIÓN II

CÓMO MEDIR LA EFICIENCIA EN ALGORITMOS PARALELOS

Escuela Politécnica Superior de Linares


ALUMNO: Francisco Javier Bris Peñalver
2º de Ingeniería Técnica de Telecomunicación
PROFESORES: D. Francisco Charte Ojeda (T)
D. José Ramón Cano de Amo (P)
CORREO: fjbp0004@estudiante.ujaen.es
FECHA: 28 de mayo de 2011
  2  
 
Índice
 
I. Definición y fundamentación del problema 4
1. Introducción. Fundamentación. 4
2. Búsqueda de nuevos métodos de análisis. 5
II. Algoritmos paralelos 6
1. Definición. 6
2. Paralelización, división, granularidad. 6
3. Punto de saturación. Ley de Amdahl. 7
4. La importancia del coste. Tipo de memoria. 8
5. Ventajas de la computación paralela. 9
III. Medida de la eficiencia 10
1. Tiempo de ejecución de un programa paralelo. 10
2. Reducción de prestaciones. Límites. 11
3. Ganancia de velocidad. Speed-up. 11
4. Medida de la eficiencia. 12
5. Coste y distribución del trabajo. 13
6. Función de Isoeficiencia. 13
7. Aplicación práctica de conceptos. 14
IV. Bibliografía 17

  3  
 
I. Definición y fundamentación del problema

La problemática que se trata en este trabajo es cómo podemos medir la eficiencia en


algoritmos paralelos. Para ello comenzaremos definiendo el problema, argumentando
por qué los métodos ‘tradicionales’ de análisis no son válidos y dando las primeras
pinceladas a las posibles soluciones. Posteriormente, en el punto II explicaremos el
concepto de algoritmo paralelo y trataremos de exponer de la forma más concisa
posible su funcionamiento y características principales. Para terminar, el punto III
aborda la solución del problema aplicando distintas reglas y conceptos.
De forma general, la medida de la eficiencia de algoritmos nos da una información
precisa sobre la cantidad de recursos computacionales que va a consumir la ejecución
de dicho algoritmo, y a la hora de elegir entre distintos algoritmos permite que nos
decantemos por el que mejor se ajusta a nuestras necesidades o requerimientos.

De forma empírica, este consumo de recursos se medirá fundamentalmente en tiempo.


Esta forma de medición conlleva una serie de problemas, como la influencia de
factores externos (lenguaje de programación, máquina, compilador, carga del
sistema…) y la imposibilidad de ensayo para tamaños muy grandes del problema en
cierto tipo de algoritmos (algoritmos genéticos…).
Estos inconvenientes hacen necesaria la determinación matemática de su orden de
eficiencia general, de una forma completamente teórica sin necesidad de tomar en
cuenta factores como el compilador, el lenguaje, la máquina, etc… y genérica para
cualquier tamaño del problema.
La   medida   de   la   eficiencia   teórica   se   basa   en   el   Principio   de   Invarianza:   Dos  
medidas  distintas  de  un  mismo  algoritmo  no  difieren  en  eficiencia  más  que  en  una  
constante   multiplicativa,   quedándonos   con   ‘el   orden’   de   eficiencia   de   dicho  
algoritmo   (n,   n·log(n),   n!   …).   Este   método   general   de   análisis   se   denomina  
notación   asintótica,   y   cabe   destacar   que   es   ampliamente   utilizado   por   ser   una  
herramienta   matemática   que   simplifica   notablemente   los   análisis   de   costes   y  
permite  expresar,  de  una  forma  concisa,  los  resultados.  
 
En el plano de los algoritmos paralelos, el análisis de la eficiencia de éstos suscita un
gran interés ya que es más rápido tratar grandes tareas de computación mediante la
paralelización que mediante técnicas secuenciales.
Es digno de mención que, en cuanto al desarrollo de microprocesadores actuales, se
trabaja con la paralelización ya que se ha llegado a un punto en el que es más difícil
incrementar la capacidad de procesamiento de información de un procesador “mono-
núcleo” que tratar de aumentar dicha capacidad mediante la inclusión de diversas
unidades de ejecución en paralelo, consiguiendo de esta manera la ejecución de varias
líneas de instrucciones de forma simultanea. Esta demanda de mayor poder
computacional viene respaldada por las necesidades en cuanto a modelado y
simulación numérica, cálculos iterativos sobre grandes cantidades de datos y

  4  
 
algoritmos con fuertes restricciones temporales. Son sistemas cada vez más complejos
que requieren mayor tiempo de cómputo.

Búsqueda de nuevos métodos de análisis.


En el caso de el análisis de eficiencia para algoritmos paralelos la complejidad
aumenta. El análisis para programas secuenciales no es válido para algoritmos
paralelos puesto que además de los parámetros anteriormente citados que afectan a la
ejecución del algoritmo, ahora nos encontramos con nuevos factores de los que
depende la eficiencia, como el número de procesadores, la interconexión entre éstos y
el tipo de memoria que utilizan. En general se puede decir que el problema trata de
conseguir que si el orden de eficiencia para el algoritmo secuencial era de T(n), ahora,
para el algoritmo paralelizado, se reduzca a T(n)/p, donde “p” será el número de
procesadores usados por el algoritmo. Con esto tratamos de acelerar la resolución del
problema.

  5  
 
II. Algoritmos paralelos

 
Definición.  
En  informática,  cuando  hablamos  de  algoritmo  paralelo  nos  estamos  refiriendo  a  
un   algoritmo   que   puede   ser   ejecutado   por   partes,   o   de   un   modo   más   formal,   el  
tipo   de   algoritmo   en   el   que   programa,   procesador   y   puertos   de   comunicación  
interaccionan  intercambiando  tareas  a  través  de  canales  para  la  resolución  de  un  
problema.  
 

Paralelización,  división,  granularidad.  

Dada  la  definición,  instintivamente  nos  preguntamos  ¿Hasta  qué  punto  podemos  
dividir   la   tarea   en   otras   pequeñas   tareas   paralelizadas?   Para   contestar   a   esta  
pregunta,  tenemos  que  comprender  el  concepto  de  granularidad.  
La   granularidad   de   un   sistema,   entendiendo   sistema   como   la   conjunción   de  
software   (nuestro   algoritmo)   con   hardware   (nuestro   equipo   multiprocesador),  
indica   la   cantidad   de   computación   y   datos   asignados   a   cada   procesador.   La  
granularidad   está   determinada   por   el   número   y   el   tamaño   de   las   tareas   en   el   cual  
un   problema   es   descompuesto,   pudiendo   distinguir   así   entre   grano   fino   y   grano  
grueso.  

Grano  fino  corresponde  a  una  asignación  de  pocos  datos  por  procesador  o  a  una  
baja   computación   entre   comunicaciones.   Grano   grueso,   por   el   contrario,   es   la  
granularidad   que   se   da   cuando   existe   una   gran   carga   de   datos   por   cada  
procesador   o   bien   se   realiza   mucha   computación   entre   comunicaciones.   En  
cuanto   a   algoritmos,   solo   nos   interesará   la   programación   paralela   cuando   el  
sistema   sea   de   grano   grueso,   ya   que   es   preferible   una   cantidad   de   datos   a  
procesar  aceptable  con  pocos  hilos  de  proceso  que  numerosos  procesadores  con  
escasa  cantidad  de  datos  a  procesar,  con  la  información  muy  dividida.  
Algunos   algoritmos   son   más   fáciles   de   dividir   en   partes   que   otros,   así   podemos  
poner  como  ejemplo  de  un  problema  difícilmente  paralelizable  el  problema  de  los  
tres  cuerpos,  que  consiste  en  determinar,  a  partir  de  las  posiciones  y  velocidades  
de  éstos  los  resultados  de  la  interacción  de  tres  cuerpos  en  un  campo  de  fuerzas  
aislado.   Este   tipo   de   problemas   se   conoce   como   problemas   inherentemente  
secuenciales.   Otros   problemas   sin   embargo   son   fácilmente   divisibles   en  
subprocesos,  como  el  algoritmo  ray  tracing,  propuesto  por  primera  vez  en  1968,  
por   Apple  y  que  actualmente   es   una  de  las  simulaciones  más  completas  en  cuanto  
a  modelos  de  iluminación  y  reflexión  por  computadora.  

En   la   figura   2.1   podemos   ver   un   sencillo   gráfico   donde   se   muestra   la   mejora  


teórica  de  un  algoritmo  paralelizado  con  p  procesadores.  

  6  
 
!"#$%&%&'()'*$+,-%./,&'0*-*$)$,&
  Aceleración según la ley de Amdahl
ts
fts (1 - f)ts

Serial section Parallelizable sections


(a) One processor

(b) Multiple
processors

p processors

tp (1 - f)ts /p
 
Introducción a la Computación Paralela 43
figura 2.1

 
Punto  de  saturación.  Ley  de  Amdahl.  
Debemos   tener   cuidado   con   la   granularidad   de   nuestro   algoritmo.   No   podemos  
olvidar   que   por   mucho   que   lo   dividamos,   siempre   se   va   a   mantener   una   parte  
secuencial  por  lo  que  la  división  en  un  excesivo  número  de  subprogramas  puede  
llevar  a  un  punto  de  saturación,  en  el  que  el  uso  de  más  procesadores  no  induce  
mejora  alguna.    
Para  averiguar  la  mejora  máxima  del  sistema  cuando  solo  una  de  las  divisiones  de  
éste  es  mejorada  se  utiliza  la  ley  de  Amdahl:    
<<La mejora obtenida en el rendimiento de un sistema debido a la alteración de uno de sus
componentes está limitada por la fracción de tiempo que se utiliza dicho componente>>

Matemáticamente:  
Tuso mejorado
(
Tejecución mejorado = Tejecución antiguo ⋅ (1 − Tuso mejorado + ) f mejora
 

con:  

€ Tejecución antiguo
Gananciavelocidad =  
Tejecución mejorado

  7  
 
O  trasladado  a  otras  palabras,  el  incremento  de  velocidad  de  una  tarea  utilizando  
varias   unidades   de   proceso   en   computación   distribuida   (concepto   que  
introduciremos  más  adelante)  está  limitado  por  la  mínima  fracción  secuencial  de  
la   tarea,   momento   este   en   el   que   se   llega   al   punto   de   saturación   y   no   se   puede  
paralelizar  más  el  algoritmo.  

Esta  ley  nos  indica  que  dada  una  tarea  con  T  divisiones  independientes,  tendrán  
mayores  índices  de  mejora  aquellas  partes  que  contenga  más  datos,  que  necesiten  
más  tiempo  de  ejecución,  de  ahí  el  principio:    
“Siempre se debe optimizar el caso más común”

La  importancia  del  coste.  Tipo  de  memoria.  

El  coste  representa  el  trabajo  realizado  por  todo  el  sistema  para  la  resolución  del  
problema.  Como  hemos  visto,  los  algoritmos  paralelos  no  solo  tienen  un  coste  en  
términos   del   espacio   (memoria)   y   tiempo   (ciclos   de   procesador),   sino   que  
también   necesitan   optimizar   la   comunicación   entre   diferentes   unidades   de  
procesamiento.   Esto   se   consigue   mediante   la   aplicación   de   dos   técnicas  
ampliamente  extendidas,  memoria  compartida  o  paso  de  mensajes.  
En   memoria   compartida   nos   encontramos   con   un   único   espacio   de   memoria.  
Todos   los   procesadores   tienen   acceso   a   la   memoria   a   través   de   una   red   de  
conexión  que  puede  ser  un  bus,  una  red  de  barras  cruzadas  o  una  red  multietapa.  
• Redes  basadas  en  buses:  Es  simple  y  con  
buena   capacidad   de   acceso   a   memoria.  
En   contraposición,   la   cantidad   de   datos  
a   transmitir   limitada   por   el   bus,   y   el  
rendimiento   se   satura   para   un   número  
de   procesadores   bajo.   Esto   último   se  
puede   solventar   mediante   memorias  
locales   de   caché   en   los   procesadores  
(ver  figura  2.2)  
• Redes   de   barras   cruzadas:   Conecta   un    
número   determinado   de   procesadores   figura 2.2  
con    una  serie  de    módulos    de    memoria    
mediante  el  uso  de  una  red  de  conmutadores.    
• Conforme   crece   el   número   de   procesadores   la   complejidad   de   la   red  
aumenta  cuadráticamente  por  lo  que  no  son  muy  escalables.  
• Redes   de   interconexión   multietapa:   Es   un   tipo   de   red   intermedia   en  
términos  de  escalabilidad  en  costo  y  rendimiento  

La   técnica   memoria   compartida   necesita   del   uso   de   cerrojos   (latches)   en   los   datos  
para   impedir   que   un   bloque   de   información   se   modifique   simultáneamente   por  
dos   o   más   procesadores,   por   lo   que   se   produce   un   coste   extra   en   ciclos   de  
procesador.  

  8  
 
Con   memoria   distribuida   el   computador   se   convierte   básicamente   en   una  
colección  de  procesadores  secuenciales  que  trabajan  conjuntamente,  donde  cada  
procesador   tiene   su   propia   memoria   local   (ver   figura   2.3).   Se   utiliza   el   paso   de  
mensajes  para  intercambiar  datos  entre  procesadores  (acceso  a  memoria  de  otro  
procesador),  normalmente    mediante    redes    o    sistemas    de    interconexión  de    alta  

velocidad.   Independientemente   de  
esta   red,   cada   procesador   tiene  
acceso   rápido   a   su   propia   memoria.  
Los   datos   son   intercambiados   entre  
los  nodos  como  mensajes  a  través  de  
la   red,   por   lo   que   las   redes   de  
ordenadores   cobran   especial   interés  
para   la   resolución   de   problemas   con  
este  tipo  de  algoritmos  paralelos.    
La  técnica  paso  de  mensajes  añade  un  
  coste      al      bus,        que      se      traduce      en    
figura 2.3  
memoria   adicional   para   las   colas   y   los   mensajes.   A   la   hora   de   diseñar   un  
procesador   paralelo   conviene   usar   canales   especiales   para   que   el   coste   de   la  
comunicación  sea  lo  menor  posible.  
 
Ventajas    de  la  computación  paralela.  

La   principal   ventaja   de   la   programación   paralela   es   que   permite   proveer   al  


sistema  de  la  potencia  computacional  necesaria  para  tratar  y  resolver  problemas  
de   gran   envergadura   y/o   reducir   los   tiempos   de   ejecución   para   acelerar   la  
obtención  de  soluciones.    

De  una  forma  esquemática  podríamos  reducirlo  en:  


• Resolver  problemas  que  no  caben  en  una  CPU  
• Resolver  problemas  que  no  se  resuelven  en  un  tiempo  razonable  
• Se  pueden  ejecutar  problemas  mayores  
• Resolver  problemas  más  rápidamente  (con  mayor  aceleración)  

  9  
 
III. Medida de la eficiencia
 
 
Tiempo  de  ejecución  de  un  programa  paralelo.  
En   el   caso   de   un   programa   secuencial,   el   tiempo   de   ejecución   es   el   tiempo   que  
transcurre   desde   que   se   inicia   la   ejecución   hasta   que   finaliza.   En   cambio,   en   el  
caso   de   un   programa   paralelo   es   el   tiempo   transcurrido   desde   que   comienza   la  
ejecución   por   parte   del   primer   procesador   (primer   hilo   que   se   lanza)   hasta   el  
momento  en  que  el  último  procesador  finaliza  su  ejecución.  
No  siempre  va  a  ser  fácil  determinar  el  orden  en  que  los  procesadores  empiezan  y  
acaban,  ya  que  hemos  de  tener  en  cuenta  la  existencia  de  una  serie  de  puntos  de  
sincronización  a  los  que  llegan  los  distintos  procesos  en  un  orden  indefinido.  Por  
ellos,   estos   puntos   de   sincronización   en   memoria   tienen   una   duración   que   no  
siempre  podemos  determinar.  
A  priori  el  tiempo  de  ejecución  vendrá  determinado  por:  

t(n, p) = t a (n, p) + t c (n, p)  


Siendo  p  el  número  de  procesadores,  n  el  tamaño  del  problema,  Ta(n,p)  la  suma  
de   los   tiempos   de   ejecución   de   las   operaciones   en   distintas   partes   de  
computación,  también  conocido  como  tiempo  aritmético.  Tc(n,p)  será  el  tiempo  de  
comunicación,   €el   tiempo   que   tarda   el   sistema   multiprocesador   en   ejecutar  
transferencias  de  datos  
Existe   un   tiempo   de   sobrecarga,   overhead,   que   puede   ser   debido   a   la  
sincronización   de   la   máquina,   la   puesta   en   marcha   de   los   procesos   y   a   posibles  
retardos  de  la  red  de  comunicación.  También  existe  el  tiempo  de  solapamiento,  
que   se   puede   definir   como   el   intervalo   de   tiempo   en   el   que   las   operaciones  
aritméticas  y  las  de  comunicaciones  se  realizan  de  forma  simultánea.  Este  tiempo,  
aún  siendo  muy  importante,  suele  ser  muy  difícil  de  calcular.  

Por  tanto,  el  tiempo  de  ejecución  se  puede  expresar  de  una  forma  más  detallada:  
 

t(n, p) = t a (n, p) + t c (n, p) + t ov (n, p) − t sol (n, p)  


 
A  partir  de  esta  fórmula  podemos  concluir  que  se  puede  llevar  a  cabo  una  buena  
mejora  
€ de   la   eficiencia   del   algoritmo   reduciendo   al   mínimo   el   tiempo   de  
sobrecarga  y  maximizando  el  tiempo  de  solapamiento.  
 

  10  
 
Reducción  de  prestaciones.  Límites.  
• Código   secuencial:   Como   ya   hemos   comentado   en   apartados   anteriores,  
puede   haber   parte   imposible   de   paralelizar.   Un   ejemplo   puede   ser   la  
inicialización  de  variables.  
• Contención   de   memoria:   Problema   que   se   da   con   el   acceso   a   datos  
comunes  o  que  están  en  el  mismo  bloque  de  memoria.  En  el  caso  en  que  los  
datos  son  de  lectura,  normalmente  no  se  da  ese  problema.  
• Tiempo   de   creación   de   procesos:   Cuantos   más   subprocesos   se   quieran  
crear,  más  tarda  el  programa  en  ponerlos  en  marcha.  El  coste  de  creación  
de   los   procesos   puede   ser   importante   si   la   granularidad   de   éstos   es  
pequeña.  
• Comunicaciones:   Como   hemos   mencionado,   es   el   tiempo   de   transferencia  
de  datos  entre  procesadores.    
• Tiempo   de   sincronización:   Se   da   cuando   un   proceso   tiene   que   esperar   a  
que  estén  disponibles  datos  procesados  por  otro.    
• Desbalanceo   de   la   carga:   Se   define   como   la   carencia   de   una   distribución  
equitativa   del   volumen   de   computación   entre   todos   los   procesadores.  
Puede  darse  que  el  volumen  de  datos  varíe  a  lo  largo  de  la  ejecución,  lo  que  
haría  necesario  algún  tipo  de  balanceo  dinámico.  
 
Ganancia  de  velocidad.  Speed-­up.  

Fundamentalmente  el  Speed-­‐Up  es  una  técnica  de  la  que  se  obtiene  una  relación  
de  mejora  entre  el  tiempo  de  ejecución  de  un  programa  secuencial  (con  un  solo  
procesador)  y  en  paralelo  (con  p  procesadores).  Viene  definido  por  la  siguiente  
fórmula:  
t(n)
Speed-­Up:       S(n, p) =
t(n, p)  

 
A   partir   de   esta   fórmula   podemos  
€ pensar   aplicando   una   lógica   sencilla   que   el  
Speed-­‐Up   simplemente   corresponderá   con   el   número   de   procesadores   del  
algoritmo   paralelo.   Esta   afirmación   se   conoce   como   Speed-­Up   ideal   y   está  
considerada  como  una  buenísima  escalabilidad  del  algoritmo.  Sin  embargo,  en  la  
práctica   es   bastante   complicado   ya   que   conduciría   a   una   ganancia   de   velocidad  
lineal,   donde   doblando   el   número   de   procesadores   se   doblara   la   velocidad   de  
cómputo.  

  11  
 
300  

250  

200  

150   Speed-­‐Up  ideal  

100   Speed-­‐Up  real  

50  

0  
0   32   64   96   128   160   192   224   256  
 
figura 3.1  

Excepcionalmente   puede   darse   un   Speed-­‐Up   supralineal,   que   consiste  


teóricamente  en  superar  una  ganancia  de  velocidad  lineal  del  programa  paralelo  
respecto  al  secuencial.  Este  fenómeno  se  suele  dar  a  causa  de  una  mejor  gestión  
de   memoria   y   por   la   acumulación   de   memoria   caché   de   los   procesadores.  
También   es   relativamente   usual   cuando   se   implementan   algoritmos   con  
backtraking  en  paralelo.  
 

Medida  de  la  eficiencia.  Escalabilidad.    


La  eficiencia  se  define  en  un  algoritmo  paralelo  como  el  cociente  entre  el  Speed-­‐
Up   y   el   número   p   de   procesadores.   Nos   proporciona   una   idea   de   la   porción   de  
tiempo   que   los   procesadores   se   dedican   a   trabajo   útil,   también   entendido   como  
rendimiento.    
S(n, p)
E=  
p

El   valor   máximo   que   puede   alcanzar   es   uno,   que   corresponde   con   el   índice   de  
máximo   aprovechamiento,   100%.   Normalmente,   al   aumentar   el   número   de  
procesadores   el   índice  € de   eficiencia   se   aleja   del   valor   de   máximo  
aprovechamiento;   en   cambio,   para   un   número   de   procesadores   determinado,  
aumentará  conforme  aumente  el  tamaño  del  problema…  

Cuando   hablamos   de   que   en   ciertos   sistemas   las   prestaciones   se   mantienen  


cuando  aumenta  tanto  el  número  de  procesadores  como  el  tamaño  del  problema  
hablamos  de  la  escalabilidad  del  sistema.  
Conocer  si  un  sistema  es  escalable  es  muy  importante  para  saber  si  en  un  futuro,  
dado   un   hipotético   aumento   del   tamaño   del   problema   y   de   la   cantidad   de  
procesadores   se   mantendrá   la   eficiencia   del   programa.   Si   un   algoritmo   no   es  
escalable,   aunque   se   aumente   el   número   de   procesadores,   no   se   conseguirá  
mantener   la   eficiencia   aunque   se   aumente   a   la   vez   el   tamaño   del   problema,   con   lo  
que  cada  vez  se  aprovechará  menos  la  potencia  de  los  procesadores.  

  12  
 
 
Distribución  del  trabajo.  Mapeo  y  equilibrado  de  carga.  

El   mapeo   es   el   proceso   por   el   cual   decidimos   asignar   tareas   a   procesadores.   El  


objetivo  es  obtener  un  programa  que  se  ejecute  de  la  forma  más  eficiente  posible  
en  el  sistema  del  que  disponemos.    
Partimos   de   un   conjunto   de   tareas   o   hilos   que   se   pueden   lanzar  
concurrentemente   y   un   conjunto   de   enlaces   entre   ellas   que   representan   los  
requerimientos  de  comunicación.  En  función  de  esto  y  de  los  recursos  disponibles  
debemos  diseñar  una  distribución  de  trabajo  lo  más  equilibrada  posible.    
El   balanceo   o   equilibrado   de   la   carga   es   la   distribución   o   división   del   trabajo   de  
una   forma   equitativa   entre   los   procesadores   de   nuestro   sistema.   Para   algunos  
problemas   puede   ser   necesario   un   proceso   de   equilibrado   continuo   de   carga  
(equilibrado  dinámico).  
Una  correcta  distribución  del  trabajo:  

• En   memoria   distribuida:   Puede   reducir   el   coste   de   las   comunicaciones  


asignando   datos   que   se   comunican   frecuentemente   a   procesadores  
vecinos.  Evita  comunicaciones  y  congestión  de  la  red  innecesaria.  
• En   memoria   compartida:   Puede   influir   en   el   coste   de   los   accesos   a  
memoria,   en   el   caso   en   que   procesadores   distintos   accedan   a   bloques  
distintos.  En  este  caso  además  mejora  el  uso  de  la  jerarquía  de  memoria.  
 
Función  de  Isoeficiencia.  

Función   cuyo   cometido   es   el   de   ofrecernos   información   acerca   de   cómo   debe  


crecer  el  tamaño  del  problema  en  función  del  número  de  procesadores  para  poder  
mantener  una  eficiencia  constante  en  sistemas  escalables.  
En   general,   para   obtener   esta   función   basta   con   comparar   el   tiempo   secuencial  
con  la  función  de  overhead.  Cuanto  menor  sea  la  función  de  Isoeficiencia,  mejor,  
ya   que   el   sistema   será   más   escalable   y   esto   conlleva   una   serie   de   beneficios   como  
los  enunciados  anteriormente.  
La  función  overhead  (no  confundir  con  el  concepto  de  overhead)  es  la  diferencia  
entre  el  tiempo  de  ejecución  del  algoritmo  y  el  tiempo  de  ejecución  del  algoritmo  
idealizado,  es  muy  difícil  de  medir.    

  13  
 
Aplicación  práctica  de  conceptos.  
A   partir   de   los   conceptos   previamente   expuestos   vamos   a   proceder   a   comentar  
algunos   aspectos   de   un   algoritmo:   “búsqueda   de   un   archivo   de   manera  
paralelizada”,  implementado  por  José  Carlos  Rodríguez.  
import java.io.File;
public class Busqueda extends Thread
{
String nombreBuscar;
File[] entradas; Declaraciones  previas…  
public Busqueda(String nombreBuscar, File ruta)  
{  
entradas = ruta.listFiles();  
this.nombreBuscar=nombreBuscar;  
}  
 
@Override  
public void run()  
{  
String nombreArchivo;
 
String nombre[];
 
for (File entrada : entradas) Para   cada   una   de   las  
{ entradas  
 
if(entrada.isDirectory()) Comprueba  si  la  entrada  
{ es   una   carpeta.   En   caso  
new Busqueda(nombreBuscar, entrada).start(); afirmativo   inicia   un  
nuevo   proceso   de  
} búsqueda.  
if(entrada.isFile()) Comprueba  si  entrada  es  
{ un   fichero.   En   caso  
nombre=entrada.getName().split("[.]"); afirmativo   comprueba   si  
tiene   el   nombre  
nombreArchivo=nombre[0];
buscado.   En   caso  
if(nombreArchivo.equals(nombreBuscar)) afirmativo   devuelve  
{ ubicación.
System.out.println("Archivo Encontrado
en:\n\n");
System.out.println(entrada+"\n\n");
}
}
}
}

El   funcionamiento   del   algoritmo   es   el   siguiente:   para   cada   nivel   de   directorio,  


realiza   una   búsqueda   comprobando   cada   elemento   para   ver   si   es   el   fichero  
buscado  (caso  en  el  que  terminaría  el  programa)  o  es  un  directorio.  

  14  
 
Por   cada   directorio   que   se   encuentre   en   el   nivel,   se   accede   a   éste   mediante   un  
nuevo   proceso   que   lanza   de   nuevo   el   algoritmo   de   búsqueda   comparando   cada  
elemento  de  la  lista  de  ficheros  con  el  buscado.    

En   función   de   las   variables   del   problema   que   podríamos   determinar   como  


número   medio   de   ficheros   por   directorio   y   número   de   directorios,   podemos  
distinguir  varios  casos:  
Caso  primero:  Pocos  ficheros  y  pocos  directorios.  
En   este   caso   el   uso   de   un   algoritmo   paralelo   no   tiene   sentido   ya   que,   como  
hemos   visto,   éstos   son   ventajosos   para   tratar   y   resolver   problemas   de   gran  
envergadura.   Para   pocos   ficheros   y   pocos   directorios   no   se   requiere   una   gran  
potencia  computacional  ni  consumirá  excesivo  tiempo,  al  no  ser  un  problema  de  
envergadura.    
Además,  una  hipotética  mejora  del  rendimiento  (mayor  aceleración)  inducida  por  
el  uso  de  computadores  paralelos  no  sería  significativa.  

Caso  segundo:  Pocos  ficheros  y  muchos  directorios.  


En   este   caso   el   uso   de   un   algoritmo   paralelo   no   solo   no   tiene   sentido   por   los  
motivos  expuestos  en  el  apartado  anterior,  sino  que  además  puede  empeorar  los  
tiempos  debido  a  que,  al  ser  un  problema  con  una  alta  granularidad  (poca  carga  
de   trabajo   para   gran   número   de   procesos),   tenemos   una   importante   reducción   de  
las   prestaciones   por   la   creación   de   procesos,   el   tiempo   de   comunicación   entre  
procesadores  y  el  tiempo  de  sincronización.    

Es  posible  que  con  un  algoritmo  con  balanceo  dinámico  de  la  carga,  que  reparta  
rápidamente   las   cargas   de   trabajo   entre   los   distintos   procesadores   las  
prestaciones   se   mantuvieran,   pero   en   cualquier   caso   estamos   hablando   de   una  
alta   complejidad   del   programa   para   mantener   las   prestaciones   de   antes   de  
paralelizar  el  algoritmo.  
Caso  tercero:  Muchos  ficheros  y  pocos  directorios  

Este   es   el   caso   en   el   que   probablemente   tiene   todo   el   sentido   el   uso   de   un  


programa   paralelo,   ya   que   estamos   ante   una   muy   baja   granularidad   (una   gran  
carga   de   datos   por   cada   procesador),  lo  que  se  traduce  en   una  buena  ganancia  de  
velocidad  al  ejecutar  varios  hilos  simultáneamente.  
Además,  estamos  ante  un  caso  en  el  que  quedan  bastante  limitados  los  tiempos  de  
comunicación  entre  procesadores  y  de  creación  de  procesos,  lo  que  contribuye  a  
una  buena  eficiencia  del  algoritmo.  
Cabe   destacar   que   la   ejecución   de   este   algoritmo,   por   la   comparación   de   cada  
elemento  con  el  buscado  secuencialmente,  puede  llevarnos  a  tiempos  prohibitivos  
si  nos  movemos  con  un  elevado  número  de  ficheros.  
 

  15  
 
Caso  cuarto:  Muchos  ficheros  y  muchos  directorios  
En   este   caso   tenemos   los   beneficios   del   caso   inmediatamente     anterior   a   este,  
como   la   baja   granularidad   y   la   buena   ganancia   de   velocidad   al   ejecutar   varios  
hilos   simultáneamente,   pero   perdemos   algunos   otros   beneficios   ya   que   tenemos  
una   bajada   de   prestaciones   debida   a   los   tiempos   de   comunicación   entre  
procesadores  y  de  creación  de  procesos.    
Dicho   esto,   en   este   caso   también   sería   apropiado   el   uso   de   algoritmos   paralelos  
ya   que   podemos   obtener   una   buena   ganancia   en   velocidad   sobre   todo   si,   aun  
siendo   ambas   altas,   la   cantidad   de   ficheros   es   muy   elevada   en   comparación   con   el  
número  de  directorios.  
Como   conclusión,   extensible   a   la   gran   mayoría   de   los   programas,   la  
paralelización   de   un   algoritmo   solo   se   justifica   cuando   exista   una   fuerte   demanda  
de   capacidad   de   cómputo,   y   será   prohibitivo   su   uso   cuando   estemos   ante  
algoritmos  con  poco  consumo  de  recursos  y/o  muy  subdivididos.  

  16  
 
IV. Bibliografía

Para la realización de este trabajo me he basado en numerosas fuentes:


• Apuntes de la asignatura: “Computación de altas prestaciones” (cuyas referecias
son: Foster, cap 3; Kumar, Grama, Gupta, Karypis, cap 4; Wilkinson, Allen, cap
2.3 y 2.4)
• Información obtenida de diversos artículos de Wikipedia:
o Algoritmo paralelo
o Computación paralela
o Hilo de ejecución
• Apuntes variados del Departamento de Ciencias de la Computación de la
Universidad de Chile.
• Transparencias de “Arquitectura e Ingeniería de Computadores II” (Profersor: D.
Juan Antonio Maestro, de la Universidad Antonio de Nebrija)
• Transparencias de la asignatura “Algoritmos Paralelos” Tema 1. Introducción a la
computación paralela. (Profesor: D. Vicente Cerverón, de la Universidad de
Valencia)

Cabe destacar también que me ha sido de ayuda poder contrastar información con
algunos puntos de la Tesis Doctoral sobre Algoritmos Paralelos de D. Rafael Arturo
Trujillo Rasúa, de la Universidad Politécnica de Valencia.

  17  
 

Das könnte Ihnen auch gefallen