Errors, bugs, questions - page 2507

 
Vict:

I've worked out the original idea (the first code didn't count the addresses correctly). If you don't mind, it will be interesting to see the result with you.

It varies a lot from run to run, you can't tell the difference from one side to the other. Of course, I'm running the Release version.

#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:
A dynamic array has more checks, Renat once wrote, I can't find the post, just talking about index access, why it is significantly slower than pluses

It turns out that when filling dynamic arrays, it is better to fill static arrays first, and then do ArrayCopy to dynamic arrays.

 
fxsaber:
What causes this slowdown?

You have made a dynamic array out of a static one. Hence all the resulting type problems:

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]++;
        }
}

When the first and second loops run at different speeds.

 
fxsaber:

Thank you. It's strange, of course. I have a stable difference.

 
Vict:

Thank you. It's strange, of course. I have a stable difference.

I don't have a difference either.
 
fxsaber:

It turns out that when filling dynamic arrays, it is better to fill static arrays first, and then do ArrayCopy to dynamic arrays.

So it is!

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:

It is!

Well initialisation is usually a one-time thing and most of the time you don't have to worry about speed. (plus memory overhead)

But if there is constant index access and for example in ~99.9% of cases maximal array size is known, probably it makes sense to write your own simple wrapper around static array to replace dynamic one.

 
TheXpert:

Well initialisation is usually a one-time thing and most of the time you don't have to worry about speed. (plus memory overhead).

I have a record slowing down when parsing ticks. There are tens of millions of them, so it matters.

But if there is constant reference by indexes and for example in ~99.9% cases maximal size of array is known, probably it makes sense to write your simple wrapper around static array instead of dynamic one.

It might make sense to do a wrap on read as well.


SZZ On read, I can't get any speedup.

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:

It is!

my fillarray1 is slightly faster

and the reading's a mess.

 
TheXpert:

my fillarray1 is slightly faster

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

Release version is running. Optimisation enabled.

Reason: