Erros, bugs, perguntas - página 2507

 
Vict:

Tive a ideia original (o primeiro código não contava correctamente os endereços). Se não se importar, será interessante ver o resultado consigo.

Varia muito de corrida para corrida, não se nota a diferença de um lado para o outro. Claro, estou a executar a versão Release.

#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:
Uma matriz dinâmica tem mais verificações, Renat uma vez escreveu, não consigo encontrar o post, apenas falando sobre o acesso ao índice, porque é significativamente mais lento do que as vantagens

Acontece que ao encher arrays dinâmicos, é melhor primeiro encher arrays estáticos, e depois fazer ArrayCopy a arrays dinâmicos.

 
fxsaber:
O que causa este abrandamento?

Fez uma matriz dinâmica a partir de uma matriz estática. Daí todos os 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]++;
        }
}

Quando o primeiro e segundo loops funcionam a velocidades diferentes.

 
fxsaber:

Obrigado. É estranho, é claro. Tenho uma diferença estável.

 
Vict:

Obrigado. É estranho, é claro. Tenho uma diferença estável.

Eu também não tenho diferença.
 
fxsaber:

Acontece que ao encher arrays dinâmicos, é melhor primeiro encher arrays estáticos, e depois fazer ArrayCopy a arrays dinâmicos.

Assim é!

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:

E é!

A iniciação bem sucedida é normalmente uma coisa única e na maioria das vezes não tem de se preocupar com a velocidade. (mais despesas gerais de memória)

Mas se houver um acesso de índice constante e por exemplo em ~99,9% dos casos o tamanho máximo da matriz é conhecido, provavelmente faz sentido escrever a sua própria embalagem simples em torno da matriz estática para substituir a dinâmica.

 
TheXpert:

A inicialização é normalmente uma coisa única e na maioria das vezes não é preciso preocupar-se com a velocidade. (mais despesas gerais de memória).

Tenho um recorde de desaceleração na análise de carrapatos. Há dezenas de milhões deles, por isso é importante.

Mas se houver uma referência constante por índices e por exemplo em ~99,9% dos casos o tamanho máximo de matriz é conhecido, provavelmente faz sentido escrever a sua simples embalagem em torno de matriz estática em vez de dinâmica.

Pode fazer sentido fazer um embrulho também na leitura.


SZZ Em leitura, não consigo obter qualquer aceleração.

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:

E é!

o meu fillarray1 é ligeiramente mais rápido

e a leitura é uma confusão.

 
TheXpert:

o meu fillarray1 é ligeiramente mais rápido

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

A versão de lançamento está a correr. Optimização activada.