• Publicidad

Optimizar esta traducción

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Optimizar esta traducción

Notapor slopal » 2006-02-28 11:20 @513

Como ya os he dicho en otro mensaje, tengo problemas de duración de tiempo en mi script. Mirando, mirando, he visto que la parte que más tiempo tarda (¡también es la que hace más cosas!) es esta. Es el algoritmo Horspool y lo he traducido directamente del C. Pero seguro que en Perl se puede optimizar con muchos truquillos de estos que sabéis vosotros ;):

Programa Original C
Sintáxis: [ Descargar ] [ Ocultar ]
Using c Syntax Highlighting
  1. void HORSPOOL(char *tupla, int mida_tupla, char *cadena, int mida_cadena) {
  2.    int j, bmBc[ASIZE];
  3.    char c;
  4.  
  5.    /* Preprocessing */
  6.    preBmBc(tupla, mida_tupla, bmBc);
  7.  
  8.    /* Searching */
  9.    j = 0;
  10.    while (j <= mida_cadena - mida_tupla) {
  11.       c = cadena[j + mida_tupla - 1];
  12.       if (tupla[mida_tupla - 1] == c && memcmp(tupla, cadena + j, mida_tupla - 1) == 0)
  13.          OUTPUT(j);
  14.       j += bmBc[c];
  15.    }
  16. }
  17.  
  18. void preBmBc(char *tupla, int mida_tupla, int bmBc[]) {
  19.    int i;
  20.  
  21.    for (i = 0; i < ASIZE; ++i)
  22.       bmBc[i] = mida_tupla;
  23.    for (i = 0; i < mida_tupla - 1; ++i)
  24.       bmBc[tupla[i]] = mida_tupla - i - 1;
  25. }
  26.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Mi Horspool en "mi" Perl...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my ( $j, $c, $k );
  2.  
  3. #### Preprocessat
  4.  
  5. preBmBc();
  6. #### Cerca
  7.  
  8. $j = 0;
  9.  
  10. while ( $j <= $mida_cadena - $mida_tupla ) {
  11.     $c = $cadena[ $j + $mida_tupla - 1 ];
  12.     $k = $j + $mida_tupla - 1;
  13.  
  14.     my $part_a_comparar = join( '', @cadena[ $j .. $k ] );
  15.     if ( ( $tupla[ $mida_tupla - 1 ] eq $c ) and ( $part_a_comparar eq $tupla ) ) {
  16.         $trobada       = 1;
  17.         $freq_trobades = $freq_trobades + 1;    # augmentem la freqüència
  18.         push( @posicions, $j );
  19.     }
  20.     $j = $j + $bmbc{$c};
  21. }
  22.  
  23. sub preBmBc()                          #ordre ==> a c g t
  24. {
  25.     %bmbc = (
  26.         'A' => $mida_tupla,
  27.         'C' => $mida_tupla,
  28.         'G' => $mida_tupla,
  29.         'T' => $mida_tupla,
  30.     );
  31.  
  32.     for ( my $i = 0; $i < $mida_tupla - 1; ++$i ) {
  33.         $bmbc{ $tupla[$i] } = $mida_tupla - $i - 1;
  34.     }
  35. }                                      # sub preBmBc
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
slopal
Perlero nuevo
Perlero nuevo
 
Mensajes: 78
Registrado: 2005-11-23 11:41 @528

Publicidad

Re: Optimizar esta traducción

Notapor explorer » 2006-03-01 13:45 @614

