Download Anexos Parallel Java - LCAR - Universidad Nacional Experimental
Document related concepts
no text concepts found
Transcript
Anexo C UNIVERSIDAD NACIONAL EXPERIMENTAL DEL TÁCHIRA INGENIERÍA EN INFORMÁTICA Anexos Parallel Java Autor: Leonel Hernández Anexo C.1 Instalación, configuración y compilación del Parallel Java. Luego de estudiar las características y funcionalidad del Algoritmo Paralelizado se procedió con estudio e instalación de PJ. Parallel Java es una API y middleware para programación en paralelo en Java sobre multiprocesadores de memoria compartida (SMP) en paralelo, cluster, e híbridos entre estas dos tecnologías. Al instalar este paquete se debe tener en cuenta lo siguiente: Para la instalación en el cluster beowulf basado en Debian 6.0 o anterior, se recomienda la versión pre-empaquetada de la librería. Se instala con la siguiente sentencia: $apt-get install libpj-java La librería quedara ubicada en la siguiente ubicación /usr/share/java/. Agregar el PJ al entorno de ambiente de variable $CLASSPATH. $ export CLASSPATH=/usr/share/java/pj.jar:$CLASSPATH Para poder correr programas en PJ sobre un cluster beowulf se requiere tener configurado el acceso del servicio SSH* a los nodos mediante llaves públicas. Se procede de la siguiente manera: o Primero se ingresa en el nodo principal como usuario de trabajo y se generan los archivos de las llaves pública y privada SSL. El parámetro contraseña deja en blanco: #ssh-keygen o Esto generara 2 archivos id_rsa.pub e id_rsa y se crea el directorio /home/nombre_usuario/.ssh. La /home/nombre_usuario/id_rsa. llave y privada la llave se guarda publica en en /home/nombre_usuario/id_rsa.pub. o Finalmente, dado que es un cluster beowulf *NIX, los directorios /home se encuentran compartidos, se añade la nueva llave privada al archivo autorized_keys dentro del mismo directorio .ssh del usuario: $cat .ssh/id_rsa.pub >> .ssh/authorized_keys‟ Se requiere de la creación del planificador de Parallel Java para que la librería haga la conexión entre el nodo principal y los nodos secundarios. Para configura el planificador se debe crear un archivo de texto nombrado scheduler.conf que se puede ubicar en la dirección que el usuario de la librería lo desee. El archivo de configuración del planificador de trabajos contiene lo siguiente: o Cluster: el nombre del cluster. o Logfile: la ubicación y el nombre del archivo donde se añadirán las entradas de registro de PJ. o WebHost: host name de la interfaz web del planificador de trabajos. o WebPort: el número del puerto para la interfaz web del planificador. Por defecto el número del puerto es 8080, para nuestro caso fue modificado ya que este coincide con el puerto de escucha de Apache Tomcat. o Schedulehost: host name a la que el planificador de trabajos escucha para las conexiones de los procesos de interfaz de trabajo. Si no se especifica, por defecto este toma localhost. o Shedulerport: el número del puerto donde el planificador escucha para las conexiones de interfaz de procesos. Si no es especificada el número del puerto por defecto es 20617. o Frontendhost: La dirección IP del nodo principal que escuchan las conexiones de los nodos secundarios. o Backend: de las computadoras paralelas se incluyen el nombre del nodo, el número de procesadores que posee, la dirección IP para el acceso remoto, la ruta de acceso absoluta a la Java Virtual Machine (JVM) y la ubicación de la clase PJ en el nodo secundario. Un ejemplo del archivo de configuración del planificador de trabajos se puede ver en el anexo C.2 Configurado el planificador se debe ejecutar antes de poner a prueba cualquier aplicación con la librería. La sentencia para ejecutar el planificador es la siguiente: $java -classpath scheduler.conf /usr/share/java/pj.jar edu.rit.pj.cluster.JobScheduler Esta sentencia se debe ejecutar desde la dirección donde se encuentra el archivo scheduler.conf Para que el scheduler se cargue al iniciar el sistema en una Debían 6.0 se agrega la siguiente sentencia en el archivo „/etc/rc.local‟: # su –c “java –classpath /usr/share/java/pj.jar edu.rit.pj.cluster.JobScheduler /ubicacion/scheduler.conf” nombre_usuario. Para que un programa sea compatible con el PJ se debe incluir como una librería externa en el programa que se esté realizando. En la ejecución de este proyecto se utilizo el entorno de desarrollo NetBeans IDE 6.7* y para incluir la librería en un proyecto se realizaron los siguientes pasos: o Se ingresa a la pestaña Herramientas -> Librerías o En el administrador de Librerías se incluye una nueva librería y se le da un nombre. o Luego se presiona el botón Agregar JAR/Carpeta, buscar la librería PJ en la ubicación donde fue instalada. o Para finalizar se agrega esta nueva librería al proyecto que se está creando, en el paquete Bibliotecas del proyecto. Para ejecutar la aplicación creada en consola se deben utilizar las siguientes sentencias: $java –Dpj.np=5 Ejemplo O sí se utiliza el NetBeans, click derecho del ratón sobre el Proyecto -> Propiedades » Ejecución, en la casilla de texto “Opciones de VM” se añade lo siguiente: –Dpj.np=5 Donde, -Dpj.np=5 es una propiedad de PJ que especifica el número de procesos, estos procesos son el nodo principal y los nodos secundarios utilizados para ejecutar el programa paralelo. Para este ejemplo el número de procesos es de 5. Anexo C.2 Archivo de configuración del planificador de tareas de Parallel Java. Archivo scheduler.conf # Archivo de configuración de Parallel Java Job Scheduler # Frontend node: Nodo00 # Backend nodes: Nodo02-Nodo04-Nodo06-Nodo08 cluster Hydra logfile /home/leonel-hernandez/scheduler.log webhost 172.18.40.132 webport 8080 schedulerhost localhost schedulerport 20617 frontendhost 10.0.25.1 backend nodo02 1 10.0.25.3 /usr/lib/jvm/java-1.5.0-sun/bin/java backend nodo04 1 10.0.25.5 /usr/lib/jvm/java-1.5.0-sun/bin/java backend nodo06 1 10.0.25.7 /usr/lib/jvm/java-1.5.0-sun/bin/java backend nodo08 1 10.0.25.9 /usr/lib/jvm/java-1.5.0-sun/bin/java backend nodo00 1 10.0.25.1 /usr/lib/jvm/java-1.5.0-sun/bin/java /usr/share/java/pj.jar /usr/share/java/pj.jar /usr/share/java/pj.jar /usr/share/java/pj.jar /usr/share/java/pj.jar -server -server -server -server -server Anexo C.3 Hola Mundo con Parallel Java. Archivo Hello.java package helloworld; import edu.rit.pj.*; import edu.rit.mp.buf.*; /** * * @author leonel-hernandez */ public class Hello { /** * @param args the command line arguments */ public static void main(String[] args) throws Exception{ Comm.init(args); int source; int dest; int myrank = Comm.world().rank(); int size = Comm.world().size(); if (myrank != 0){ //System.out.println("Hola soy " + Comm.world().host()+" con Rango: "+myrank); char [ ] message =("Saludos desde: "+Comm.world().host()+" con Rango: "+myrank).toCharArray(); Comm.world().send(0, CharacterArrayBuf.buffer(message)); }else{ for(source=1;source<size;source++){ char [] message=new char[37]; Comm.world().receive(source,CharacterArrayBuf.buffer(message)); System.out.println(new String(message)); } } } } Anexo C.4 Repartir vector con Parallel Java. Archivo RepartirVector.java package repartirvector; import edu.rit.mp.buf.*; import edu.rit.pj.*; /** * @author leonel-hernandez */ public class RepartirVector { static Comm world; static int rank; static int size; static int vector1[], vector2[]; static int pedazo, primero1[], primero2[], sum1[], sum2[] ; static int x; public static void main(String[] args) throws Exception { Comm.init(args); world = Comm.world(); rank = world.rank(); size = world.size(); x = Integer.parseInt(args[0]); vector1 = new int[x]; vector2 = new int[x]; primero1 = new int[size]; primero2 = new int[size]; sum1 = new int[1]; sum2 = new int[1]; for(int i=1;i<x;i++) vector1[i] = 0; for(int l=1;l<size-1;l++) primero2[l] = 0; pedazo = x/size; if (rank==0){ int total=0; for(int j=1;j<size;j++){ primero1[j] = j * pedazo; world.send(j,IntegerArrayBuf.buffer(primero1)); System.out.println ("Envie a "+j+": "+primero1[j]); } for(int m=1;m<size;m++){ world.receive(m,IntegerArrayBuf.buffer(sum2)); System.out.println ("Recibi de "+m+": "+sum2[0]); total=total+sum2[0]; } System.out.println ("Total:"+total); }//end if else{ world.receive(0,IntegerArrayBuf.buffer(primero2)); for(int i=1;i<primero2[rank];i++){ vector1[i]=i; sum1[0]=sum1[0]+vector1[i]; }//endfor world.send(0, IntegerArrayBuf.buffer(sum1)); System.out.println ("Soy "+rank + " Y Respondi a 0"); }//endelse }//end main }//end class Anexo C.5 Repartir objetos con Parallel Java. Archivo vector.java package repartirobjetos; import edu.rit.pj.*; import edu.rit.mp.buf.*; /** * @author leonel-hernandez */ public class RepartirObjetos { static Comm world; static int rank; static int size; static int tamaño = 500000, pedazo; static Circulo enviarObjeto[], circulo[]; static double sum, psumE[], psumR[]; static int primero[], primeroR[]; public static void main(String[] args) throws Exception { Comm.init(args); int num =Integer.parseInt(args[0]); System.out.println("Aqui "+ num); world = Comm.world(); rank = world.rank(); size = world.size(); //Inicializar Variables pedazo = tamaño / size; circulo = new Circulo[tamaño]; psumE = new double[1]; primero = new int [1]; enviarObjeto = new Circulo[1]; if (rank == 0) { for (int i = 0; i < tamaño; i++) circulo[i] = new Circulo(i); for (int j = 1; j < size; j++) { primero[0] = j * pedazo; world.send(j,ObjectArrayBuf.buffer(circulo)); world.send(j,IntegerArrayBuf.buffer(primero)); } sum = 0; for (int k = 0; k < pedazo; k++) sum = sum + circulo[k].calcularSuperficie(); System.out.println(world.host()+" Envia: " + sum); for (int l = 1; l < size; l++) { world.receive(l,DoubleArrayBuf.buffer(psumE)); sum = sum + psumE[0] + num; } System.out.println("El resultado de la suma es:"+ sum+" y recibio: " + world.host()); }//end if else { world.receive(0, ObjectArrayBuf.buffer(circulo)); world.receive(0, IntegerArrayBuf.buffer(primero)); pedazo = pedazo + primero[0]; psumE[0] = 0; for (int i = primero[0]; i < pedazo; i++) { psumE[0] = psumE[0] + circulo[i].calcularSuperficie(); } System.out.println(world.host() + " Envia: " + psumE[0]); world.send(0, DoubleArrayBuf.buffer(psumE)); }//end else } }//end main Archivo Circulo.java package Repartir; import java.io.*; public class Circulo implements Serializable{ double radio; Circulo (double r) { radio = r; } Circulo () { radio = 2.0; } double calcularSuperficie() { return radio*radio*3.141592653589793; } }