Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Jare en 19 de Diciembre de 2005, 07:44:30 PM

Título: Debate Sobre C++ Y Oop
Publicado por: Jare en 19 de Diciembre de 2005, 07:44:30 PM
 Y dejar a los pobres de General en paz.
Título: Debate Sobre C++ Y Oop
Publicado por: seryu en 19 de Diciembre de 2005, 08:05:15 PM
 Que bien, voy a estrenarlo. ¿Cuantos compiladores conoceis que para una cadena de texto definida tal que asi:

char variable[] = "Meto lo que me da la gana.";

no guarde los datos de la cadena de forma alineada?
Título: Debate Sobre C++ Y Oop
Publicado por: Jare en 19 de Diciembre de 2005, 08:35:59 PM
 Algunas notas sobre lo que se ha dicho en el thread:

sizeof(char) == 1 por definicion del lenguaje, no hay que "asumirlo" porque es tan cierto como que 1+1 = 1.9999f. ;)

El almacenamiento de datos en la memoria es decisión del compilador. SIN EMBARGO, lo que el compilador debe garantizar es que la aritmética de punteros es consistente. "a", si 'a' no tiene el operator[] sobrecargado, está definido por el lenguaje como "*( a + b )", lo que establece la relación entre aritmética de punteros e indexación de arrays. Un curioso efecto secundario es que
char a = 3["abcdefg"];
compila perfectamente (¡probadlo!), y asigna el carácter 'd' a la variable a. Por cierto, que esto es de C, y C++ no lo altera.

Este tipo de peculiaridades es importante, porque EXISTEN arquitecturas de lo más raro, sobre las que se han implementado compiladores de C y C++. En esas arquitecturas, la implementación de los punteros puede incluir estructuras de datos internas complejas, con selectores, modificadores, descriptores y dios sabe qué mas. Es un dolor de cabeza para los programadores del compilador, pero ahi están. El C y el C++ son lenguajes muy cercanos a un concepto concreto de arquitectura, pero si otro sistema diferente quiere tener su compilador de C/C++, tiene que garantizar la sintaxis y semántica definida por el lenguaje, o establecer sus propias extensiones.