El algoritmo Boyer-Moore-Horspool se encuentra descrito en el libro Mastering Algorithms with Perl (http://www.azet.org/pub/ebooks/O'Reilly ... tering.pdf), páginas 373-376.

Bueno, más bien sólo está descrito el Boyer-Moore, y luego comentan la reducción al Hospool.

En cuanto a trucos, sí que se pueden poner algunos, como por ejemplo, reordenar las condiciones dentro de los if para que se evalúen las condiciones más ligeras (como por ejemplo, poner $part_a_comparar eq $tupla antes de ($tupla[$mida_tupla -1] eq $c)).

Lo que he visto es muy parecido al algoritmo original, pero distinto del que aparece en el libro.

De todas formas... depende de lo grande que sea el lugar donde estás buscando. Si es muy, muy grande, yo lo haría en C, dentro del código Perl, con el módulo Inline::C. Yo lo hice una vez cuando necesitaba velocidad y me fue muy bien. Lo más difícil fue ver cómo pasar los argumentos a la parte de C, pero si son variables sencillas, igual de sencillo es pasarlas.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor slopal » 2006-03-02 13:10 @590

Gracias, ¡me miraré todo esto!

Si no tengo problemas para acceder al módulo éste de C..... Pues también lo intentaré (ojalá).
slopal
Perlero nuevo
Perlero nuevo
 
Mensajes: 78
Registrado: 2005-11-23 11:41 @528

Notapor slopal » 2006-03-15 15:06 @671

Por no crear otro hilo lo pongo aquí. Tengo esta parte de código, no sé si lo estoy haciendo bien, es una de las partes que más tarde, y en parte es normal porque los ficheros pueden ser "grandes"... pero por si acaso. No tengo muy claro qué valor tendría que poner para que fuera óptimo, en el campo del número del read (¿¿¿¿ qué he puesto ???? Para que quede más claro?)

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while ( my $bytesread = read( $Input{'cadena'}, my $buffer, ??
  2.         ? ??
  3.                 ? ) ) {
  4.             print OUTFILE $buffer;
  5.     }
  6.  
  7.     close(OUTFILE);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Si sabéis otra manera mucho más mejor :P Acepto todo tipo de comentarios. thanx!
slopal
Perlero nuevo
Perlero nuevo
 
Mensajes: 78
Registrado: 2005-11-23 11:41 @528

Re: Optimizar esta traducción

Notapor explorer » 2006-03-15 18:35 @816

Una opción sería... no leer el fichero a memoria...

Me explico... en el caso de que los ficheros que tengas que leer sean muy grandes y estés usando Linux (o UNIX), lo más cómodo es usar la función del sistema 'mmap', cuya función es hacer 'mapear' el fichero a memoria, como si se estuviera leyendo, pero lo bueno es que todas las operaciones de lectura/escritura y gestión de direcciones de memoria las realiza el sistema operativo (una tarea muy rápida).

En Perl v5.8.8. está la opción de usar PerlIO con un 'layer' mmap. Sería algo así como esto:

open($bases, "<:raw:mmap", "raton_almizclero_cromosoma_2.txt");

y a partir de ese momento, hacer seek() para posicionarte dentro del fichero en la posición que quieras leer, y luego, read().

Hay dos opciones más. Con el módulo Sys::Mmap se puede mapear todo un fichero a una variable escalar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use Sys::Mmap;
  2.  
  3. # Aquí abres el fichero y el FILEHANDLE es el file handle del fichero. Luego lo mapeas con
  4. mmap($foo, 0, PROT_READ, MAP_SHARED, FILEHANDLE) or die "mmap: $!";
  5.  
  6. # Trabajar aquí con $foo, por ejemplo substr( )
  7. munmap($foo) or die "munmap: $!";
  8. close FILEHANDLE;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Otra forma:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use Sys::Mmap;
  2.  
  3. new Mmap $cadena, 0, 'humano_bases_8333.txt' or die $!;
  4. # Trabajar con el escalar $cadena como si fuera cualquier otra cadena.
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y otra opción interesante es Tie::MmapArray, que mapea un fichero a un array en vez de a un escalar.

Si no tienes más remedio que usar el bucle que has escrito antes, el tamaño a indicar en ????? debería ser igual o múltiplo al tamaño del búfer que el sistema operativo usa para el intercambio de datos entre el disco y la memoria. En algunos sistemas pueden ser 4 Kb, en otros 32 Kb, etc... Puedes realizar experimentos cambiando el tamaño y comprobar con la función timer si ha tardado más o menos. Debes ejecutar el mismo bucle con el mismo tamaño dos o tres veces para tener una confirmación del tiempo que tarda.

En este tema puede pasar una cosa muy curiosa... puede que con un tamaño de 16 Kb vaya más rápido que con uno de 32 Kb, pero menos que uno de 8 Kb.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados

cron