Errores, fallos, preguntas - página 2507

 
Vict:

He solucionado la idea original (el primer código no contaba las direcciones correctamente). Si no te importa, será interesante ver el resultado contigo.

Varía mucho de una carrera a otra, no se nota la diferencia de un lado a otro. Por supuesto, estoy ejecutando la versión de lanzamiento.

#define  WRONG_ALIGNED
#define  CACHE_LINE_SIZE 64

struct Data {
#ifdef  WRONG_ALIGNED
   ushort pad;
#else
   uint pad;
#endif
   uint ar[CACHE_LINE_SIZE/sizeof(int)+1];
};

#import "msvcrt.dll"
  long memcpy(uint &, uint &, long);
#import
#define  getaddr(x) memcpy(x, x, 0)

void OnStart()
{
//   Data data[32768];
   Data data[];
  
   ArrayResize(data, 32768); // для не static-массива жуткие тормоза выходят. 
   ZeroMemory(data);
   
   ulong start_time = GetMicrosecondCount();
   
   for(unsigned i = 0; i < 10000; ++ i) {
    for (int j = ArraySize(data) - 1; j >= 0; j--)
    {
         int index = int(CACHE_LINE_SIZE - getaddr(data[j].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
         ++ data[j].ar[index];
         ++ data[j].pad;
      }
   }
      
   Alert(GetMicrosecondCount() - start_time);
   
//   Print(data[100].ar[0]);
//   Print(data[100].pad);
}
 
TheXpert:
Un array dinámico tiene más comprobaciones, Renat escribió una vez, no encuentro el post, sólo hablando del acceso a los índices, por qué es significativamente más lento que los pluses

Resulta que cuando se llenan arrays dinámicos, es mejor llenar primero los arrays estáticos y luego hacer ArrayCopy a los arrays dinámicos.

 
fxsaber:
¿Cuál es la causa de esta ralentización?

Has hecho un array dinámico a partir de uno estático. De ahí todos los problemas de tipo resultantes:

int a[][100];
ArrayResize(a, 100);
ZeroMemory(a);

// Первый цикл
for(int i; i < 100; ++i)
{
        for(int n; n < 100; ++n)
        {
                a[i][n]++;
        }
}

// Второй цикл
for(int n; n < 100; ++n)
{
        for(int i; i < 100; ++i)
        {
                a[i][n]++;
        }
}

Cuando el primer y el segundo bucle funcionan a diferentes velocidades.

 
fxsaber:

Gracias. Es extraño, por supuesto. Tengo una diferencia estable.

 
Vict:

Gracias. Es extraño, por supuesto. Tengo una diferencia estable.

Yo tampoco tengo ninguna diferencia.
 
fxsaber:

Resulta que cuando se llenan arrays dinámicos, es mejor llenar primero los arrays estáticos y luego hacer ArrayCopy a los arrays dinámicos.

Así es.

void FillArray1( int &Array[] )
{
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size; i++)
    Array[i] = i;
}

#define  ARRAY_SIZE 10000

void FillArray2( int &Array[] )
{
  int ArrayStatic[ARRAY_SIZE];
  
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size;)
  {
    const int Size2 = i + ARRAY_SIZE < Size ? ARRAY_SIZE : Size - i;
    
    for (int j = 0; j < Size2; j++)
      ArrayStatic[j] = i++;
      
    if (Size2)
      ArrayCopy(Array, ArrayStatic, i - Size2, 0, Size2);
  }
}

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  int Array1[];
  ArrayResize(Array1, 1 e7);

  int Array2[];
  ArrayResize(Array2, 1 e7);
  
  BENCH(FillArray1(Array1));
  BENCH(FillArray2(Array2));
}
 
fxsaber:

Lo es.

La inicialización suele ser algo puntual y la mayoría de las veces no hay que preocuparse por la velocidad. (más la sobrecarga de memoria)

Pero si hay un acceso constante a los índices y, por ejemplo, en el ~99,9% de los casos se conoce el tamaño máximo de la matriz, probablemente tenga sentido escribir su propia envoltura simple alrededor de la matriz estática para reemplazar la dinámica.

 
TheXpert:

La inicialización suele ser algo puntual y la mayoría de las veces no hay que preocuparse por la velocidad. (más la sobrecarga de memoria).

Tengo un registro que se ralentiza al analizar los ticks. Hay decenas de millones de ellos, así que es importante.

Pero si hay una referencia constante por índices y, por ejemplo, en el ~99,9% de los casos se conoce el tamaño máximo de la matriz, probablemente tiene sentido escribir su simple envoltura alrededor de la matriz estática en lugar de la dinámica.

Podría tener sentido hacer una envoltura en la lectura también.


SZZ En la lectura, no puedo obtener ningún aumento de velocidad.

long ArraySum1( int &Array[] )
{
  long Sum = 0;
  
  const int Size = ArraySize(Array);
  
  for (int i = 0; i < Size; i++)
    Sum += Array[i];
    
  return(Sum);
}

#define  ARRAY_SIZE 100000

long ArraySum2( int &Array[] )
{
  long Sum = 0;

  const int Size = ArraySize(Array);  
  
  int ArrayStatic[ARRAY_SIZE];  
  
  for (int i = 0; i < Size;)
  {
    const int Size2 = i + ARRAY_SIZE < Size ? ARRAY_SIZE : Size - i;

    ArrayCopy(ArrayStatic, Array, 0, i, Size2);
    
    for (int j = 0; j < Size2; j++)
      Sum += ArrayStatic[j];
      
    i += Size2;
  }
  
  return(Sum);
}

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1 e8);
  ArrayInitialize(Array, 1);
      
  BENCH(Print(ArraySum1(Array)));
  BENCH(Print(ArraySum2(Array)));
}
 
fxsaber:

Lo es.

mi fillarray1 es ligeramente más rápido

y la lectura es un desastre.

 
TheXpert:

mi fillarray1 es ligeramente más rápido

Time[FillArray1(Array1)] = 39501
Time[FillArray2(Array2)] = 30304

La versión de lanzamiento está en marcha. Optimización habilitada.