Sie sind auf Seite 1von 14

Procesamiento Paralelo para el Modelamiento de

Objetos 2D y 3D
Carbajal Ipenza, Juan Carlos
Algoritmos Paralelos
Escuela de Ciencias de la Computacion
Facultad de Ciencias de la UNI
Resumen
Actualmente el modelamiento de la supercie de objetos en tres dimensiones (3D) es
importante en la medicina, videojuegos, fsica y algunas ciencias. Por lo que es necesario un
algoritmo para modelar estos objetos por la gran cantidad de datos y el tiempo que estos
demandan. Uno de los mas usados es el algoritmo Marching Cubes. Este crea una supercie
de malla desde un n umero extenso de imagenes. Este algoritmo se puede simplicar y plasmar
mediante curvas conexas en el espacio 2D con el algoritmo Marching Squares.
El aporte es la implementacion secuencial y paralela del algoritmo Marching Squares en base de
la programacion orientada a objetos. El tiempo de ejecucion del algoritmo Marching Squares
paralelizado con 128 hilos o procesos es 128,84 veces menor que su version secuencial, todo
esto en una computadora de 2 n ucleos. El procesamiento paralelo incrementa notoriamente la
eciencia computacional en una computadora multin ucleos. En base a otras investigaciones, que
son mejoras del algoritmo Marching Squares como el algoritmo Consesus-Surface, los resultados
de velocidad son similares en cambio los de precision en la renderizacion son diferentes.
1. Estado del Arte
Marching Cubes es un algoritmo de construccion
de la supercie de un objeto usado para ver
datos en 3D [3]. Este crea una representacion
poligonal de densidad constante de supercie por
una interpolacion de una cadena en 3D de discretas
conocidas guras.
Para entender el algoritmo Marching Cubes
introducimos al algoritmo Marching Squares
que usa el mismo aprovechamiento para el
modelamiento de un curvas conexas en 2D [4].
1.1. Marching Squares
El algoritmo Marching Squares permite dibujar
lneas entre valores interpolados a lo largo de los
bordes de un cuadrado, considerando dar pesos en
las esquinas y un valor de referencia (isovalor).
Si los vertices de una arista tienen los pesos v1 y
v2, entonces si el isovalor (k) que es un n umero
esta entre esos pesos ( v1 k v2 o v2 k v1 )
entonces la curva pasa por esa arista de lo contrario
la arista se ubica fuera ( k > max(v1, v2) ) o dentro
de la curva ( k < min(v1, v2) ).
Esto se muestra en la Fig. 1. Para mostrar
esta curva consideraremos cada cuadrado de la
malla. Son posibles 16 conguraciones (casos)
enumeradas, cuales permiten la representacion de
todos los tipos de lneas en el espacio 2D (Fig. 2).
En este algoritmo existen casos ambiguos los cuales
son el cinco y diez (Fig. 3 ).
Si planteamos el algoritmo Marching Squares en
3D obtenemos el algoritmo Marching Cubes.
1
2 Carbajal Ipenza, Juan Carlos
Figura 1: Cada punto de la malla tiene un peso y el
valor de referencia (isovalor) es 5. Para dibujar la
curva cuyo valor es constante se tienen diferentes
tipos de interpolacion que pueden ser usados. Uno
de ellos consiste en considerar individualmente cada
cuadrado de la malla. Este es el algoritmo Marching
Squares. Ref. im. [4].
Figura 2: Todos los posibles casos de Marching
squares. Son 16 casos enumerados obtenidos de
dos posibilidades en los cuatro vertices (negro
o blanco). Sean v1, v2, v3 y v4 la ubicacion
del vertice del cuadrado en la esquina inferior
izquierda, inferior derecha, superior derecha y
superior izquierda, respectivamente; entonces el
caso se nombra como caso (v4)(v3)(v2)(v1). Ref.
im. [4].
Figura 3: Como se ve en la gura no se es capaz
de tomar una decision en la interpretacion de este
tipo de situacion. Sin embargo, esto no representan
ning un error real ya que los bordes se mantienen
cerrados. Ref. de im. [4].
Figura 4: Familias de Marching Cubes. Son 16 casos
enumerados obtenidos de dos posibilidades en los
ocho vertices (azul o rojo). Ref. im. [4].
1.2. Marching Cubes
De la misma forma que Marching Squares
nosotros tenemos 256 diferentes situaciones para
el espacio 3D. Todos estos casos pueden ser
generalizados en 16 familias por rotacion y simetra
(Fig. 4). Para cada caso se puede adoptar una
notacion. Esto nos permite referenciar cada caso
por un ndice creado desde una interpretacion
binaria de los pesos de las esquinas (Fig. 5).
De la misma forma que Marching Squares existen
casos ambiguos. Los cubos de las familias cuatro y
diez son casos ambiguos, sin embargo estos tienen
una solucion topologica. No solo la ambiguedad
genera problemas topologicos, algunas familias son
incompatibles. Los problemas de incompatibilidad
se pueden solucionar mediante teora de grafos [5] o
se pueden a nadir 6 familias a los casos de Marching
Cubes (Fig. 6).
El algoritmo Consensus-Surface estima la distancia
se nalada de la supercie del objeto, mejorando
Marching Cubes [2]. Esto captura peque nos detalles
de la geometra del objeto y elimina errores en
los datos de la imagen, como los problemas de
ambiguedad. Este metodo utiliza octrees para
representar la supercie resultante.
Un octree es un arbol con 8 hijos, en un cubo a
cada hijo se le asigna un subcubo que es la octava
parte del cubo original.
Facultad de Ciencias - Universidad Nacional de Ingeniera
3 Carbajal Ipenza, Juan Carlos
Figura 5: Sean v1, v2, v3, v4, v5, v6, v7 y
v8 la ubicacion de los vertices en las esquinas
del cubo entonces el caso se nombra como caso
(v8)(v7)(v6)(v5)(v4)(v3)(v2)(v1). El lugar donde
se interpola la supercie en las aristas se representa
con e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 y e12.
Ref. im. [4].
Figura 6: Estas familias han sido usados para
casos complementarios. Por ejemplo, para la
incompatibilidad con el caso 12 tienes que
reemplazarlo por el caso 12c. Ref. de im. [4].
Figura 7: Asignacion de espacios parciales de un
octree para cada CPU y recorrido transversal de
cada sub-octree. Ref. im. [1].
La paralelizacion del algoritmo Consensus-Surface
esta basada en dos motivaciones [1].
La primera distribuye la asignacion de datos en
m ultiples computadoras, asi maneja el gran tama no
de datos y la segunda divide el octree en sub-
octrees y asigna el recorrido de un sub-octree a cada
ordenador. El sub-octree se obtendra de convertir
a un hijo de un octree en un nuevo octree (Fig. 7).
2. Implementaci on
El lenguaje de programacion que se utiliza es
Java, ya que provee de una programacion orientada
a objetos. Ademas que se hace uso del GUI de Java
como libreras gracas para plasmar y representar
los resultados. En la paralelizacion del codigo
se usan hilos en las lbrerias de procesamiento
concurrente de Java.
Todo esto en una computadora con procesador
Intel R Core 2 Duo CPU T6600 2.20Ghz x
2, sistema operativo GNU/Linux 3.2.0-4 amd64,
distribucion Debian (wheezy) 7.4 de 64-bit y
compilador Java 1.7.0.25.
2.1. Adquisicion de datos
La fuentes de datos para la simulacion con el
algoritmo Marching Squares son los pxeles de las
imagenes, ya que estos proveen pesos en cada punto
de la imagen. De igual manera para el algoritmo
Marching Cubes se utilizara voxeles que es lo
analogo a pxel en el espacio 3D. Las imagenes que
se usan son jpeg, ya que sus pixeles constan de 4
bytes. El primer byte nos indica la transparencia, el
segundo el color rojo, el tercero el verde y el ultimo
el azul.
A partir de un archivo jpeg se obtiene la imagen,
su ancho y alto en un objeto Imagen a partir de
la clase ImageIO del API de Java (lneas 2,4,5).
Facultad de Ciencias - Universidad Nacional de Ingeniera
4 Carbajal Ipenza, Juan Carlos
En un arreglo de enteros se guarda los valores de
los pixeles de la imagen por medio de un objeto
PixelGrabber del API de Java (lneas 6,9-11).
A cada pixel se le elimina su byte de transparencia
y se simplica a la capacidad de un byte, y estos se
guardan en una matriz de pesos (lneas 7,12-26).
- MSFrame permite visualizar el algoritmo
Marching Squares por medio del GUI de Java.
Ademas ayuda en la manipulacion, edicion,
salvado en un archivo y abrir un archivo de esta
implementacion de Marching Squares.
MSFrame.java
1 ...
2 imagenFuente=ImageIO.read(fileImagen);
3 ...
4 iniAncho=imagenFuente.getWidth(this);
5 iniAlto=imagenFuente.getHeight(this);
6 int[]pix=new int[iniAncho*iniAlto];
7 int[][]datos=new int[iniAlto][iniAncho];
8 try {
9 PixelGrabber pgObj=new PixelGrabber(
10 imagenFuente, 0, 0, iniAncho,
11 iniAlto, pix, 0, iniAncho );
12 if (pgObj.grabPixels()) {
13 int i = 0, j = 0;
14 while ( i < iniAlto ) {
15 j = 0;
16 while ( j < iniAncho ) {
17 datos[i][j]=(pix[i*iniAlto+j]
18 & 0x00FFFFFF );
19 datos[i][j]=(datos[i][j]/(int
20 )(Math.pow(2.0,16.0)) );
21 j++;
22 }
23 i++;
24 }
25 }
26 ...
2.2. Creaci on del modelo
Para implementar Marching Squares y Marching
Cubes es muy obvio crear una clase cubo y
cuadrado en Java, respectivamente.
En la malla al cambiar el valor del peso de un
vertice, este valor tiene que cambiar para todos los
cubos y cuadrados. Los vertices tienen que tener
una relacion de puntero para gestionar esto.
Por eso el peso del vertice no puede ser un entero
ya que este no lo encapsula, por lo tanto se le tiene
que encerrar en una clase.
- MSInt encapsula un valor entero, usado para
la relacion entre vertices.
MSInt.java
1 public class MSInt {
2 protected int value;
3 ...
4 public MSInt( int value ){
5 this.value = value;
6 }
7 }
En consecuencias se dene la estructura vertice.
Sus campos son su peso y posicion (lneas 5,6) y
sus constructores en base de estos (lneas 8-11). Su
metodo weight devuelve el peso del vertice; equals
compara con otro vertice si se trata del mismo
vertice esto en base de su posicion y tama no; y
display dibuja al vertice en el GUI (lneas 13-20).
- MSVector2 representa a un vector en dos
dimensiones asi como sus propiedades. Esto
para dibujar guras en el espacio 2D como las
aristas del cuadrado y sus esquinas
- MSVertex representa a un vertice de un
cuadrado asi como sus propiedades.
MSVertex.java
1 public class MSVertex {
2 public static int DEFAULT_WEIGHT=128;
3 public static int SIZE=
4 (int)(MSSquare.SIZE/3);
5 protected MSInt weight;
6 protected MSVector2 position;
7 ...
8 public MSVertex(MSVector2 position){
9 ...
10 public MSVertex(MSVector2 position,
11 int weight) {
12 ...
13 public int weight() {
14 ...
15 public boolean equals(MSVertex v){
16 ...
17 public void display() {
18 ...
Facultad de Ciencias - Universidad Nacional de Ingeniera
5 Carbajal Ipenza, Juan Carlos
19 public void display(Graphics gpd,
20 int cX, int cY) {
21 ...
22 }
Conociendo los pesos de los vertices de los cubos
y cuadrados se calcula los valores interpolados a lo
largo de los bordes para dibujar los trangulos y
lneas, respectivamente. Esto se calcula usando un
metodo de interpolacion lineal que consiste en la
solucion de una ecuacion de primer grado.
Sea A y B pesos de los dos extremos de un borde,
R el valor de referencia (isovalor) y t el valor
interpolado, entonces:
(1 t) A+t B = R
resolviendo:
t = (R A)/(B A)
Con los valores interpolados se determina que
triangulos o lneas dibujar.
Por lo tanto se dene un metodo computeEdge
donde se aplica esta formula (lneas 4-6) en la
clase cuadrado. Este metodo computa el valor
interpolado y halla su posicion (lneas 8-13).
Ademas se dene otro metodo que computa todos
los vertices (lneas 18-28)
- MSSquare representa a un cuadrado asi como
sus propiedades.
MSSquare.java
1 ...
2 private MSVector2 computeEdge( MSVertex
3 v1, MSVertex v2 ) {
4 double t = ( seekValue-v1.weight())
5 / (double) ( v2.weight() -
6 v1.weight() );
7 if ( t >= 0 && t <= 1 ) {
8 MSVector2 vDir = ( new
9 MSVector2(v2.position)
10 ).sub(v1.position);
11 return ( new MSVector2(
12 v1.position) ).add(
13 vDir.mult(t));
14 }
15 return null;
16 }
17 ...
18 public MSSquare computeEdges() {
19 this.e[0] = this.computeEdge(
20 v[0], v[1] );
21 this.e[1] = this.computeEdge(
22 v[1], v[2] );
23 this.e[2] = this.computeEdge(
24 v[2], v[3] );
25 this.e[3] = this.computeEdge(
26 v[3], v[0] );
27 return this;
28 }
29 ...
Cada cuadrado se representa en binario como en la
Fig. 2. Asi se tienen 16 casos y se les nombra caso
(v4)(v3)(v2)(v1). Y a la arista entre v1 y v2, v2 y
v3, v3 y v4 ;y v4 y v1 se les nombra e1, e2, e3 y e4;
respectivamente. El n umero maximo de lneas que
pueden pasar por un cuadrado son 2 por lo que para
representar a una curva que corta a un cuadrado se
necesitan de 4 datos, las que son las 4 aristas.
Si una curva pasa por una arista se guarda el ndice
de la arista (por ejemplo si pasa por e3 se guarda
el dato 3) y si no pasa se guarda -1.
Asi, por ejemplo, para el caso 7 se tendran los
siguientes datos 2, 3, -1 y -1, siendo los dos primeros
los de la primera lnea y los siguientes de la
siguiente lnea. En los casos ambiguos (5 y 10) los
datos de cada caso pueden variar entre 0, 1, 2 y 3 ;y
0, 3, 1 y 2. Asi tenemos una lista de los 16 posibles
casos con 4 datos en cada caso que especifcan por
donde pasan las lneas.
Por lo tanto se dene un campo con estas lneas en
la clase del cuadrado, donde se ven los 16 posibles
casos. Los dos primeros indican la primera curva
que corta al cuadrado y los restantes la otra curva.
- MSSquare
MSSquare.java
1 ...
2 // linea para ser dibujada en cada caso
3 private static int lines[] = {
4 -1, -1, -1, -1,
5 0, 3, -1, -1,
6 0, 1, -1, -1,
7 1, 3, -1, -1,
8 1, 2, -1, -1,
9 0, 1, 2, 3,
10 0, 2, -1, -1,
11 2, 3, -1, -1,
12 2, 3, -1, -1,
13 0, 2, -1, -1,
Facultad de Ciencias - Universidad Nacional de Ingeniera
6 Carbajal Ipenza, Juan Carlos
14 0, 3, 1, 2,
15 1, 2, -1, -1,
16 1, 3, -1, -1,
17 0, 1, -1, -1,
18 0, 3, -1, -1,
19 -1, -1, -1, -1
20 };
21 ...
Cuando se adiciona otro cuadrado es necesario
escanear otros cuadrados en la misma posicion,
si la b usqueda es correcta fusionamos a los
cuadrados topologicamente. Para esto se guardan
los cuadrados en un vector el cual es el campo
de una nueva clase, MSMesh, que encierra a
todos los cuadrados. En esta clase se denen
los metodos addSquare (lneas 6-14,50,51) y
deleteSquare (lneas 60), los cuales agrega un
cuadrado a la malla y elimina un cuadrado de la
malla, respectivamente.
El metodo addSquare escanea a los vecinos para
establecerlos como tales (lneas 15-49) y el metodo
deleteSquare escanea a los vecinos para eliminar su
presencia de ellos (lneas 61-76). Al nal de cada
metodo se vuelve a centralizar la malla (lneas 52-
55,78-81).
- MSMatrix3 representa a una matriz de 3x3 asi
como sus propiedades. Esto para que junto con
MSVector3 resolver los problemas de rotacion,
traslacion y camara en el espacio 2D.
- MSVector3
representa a un vector en dos dimensiones
con un dato adicional de homogeneidad asi
como sus propiedades. Esto para que junto con
MSMatrix resolver los problemas de rotacion y
traslacion.
- MSMatrixStack representa a una pila de
matrices. Esta se utilizara como estructura
de datos al momento de las operaciones de
ubicacion.
- MSNeighbour describe topologicamente al
vecino de un cuadrado.
- MSMesh representa a una malla de cuadrados
para manipularlos como grupo.
MSMesh.java
1 ...
2 public void addSquare( MSSquare _square,
3 int w0, int w1, int w2, int w3,
4 int position, String name ) {
5 _square.vecinoCercano = position;
6 if (name.equals(""))
7 name = "Cuadrado "
8 + this.squares.size();
9 MSSquare square = new MSSquare(
10 name, w0, w1, w2, w3 );
11 square.modelView = new MSMatrix3(
12 _square.modelView);
13 square.modelView.translate(
14 MSSquare.translate(position));
15 for ( int dir = -2; dir <= 2;
16 dir++ ) {
17 if ( dir != 0 ) {
18 MSMatrix3 dummy = new
19 MSMatrix3(square.modelView);
20 dummy.translate(
21 MSSquare.translate(dir));
22 for ( int index = 0; index <
23 this.squares.size();
24 index++ ) {
25 MSSquare square_
26 =(MSSquare)
27 this.squares.elementAt(
28 index);
29 if (dummy.equals(
30 square_.modelView)) {
31 switch (dir) {
32 case MSNeighbour.SOUTH:
33 square.v[0].weight=
34 square_.v[3].weight;
35 square.v[1].weight=
36 square_.v[2].weight;
37 break;
38 ...
39 }
40 square.neighbours.add(
41 new MSNeighbour(
42 square_, dir ) );
43 square_.neighbours.add(
44 new MSNeighbour(
45 square, -dir ) );
46 }
47 }
48 }
49 }
Facultad de Ciencias - Universidad Nacional de Ingeniera
7 Carbajal Ipenza, Juan Carlos
50 this.squares.add(square);
51 square.computeEdges();
52 this.modelView = new MSMatrix3();
53 this.modelView.translate((
54 new MSVector2() ).sub(
55 this.computeCenter()));
56 }
57 ...
58 public void deleteSquare(
59 MSSquare square ) {
60 this.squares.remove(square);
61 for ( int index = 0; index <
62 square.neighbours.size();index++){
63 MSSquare ns = ( (MSNeighbour)
64 square.neighbours.elementAt(
65 index) ).square;
66 for ( int n = 0; n <
67 ns.neighbours.size(); n++ ) {
68 MSSquare nsns = ( (MSNeighbour)
69 ns.neighbours.elementAt(n)
70 ).square;
71 if ( nsns == square ) {
72 ns.neighbours.removeElementAt(
73 n);
74 n--;
75 }
76 }
77 }
78 this.modelView = new MSMatrix3();
79 this.modelView.translate((
80 new MSVector2() ).sub(
81 this.computeCenter()));
82 }
83 ...
2.3. Procesamiento secuencial de
imagen
Los datos adquiridos del archivo de imagen jpeg
se procesan en la malla para que arroje como
resultado la malla con sus respectivos cuadrados
interpolados. Todo esto se realiza en el constructor
de la malla con entrada de una matriz llamada peso,
esta matriz consta de los datos adquiridos.
En la lneas 3-7 se crea un cuadrado y se agrega al
vector de los cuadrados a partir de los cuatro pesos
de la esquina superior izquiera de la imagen para
usar el metodo addSquare.
En las lnea 8-32 se recorre la por la de cuatro
en cuatro los pesos de la imagen para adicionar un
cuadrado por cada 4 pesos en la malla por medio
del metodo addSquare.
En las lneas 33-56 se recorre todo el vector de
cuadrados para obtener el ndice del vector en
donde se ubican los cuadrados que tienen alg un
peso que no existe. Esto se realiza porque al
modicar la malla en la implementacion se puede
guardar y volver a abrir ese archivo editado por
medio de un tipo de archivo *.msdenido por
la aportacion que se hizo. En las lneas 57-69 se
eliminan los cuadrados que fueron marcados en las
lneas anteriores.
- MSMesh
MSMesh.java
1 ...
2 this.modelView = new MSMatrix3();
3 this.squares = new Vector( 0, 1 );
4 MSSquare s0 = new MSSquare( "Cuadrado 0",
5 peso[0][0], peso[0][1],
6 peso[1][1], peso[1][0] );
7 this.squares.add(s0);
8 int i = 0, j = 0;
9 while ( i < peso.length - 1 ) {
10 j = 1;
11 while ( j < peso[0].length - 1 ) {
12 this.addSquare( (MSSquare)
13 this.squares.elementAt(
14 this.squares.size() - 1 ),
15 peso[i][j], peso[i][ j + 1 ],
16 peso[ i + 1 ][ j + 1 ],
17 peso[ i + 1 ][j],
18 MSNeighbour.EAST, "" );
19 j++;
20 }
21 i++;
22 j = 0;
23 if ( i != peso.length - 1 ) {
24 this.addSquare( (MSSquare)
25 this.squares.elementAt(
26 (i-1)*(peso[0].length-1) ),
27 peso[i][j], peso[i][ j + 1 ],
28 peso[ i + 1 ][ j + 1 ],
29 peso[ i + 1 ][j],
30 MSNeighbour.NORTH, "" );
31 }
32 }
33 i = 0;
34 int k = 0;
Facultad de Ciencias - Universidad Nacional de Ingeniera
8 Carbajal Ipenza, Juan Carlos
35 boolean elimin = false;
36 Vector ayuda = new Vector( 0, 1 );
37 while ( i < peso.length - 1 ) {
38 j = 0;
39 while ( j < peso[0].length - 1) {
40 elimin = false;
41 k = 0;
42 while ( k < 4 ) {
43 if ( ( (MSSquare)
44 this.squares.elementAt(
45 i*(peso[0].length-1)+j)
46 ).v[k].weight.value ==
47 Integer.MIN_VALUE )
48 elimin = true;
49 k++;
50 }
51 if ( elimin ) ayuda.add(
52 i*(peso[0].length-1)+j );
53 j++;
54 }
55 i++;
56 }
57 i = 0;
58 while ( i < ayuda.size() ) {
59 this.deleteSquare( (MSSquare)
60 this.squares.elementAt(
61 (int) ayuda.elementAt(i) ) );
62 i++;
63 j = i;
64 while ( j < ayuda.size() ) {
65 ayuda.setElementAt( ( (int)
66 ayuda.elementAt(j)-1),j );
67 j++;
68 }
69 }
70 ...
Un archivo ms se dene como un archivo en el que
su primera la describe al isovalor; en la segunda
el ancho y alto de la malla; y en las restantes los
pesos a lo largo y ancho de toda la malla.
Si un peso no existe le corresponde un caracter N.
Este tipo de archivo se utiliza para guardar y abrir
las modicaciones que se realizan en la malla en la
implementacion (Fig. 8).
Figura 8: Malla a partir de la entrada0.ms en la
implementacion.
- Archivo tipo ms
entrada0.ms
1 5
2 5 5
3 0 N 1 3 2
4 1 3 6 6 3
5 3 7 N 7 -3
6 2 7 8 6 2
7 1 2 3 4 3
2.4. Procesamiento paralelo de
imagen
El procesamiento paralelo en Java se realiza por
medio de hilos de la clase Threads del API de
Java, sin embargo esta clase no es recomendable
usarla directamente por lo que se usa una interfaz
Runnable o clase padre SwingWorker ( utilizado
en el subprocesamiento de componentes GUI de
Java para el manejo de eventos ) del API de Java.
Para ejecutar cada hilo, asi como su manipulacion,
se hace uso de la interfaz Executor denida por
ExecutorService [6].
Se paralelizan las lneas 8-32 y 33-56 del codigo de
la subseccion anterior.
Primero se paraleliza las lneas 8-32.
Estas se reemplazan por lo siguiente, ademas se
agrega un metodo llamado union.
Previamente se agregan tan solo los primeros
Facultad de Ciencias - Universidad Nacional de Ingeniera
9 Carbajal Ipenza, Juan Carlos
cuadrados de cada la de la malla al vector de
cuadrados de la malla. Se declaran las clases
Runnable (cada objeto es un hilo) en las lneas
5,6 y se crean los vectores de cuadrados unico que
tendra cada hilo en las lneas 7-10. Luego se realiza
la reparticion del vector de cuadrados de la malla
en los vectores de cuadrados de cada hilo en las
lneas 11-21,25,26, para enviarse a cada proceso
por medio del constructor de la clase MSRunnable
en las lneas 22-24. Se ejecutan todos los procesos
en las lneas 27-45 y los vectores de cuadrados
regresan con las las llenas de todos los cuadrados
de la misma la correspondiente a cada cuadrado
previamente agregado. Al tener todos estos vectores
de cuadrados tan sol falta unirlos en el vector de
cuadrados principal de la malla (lneas 56-58).
Sin embargo la ultima la de un vector de
cuadrados de un proceso y la primera la de un
vector de cuadrados del que le sigue no estan
unidas, no estan se naladas como vecinos y no
apuntan al mismo peso; por eso en las lneas 47-
55 se arregla ese problema con un metodo llamado
union denido en las lneas 65-124.
- MSMesh
MSMesh.java
1 ...
2 // -----INICIO DEL ESPACIO PARALELIZADO
3 int offset1, rows1, extra1, averow1,
4 destino1;
5 MSRunnable[] proceso1 =
6 new MSRunnable[numworkers];
7 Vector[] filas=new Vector[numworkers];
8 for ( destino1 = 0; destino1 <
9 numworkers; destino1++ )
10 filas[destino1] = new Vector(0,1);
11 averow1 = (squares.size())/numworkers;
12 extra1 = (squares.size())%numworkers;
13 offset1 = 0;
14 for ( destino1 = 1; destino1 <=
15 numworkers; destino1++ ) {
16 rows1 = ( destino1 <= extra1 ) ?
17 averow1 + 1 : averow1;
18 for ( i = 0; i < rows1; i++ )
19 filas[destino1-1].add((MSSquare)
20 this.squares.elementAt(
21 offset1 + i ) );
22 proceso1[ destino1 - 1 ] =
23 new MSRunnable( offset1, rows1,
24 peso, filas[ destino1 - 1 ] );
25 offset1 = offset1 + rows1;
26 }
27 ExecutorService ejecutor1 =
28 Executors.newCachedThreadPool();
29 for ( destino1 = 0; destino1 <
30 numworkers; destino1++ ) {
31 ejecutor1.execute(proceso1[destino1]);
32 }
33 ejecutor1.shutdown();
34 try {
35 boolean tareasTerminaron1 =
36 ejecutor1.awaitTermination(
37 10, TimeUnit.MINUTES );
38 if (!tareasTerminaron1)
39 System.out.println(
40 "Se agoto el tiempo" );
41 }
42 catch ( InterruptedException ex ) {
43 System.out.println(
44 "Hubo una interrupcion" );
45 }
46 this.squares = new Vector( 0, 1 );
47 for ( destino1=0; destino1<numworkers
48 - 1; destino1++ ) {
49 if ( filas[destino1].size() != 0
50 && filas[ destino1 + 1 ].size()
51 !=0)
52 union( filas[destino1],
53 filas[ destino1 + 1 ],
54 peso[0].length - 1 );
55 }
56 for ( destino1 = 0; destino1 <
57 numworkers; destino1++ )
58 squares.addAll(filas[destino1]);
59 this.modelView = new MSMatrix3();
60 this.modelView.translate(
61 (new MSVector2()).sub(
62 this.computeCenter()));
63 // -----FIN DEL ESPACIO PARALELIZADO
64 ...
65 public void union( Vector up, Vector
66 down, int ancho ) {
67 int f = up.size() / ancho - 1;
68 int l = down.size() / ancho;
69 MSSquare square =
70 (MSSquare) up.elementAt(f);
71 MSSquare square_ =
Facultad de Ciencias - Universidad Nacional de Ingeniera
10 Carbajal Ipenza, Juan Carlos
72 (MSSquare) down.elementAt(0);
73 int dir = MSNeighbour.NORTH;
74 square.v[3].weight =
75 square_.v[0].weight;
76 square.v[2].weight =
77 square_.v[1].weight;
78 square.neighbours.add(
79 new MSNeighbour( square_, dir ));
80 square_.neighbours.add(
81 new MSNeighbour( square, -dir ));
82 square_=(MSSquare)down.elementAt(l);
83 f = up.size() - ancho + 1;
84 while ( f < up.size() - 1 ) {
85 square =
86 (MSSquare) up.elementAt(f);
87 square_ =
88 (MSSquare) down.elementAt(l);
89 dir = MSNeighbour.NORTH;
90 square.v[3].weight =
91 square_.v[0].weight;
92 square.v[2].weight =
93 square_.v[1].weight;
94 square.neighbours.add(
95 new MSNeighbour( square_,
96 dir ) );
97 square_.neighbours.add(
98 new MSNeighbour( square,
99 -dir ) );
100 square_ =
101 (MSSquare)down.elementAt(l+1);
102 l++;
103 f++;
104 }
105 f = up.size() - 1;
106 l = down.size() / ancho + ancho - 2;
107 square =
108 (MSSquare) up.elementAt(f);
109 square_ =
110 (MSSquare) down.elementAt(l);
111 dir = MSNeighbour.NORTH;
112 square.v[3].weight =
113 square_.v[0].weight;
114 square.v[2].weight =
115 square_.v[1].weight;
116 square.neighbours.add(
117 new MSNeighbour( square_,
118 dir ) );
119 square_.neighbours.add(
120 new MSNeighbour( square,
121 -dir ) );
122 square_ =
123 (MSSquare)down.elementAt(l-1);
124 }
125 ...
Se dene cada hilo en una clase MSRunnable con
interface Runnable. Esta Recive el oset, tama no
de cada la, los pesos y el vector propio de
cuadrados que esta clase se encargara de llenar
(lneas 3-17). Como el metodo addSquare de la
malla solo llena al vector principal de la clase
MSMesh, en esta clase se dene un metodo similar
con la unica diferencia que agrega el cuadrado al
vector de cuadrados propio del hilo (lneas 47-56).
En el metodo run, donde se ejecuta el hilo, se
agregan los cuadrados en el vector de cuadrados
propio del hilo seg un su oset y tama no de las
que le corresponde (lneas 19-46).
- MSRunnable representa a un hilo en el cual
se crean, computan y agregan los cuadrados a
un vector particionado del vector de cuadrados
principal de MSMesh.
MSRunnable.java
1 public class MSRunnable
2 implements Runnable {
3 private final int offset;
4 private final int rows;
5 private final int[][] peso;
6 private final Vector subSquares;
7
8 public MSRunnable(
9 int offset,
10 int rows,
11 int[][] peso,
12 Vector subSquares ) {
13 this.offset = offset;
14 this.rows = rows;
15 this.peso = peso;
16 this.subSquares = subSquares;
17 }
18
19 public void run() {
20 int i, j, k;
21 i = 0;
22 j = 0;
23 k = 0;
24 while ( i < this.rows ) {
25 j = 1;
Facultad de Ciencias - Universidad Nacional de Ingeniera
11 Carbajal Ipenza, Juan Carlos
26 k = offset + i;
27 this.addSquare((MSSquare)
28 this.subSquares.elementAt(i),
29 peso[k][j],peso[k][j+1],
30 peso[k+1][j+1],peso[k+1][j],
31 MSNeighbour.EAST, "" );
32 j = 2;
33 while (j<peso[0].length-1){
34 this.addSquare( (MSSquare)
35 this.subSquares.elementAt(
36 this.subSquares.size()-1)
37 ,peso[k][j]
38 ,peso[k][j+1]
39 ,peso[k+1][j+1]
40 ,peso[k+1][j],
41 MSNeighbour.EAST, "" );
42 j++;
43 }
44 i++;
45 }
46 }
47 public void addSquare(
48 MSSquare _square,
49 int w0,
50 int w1,
51 int w2,
52 int w3,
53 int position,
54 String name ) {
55 ...
56 }
57 }
Ahora se paraleliza las lneas 33-56 del codigo
de la subseccion anterior. Se declaran las clases
Runnable (cada objeto es un hilo) en las lneas
7,8 y el vector ayuda (lnea 6) que almacenara los
ndices de los cuadrados que no existen en el vector
de cuadrados de la malla. Luego se realiza la
reparticion del vector de cuadrados de la malla a
cada hilo en las lneas 9-19,23,24, para enviarse a
cada proceso por medio del constructor de la clase
MSDeleteRunnable en las lneas 20-22.
Se ejecutan todos los procesos en las lneas 25-
45 y el vector ayuda regresa con todos los ndices
de los cuadrados que tienen que ser eliminados.
En este caso hay repartija de datos, pero no hay
union de resultados porque todos los resultados se
almacenan en un mismo vector (ayuda).
- MSMesh
MSMesh.java
1 ...
2 // -----INICIO DEL ESPACIO PARALELIZADO
3 int offset, rows, extra, averow,
4 destino, ancho;
5 ancho = peso[0].length;
6 Vector ayuda = new Vector( 0, 1 );
7 MSDeleteRunnable[] proceso =
8 new MSDeleteRunnable[numworkers];
9 averow = (peso.length-1) / numworkers;
10 extra = (peso.length-1) % numworkers;
11 offset = 0;
12 for ( destino = 1; destino <=
13 numworkers; destino++ ) {
14 rows = ( destino <= extra ) ?
15 averow + 1 : averow;
16 List subSquares = new Vector( 0, 1 );
17 subSquares = squares.subList( offset
18 * ( ancho - 1 ), ( offset + rows )
19 * ( ancho - 1 ) );
20 proceso[ destino - 1 ] =
21 new MSDeleteRunnable( offset,
22 rows, ancho, subSquares, ayuda );
23 offset = offset + rows;
24 }
25 ExecutorService ejecutor =
26 Executors.newCachedThreadPool();
27 for ( destino = 0; destino<numworkers;
28 destino++ ) {
29 ejecutor.execute(proceso[destino]);
30 }
31 ejecutor.shutdown();
32 try {
33 boolean tareasTerminaron =
34 ejecutor.awaitTermination( 10,
35 TimeUnit.MINUTES );
36 if (!tareasTerminaron)
37 System.out.println(
38 "Se agoto el tiempo" );
39 }
40 catch ( InterruptedException ex ) {
41 System.out.println(
42 "Hubo una interrupcion" );
43 }
44 // -----FIN DEL ESPACIO PARALELIZADO
45 ...
Facultad de Ciencias - Universidad Nacional de Ingeniera
12 Carbajal Ipenza, Juan Carlos
Se dene cada hilo en una clase MSDeleteRunnable
con interface Runnable. Esta Recive el oset,
tama no de cada la, ancho de la la, el subvector
del vector de cuadrados de la malla y el vector que
almacena los ndices (lneas 3-20).
En el metodo run, donde se ejecuta el hilo, se
recorren los cuadrados en el vector de cuadrados
propio del hilo seg un su oset y tama no de las que
le corresponde para asi marcar si estos cuadrados
deben ser eliminados (lneas 22-51).
- MSDeleteRunnable representa a un hilo en
el cual se procesan todos los cuadrados para
saber cuales no existen segun los pesos que se
obtuvieron en el constructor de MSMesh para
luego eliminarlos.
MSDeleteRunnable.java
1 public class MSDeleteRunnable
2 implements Runnable {
3 private final int offset;
4 private final int rows;
5 private final int ancho;
6 private final List subSquares;
7 private final Vector ayuda;
8
9 public MSDeleteRunnable(
10 int offset,
11 int rows,
12 int ancho,
13 List subSquares,
14 Vector ayuda ) {
15 this.offset = offset;
16 this.rows = rows;
17 this.ancho = ancho;
18 this.subSquares = subSquares;
19 this.ayuda = ayuda;
20 }
21
22 public void run() {
23 int i, j, k;
24 boolean elimin = false;
25 i = 0;
26 j = 0;
27 k = 0;
28 while ( i < this.rows ) {
29 j = 0;
30 while (j<this.ancho-1) {
31 elimin = false;
32 k = 0;
33 while ( k < 4 ) {
34 if ( ( (MSSquare)
35 this.subSquares.get(i
36 *(this.ancho-1)+j)
37 ).v[k].weight.value
38 ==Integer.MIN_VALUE)
39 elimin = true;
40 k++;
41 }
42 if ( elimin ) {
43 this.ayuda.add((i+
44 this.offset)*(
45 this.ancho-1)+j);
46 }
47 j++;
48 }
49 i++;
50 }
51 }
52 }
2.5. Visualizacion
Para la visualizacion se ha implementado las
siguientes clases:
- MSMaterial representa un material para ser
asignado hacia un objeto usado para describir
el aspecto del objeto.
- MSRenderer es un renderizador estatico
dedicado para marching squares usado para
computar frames para ser mostrados.
Esta clase junto con los metodos de dibujo
de MSSquare y MSMesh dibujan en el lienzo
MSCanvas a la malla de cuadrados.
- MSCanvas representa un lienzo cuyo objetivo
es mostrar los marching squares.
Hijo de la clase Canvas del API de Java que
muestra un graco frame por frame.
- MSFrame es hijo de la clase JFrame donde
se utilizan los compenentes y eventos del
GUI de Java para poder manipular y editar
correctamente a los cuadrados interpolados.
Sirve como un intermediario entre el usuario
y la implementacion.
El tutorial de Marching Cubes [4] ha sido una gua
para la implementacion de las clases MSVector2,
MSVector3, MSMatrix3, MSMatrixStack, MSInt,
Facultad de Ciencias - Universidad Nacional de Ingeniera
13 Carbajal Ipenza, Juan Carlos
Figura 9: GUI al principio de la implementacion
Figura 10: GUI modcado a lo largo de la
implementacion
MSNeighbour, MsVertex, MSSquare, MSMesh,
MSMaterial, MSRenderer, MSCanvas y MSFrame.
A lo largo del proceso de implementacion se
ha modicado el entorno de visualizacion con
nuevos componentes, nuevas funciones y nuevas
caractersticas (Fig. 9 y Fig. 10).
3. Resultados
Al terminar la implementacion de forma
secuencial y paralela del algoritmo Marching
Squares. Esta implementacion se puso a prueba
para diferentes tama nos de matriz de entrada, o sea
la resolucion del archivo imagen, versus la version
secuencial y las versiones paralelas (Fig. 11).
Las versiones paralela se testiaron para diferentes
n umeros de hilos. Mientras la resolucion de la
imagen sea menor a 40 x 40 no se nota diferencia
alguna entre el uso de la version secuencial o las
versiones paralelas, sin embargo (para este caso)
en cuestion de n umeros la version secuencial es
mas rapida ya que al tener pocas las no pierde
tiempo en particionarlas y unirlas. Al analizar la
resoluciones de imagenes mayores a 40 x 40 se nota
que la rapidez aumenta signicativamente mientras
Figura 11: Tiempo de ejecucion en segundos de
Marching Squares
Figura 12: Tiempo de ejecucion en un cluster de
computadoras de Marching Cubes. Ref. im. [1].
mas procesos tenga la implementacion.
Al promediar los cambias entre un proceso y otro
se obtiene que al duplicar el n umero de procesos
el tiempo de ejecucion es , en promedio, 2,71 veces
menor. Esto es muy notorio al observar el tiempo de
ejecucion de la matriz de 150 x 150 para la version
secuencial (10 min 4,889 seg) y paralela con 128
hilos (4,695 seg), claramente la version paralela con
128 hilos es 128,84 veces menor que la secuencial.
Al comparar con los resultados de renderizacion del
algoritmo Consensus-Surface (mejora de Marching
Cubes) con los obtenidos se nota que los tiempo de
ejecucion de ambos disminuye a la mitad al duplicar
el n umero de procesos. Esto nos muestra que la
paralelizacion en los algoritmos es muy importante
porque disminuye sifnicativamente el tiempo de
ejecucion de los algoritmos y mas importante si se
usan matrices o vectores como es el caso de esta
implementacion.
Facultad de Ciencias - Universidad Nacional de Ingeniera
14 Carbajal Ipenza, Juan Carlos
4. Trabajo a futuro
Se propone las mejoras o implementaciones de
los siguientes puntos en la implementacion del
algoritmo Marching Squares:
- El cambio de tama no de la malla cambiando la
posicion de cada cuadrado, esto en el campo
modelView de cada cuadrado y en la matriz
stack de la clase MSCanvas.
Todo esto modicando o replanteando el
metodo resize de la clase MSMesh.
- El correcto funcionamiento de la clase
MSPosicion que esta planteada.
Esta clase debe mostrar en un lienzo al
actual cuadrado seleccionado en la GUI de la
implementacion, asi como sus propiedades.
Esto se podra lograr replanteando la clase
MSCanvas y MSRenderer.
- Desligar la dependencia del MSFrame y
MSRenderer con MSCanvas para asi poder
abrir en paralelo varias mallas al mismo tiempo
mediante la clase JTabbedPane del GUI de
Java.
- Concretar un subprocesamiento m ultiple con
GUIs al momento de procesar la malla para
que el GUI no se bloquee al momento de
realizar los calculos. Esto se podra realizar
con la Clase SwingWorker del API de Java
dentro del constructor de la clase MSMesh.
Ademas asi se podra adicionar un componente
JProgressBar del API de Java para mostrar el
porcentaje de datos que se ha procesado.
- Aumentar el procesamiento implementando el
algoritmo Consensus-Surface [2] asi como su
version paralela [1] en el algoritmo Marchimg
Squares.
Trabajo a futuro para implementar la version 3D
de Marching Squares (Marching Cubes) en base a
esta implementacion y a estos aportes.
Referencias
[1] R. Sagawa, K. Nishino, M.D. Wheeler and K.
Ikeuchi. Parallel Processing of Range Data Merging.
Proc. IEEE/RSJ International Conference on Intelligent
Robots and Systems, vol. 1, pp. 577-583, 2001, Maui,
October.
[2] M.D. Wheeler, Y. Sato and K. Ikeuchi. Consensus
Surfaces for Modeling 3D Objects from Multiple Range
Images. In Proc. International Conference on Computer
Vision, January 1998.
[3] W. Lorensen and H. Cline. Cubes: a High
Resolution 3D Surface Construction Algorithm. In
Proc. SIGGRAPH 87, pp. 163-170, ACM, 1987.
[4] R. Gervaise and K. Richard. Marching Cubes
Tutorial: Development Report. Second year project at
ESSI from May 17 2002 to June 6 2002.
[5] S. V. Matveyev. Approximation of Isosurface in the
Marching Cube: Ambiguity Problem. Visualization 94,
Proceedings, IEEE Conference on Source: IEEE Xplore,
pp. 288-292, October 1994.
[6] P. J. Deitel y H. M. Deitel. C omo programar en Java.
Septima edici on, Cap. 23 Subprocesamiento m ultiple,
pp. 925-991. PEARSON EDUCACI

ON, Mexico 2008.


Facultad de Ciencias - Universidad Nacional de Ingeniera

Das könnte Ihnen auch gefallen