En cualquier caso, lo que es absurdo es manejar este tipo de discusiones como si estuvieran sujetas a opinion. La Referencia del lenguaje C++ existe y es quien dice lo que es cierto y lo que no - nuestra opinión al respecto es irrelevante. La referencia anotada original de Stroustrup (no he leido las ultimas ediciones) incluía notas sobre cómo los compiladores puede implementar determinados aspectos, con la intención de aclarar posibles ambiguedades; no se tiene por qué implementar así, pero la implementación debe respetar esos resultados.
Título: Debate Sobre C++ Y Oop
Publicado por: Pogacha en 19 de Diciembre de 2005, 08:39:38 PM
 No entiendo este thread :( , es para gente que este aburrida?

Edit:http://www.stratos-ad.com/forums/index.php...7&t=5773&st=270
Ignoren el post.
Título: Debate Sobre C++ Y Oop
Publicado por: ethernet en 19 de Diciembre de 2005, 09:05:55 PM
Cita de: Jare
En cualquier caso, lo que es absurdo es manejar este tipo de discusiones como si estuvieran sujetas a opinion. La Referencia del lenguaje C++ existe y es quien dice lo que es cierto y lo que no ...

En este foro discutimos las opiniones y las ideas, cosa que es sana, lo que es el colmo es que discutimos los datos. Nos empezamos a parecer a los políticos españoles.

En cuanto al tema, hay un montón de cosas tan caracterísitcas de los lenguajes.. de hecho por la red proliferan test de conocimientos del lenguaje sobre C/C++ como este.  
Título: Debate Sobre C++ Y Oop
Publicado por: zxs en 19 de Diciembre de 2005, 09:32:46 PM
 
CitarY vamos a ver... Zupervaca... lo de la alineación de la memoria, no es ni mucho menos lo que estás imaginandote. Lo que se intenta con la alineación es que datos de más de 4 bytes de tamaño, estén en colocados en posiciones múltiplo de 4 (0, 4, 8, 12, 16, ...) Porque a la hora de hacer una lectura en memoria con los micros de 32 bits, ante una situación como esta, puedes leer 4 bytes de golpe ahorrando ciclos del micro. Es un tema complicado, que seguramente en los manuales de Intel sobre la arquitectura de sus micros de 32 bits vendrá claramente explicado.

cierto y digo más, poneos a usar cosas que corran sobre otras tecnologías x86 como los buses (PCI/acceso a memoria directo I-O/ISA), en mi caso uso el bus PC/104, te puedes encontrar cosas de lo más "raro" y que respetan el status quo del PC/104: necesidad de leer datos en dos lecturas, en una, en la madre que lo parió... manuales que no explican el tipo de las tarjetas (8-16bits) econtrándote tarjetas de 8 bits con las ranuras de 16 bits y las sorpresitas que te llevas luego al intentar leer la memoria y ver que salen "cositas especiales" y tu te vuelves loco (bueno, esto es un galimatias, pero os aseguro que es bastante divertido  (nooo)  el programar los drivers de tarjetas de estas con los datasheet que vienen incluidos con ellas)
Título: Debate Sobre C++ Y Oop
Publicado por: [Over] en 19 de Diciembre de 2005, 10:50:57 PM
 Hola.

Si teneis más test como ese que habeis pasado os lo agradeceria :D.

Un saludo.
Título: Debate Sobre C++ Y Oop
Publicado por: marcode en 20 de Diciembre de 2005, 01:03:35 AM
 He visto en el hilo anterior que se está discutiendo sobre si la memoria está en ocasiones dividida, o fragmentada y alguien dijo anteriormente que había limitaciones con la memoria estática en cuanto al acceso.

Supongamos que quiero quitar el primer carácter de la cadena, desplazando el resto al principio, y lo hago así:.


char cadena[]="@quítame la berruga";

char *pIndCadena = cadena;
char *pFinCadena = cadena + strlen(cadena);

do
{
    *(pIndCadena) = *(pIndCadena+1);
}
while ( (pIndCadena++) != pFinCadena );



y ya puestos me interesaría asegurarme de que esta forma también es correcta, a mi no me da ningún problema:


memcpy( cadena, cadena+1, strlen(cadena));


¿Veis algún problema en manejar así la memoria en cualquier compilador o circustancia?
Título: Debate Sobre C++ Y Oop
Publicado por: synchrnzr en 20 de Diciembre de 2005, 10:27:55 AM
 Me gusta más el código de arriba. En el segundo no tienes ninguna garantía que la implementación de memcpy copie los datos de delante hacia atrás como lo has hecho en el primer fragmento de código. Además, suele haber una recomendación sobre no usar memcpy con fragmentos de memoria solapados (ya sabes, may cause unpredictable results) si no recuerdo mal.

sync
Título: Debate Sobre C++ Y Oop
Publicado por: marcode en 20 de Diciembre de 2005, 03:08:12 PM
 Gracias, tampoco me fiaba yo mucho del segundo caso, ni se gana mucho en velocidad, aunque lo cierto es que funciona.

Pero si alguien me dice que el primer caso pueda dar algun problema en alguna circustancia........... me la corto. (asco)

Tendría que tirar a la basura todo lo que he hecho hasta ahora. :lol:  
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 20 de Diciembre de 2005, 03:57:16 PM
...
Título: Debate Sobre C++ Y Oop
Publicado por: Pogacha en 20 de Diciembre de 2005, 04:21:06 PM
 d(char*c){while(*c)*c++=c[1];}

Me gane algo ?
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 20 de Diciembre de 2005, 04:30:21 PM
 segun mi forma de programar que difiere a los demas (se presupone que esta funcion solo vale para nSlide positivos)
char *SlideString( char *psz, size_t nLength, int nSlide )
{
if( psz != NULL && nLength > 0 )
{
 size_t nCount = nLength -nSlide +1;
 if( nCount > 0 )
 {
  char *pszRet = new char[nCount];
  if( pszRet != NULL )
  {
   memcpy( pszRet, psz + nSlide, nCount );
   return pszRet;
  }
 }
}
return NULL;
}
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 20 de Diciembre de 2005, 06:58:24 PM
...
Título: Debate Sobre C++ Y Oop
Publicado por: senior wapo en 20 de Diciembre de 2005, 07:19:07 PM
Cita de: LexDios que manía tiene la gente de usar la aritmética de punteros, cuando podrían usar el [] y sería más claro XD Además no se que problema hay con usar un int para el indice, y si te apuras usas un unsigned int, que creo que cadenas de más de 4GB no vais a encontrar por ahí, de hecho cadenas de texto de 2GB tampoco son especialmente frecuentes en memoria...
El hecho de usar punteros en lugar de índices es porque "potencialmente" es más rápido si el compilador no optimiza como debe (o puede). No es por el desbordamiento de la variable que hace de índice.

Generalmente, yo uso punteros antes que indices, menos cuando me da pereza y nadie va a ver el código :D

Pero vamos, eso ya lo sabrías, lo dices por claridad del código. Que más da, al fin y al cabo.


A mi estos hilos, quitando el post suelto que muestra alguna curiosidad, me dan repelús porque al final se convierten en un concurso para ver quien la tiene más grande (y yo, si me da mucho el aire, me costipo en seguida).  (twist)

Título: Debate Sobre C++ Y Oop
Publicado por: Pogacha en 20 de Diciembre de 2005, 08:06:13 PM
Cita de: Lexvoid DesplazarCadena (char * cadena, unsigned int posiciones)
{
  int i;
  int tam = strlen(cadena) - (posiciones - 1);

  if(cadena == NULL) return;

  for(i = 0; i < tam; i++)
     cadena[i] = cadena[i+posiciones];
}


Espero y creo que funciona XDDD
Lamentablemente no:

DesplazarCadena(MiCadena, - 1);
Título: Debate Sobre C++ Y Oop
Publicado por: marcode en 20 de Diciembre de 2005, 08:20:38 PM
Cita de: LexDios que manía tiene la gente de usar la aritmética de punteros, cuando podrían usar el [] y sería más claro XD Además no se que problema hay con usar un int para el indice, y si te apuras usas un unsigned int, que creo que cadenas de más de 4GB no vais a encontrar por ahí, de hecho cadenas de texto de 2GB tampoco son especialmente frecuentes en memoria... Yo lo hubiera hecho así:


void DesplazarCadena (char * cadena)
{
  int i;
  int tam = strlen(cadena);

  for(i = 0; i < tam; i++)
     cadena[i] = cadena[i+1];
}
Hombre, tampoco es que yo use siempre la aritmética de punteros, y menos para tratar una simple cadena de texto, simplemente trataba un poco de llevar al extremo el ejemplo para asegurarme.

Me ha sorprendido incluso que en una prueba que he hecho con los ejemplos anteriores va igual de velocidad de las dos maneras, con punteros como con índices [], en cambio con el memcpy aumenta en muchas veces su velocidad.
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 20 de Diciembre de 2005, 08:27:43 PM
 La única pega que le veo es que no esta optimizado, sacrificas claridad de código por optimización, lo cual no significa que este mal, por ejemplo, poner dentro de esta función el strlen en principio a mi forma de ver las cosas no seria correcto ya que puede que fuera de la función el programador ya haya obtenido la longitud de la cadena por que haya usado otras funciones que la requieran, de hay el motivo por el cual prefiero pasárselo a la función, también al usar [] estas realizando operaciones que con aritmética de punteros no harías: direccionbase+indice*tamañoelemento, no obstante dependiendo del compilador se optimizaría o no, como consecuencia de usar [] tienes que crear otra variable para saber cuando termina la cadena, en cambio al usar punteros podrías comprobar que el contenido no fuera barra 0, 0 binario, NULL o mediante la dirección final de la cadena, la comprobación a NULL del puntero en principio no creo que importe que te la olvidaras ya que muchos programadores prefieren hacerla fuera por que después de crear varias librerías usándose entre ellas (bla bla bla) realmente no sabes si dentro se comprueba o no con lo que a veces es mejor no ponerla y ahorrarse ese if ya que el programador lo pondrá fuera, el motivo de por que lo pongo en mi código es por que esta pensado para seguridad y mas que nada por acompañar a nLength > 0, el haber puesto esta comprobación de nLength > 0 no es por seguridad, es para poder especificar la forma de comportarse la función, al poner que sea mayor a 0 la cadena que tenga una longitud de 1 hará la rotación correctamente quedando la cadena limpia, si se pusiera que fuera mayor a 1 la rotación daría error, dependiendo de que el jefe de equipo vea correcto o no que se pueda rotar una cadena de longitud 1 se pondría uno u otro valor y así no tener que tocar apenas algo de código.
Repito, esto no quiere decir que el código que hayas puesto no sea correcto, que no quiero entrar en discusiones que no llevan a ninguna parte.
He puesto previsualizar el mensaje y veo que han puesto que un valor negativo fallaría, yo me imagino que presupones al igual que yo que no se pueden hacer rotaciones en el otro sentido.
El motivo de por que el memcpy acelere mucho su velocidad es que realiza estas operaciones antes de comenzar a copiar:
- Mirar si el origen y destino están en una dirección impar, si los dos están realizar la copia del primer byte y así alienar la copia en direcciones pares de memoria que es mucho más rápido.
- Copia lo máximo posible del origen sobre el destino con una longitud múltiplo de 4. (usando el rep de asm)
- Si el tamaño que queda por copiar es 3 copia dos bytes, luego 1 y sale del memcpy.
- Si el tamaño que queda por copiar es 1 copia un byte y sale del memcpy.
Título: Debate Sobre C++ Y Oop
Publicado por: seryu en 20 de Diciembre de 2005, 10:06:05 PM
 recordemos que los punteros tambien son variables..
Título: Debate Sobre C++ Y Oop
Publicado por: seryu en 20 de Diciembre de 2005, 10:07:20 PM
Cita de: Pogachad(char*c){while(*c)*c++=c[1];}

Me gane algo ?
Un cerdito  :P

el codigo ese es un buen ejemplo de algo que no deberia hacerse hoy dia  :D  
Título: Debate Sobre C++ Y Oop
Publicado por: marcode en 20 de Diciembre de 2005, 10:18:08 PM
 El ejemplo que he puesto ni lo he usado ni tengo intención de hacerlo, ni de hacerlo lo más rapido posible, era simplemente para hacer referencia a la conveniencia o no de tratar toda la memoria de forma lineal (de ahí el uso de punteros) sin preocuparse independientemente de como ha sido creada, a propósito de este comentario que has hecho anteriormente.

Citar
Hay estas creando un array de bytes de tamaño fijo que dependiendo de uno u otro compilador puede que tengas que tener acceso a el mediante un indice ya que nadie te asegura que la memoria de ese array sea continua
Entonces me dió a entender que esto no era valido (cambiaré el ejemplo).


int DATA[10000];
int *pData=DATA;

for (int i=0;i<10000;i++)
{
*(pData++) = 0;
}


pero esto sí:


int DATA[10000];
for (int i=0;i<10000;i++)
{
DATA[i]=0;
}


yo entiendo que es tan válido uno como otro.

Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 20 de Diciembre de 2005, 10:38:18 PM
Cita de: seryurecordemos que los punteros tambien son variables..
:blink:

pd: Me imagino que va por algo de lo que he escrito ya que va después de mi post, pero no se el que.
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 20 de Diciembre de 2005, 11:43:07 PM
...
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 20 de Diciembre de 2005, 11:58:20 PM
...
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 12:33:01 AM
 Bueno como veo que no se entiende bien la frase que puse, mejor la explico con código que es más robótico y me resulta más sencillo expresarme así:

// Con indices
void SlideString1( char *psz, size_t nLength )
{
for( size_t i = 0; i < nLength; i++ )
{
 psz[i] = psz[i+1];
 //*(psz + i * sizeof(char)) = *(psz + (i + 1) * sizeof(char));
 /*
 El compilador cambian los [] de esta manera:
  psz[i]  -> psz + i * sizeof(char)
  psz[i+1] -> psz + (i + 1) * sizeof(char)
 Con lo que el codigo final es:
  *(psz + i * sizeof(char)) = *(psz + (i + 1) * sizeof(char));
 La mayoria de los compiladores se dan cuenta de lo
 que se esta haciendo y optimizan el codigo
 */
}
}

// Con aritmetica de punteros
void SlideString2( char *psz, size_t nLength )
{
//char *pszEnd = psz + nLength;
//while( psz != pszEnd )
while( *psz != 0 )
{
 *psz = *(psz+1);
 psz++;
}
}

Vemos que en SlideString1 hace falta más variables y operaciones matemáticas que en la función SlideString2 que al final queda muy sencilla y optimizada, para que se vuelva mas legible os recomiendo poner el código en el visual c++ u otro ide.

Referente a lo que se parte los arrays no creo que suceda actualmente, estos casos sucedían en el viejo ms-dos y los compiladores que daban soporte a mas de 64kb trabajando con este limitación igualmente, no obstante nunca me quiero arriesgar a que mi código se compile en una plataforma con este tipo de limitaciones y el compilador de soporte a esta funcionalidad, a parte los arrays de tamaño fijo suele crearse como memoria automática, es decir, se crean en la pila, cosa peligrosa si por algún casual es pequeña o se exige que sea pequeña, aunque lo dicho, actualmente estos casos no creo que se den.
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 21 de Diciembre de 2005, 02:01:36 AM
...
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 21 de Diciembre de 2005, 03:33:27 AM
...
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 10:53:25 AM
 Haz la prueba con esta también, aunque su filosofía sea diferente veras que va más rápido aun que la creada en ensamblador por las optimizaciones que hace el memcpy. La variable pszDest debe estar creada.


void SlideString( char *psz, size_t nLength, int nSlide, char *pszDest )
{
if( psz != NULL && nLength > 0 )
{
 size_t nCount = nLength -nSlide +1;
 if( nCount > 0 )
 {
  memcpy( pszDest, psz + nSlide, nCount );
 }
}
}


Resultados en modo debug:
DesplazarCadenaExtremo: 891
DesplazarCadena: 1609
DesplazarCadenaAP: 1328
DesplazarCadenaSlide: 594

Resultados en modo release:
DesplazarCadenaExtremo: 468
DesplazarCadena: 1172
DesplazarCadenaAP: 469
DesplazarCadenaSlide: 187
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 21 de Diciembre de 2005, 11:55:49 AM
...
Título: Debate Sobre C++ Y Oop
Publicado por: sés en 21 de Diciembre de 2005, 12:11:16 PM
 La función memcpy() seguramente tiene optimizaciones que el código de arriba no tiene.

Ensamblador no significa velocidad si no se optimiza de verdad.
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 12:12:40 PM
 Estoy usando el .NET 2003 y por lo visto optimiza mucho mejor que el Visual C++ 6.0, increíble.
Te paso tu código modificado con otro método mucho mas rápido aun para copiar cadenas (DesplazarCadenaHyperSlide), es usando el memmove. También podrías usar el strcpy que iría igual de rápido que el memmove. La ventaja del memmove es que si se solapan lo resuelve copiando byte a byte, si no se solapan copia con las optimizaciones del memcpy.
He cambiado la función DesplazarCadena, ahora se le pasa también el tamaño, como se ve el strlen es una operación costosa por lo que siempre es mejor pasar el tamaño de las cadenas a la función.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <conio.h>
//--------------------------------------------------------------------------------
#define MAX 8000000 //100000000
//--------------------------------------------------------------------------------
void DesplazarCadenaHyperSlide (char * psz, int nLength, int nSlide)
{
if( psz != NULL && nLength > 0 )
{
 size_t nCount = nLength -nSlide +1;
 if( nCount > 0 )
 {
  memmove( psz, psz + nSlide, nCount );
 }
}
}
//--------------------------------------------------------------------------------
void DesplazarCadenaExtremo (char * cadena)
{
    __asm
    {
          mov  EBX, cadena

          cmp  BYTE PTR [EBX], 0
          jz   fin

inicio:
          mov  AL, BYTE PTR [EBX+1]
          mov  BYTE PTR [EBX], AL
          cmp  BYTE PTR [EBX+1], 0
          jz   fin
          inc  EBX
          jmp  inicio
fin:
    }
}
//--------------------------------------------------------------------------------
void DesplazarCadena (char * cadena, size_t tam)
{
    for(size_t i = 0; i < tam; i++)
          cadena[i] = cadena[i+1];
}
//--------------------------------------------------------------------------------
void DesplazarCadenaAP (char * cadena)
{
    while(*cadena)
    {
          *(cadena) = *(cadena+1);
          cadena++;
}
}
//--------------------------------------------------------------------------------
void SlideString( char *psz, size_t nLength, int nSlide, char *pszDest )
{
if( psz != NULL && nLength > 0 )
{
 size_t nCount = nLength -nSlide +1;
 if( nCount > 0 )
 {
  memcpy( pszDest, psz + nSlide, nCount );
 }
}
}
//--------------------------------------------------------------------------------

int main(int argc, char* argv[])
{
    clock_t ti, tf;
    int i;

    char * jose = (char *) malloc(20);
 strcpy(jose, "a mi me gusta luisa");
  size_t tamanio = strlen(jose);
 char *resultado = new char[tamanio];


    //----------------------------------------------------------------------------

    ti = ((clock() * 1000) / CLK_TCK);

    for(i = 0; i < MAX; i++)
    {
          strcpy(jose, "a mi me gusta luisa");
          DesplazarCadenaExtremo(jose);
    }

    tf = ((clock() * 1000) / CLK_TCK);

    printf("DesplazarCadenaExtremo = %d\n", tf-ti);

    //----------------------------------------------------------------------------

    ti = ((clock() * 1000) / CLK_TCK);

    for(i = 0; i < MAX; i++)
    {
          strcpy(jose, "a mi me gusta luisa");
          DesplazarCadena(jose, tamanio);
    }

    tf = ((clock() * 1000) / CLK_TCK);

    printf("DesplazarCadena        = %d\n", tf-ti);

    //----------------------------------------------------------------------------

    ti = ((clock() * 1000) / CLK_TCK);

    for(i = 0; i < MAX; i++)
    {
          strcpy(jose, "a mi me gusta luisa");
          DesplazarCadenaAP(jose);
    }

    tf = ((clock() * 1000) / CLK_TCK);

    printf("DesplazarCadenaAP      = %d\n", tf-ti);

    //----------------------------------------------------------------------------

    ti = ((clock() * 1000) / CLK_TCK);

    for(i = 0; i < MAX; i++)
    {
    strcpy(jose, "a mi me gusta luisa");
 SlideString(jose, tamanio, 1, resultado);
    }

    tf = ((clock() * 1000) / CLK_TCK);

    printf("DesplazarCadenaSlide      = %d\n", tf-ti);

    //----------------------------------------------------------------------------

    ti = ((clock() * 1000) / CLK_TCK);

    for(i = 0; i < MAX; i++)
    {
          strcpy(jose, "a mi me gusta luisa");
    DesplazarCadenaHyperSlide(jose, tamanio, 1);
    }

    tf = ((clock() * 1000) / CLK_TCK);

    printf("DesplazarCadenaHyperSlider      = %d\n", tf-ti);

    //----------------------------------------------------------------------------

 delete resultado;
 free(jose);
 //getch();
    return 0;
}


Ultimos resultados:
DesplazarCadenaExtremo: 468
DesplazarCadena: 657
DesplazarCadenaAP: 469~484 (De tres pruebas sufri estas variaciones, de quedarme siempre prefiero quedarme con los valores mas altos)
DesplazarCadenaSlide: 178~250
DesplazarCadenaHyperSlide: 109~187

Editado: Es importante indicar que con la prueba SlideString se esta realizando el strcpy, el cual no haría falta ya que no se esta modificando la cadena origen, con lo que se ganaría velocidad.
Título: Debate Sobre C++ Y Oop
Publicado por: Lex en 21 de Diciembre de 2005, 12:46:55 PM
...
Título: Debate Sobre C++ Y Oop
Publicado por: sés en 21 de Diciembre de 2005, 01:01:40 PM
 Yo ante esas cosas: (ses)
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 01:14:50 PM
 Mira ver si en modo release tienes la opción de optimizar para velocidad o si esta desactivado. Con la opción desactivada no veas lo cutre que se vuelve el tema.
Título: Debate Sobre C++ Y Oop
Publicado por: senior wapo en 21 de Diciembre de 2005, 01:29:03 PM
 Si de verdad tienes interés mírate el código ensamblador generado por el compilador, ya que el compilador puede modificar el código ensamblador que le metes (al menos gcc lo hace, por eso tiene esa manera tan rara de incluir fragmentos asm, indicando que registros usas y cuales modificar).

Además, incluir fragmentos asm puede cargarse ciertas optimizaciones si considera el bloque asm como algo opaco, porque entonces no puede asumir ciertas cosas de cara a optimizar (o hacerlo mal).

Pero vamos, que suponer está muy bien y tal, pero la verdadera respuesta para cada Build de cada compilador la ves mirando el código generado. Después, a jugar con los parámetros que se le pasa al compilador en la línea de comandos.

Un poco friki todo esto de las cadenas, ¿ no ? :P  
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 01:37:51 PM
 Vamos al frikismo extremo  :lol:, he hecho lo que supuestamente hace el memcpy en c salvo la comprobación de si el origen y el destino están en dirección impar y mi sorpresa es que esta función es más rápida que el memcpy, por lo menos con cadenas cortas ya que el rep al principio consume algun ciclo que otro.


void MemCpy( char *pszDest, char *pszSource, size_t nSize )
{
int *pszDestI = (int*)pszDest, *pszSourceI = (int*)pszSource;
int *pszDestEndI = (int*)pszDest + (nSize >> 2);
while( pszDestI != pszDestEndI )
{
 *pszDestI = *pszSourceI;
 pszDestI++;
 pszSourceI++;
}
if( (nSize & 3) == 3 )
{
 *((short*)pszDestI) = *((short*)pszSourceI);
 *(((char*)pszDestI)+2) = *(((char*)pszSourceI)+2);
}
else
{
 if( (nSize & 1) == 1 )
 {
  *((char*)pszDestI) = *((char*)pszSourceI);
 }
}
}


DesplazarCadenaSlide me da ahora 171~187 siempre (ole)
Título: Debate Sobre C++ Y Oop
Publicado por: senior wapo en 21 de Diciembre de 2005, 01:48:26 PM
 memcpy() tiene mayor overhead porque alinea las direcciones a múltiplos de 4 bytes de forma que no se produzcan 'stalls' en el procesador al mover un DWORD de/a una dirección no alineada.

En tu código, si los punteros no estan alineados a 4bytes (2bits inferiores deberían ser 0) cada copia de DWORD recibe una penalización de varios ciclos (no era 1 ciclo por cada byte de desplazamiento? no me acuerdo ya). Al menos, esto era así allá por la époce pre-pentium III no se ahora, ni si pasa con los AMDs, pero imagino que continúa pasando. Hace muchísimo que no reescribo bucles en asm.

El caso es que para cadenas cortas (7-12 bytes?) puede que la carga extra que supone alinear (debido a los CMPs y JMPs) puede ser más lenta que el parón que se produce por no estar alineado.
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 02:00:51 PM
 Ya, si lo puse en mi post eso: "salvo la comprobación de si el origen y el destino están en dirección impar"
El motivo de por que es mas rápido esta función es que el memcpy no puede alinear la memoria a direcciones pares ya que el destino siempre es el origen +1, es decir, una dirección impar si el origen es par y una direccion par si el origen es impar.

No obstante haciendo una modificación a mi código puedes solapar memoria y que se copie correctamente, lo cual no esta mal si te asegura que se copie bien. (Presuponiendo que seguimos con que nSlide sea positivo claro).
void MemCpy2( char *pszDest, char *pszSource, size_t nSize )
{
char *pszDestEnd = pszDest + (nSize >> 2);
while( pszDest != pszDestEnd )
{
 *((int*)pszDest) = *((int*)pszSource);
 pszDest += 4;
 pszSource += 4;
}
if( (nSize & 1) == 1 )
{
 *((char*)pszDest) = *((char*)pszSource);
 pszDest++;
 pszSource++;
}
if( (nSize & 2) == 2 )
{
 *((short*)pszDest) = *((short*)pszSource);
}
}


DesplazarCadenaHyperSlide se quearia en 157.
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 21 de Diciembre de 2005, 02:24:51 PM
 Perdonar que ponga dos post seguidos, pero es que no me deja editar el anterior.
El código final es así, salvo algún error que no me haya dado cuenta:

void MemCpy( char *pszDest, char *pszSource, size_t nSize )
{
// Alinear a direcciones pares
if( ((__int64)pszDest & 1) == 1 && ((__int64)pszSource & 1) == 1 )
{
 *((char*)pszDest) = *((char*)pszSource);
 pszDest++;
 pszSource++;
 nSize--;
}
// Alinear a direcciones multiplo de 4
if( ((__int64)pszDest & 2) == 2 && ((__int64)pszSource & 2) == 2 )
{
 *((short*)pszDest) = *((short*)pszSource);
 pszDest += 2;
 pszSource += 2;
 nSize -= 2;
}
// Copiar de 4 en 4 bytes
int *pszDestI = (int*)pszDest, *pszSourceI = (int*)pszSource;
int *pszDestEndI = (int*)pszDest + (nSize >> 2);
while( pszDestI != pszDestEndI )
{
 *pszDestI = *pszSourceI;
 pszDestI++;
 pszSourceI++;
}
// Copiar 3 bytes si quedan
if( (nSize & 3) == 3 )
{
 *((short*)pszDestI) = *((short*)pszSourceI);
 *(((char*)pszDestI)+2) = *(((char*)pszSourceI)+2);
}
else
{
 // Copiar el ultimo byte si queda
 if( (nSize & 1) == 1 )
 {
  *((char*)pszDestI) = *((char*)pszSourceI);
 }
}
}


No he notado cambio de velocidad por lo que comentaba antes.
Título: Debate Sobre C++ Y Oop
Publicado por: Mars Attacks en 21 de Diciembre de 2005, 04:33:44 PM
 Wenas. Toy un poco amodorrado, así que no me hagáis mucho caso... (ni me he leído el tema entero ni sé si va de esto, así que... XD)


#include <stdio.h>

int main(){

char lalala[]="lalala";
char *lerele=&lalala[1];

printf("%s\n",lalala);
printf("%s\n",lerele);

}


My 0'02 €
Título: Debate Sobre C++ Y Oop
Publicado por: synchrnzr en 22 de Diciembre de 2005, 10:09:22 AM
 Va a ser que el método de Mars es el más rápido (ole)

sync
Título: Debate Sobre C++ Y Oop
Publicado por: zupervaca en 22 de Diciembre de 2005, 11:23:11 AM
 Va ser que no vale <_<, debe de modificarse el búfer origen o el destino ya que si te devuelve el origen +1 y después haces un delete de ese puntero o del que le has pasado a la función... como broma valdría.
Título: Debate Sobre C++ Y Oop
Publicado por: Mars Attacks en 22 de Diciembre de 2005, 10:40:39 PM
 Yo sólo digo que os pasáis la vida buscando la solución más óptima a problemas estúpidos: invertir cadenas, desplazar cadenas... Luego en la "vida real" suele haber una forma "chachiguay" de solucionar cada problema en concreto.
De todas formas, no soy coder, así que no tengo el cerebro tan enfermo y reblandecido y no os entiendo. Cada cual con sus pasatiempos  ;)